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