mp4_atom/moov/trak/mdia/minf/stbl/stsd/hevc/
hvcc.rs

1use crate::*;
2
3#[derive(Default, Debug, Clone, PartialEq, Eq)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Hvcc {
6    pub configuration_version: u8,
7    pub general_profile_space: u8,
8    pub general_tier_flag: bool,
9    pub general_profile_idc: u8,
10    pub general_profile_compatibility_flags: [u8; 4],
11    pub general_constraint_indicator_flags: [u8; 6],
12    pub general_level_idc: u8,
13    pub min_spatial_segmentation_idc: u16,
14    pub parallelism_type: u8,
15    pub chroma_format_idc: u8,
16    pub bit_depth_luma_minus8: u8,
17    pub bit_depth_chroma_minus8: u8,
18    pub avg_frame_rate: u16,
19    pub constant_frame_rate: u8,
20    pub num_temporal_layers: u8,
21    pub temporal_id_nested: bool,
22    pub length_size_minus_one: u8,
23    pub arrays: Vec<HvcCArray>,
24}
25
26impl Hvcc {
27    pub fn new() -> Self {
28        Self {
29            configuration_version: 1,
30            ..Default::default()
31        }
32    }
33}
34
35#[derive(Debug, Clone, PartialEq, Eq, Default)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub struct HvcCArray {
38    pub completeness: bool,
39    pub nal_unit_type: u8,
40    pub nalus: Vec<Vec<u8>>,
41}
42
43impl Atom for Hvcc {
44    const KIND: FourCC = FourCC::new(b"hvcC");
45
46    fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
47        let configuration_version = u8::decode(buf)?;
48        let params = u8::decode(buf)?;
49        let general_profile_space = params & (0b11000000 >> 6);
50        let general_tier_flag = (params & (0b00100000 >> 5)) > 0;
51        let general_profile_idc = params & 0b00011111;
52
53        let general_profile_compatibility_flags = <[u8; 4]>::decode(buf)?;
54        let general_constraint_indicator_flags = <[u8; 6]>::decode(buf)?;
55        let general_level_idc = u8::decode(buf)?;
56        let min_spatial_segmentation_idc = u16::decode(buf)? & 0x0FFF;
57        let parallelism_type = u8::decode(buf)? & 0b11;
58        let chroma_format_idc = u8::decode(buf)? & 0b11;
59        let bit_depth_luma_minus8 = u8::decode(buf)? & 0b111;
60        let bit_depth_chroma_minus8 = u8::decode(buf)? & 0b111;
61        let avg_frame_rate = u16::decode(buf)?;
62
63        let params = u8::decode(buf)?;
64        let constant_frame_rate = params & (0b11000000 >> 6);
65        let num_temporal_layers = params & (0b00111000 >> 3);
66        let temporal_id_nested = (params & (0b00000100 >> 2)) > 0;
67        let length_size_minus_one = params & 0b000011;
68
69        let num_of_arrays = u8::decode(buf)?;
70
71        let mut arrays = Vec::with_capacity(num_of_arrays as _);
72        for _ in 0..num_of_arrays {
73            let params = u8::decode(buf)?;
74            let num_nalus = u16::decode(buf)?;
75            let mut nalus = Vec::with_capacity(num_nalus as usize);
76
77            for _ in 0..num_nalus {
78                let size = u16::decode(buf)? as usize;
79                let data = Vec::decode_exact(buf, size)?;
80                nalus.push(data)
81            }
82
83            arrays.push(HvcCArray {
84                completeness: (params & 0b10000000) > 0,
85                nal_unit_type: params & 0b111111,
86                nalus,
87            });
88        }
89
90        Ok(Hvcc {
91            configuration_version,
92            general_profile_space,
93            general_tier_flag,
94            general_profile_idc,
95            general_profile_compatibility_flags,
96            general_constraint_indicator_flags,
97            general_level_idc,
98            min_spatial_segmentation_idc,
99            parallelism_type,
100            chroma_format_idc,
101            bit_depth_luma_minus8,
102            bit_depth_chroma_minus8,
103            avg_frame_rate,
104            constant_frame_rate,
105            num_temporal_layers,
106            temporal_id_nested,
107            length_size_minus_one,
108            arrays,
109        })
110    }
111
112    fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
113        self.configuration_version.encode(buf)?;
114        let general_profile_space = (self.general_profile_space & 0b11) << 6;
115        let general_tier_flag = u8::from(self.general_tier_flag) << 5;
116        let general_profile_idc = self.general_profile_idc & 0b11111;
117
118        (general_profile_space | general_tier_flag | general_profile_idc).encode(buf)?;
119        self.general_profile_compatibility_flags.encode(buf)?;
120        self.general_constraint_indicator_flags.encode(buf)?;
121        self.general_level_idc.encode(buf)?;
122
123        (self.min_spatial_segmentation_idc & 0x0FFF).encode(buf)?;
124        (self.parallelism_type & 0b11).encode(buf)?;
125        (self.chroma_format_idc & 0b11).encode(buf)?;
126        (self.bit_depth_luma_minus8 & 0b111).encode(buf)?;
127        (self.bit_depth_chroma_minus8 & 0b111).encode(buf)?;
128        self.avg_frame_rate.encode(buf)?;
129
130        let constant_frame_rate = (self.constant_frame_rate & 0b11) << 6;
131        let num_temporal_layers = (self.num_temporal_layers & 0b111) << 3;
132        let temporal_id_nested = u8::from(self.temporal_id_nested) << 2;
133        let length_size_minus_one = self.length_size_minus_one & 0b11;
134        (constant_frame_rate | num_temporal_layers | temporal_id_nested | length_size_minus_one)
135            .encode(buf)?;
136        (self.arrays.len() as u8).encode(buf)?;
137        for arr in &self.arrays {
138            ((arr.nal_unit_type & 0b111111) | (u8::from(arr.completeness) << 7)).encode(buf)?;
139            (arr.nalus.len() as u16).encode(buf)?;
140
141            for nalu in &arr.nalus {
142                (nalu.len() as u16).encode(buf)?;
143                nalu.encode(buf)?;
144            }
145        }
146
147        Ok(())
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154
155    #[test]
156    fn test_hev1() {
157        let expected = Hev1 {
158            visual: Visual {
159                data_reference_index: 1,
160                width: 320,
161                height: 240,
162                horizresolution: 0x48.into(),
163                vertresolution: 0x48.into(),
164                frame_count: 1,
165                compressor: "ya boy".into(),
166                depth: 24,
167            },
168            hvcc: Hvcc {
169                configuration_version: 1,
170                ..Default::default()
171            },
172        };
173        let mut buf = Vec::new();
174        expected.encode(&mut buf).unwrap();
175
176        let mut buf = buf.as_ref();
177        let decoded = Hev1::decode(&mut buf).unwrap();
178        assert_eq!(decoded, expected);
179    }
180}