mp4_atom/moov/trak/mdia/minf/stbl/stsd/
vp09.rs

1use crate::*;
2
3// https://www.webmproject.org/vp9/mp4/
4#[derive(Debug, Clone, PartialEq, Eq, Default)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct Vp09 {
7    pub visual: Visual,
8    pub vpcc: VpcC,
9}
10
11impl Atom for Vp09 {
12    const KIND: FourCC = FourCC::new(b"vp09");
13
14    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
15        let visual = Visual::decode(buf)?;
16
17        let mut vpcc = None;
18        while let Some(atom) = Any::decode_maybe(buf)? {
19            match atom {
20                Any::VpcC(atom) => vpcc = atom.into(),
21                _ => tracing::warn!("unknown atom: {:?}", atom),
22            }
23        }
24
25        Ok(Self {
26            visual,
27            vpcc: vpcc.ok_or(Error::MissingBox(VpcC::KIND))?,
28        })
29    }
30
31    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
32        self.visual.encode(buf)?;
33        self.vpcc.encode(buf)?;
34
35        Ok(())
36    }
37}
38
39ext! {
40    name: Vpcc,
41    versions: [1],
42    flags: {}
43}
44
45#[derive(Debug, Clone, PartialEq, Eq, Default)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47pub struct VpcC {
48    pub profile: u8,
49    pub level: u8,
50    pub bit_depth: u8,
51    pub chroma_subsampling: u8,
52    pub video_full_range_flag: bool,
53    pub color_primaries: u8,
54    pub transfer_characteristics: u8,
55    pub matrix_coefficients: u8,
56    pub codec_initialization_data: Vec<u8>,
57}
58
59impl AtomExt for VpcC {
60    const KIND_EXT: FourCC = FourCC::new(b"vpcC");
61
62    type Ext = VpccExt;
63
64    fn decode_body_ext<B: Buf>(buf: &mut B, _ext: VpccExt) -> Result<Self> {
65        let profile = u8::decode(buf)?;
66        let level = u8::decode(buf)?;
67        let (bit_depth, chroma_subsampling, video_full_range_flag) = {
68            let b = u8::decode(buf)?;
69            (b >> 4, (b >> 1) & 0x01, b & 0x01 == 1)
70        };
71        let color_primaries = u8::decode(buf)?;
72        let transfer_characteristics = u8::decode(buf)?;
73        let matrix_coefficients = u8::decode(buf)?;
74        let _codec_initialization_data_size = u16::decode(buf)?;
75        let codec_initialization_data = Vec::decode(buf)?; // assert same as data_size
76
77        Ok(Self {
78            profile,
79            level,
80            bit_depth,
81            chroma_subsampling,
82            video_full_range_flag,
83            color_primaries,
84            transfer_characteristics,
85            matrix_coefficients,
86            codec_initialization_data,
87        })
88    }
89
90    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<VpccExt> {
91        self.profile.encode(buf)?;
92        self.level.encode(buf)?;
93        ((self.bit_depth << 4)
94            | (self.chroma_subsampling << 1)
95            | (self.video_full_range_flag as u8))
96            .encode(buf)?;
97        self.color_primaries.encode(buf)?;
98        self.transfer_characteristics.encode(buf)?;
99        self.matrix_coefficients.encode(buf)?;
100        (self.codec_initialization_data.len() as u16).encode(buf)?;
101        self.codec_initialization_data.encode(buf)?;
102
103        Ok(VpccVersion::V1.into())
104    }
105}
106
107#[cfg(test)]
108mod tests {
109    use super::*;
110
111    #[test]
112    fn test_vpcc() {
113        let expected = VpcC {
114            profile: 0,
115            level: 0x1F,
116            bit_depth: 8,
117            chroma_subsampling: 0,
118            video_full_range_flag: false,
119            color_primaries: 0,
120            transfer_characteristics: 0,
121            matrix_coefficients: 0,
122            codec_initialization_data: vec![],
123        };
124        let mut buf = Vec::new();
125        expected.encode(&mut buf).unwrap();
126
127        let mut buf = buf.as_ref();
128        let decoded = VpcC::decode(&mut buf).unwrap();
129        assert_eq!(decoded, expected);
130    }
131
132    #[test]
133    fn test_vp09() {
134        let expected = Vp09 {
135            visual: Visual {
136                width: 1920,
137                height: 1080,
138                ..Default::default()
139            },
140            vpcc: VpcC::default(),
141        };
142        let mut buf = Vec::new();
143        expected.encode(&mut buf).unwrap();
144
145        let mut buf = buf.as_ref();
146        let decoded = Vp09::decode(&mut buf).unwrap();
147        assert_eq!(decoded, expected);
148    }
149}