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

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