mp4_atom/moov/trak/mdia/minf/stbl/stsd/vp9/
vpcc.rs

1use crate::*;
2
3ext! {
4    name: Vpcc,
5    versions: [1],
6    flags: {}
7}
8
9#[derive(Debug, Clone, PartialEq, Eq, Default)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct VpcC {
12    pub profile: u8,
13    pub level: u8,
14    pub bit_depth: u8,
15    pub chroma_subsampling: u8,
16    pub video_full_range_flag: bool,
17    pub color_primaries: u8,
18    pub transfer_characteristics: u8,
19    pub matrix_coefficients: u8,
20    pub codec_initialization_data: Vec<u8>,
21}
22
23impl AtomExt for VpcC {
24    const KIND_EXT: FourCC = FourCC::new(b"vpcC");
25
26    type Ext = VpccExt;
27
28    fn decode_body_ext<B: Buf>(buf: &mut B, _ext: VpccExt) -> Result<Self> {
29        let profile = u8::decode(buf)?;
30        let level = u8::decode(buf)?;
31        let (bit_depth, chroma_subsampling, video_full_range_flag) = {
32            let b = u8::decode(buf)?;
33            (b >> 4, (b >> 1) & 0x01, b & 0x01 == 1)
34        };
35        let color_primaries = u8::decode(buf)?;
36        let transfer_characteristics = u8::decode(buf)?;
37        let matrix_coefficients = u8::decode(buf)?;
38        let _codec_initialization_data_size = u16::decode(buf)?;
39        let codec_initialization_data = Vec::decode(buf)?; // assert same as data_size
40
41        Ok(Self {
42            profile,
43            level,
44            bit_depth,
45            chroma_subsampling,
46            video_full_range_flag,
47            color_primaries,
48            transfer_characteristics,
49            matrix_coefficients,
50            codec_initialization_data,
51        })
52    }
53
54    fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<VpccExt> {
55        self.profile.encode(buf)?;
56        self.level.encode(buf)?;
57        ((self.bit_depth << 4)
58            | (self.chroma_subsampling << 1)
59            | (self.video_full_range_flag as u8))
60            .encode(buf)?;
61        self.color_primaries.encode(buf)?;
62        self.transfer_characteristics.encode(buf)?;
63        self.matrix_coefficients.encode(buf)?;
64        (self.codec_initialization_data.len() as u16).encode(buf)?;
65        self.codec_initialization_data.encode(buf)?;
66
67        Ok(VpccVersion::V1.into())
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_vpcc() {
77        let expected = VpcC {
78            profile: 0,
79            level: 0x1F,
80            bit_depth: 8,
81            chroma_subsampling: 0,
82            video_full_range_flag: false,
83            color_primaries: 0,
84            transfer_characteristics: 0,
85            matrix_coefficients: 0,
86            codec_initialization_data: vec![],
87        };
88        let mut buf = Vec::new();
89        expected.encode(&mut buf).unwrap();
90
91        let mut buf = buf.as_ref();
92        let decoded = VpcC::decode(&mut buf).unwrap();
93        assert_eq!(decoded, expected);
94    }
95}