1#![allow(dead_code, unused_variables)]
4
5use std::convert::From;
6use std::fmt;
7use std::ptr::copy_nonoverlapping;
8use std::sync::Arc;
9
10use byte_slice_cast::*;
11use bytes::BytesMut;
12
13use crate::audiosample::*;
14use crate::pixel::*;
15use crate::timeinfo::*;
16
17use self::FrameError::*;
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
21pub enum FrameError {
22 InvalidIndex,
24 InvalidConversion,
26}
27
28impl std::error::Error for FrameError {}
29
30impl fmt::Display for FrameError {
31 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32 match self {
33 InvalidIndex => write!(f, "Invalid Index"),
34 InvalidConversion => write!(f, "Invalid Conversion"),
35 }
36 }
37}
38
39#[derive(Clone, Debug, PartialEq, Eq, Hash)]
42#[allow(clippy::upper_case_acronyms)]
43pub enum FrameType {
44 I,
46 P,
48 B,
50 SKIP,
55 OTHER,
57}
58
59impl fmt::Display for FrameType {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 match *self {
62 FrameType::I => write!(f, "I"),
63 FrameType::P => write!(f, "P"),
64 FrameType::B => write!(f, "B"),
65 FrameType::SKIP => write!(f, "Skip"),
66 FrameType::OTHER => write!(f, "x"),
67 }
68 }
69}
70
71#[derive(Clone, Debug)]
73pub struct VideoInfo {
74 pub width: usize,
76 pub height: usize,
78 pub flipped: bool,
80 pub frame_type: FrameType,
82 pub format: Arc<Formaton>,
84 pub bits: u8,
86}
87
88impl VideoInfo {
89 pub fn new(
91 width: usize,
92 height: usize,
93 flipped: bool,
94 frame_type: FrameType,
95 format: Arc<Formaton>,
96 ) -> Self {
97 let bits = format.get_total_depth();
98 VideoInfo {
99 width,
100 height,
101 flipped,
102 frame_type,
103 format,
104 bits,
105 }
106 }
107
108 pub fn get_width(&self) -> usize {
110 self.width
111 }
112 pub fn get_height(&self) -> usize {
114 self.height
115 }
116 pub fn is_flipped(&self) -> bool {
118 self.flipped
119 }
120 pub fn get_frame_type(&self) -> &FrameType {
122 &self.frame_type
123 }
124 pub fn get_format(&self) -> Formaton {
126 *self.format
127 }
128
129 pub fn set_width(&mut self, width: usize) {
131 self.width = width;
132 }
133 pub fn set_height(&mut self, height: usize) {
135 self.height = height;
136 }
137
138 pub fn size(&self, align: usize) -> usize {
140 let mut size = 0;
141 for &component in self.format.into_iter() {
142 if let Some(c) = component {
143 size += c.get_data_size(self.width, self.height, align);
144 }
145 }
146 size
147 }
148}
149
150impl fmt::Display for VideoInfo {
151 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
152 write!(f, "{}x{}", self.width, self.height)
153 }
154}
155
156impl PartialEq for VideoInfo {
157 fn eq(&self, info2: &VideoInfo) -> bool {
158 self.width == info2.width && self.height == info2.height && self.format == info2.format
159 }
160}
161
162#[derive(Clone, Debug)]
164pub struct AudioInfo {
165 pub samples: usize,
167 pub sample_rate: usize,
169 pub map: ChannelMap,
171 pub format: Arc<Soniton>,
173 pub block_len: Option<usize>,
177}
178
179impl AudioInfo {
180 pub fn new(
182 samples: usize,
183 sample_rate: usize,
184 map: ChannelMap,
185 format: Arc<Soniton>,
186 block_len: Option<usize>,
187 ) -> Self {
188 AudioInfo {
189 samples,
190 sample_rate,
191 map,
192 format,
193 block_len,
194 }
195 }
196 pub fn get_sample_rate(&self) -> usize {
198 self.sample_rate
199 }
200 pub fn get_channels_number(&self) -> usize {
202 self.map.len()
203 }
204 pub fn get_format(&self) -> Soniton {
206 *self.format
207 }
208 pub fn get_samples(&self) -> usize {
210 self.samples
211 }
212
213 pub fn get_block_len(&self) -> Option<usize> {
215 self.block_len
216 }
217
218 pub fn size(&self, align: usize) -> usize {
220 self.format.get_audio_size(self.samples, align) * self.map.len()
221 }
222}
223
224impl fmt::Display for AudioInfo {
225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 write!(
227 f,
228 "{} Hz, {} ch",
229 self.sample_rate,
230 self.get_channels_number()
231 )
232 }
233}
234
235impl PartialEq for AudioInfo {
236 fn eq(&self, info2: &AudioInfo) -> bool {
237 self.sample_rate == info2.sample_rate
238 && self.map == info2.map
239 && self.format == info2.format
240 }
241}
242
243#[derive(Clone, Debug, PartialEq)]
245pub enum MediaKind {
246 Video(VideoInfo),
248 Audio(AudioInfo),
250}
251
252impl MediaKind {
253 pub fn get_video_info(&self) -> Option<VideoInfo> {
255 if let MediaKind::Video(vinfo) = self {
256 Some(vinfo.clone())
257 } else {
258 None
259 }
260 }
261 pub fn get_audio_info(&self) -> Option<AudioInfo> {
263 if let MediaKind::Audio(ainfo) = self {
264 Some(ainfo.clone())
265 } else {
266 None
267 }
268 }
269 pub fn is_video(&self) -> bool {
271 matches!(self, MediaKind::Video(_))
272 }
273 pub fn is_audio(&self) -> bool {
275 matches!(self, MediaKind::Audio(_))
276 }
277}
278
279impl fmt::Display for MediaKind {
280 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
281 let ret = match self {
282 MediaKind::Audio(fmt) => format!("{}", fmt),
283 MediaKind::Video(fmt) => format!("{}", fmt),
284 };
285 write!(f, "{}", ret)
286 }
287}
288
289impl From<VideoInfo> for MediaKind {
290 fn from(v: VideoInfo) -> Self {
291 MediaKind::Video(v)
292 }
293}
294
295impl From<AudioInfo> for MediaKind {
296 fn from(a: AudioInfo) -> Self {
297 MediaKind::Audio(a)
298 }
299}
300
301pub trait FrameBuffer: Send + Sync {
303 fn linesize(&self, idx: usize) -> Result<usize, FrameError>;
305 fn count(&self) -> usize;
307 fn as_slice_inner(&self, idx: usize) -> Result<&[u8], FrameError>;
310 fn as_mut_slice_inner(&mut self, idx: usize) -> Result<&mut [u8], FrameError>;
313}
314
315mod private {
316 use byte_slice_cast::*;
317
318 pub trait Supported: FromByteSlice {}
319 impl Supported for u8 {}
320 impl Supported for i16 {}
321 impl Supported for f32 {}
322}
323
324pub trait FrameBufferConv<T: private::Supported>: FrameBuffer {
327 fn as_slice(&self, idx: usize) -> Result<&[T], FrameError> {
330 self.as_slice_inner(idx)?
331 .as_slice_of::<T>()
332 .map_err(|e| InvalidConversion)
333 }
334 fn as_mut_slice(&mut self, idx: usize) -> Result<&mut [T], FrameError> {
337 self.as_mut_slice_inner(idx)?
338 .as_mut_slice_of::<T>()
339 .map_err(|e| InvalidConversion)
340 }
341}
342
343impl FrameBufferConv<u8> for dyn FrameBuffer {}
344impl FrameBufferConv<i16> for dyn FrameBuffer {}
345impl FrameBufferConv<f32> for dyn FrameBuffer {}
346
347pub trait FrameBufferCopy {
349 fn copy_plane_to_buffer(&self, plane_index: usize, dst: &mut [u8], dst_linesize: usize);
351 fn copy_frame_to_buffer<'a, IM: Iterator<Item = &'a mut [u8]>, IU: Iterator<Item = usize>>(
353 &self,
354 dst: IM,
355 dst_linesizes: IU,
356 );
357 fn copy_from_slice<'a, I: Iterator<Item = &'a [u8]>, IU: Iterator<Item = usize>>(
359 &mut self,
360 src: I,
361 src_linesize: IU,
362 );
363}
364
365impl fmt::Debug for dyn FrameBuffer {
366 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367 write!(f, "FrameBuffer")
368 }
369}
370
371const ALIGNMENT: usize = 32;
372
373struct Plane {
374 buf: BytesMut,
375 linesize: usize,
376}
377
378struct DefaultFrameBuffer {
379 buf: BytesMut,
380 planes: Vec<Plane>,
381}
382
383impl FrameBuffer for DefaultFrameBuffer {
384 fn linesize(&self, idx: usize) -> Result<usize, FrameError> {
385 match self.planes.get(idx) {
386 None => Err(FrameError::InvalidIndex),
387 Some(plane) => Ok(plane.linesize),
388 }
389 }
390 fn count(&self) -> usize {
391 self.planes.len()
392 }
393
394 fn as_slice_inner(&self, idx: usize) -> Result<&[u8], FrameError> {
395 match self.planes.get(idx) {
396 None => Err(FrameError::InvalidIndex),
397 Some(plane) => Ok(&plane.buf),
398 }
399 }
400 fn as_mut_slice_inner(&mut self, idx: usize) -> Result<&mut [u8], FrameError> {
401 match self.planes.get_mut(idx) {
402 None => Err(FrameError::InvalidIndex),
403 Some(plane) => Ok(&mut plane.buf),
404 }
405 }
406}
407
408impl DefaultFrameBuffer {
409 pub fn new(kind: &MediaKind) -> DefaultFrameBuffer {
410 match *kind {
411 MediaKind::Video(ref video) => {
412 let size = video.size(ALIGNMENT);
413 let buf = BytesMut::zeroed(size);
414 let mut buffer = DefaultFrameBuffer {
415 buf,
416 planes: Vec::with_capacity(video.format.get_num_comp()),
417 };
418 for &component in video.format.iter() {
419 if let Some(c) = component {
420 let planesize = c.get_data_size(video.width, video.height, ALIGNMENT);
421 let linesize = c.get_linesize(video.width, ALIGNMENT);
422 buffer.planes.push(Plane {
423 buf: buffer.buf.split_to(planesize),
424 linesize,
425 });
426 }
427 }
428 buffer
429 }
430 MediaKind::Audio(ref audio) => {
431 let size = audio.size(ALIGNMENT);
432 let buf = BytesMut::zeroed(size);
433 let mut buffer = DefaultFrameBuffer {
434 buf,
435 planes: if audio.format.planar {
436 Vec::with_capacity(audio.map.len())
437 } else {
438 Vec::with_capacity(1)
439 },
440 };
441 if audio.format.planar {
442 for _ in 0..audio.map.len() {
443 let size = audio.format.get_audio_size(audio.samples, ALIGNMENT);
444 buffer.planes.push(Plane {
445 buf: buffer.buf.split_to(size),
446 linesize: size,
447 });
448 }
449 } else {
450 buffer.planes.push(Plane {
451 buf: buffer.buf.split_to(size),
452 linesize: size,
453 });
454 }
455 buffer
456 }
457 }
458 }
459}
460
461#[derive(Debug)]
463pub struct Frame {
464 pub kind: MediaKind,
466 pub buf: Box<dyn FrameBuffer>,
468 pub t: TimeInfo,
470}
471
472impl Frame {
473 pub fn new_default_frame<T>(kind: T, t: Option<TimeInfo>) -> Self
475 where
476 T: Into<MediaKind> + Clone,
477 {
478 let k = kind.into();
479 let buf = DefaultFrameBuffer::new(&k);
480
481 Self {
482 kind: k,
483 buf: Box::new(buf),
484 t: t.unwrap_or_default(),
485 }
486 }
487}
488
489impl FrameBufferCopy for Frame {
490 fn copy_plane_to_buffer(&self, plane_index: usize, dst: &mut [u8], dst_linesize: usize) {
491 if let MediaKind::Video(ref fmt) = self.kind {
492 let width = fmt.width;
493 let height = fmt.height;
494 let src = self.buf.as_slice_inner(plane_index).unwrap();
495 let src_linesize = self.buf.linesize(plane_index).unwrap();
496
497 copy_plane(dst, dst_linesize, src, src_linesize, width, height);
498 } else {
499 unimplemented!();
500 }
501 }
502
503 fn copy_frame_to_buffer<'a, IM, IU>(&self, dst: IM, dst_linesizes: IU)
504 where
505 IM: Iterator<Item = &'a mut [u8]>,
506 IU: Iterator<Item = usize>,
507 {
508 if let MediaKind::Video(ref fmt) = self.kind {
509 let width = fmt.width;
510 let height = fmt.height;
511 let dst_iter = dst.zip(dst_linesizes);
512 let iter = dst_iter.zip(0..self.buf.count()).zip(fmt.format.iter());
513
514 for (((d, d_linesize), plane_index), c) in iter {
515 copy_plane(
516 d,
517 d_linesize,
518 self.buf.as_slice_inner(plane_index).unwrap(),
519 self.buf.linesize(plane_index).unwrap(),
520 c.unwrap().get_width(width),
521 c.unwrap().get_height(height),
522 );
523 }
524 } else {
525 unimplemented!()
526 }
527 }
528
529 fn copy_from_slice<'a, I, IU>(&mut self, mut src: I, mut src_linesize: IU)
532 where
533 I: Iterator<Item = &'a [u8]>,
534 IU: Iterator<Item = usize>,
535 {
536 if let MediaKind::Video(ref fmt) = self.kind {
537 let mut f_iter = fmt.format.iter();
538 let width = fmt.width;
539 let height = fmt.height;
540 for i in 0..self.buf.count() {
541 let d_linesize = self.buf.linesize(i).unwrap();
542 let s_linesize = src_linesize.next().unwrap();
543 let data = self.buf.as_mut_slice(i).unwrap();
544 let ss = src.next().unwrap();
545 let cc = f_iter.next().unwrap();
546 copy_plane(
547 data,
548 d_linesize,
549 ss,
550 s_linesize,
551 cc.unwrap().get_width(width),
552 cc.unwrap().get_height(height),
553 );
554 }
555 } else {
556 unimplemented!();
557 }
558 }
559}
560
561fn copy_plane(
562 dst: &mut [u8],
563 dst_linesize: usize,
564 src: &[u8],
565 src_linesize: usize,
566 width: usize,
567 height: usize,
568) {
569 let dst_chunks = dst.chunks_mut(dst_linesize);
570 let src_chunks = src.chunks(src_linesize);
571
572 for (d, s) in dst_chunks.zip(src_chunks).take(height) {
573 unsafe {
576 copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), width);
577 }
578 }
579}
580
581pub type ArcFrame = Arc<Frame>;
583
584#[cfg(test)]
585mod test {
586 use super::*;
587 use crate::audiosample::formats;
588
589 #[test]
590 fn test_format_cmp() {
591 let mut map = ChannelMap::new();
592 map.add_channel(ChannelType::C);
593
594 let sn = Arc::new(formats::S16);
595 let info1 = AudioInfo::new(42, 48000, map.clone(), sn, None);
596
597 let sn = Arc::new(formats::S16);
598 let info2 = AudioInfo::new(4242, 48000, map.clone(), sn, None);
599
600 assert!(info1 == info2);
601
602 let mut map = ChannelMap::new();
603 map.add_channel(ChannelType::C);
604 let sn = Arc::new(formats::S16);
605 let info1 = AudioInfo::new(42, 48000, map.clone(), sn, None);
606
607 let sn = Arc::new(formats::S32);
608 let info2 = AudioInfo::new(42, 48000, map.clone(), sn, None);
609
610 assert!(!(info1 == info2));
611 }
612
613 use crate::pixel::formats::{RGB565, YUV420};
614
615 #[test]
616 fn test_video_format_cmp() {
617 let yuv420: Formaton = *YUV420;
618 let fm = Arc::new(yuv420);
619 let info1 = VideoInfo::new(42, 42, false, FrameType::I, fm);
620
621 let yuv420: Formaton = *YUV420;
622 let fm = Arc::new(yuv420);
623 let info2 = VideoInfo::new(42, 42, false, FrameType::P, fm);
624
625 assert!(info1 == info2);
626
627 let yuv420: Formaton = *YUV420;
628 let fm = Arc::new(yuv420);
629 let info1 = VideoInfo::new(42, 42, false, FrameType::I, fm);
630
631 let rgb565: Formaton = *RGB565;
632 let fm = Arc::new(rgb565);
633 let info2 = VideoInfo::new(42, 42, false, FrameType::I, fm);
634
635 assert!(!(info1 == info2));
636 }
637
638 #[test]
639 #[should_panic]
640 fn test_frame_copy_from_slice() {
641 let yuv420: Formaton = *YUV420;
642 let fm = Arc::new(yuv420);
643 let video_info = VideoInfo::new(42, 42, false, FrameType::I, fm);
644
645 let mut frame = Frame::new_default_frame(MediaKind::Video(video_info), None);
646
647 frame.copy_from_slice(
648 vec![vec![0].as_slice(); 2].into_iter(),
649 vec![40; 2].into_iter(),
650 );
651 }
652}