1use std::io::{
2 Read, Write, {self},
3};
4
5use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
6use scuffle_bytes_util::zero_copy::{Deserialize, Serialize};
7use scuffle_bytes_util::{BitReader, BitWriter, BytesCow};
8
9use crate::{ConstantFrameRate, NALUnitType, NumTemporalLayers, ParallelismType, ProfileCompatibilityFlags};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct HEVCDecoderConfigurationRecord<'a> {
16 pub general_profile_space: u8,
18 pub general_tier_flag: bool,
20 pub general_profile_idc: u8,
22 pub general_profile_compatibility_flags: ProfileCompatibilityFlags,
24 pub general_constraint_indicator_flags: u64,
27 pub general_level_idc: u8,
29 pub min_spatial_segmentation_idc: u16,
31 pub parallelism_type: ParallelismType,
33 pub chroma_format_idc: u8,
35 pub bit_depth_luma_minus8: u8,
37 pub bit_depth_chroma_minus8: u8,
39 pub avg_frame_rate: u16,
44 pub constant_frame_rate: ConstantFrameRate,
46 pub num_temporal_layers: NumTemporalLayers,
48 pub temporal_id_nested: bool,
56 pub length_size_minus_one: u8,
63 pub arrays: Vec<NaluArray<'a>>,
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct NaluArray<'a> {
72 pub array_completeness: bool,
77 pub nal_unit_type: NALUnitType,
81 pub nalus: Vec<BytesCow<'a>>,
86}
87
88impl<'a> Deserialize<'a> for HEVCDecoderConfigurationRecord<'a> {
89 fn deserialize<R>(mut reader: R) -> io::Result<Self>
90 where
91 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
92 {
93 let mut bit_reader = BitReader::new(reader.as_std());
94
95 let configuration_version = bit_reader.read_u8()?;
97 if configuration_version != 1 {
98 return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid configuration version"));
99 }
100
101 let general_profile_space = bit_reader.read_bits(2)? as u8;
102 let general_tier_flag = bit_reader.read_bit()?;
103 let general_profile_idc = bit_reader.read_bits(5)? as u8;
104 let general_profile_compatibility_flags =
105 ProfileCompatibilityFlags::from_bits_retain(bit_reader.read_u32::<BigEndian>()?);
106 let general_constraint_indicator_flags = bit_reader.read_u48::<BigEndian>()?;
107 let general_level_idc = bit_reader.read_u8()?;
108
109 bit_reader.read_bits(4)?; let min_spatial_segmentation_idc = bit_reader.read_bits(12)? as u16;
111
112 bit_reader.read_bits(6)?; let parallelism_type = bit_reader.read_bits(2)? as u8;
114
115 bit_reader.read_bits(6)?; let chroma_format_idc = bit_reader.read_bits(2)? as u8;
117
118 bit_reader.read_bits(5)?; let bit_depth_luma_minus8 = bit_reader.read_bits(3)? as u8;
120
121 bit_reader.read_bits(5)?; let bit_depth_chroma_minus8 = bit_reader.read_bits(3)? as u8;
123
124 let avg_frame_rate = bit_reader.read_u16::<BigEndian>()?;
125 let constant_frame_rate = bit_reader.read_bits(2)? as u8;
126 let num_temporal_layers = bit_reader.read_bits(3)? as u8;
127 let temporal_id_nested = bit_reader.read_bit()?;
128 let length_size_minus_one = bit_reader.read_bits(2)? as u8;
129
130 if length_size_minus_one == 2 {
131 return Err(io::Error::new(
132 io::ErrorKind::InvalidData,
133 "length_size_minus_one must be 0, 1, or 3",
134 ));
135 }
136
137 let num_of_arrays = bit_reader.read_u8()?;
138
139 let mut arrays = Vec::with_capacity(num_of_arrays as usize);
140
141 for _ in 0..num_of_arrays {
142 let array_completeness = bit_reader.read_bit()?;
143 bit_reader.read_bits(1)?; let nal_unit_type = bit_reader.read_bits(6)? as u8;
146 let nal_unit_type = NALUnitType::from(nal_unit_type);
147 if nal_unit_type != NALUnitType::VpsNut
148 && nal_unit_type != NALUnitType::SpsNut
149 && nal_unit_type != NALUnitType::PpsNut
150 && nal_unit_type != NALUnitType::PrefixSeiNut
151 && nal_unit_type != NALUnitType::SuffixSeiNut
152 {
153 return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid nal_unit_type"));
154 }
155
156 let num_nalus = bit_reader.read_u16::<BigEndian>()?;
157 let mut nalus = Vec::with_capacity(num_nalus as usize);
158 for _ in 0..num_nalus {
159 let nal_unit_length = bit_reader.read_u16::<BigEndian>()?;
160 let mut data = vec![0; nal_unit_length as usize];
161 bit_reader.read_exact(&mut data)?;
162 nalus.push(data.into());
163 }
164
165 arrays.push(NaluArray {
166 array_completeness,
167 nal_unit_type,
168 nalus,
169 });
170 }
171
172 Ok(HEVCDecoderConfigurationRecord {
173 general_profile_space,
174 general_tier_flag,
175 general_profile_idc,
176 general_profile_compatibility_flags,
177 general_constraint_indicator_flags,
178 general_level_idc,
179 min_spatial_segmentation_idc,
180 parallelism_type: ParallelismType(parallelism_type),
181 chroma_format_idc,
182 bit_depth_luma_minus8,
183 bit_depth_chroma_minus8,
184 avg_frame_rate,
185 constant_frame_rate: ConstantFrameRate(constant_frame_rate),
186 num_temporal_layers: NumTemporalLayers(num_temporal_layers),
187 temporal_id_nested,
188 length_size_minus_one,
189 arrays,
190 })
191 }
192}
193
194impl Serialize for HEVCDecoderConfigurationRecord<'_> {
195 fn serialize<W>(&self, writer: W) -> io::Result<()>
196 where
197 W: std::io::Write,
198 {
199 let mut bit_writer = BitWriter::new(writer);
200
201 bit_writer.write_u8(1)?; bit_writer.write_bits(self.general_profile_space as u64, 2)?;
204 bit_writer.write_bit(self.general_tier_flag)?;
205 bit_writer.write_bits(self.general_profile_idc as u64, 5)?;
206 bit_writer.write_u32::<BigEndian>(self.general_profile_compatibility_flags.bits())?;
207 bit_writer.write_u48::<BigEndian>(self.general_constraint_indicator_flags)?;
208 bit_writer.write_u8(self.general_level_idc)?;
209
210 bit_writer.write_bits(0b1111, 4)?; bit_writer.write_bits(self.min_spatial_segmentation_idc as u64, 12)?;
212
213 bit_writer.write_bits(0b111111, 6)?; bit_writer.write_bits(self.parallelism_type.0 as u64, 2)?;
215
216 bit_writer.write_bits(0b111111, 6)?; bit_writer.write_bits(self.chroma_format_idc as u64, 2)?;
218
219 bit_writer.write_bits(0b11111, 5)?; bit_writer.write_bits(self.bit_depth_luma_minus8 as u64, 3)?;
221
222 bit_writer.write_bits(0b11111, 5)?; bit_writer.write_bits(self.bit_depth_chroma_minus8 as u64, 3)?;
224
225 bit_writer.write_u16::<BigEndian>(self.avg_frame_rate)?;
226 bit_writer.write_bits(self.constant_frame_rate.0 as u64, 2)?;
227
228 bit_writer.write_bits(self.num_temporal_layers.0 as u64, 3)?;
229 bit_writer.write_bit(self.temporal_id_nested)?;
230 bit_writer.write_bits(self.length_size_minus_one as u64, 2)?;
231
232 bit_writer.write_u8(self.arrays.len() as u8)?;
233 for array in &self.arrays {
234 bit_writer.write_bit(array.array_completeness)?;
235 bit_writer.write_bits(0b0, 1)?; bit_writer.write_bits(u8::from(array.nal_unit_type) as u64, 6)?;
237
238 bit_writer.write_u16::<BigEndian>(array.nalus.len() as u16)?;
239
240 for nalu in &array.nalus {
241 bit_writer.write_u16::<BigEndian>(nalu.len() as u16)?;
242 bit_writer.write_all(nalu.as_bytes())?;
243 }
244 }
245
246 bit_writer.finish()?;
247
248 Ok(())
249 }
250}
251
252#[cfg(feature = "isobmff")]
253impl isobmff::IsoSized for HEVCDecoderConfigurationRecord<'_> {
254 fn size(&self) -> usize {
255 1 + 1 + 4 + 6 + 1 + 2 + 1 + 1 + 1 + 1 + 2 + 1 + 1 + self.arrays.iter().map(|array| {
269 1 + 2 + array.nalus.iter().map(|nalu| {
272 2 + nalu.len() }).sum::<usize>()
275 }).sum::<usize>()
276 }
277}
278
279#[cfg(test)]
280#[cfg_attr(all(test, coverage_nightly), coverage(off))]
281mod tests {
282 use std::io;
283
284 use scuffle_bytes_util::zero_copy::{Deserialize, Slice};
285
286 use crate::{
287 ConstantFrameRate, HEVCDecoderConfigurationRecord, NALUnitType, NumTemporalLayers, ParallelismType,
288 ProfileCompatibilityFlags, SpsNALUnit,
289 };
290
291 #[test]
292 fn test_config_demux() {
293 let data = b"\x01\x01@\0\0\0\x90\0\0\0\0\0\x99\xf0\0\xfc\xfd\xf8\xf8\0\0\x0f\x03 \0\x01\0\x18@\x01\x0c\x01\xff\xff\x01@\0\0\x03\0\x90\0\0\x03\0\0\x03\0\x99\x95@\x90!\0\x01\0=B\x01\x01\x01@\0\0\x03\0\x90\0\0\x03\0\0\x03\0\x99\xa0\x01@ \x05\xa1e\x95R\x90\x84d_\xf8\xc0Z\x80\x80\x80\x82\0\0\x03\0\x02\0\0\x03\x01 \xc0\x0b\xbc\xa2\0\x02bX\0\x011-\x08\"\0\x01\0\x07D\x01\xc0\x93|\x0c\xc9";
295
296 let config = HEVCDecoderConfigurationRecord::deserialize(Slice::from(&data[..])).unwrap();
297
298 assert_eq!(config.general_profile_space, 0);
299 assert!(!config.general_tier_flag);
300 assert_eq!(config.general_profile_idc, 1);
301 assert_eq!(
302 config.general_profile_compatibility_flags,
303 ProfileCompatibilityFlags::MainProfile
304 );
305 assert_eq!(config.general_constraint_indicator_flags, (1 << 47) | (1 << 44)); assert_eq!(config.general_level_idc, 153);
307 assert_eq!(config.min_spatial_segmentation_idc, 0);
308 assert_eq!(config.parallelism_type, ParallelismType::MixedOrUnknown);
309 assert_eq!(config.chroma_format_idc, 1);
310 assert_eq!(config.bit_depth_luma_minus8, 0);
311 assert_eq!(config.bit_depth_chroma_minus8, 0);
312 assert_eq!(config.avg_frame_rate, 0);
313 assert_eq!(config.constant_frame_rate, ConstantFrameRate::Unknown);
314 assert_eq!(config.num_temporal_layers, NumTemporalLayers::NotScalable);
315 assert!(config.temporal_id_nested);
316 assert_eq!(config.length_size_minus_one, 3);
317 assert_eq!(config.arrays.len(), 3);
318
319 let vps = &config.arrays[0];
320 assert!(!vps.array_completeness);
321 assert_eq!(vps.nal_unit_type, NALUnitType::VpsNut);
322 assert_eq!(vps.nalus.len(), 1);
323
324 let sps = &config.arrays[1];
325 assert!(!sps.array_completeness);
326 assert_eq!(sps.nal_unit_type, NALUnitType::SpsNut);
327 assert_eq!(sps.nalus.len(), 1);
328 let sps = SpsNALUnit::parse(io::Cursor::new(sps.nalus[0].clone())).unwrap();
329 insta::assert_debug_snapshot!(sps);
330
331 let pps = &config.arrays[2];
332 assert!(!pps.array_completeness);
333 assert_eq!(pps.nal_unit_type, NALUnitType::PpsNut);
334 assert_eq!(pps.nalus.len(), 1);
335 }
336
337 #[test]
338 #[cfg(feature = "isobmff")]
339 fn test_config_mux() {
340 use isobmff::IsoSized;
341 use scuffle_bytes_util::zero_copy::Serialize;
342
343 let data = b"\x01\x01@\0\0\0\x90\0\0\0\0\0\x99\xf0\0\xfc\xfd\xf8\xf8\0\0\x0f\x03 \0\x01\0\x18@\x01\x0c\x01\xff\xff\x01@\0\0\x03\0\x90\0\0\x03\0\0\x03\0\x99\x95@\x90!\0\x01\0=B\x01\x01\x01@\0\0\x03\0\x90\0\0\x03\0\0\x03\0\x99\xa0\x01@ \x05\xa1e\x95R\x90\x84d_\xf8\xc0Z\x80\x80\x80\x82\0\0\x03\0\x02\0\0\x03\x01 \xc0\x0b\xbc\xa2\0\x02bX\0\x011-\x08\"\0\x01\0\x07D\x01\xc0\x93|\x0c\xc9";
344
345 let config = HEVCDecoderConfigurationRecord::deserialize(Slice::from(&data[..])).unwrap();
346
347 assert_eq!(config.size(), data.len());
348
349 let mut buf = Vec::new();
350 config.serialize(&mut buf).unwrap();
351
352 assert_eq!(buf, data.to_vec());
353 }
354}