av_data/
frame.rs

1//! Packets and decoded frames functionality.
2
3#![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/// Frame errors.
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
21pub enum FrameError {
22    /// Invalid frame index.
23    InvalidIndex,
24    /// Invalid frame conversion.
25    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// TODO: Change it to provide Droppable/Seekable information or use a separate enum?
40/// A list of recognized frame types.
41#[derive(Clone, Debug, PartialEq, Eq, Hash)]
42#[allow(clippy::upper_case_acronyms)]
43pub enum FrameType {
44    /// Intra frame type.
45    I,
46    /// Inter frame type.
47    P,
48    /// Bidirectionally predicted frame.
49    B,
50    /// Skip frame.
51    ///
52    /// When such frame is encountered, then last frame should be used again
53    /// if it is needed.
54    SKIP,
55    /// Some other frame type.
56    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/// Video stream information.
72#[derive(Clone, Debug)]
73pub struct VideoInfo {
74    /// Frame width.
75    pub width: usize,
76    /// Frame height.
77    pub height: usize,
78    /// Frame is stored downside up.
79    pub flipped: bool,
80    /// Frame type.
81    pub frame_type: FrameType,
82    /// Frame pixel format.
83    pub format: Arc<Formaton>,
84    /// Declared bits per sample.
85    pub bits: u8,
86}
87
88impl VideoInfo {
89    /// Constructs a new `VideoInfo` instance.
90    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    /// Returns frame width.
109    pub fn get_width(&self) -> usize {
110        self.width
111    }
112    /// Returns frame height.
113    pub fn get_height(&self) -> usize {
114        self.height
115    }
116    /// Returns frame orientation.
117    pub fn is_flipped(&self) -> bool {
118        self.flipped
119    }
120    /// Returns frame type.
121    pub fn get_frame_type(&self) -> &FrameType {
122        &self.frame_type
123    }
124    /// Returns frame pixel format.
125    pub fn get_format(&self) -> Formaton {
126        *self.format
127    }
128
129    /// Sets new frame width.
130    pub fn set_width(&mut self, width: usize) {
131        self.width = width;
132    }
133    /// Sets new frame height.
134    pub fn set_height(&mut self, height: usize) {
135        self.height = height;
136    }
137
138    /// Returns video stream size with the specified alignment.
139    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/// Audio stream information contained in a frame.
163#[derive(Clone, Debug)]
164pub struct AudioInfo {
165    /// Number of samples.
166    pub samples: usize,
167    /// Sample rate.
168    pub sample_rate: usize,
169    /// Sequence of stream channels.
170    pub map: ChannelMap,
171    /// Audio sample format.
172    pub format: Arc<Soniton>,
173    /// Length of one audio block in samples.
174    ///
175    /// None if not present.
176    pub block_len: Option<usize>,
177}
178
179impl AudioInfo {
180    /// Constructs a new `AudioInfo` instance.
181    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    /// Returns audio sample rate.
197    pub fn get_sample_rate(&self) -> usize {
198        self.sample_rate
199    }
200    /// Returns the number of channels.
201    pub fn get_channels_number(&self) -> usize {
202        self.map.len()
203    }
204    /// Returns sample format.
205    pub fn get_format(&self) -> Soniton {
206        *self.format
207    }
208    /// Returns number of samples.
209    pub fn get_samples(&self) -> usize {
210        self.samples
211    }
212
213    /// Returns one audio block duration in samples.
214    pub fn get_block_len(&self) -> Option<usize> {
215        self.block_len
216    }
217
218    /// Returns audio stream size with the specified alignment.
219    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/// A list of possible stream information types.
244#[derive(Clone, Debug, PartialEq)]
245pub enum MediaKind {
246    /// Video codec information.
247    Video(VideoInfo),
248    /// Audio codec information.
249    Audio(AudioInfo),
250}
251
252impl MediaKind {
253    /// Returns video stream information.
254    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    /// Returns audio stream information.
262    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    /// Reports whether the current stream is a video stream.
270    pub fn is_video(&self) -> bool {
271        matches!(self, MediaKind::Video(_))
272    }
273    /// Reports whether the current stream is an audio stream.
274    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
301/// A series of methods to interact with the planes of frame.
302pub trait FrameBuffer: Send + Sync {
303    /// Returns the linesize (stride) of the idx-th frame plane.
304    fn linesize(&self, idx: usize) -> Result<usize, FrameError>;
305    /// Counts the number of frame planes.
306    fn count(&self) -> usize;
307    /// Returns an immutable buffer with the data associated to the idx-th
308    /// frame plane.
309    fn as_slice_inner(&self, idx: usize) -> Result<&[u8], FrameError>;
310    /// Returns a mutable buffer with the data associated to the idx-th
311    /// frame plane.
312    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
324/// A series of methods to get mutable and immutable slices of datatype `T`
325/// from frame planes.
326pub trait FrameBufferConv<T: private::Supported>: FrameBuffer {
327    /// Returns an immutable slice of datatype `T` with the data associated to
328    /// the idx-th frame plane.
329    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    /// Returns a mutable slice of datatype `T` with the data associated to
335    /// the idx-th frame plane.
336    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
347/// A series of methods to copy the content of a frame from or to a buffer.
348pub trait FrameBufferCopy {
349    /// Copies a determined plane to an output buffer.
350    fn copy_plane_to_buffer(&self, plane_index: usize, dst: &mut [u8], dst_linesize: usize);
351    /// Copies a frame to an output buffer.
352    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    /// Copies from a slice into a frame.
358    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/// Decoded frame information.
462#[derive(Debug)]
463pub struct Frame {
464    /// The kind of frame (audio or video).
465    pub kind: MediaKind,
466    /// Frame buffer containing the data associated to each plane.
467    pub buf: Box<dyn FrameBuffer>,
468    /// Timestamp information associated to a frame.
469    pub t: TimeInfo,
470}
471
472impl Frame {
473    /// Creates a new frame.
474    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    // TODO: Add proper tests
530    /// Copies from a slice into a frame.
531    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        // SAFETY:
574        // dst and src slices are initialized.
575        unsafe {
576            copy_nonoverlapping(s.as_ptr(), d.as_mut_ptr(), width);
577        }
578    }
579}
580
581/// A specialized type for reference-counted `Frame`
582pub 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}