scuffle_mp4/object_description/
sl_config.rs

1use isobmff::IsoSized;
2use nutype_enum::nutype_enum;
3use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize};
4use scuffle_bytes_util::{BitReader, BitWriter};
5
6use super::{BaseDescriptor, DescriptorTag};
7
8nutype_enum! {
9    /// [`SLConfigDescriptor::predefined`]
10    pub enum SLConfigDescriptorPredefined(u8) {
11        /// Custom.
12        Custom = 0,
13        /// Null SL packet header.
14        NullSLPacketHeader = 1,
15    }
16}
17
18impl<'a> Deserialize<'a> for SLConfigDescriptorPredefined {
19    fn deserialize<R>(reader: R) -> std::io::Result<Self>
20    where
21        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
22    {
23        u8::deserialize(reader).map(Into::into)
24    }
25}
26
27impl Serialize for SLConfigDescriptorPredefined {
28    fn serialize<W>(&self, writer: W) -> std::io::Result<()>
29    where
30        W: std::io::Write,
31    {
32        self.0.serialize(writer)
33    }
34}
35
36impl IsoSized for SLConfigDescriptorPredefined {
37    fn size(&self) -> usize {
38        1
39    }
40}
41
42/// SL Packet Header Configuration
43///
44/// ISO/IEC 14496-1 - 7.3.2.3
45#[derive(Debug, PartialEq, Eq)]
46pub struct SLConfigDescriptor {
47    /// Allows to default the values from a set of predefined parameter sets as detailed below.
48    pub predefined: SLConfigDescriptorPredefined,
49    /// Set if `predefined` is [`SLConfigDescriptorPredefined::Custom`].
50    pub custom: Option<SLConfigDescriptorCustom>,
51}
52
53impl SLConfigDescriptor {
54    /// Returns the base descriptor of this `SLConfigDescriptor`.
55    pub fn base_descriptor(&self) -> BaseDescriptor {
56        BaseDescriptor {
57            tag: DescriptorTag::SLConfigDescrTag,
58            size_of_instance: self.payload_size() as u32,
59        }
60    }
61
62    fn payload_size(&self) -> usize {
63        self.predefined.size() + self.custom.size()
64    }
65}
66
67impl<'a> Deserialize<'a> for SLConfigDescriptor {
68    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
69    where
70        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
71    {
72        let base_descriptor = BaseDescriptor::deserialize(&mut reader)?;
73        let mut reader = reader.take(base_descriptor.size_of_instance as usize);
74
75        let predefined = SLConfigDescriptorPredefined::deserialize(&mut reader)?;
76
77        let predefined_0 = if predefined == SLConfigDescriptorPredefined::Custom {
78            Some(SLConfigDescriptorCustom::deserialize(&mut reader)?)
79        } else {
80            None
81        };
82
83        Ok(Self {
84            predefined,
85            custom: predefined_0,
86        })
87    }
88}
89
90impl Serialize for SLConfigDescriptor {
91    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
92    where
93        W: std::io::Write,
94    {
95        self.base_descriptor().serialize(&mut writer)?;
96        self.predefined.serialize(&mut writer)?;
97
98        if self.predefined == SLConfigDescriptorPredefined::Custom {
99            self.custom
100                .as_ref()
101                .ok_or(std::io::Error::new(
102                    std::io::ErrorKind::InvalidData,
103                    "predefined_0 is required when predefined is 0",
104                ))?
105                .serialize(&mut writer)?;
106        }
107
108        Ok(())
109    }
110}
111
112impl IsoSized for SLConfigDescriptor {
113    fn size(&self) -> usize {
114        self.base_descriptor().size() + self.payload_size()
115    }
116}
117
118/// Present in [`SLConfigDescriptor`] when [`predefined`](SLConfigDescriptor::predefined) is [`SLConfigDescriptorPredefined::Custom`].
119#[derive(Debug, PartialEq, Eq)]
120pub struct SLConfigDescriptorCustom {
121    /// Indicates that the `accessUnitStartFlag` is present in each SL packet
122    /// header of this elementary stream.
123    pub use_access_unit_start_flag: bool,
124    /// Indicates that the `accessUnitEndFlag` is present in each SL packet header of
125    /// this elementary stream.
126    pub use_access_unit_end_flag: bool,
127    /// Indicates that the `RandomAccessPointFlag` is present in each SL
128    /// packet header of this elementary stream.
129    pub use_random_access_point_flag: bool,
130    /// Indicates that each SL packet corresponds to a random access point.
131    /// In that case the `randomAccessPointFlag` need not be used.
132    pub has_random_access_units_only_flag: bool,
133    /// Indicates that the paddingFlag is present in each SL packet header of this
134    /// elementary stream.
135    pub use_padding_flag: bool,
136    /// Indicates that time stamps are used for synchronisation of this elementary stream.
137    /// They are conveyed in the SL packet headers. Otherwise, the parameters `accessUnitDuration`,
138    /// `compositionUnitDuration`, `startDecodingTimeStamp` and `startCompositionTimeStamp`
139    /// conveyed in this SL packet header configuration shall be used for synchronisation.
140    pub use_time_stamps_flag: bool,
141    /// Indicates that `idleFlag` is used in this elementary stream.
142    pub use_idle_flag: bool,
143    /// Indicates that the constant duration of access units and composition units for this
144    /// elementary stream is subsequently signaled.
145    pub duration_flag: bool,
146    /// Is the resolution of the time stamps in clock ticks per second.
147    pub time_stamp_resolution: u32,
148    /// Is the resolution of the object time base in cycles per second.
149    pub ocr_resolution: u32,
150    /// Is the length of the time stamp fields in SL packet headers. Shall
151    /// take values between zero and 64 bit.
152    pub time_stamp_length: u8,
153    /// Is the length of the `objectClockReference` field in SL packet headers. A length of zero
154    /// indicates that no `objectClockReferences` are present in this elementary stream. If `OCRstreamFlag` is
155    /// set, `OCRLength` shall be zero. Else `OCRlength` shall take values between zero and 64 bit.
156    pub ocr_length: u8,
157    /// Is the length of the accessUnitLength fields in SL packet headers for this elementary stream.
158    /// Shall take values between zero and 32 bit.
159    pub au_length: u8,
160    /// Is the length of the `instantBitrate` field in SL packet headers for this
161    /// elementary stream.
162    pub instant_bitrate_length: u8,
163    /// Is the length of the `degradationPriority` field in SL packet headers
164    /// for this elementary stream.
165    pub degradation_priority_length: u8,
166    /// Is the length of the `AU_sequenceNumber` field in SL packet headers for this
167    /// elementary stream.
168    pub au_seq_num_length: u8,
169    /// Is the length of the `packetSequenceNumber` field in SL packet headers for this
170    /// elementary stream.
171    pub packet_seq_num_length: u8,
172    /// Reserved 2 bits.
173    pub reserved: u8,
174    /// Present if [`duration_flag`](SLConfigDescriptorCustom::duration_flag) is set.
175    pub duration: Option<SLConfigDescriptorDuration>,
176    /// Present if [`use_time_stamps_flag`](SLConfigDescriptorCustom::use_time_stamps_flag) is set.
177    pub time_stamps: Option<SLConfigDescriptorTimeStamps>,
178}
179
180impl<'a> Deserialize<'a> for SLConfigDescriptorCustom {
181    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
182    where
183        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
184    {
185        let byte = u8::deserialize(&mut reader)?;
186        let use_access_unit_start_flag = byte & 0b1000_0000 != 0;
187        let use_access_unit_end_flag = byte & 0b0100_0000 != 0;
188        let use_random_access_point_flag = byte & 0b0010_0000 != 0;
189        let has_random_access_units_only_flag = byte & 0b0001_0000 != 0;
190        let use_padding_flag = byte & 0b0000_1000 != 0;
191        let use_time_stamps_flag = byte & 0b0000_0100 != 0;
192        let use_idle_flag = byte & 0b0000_0010 != 0;
193        let duration_flag = byte & 0b0000_0001 != 0;
194
195        let time_stamp_resolution = u32::deserialize(&mut reader)?;
196        let ocr_resolution = u32::deserialize(&mut reader)?;
197        let time_stamp_length = u8::deserialize(&mut reader)?;
198        if time_stamp_length > 64 {
199            return Err(std::io::Error::new(
200                std::io::ErrorKind::InvalidData,
201                "timeStampLength must be <= 64",
202            ));
203        }
204
205        let ocr_length = u8::deserialize(&mut reader)?;
206        if ocr_length > 64 {
207            return Err(std::io::Error::new(
208                std::io::ErrorKind::InvalidData,
209                "OCRLength must be <= 64",
210            ));
211        }
212
213        let au_length = u8::deserialize(&mut reader)?;
214        if au_length > 32 {
215            return Err(std::io::Error::new(
216                std::io::ErrorKind::InvalidData,
217                "AU_Length must be <= 64",
218            ));
219        }
220
221        let instant_bitrate_length = u8::deserialize(&mut reader)?;
222
223        let bytes = u16::deserialize(&mut reader)?;
224        let degradation_priority_length = ((bytes & 0b1111_0000_0000_0000) >> 12) as u8;
225        let au_seq_num_length = ((bytes & 0b0000_1111_1000_0000) >> 7) as u8;
226        if au_seq_num_length > 16 {
227            return Err(std::io::Error::new(
228                std::io::ErrorKind::InvalidData,
229                "AU_SeqNumLength must be <= 16",
230            ));
231        }
232        let packet_seq_num_length = (byte & 0b0000_0000_0111_1100) >> 2;
233        if packet_seq_num_length > 16 {
234            return Err(std::io::Error::new(
235                std::io::ErrorKind::InvalidData,
236                "packetSeqNumLength must be <= 16",
237            ));
238        }
239        let reserved = byte & 0b0000_0000_0000_0011;
240
241        let duration = if duration_flag {
242            Some(SLConfigDescriptorDuration::deserialize(&mut reader)?)
243        } else {
244            None
245        };
246
247        let time_stamps = if use_time_stamps_flag {
248            Some(SLConfigDescriptorTimeStamps::deserialize_seed(
249                &mut reader,
250                time_stamp_length,
251            )?)
252        } else {
253            None
254        };
255
256        Ok(Self {
257            use_access_unit_start_flag,
258            use_access_unit_end_flag,
259            use_random_access_point_flag,
260            has_random_access_units_only_flag,
261            use_padding_flag,
262            use_time_stamps_flag,
263            use_idle_flag,
264            duration_flag,
265            time_stamp_resolution,
266            ocr_resolution,
267            time_stamp_length,
268            ocr_length,
269            au_length,
270            instant_bitrate_length,
271            degradation_priority_length,
272            au_seq_num_length,
273            packet_seq_num_length,
274            reserved,
275            duration,
276            time_stamps,
277        })
278    }
279}
280
281impl Serialize for SLConfigDescriptorCustom {
282    fn serialize<W>(&self, writer: W) -> std::io::Result<()>
283    where
284        W: std::io::Write,
285    {
286        let mut bit_writer = BitWriter::new(writer);
287
288        bit_writer.write_bit(self.use_access_unit_start_flag)?;
289        bit_writer.write_bit(self.use_access_unit_end_flag)?;
290        bit_writer.write_bit(self.use_random_access_point_flag)?;
291        bit_writer.write_bit(self.has_random_access_units_only_flag)?;
292        bit_writer.write_bit(self.use_padding_flag)?;
293        bit_writer.write_bit(self.use_time_stamps_flag)?;
294        bit_writer.write_bit(self.use_idle_flag)?;
295        bit_writer.write_bit(self.duration_flag)?;
296
297        self.time_stamp_resolution.serialize(&mut bit_writer)?;
298        self.ocr_resolution.serialize(&mut bit_writer)?;
299        self.time_stamp_length.serialize(&mut bit_writer)?;
300        self.ocr_length.serialize(&mut bit_writer)?;
301        self.au_length.serialize(&mut bit_writer)?;
302        self.instant_bitrate_length.serialize(&mut bit_writer)?;
303        self.degradation_priority_length.serialize(&mut bit_writer)?;
304        self.au_seq_num_length.serialize(&mut bit_writer)?;
305        self.packet_seq_num_length.serialize(&mut bit_writer)?;
306        self.reserved.serialize(&mut bit_writer)?;
307
308        if self.duration_flag {
309            self.duration
310                .as_ref()
311                .ok_or(std::io::Error::new(
312                    std::io::ErrorKind::InvalidData,
313                    "duration is required when duration_flag is set",
314                ))?
315                .serialize(&mut bit_writer)?;
316        }
317
318        if self.use_time_stamps_flag {
319            self.time_stamps
320                .as_ref()
321                .ok_or(std::io::Error::new(
322                    std::io::ErrorKind::InvalidData,
323                    "time_stamps is required when use_time_stamps_flag is set",
324                ))?
325                .serialize(&mut bit_writer, self.time_stamp_length)?;
326        }
327
328        Ok(())
329    }
330}
331
332impl IsoSized for SLConfigDescriptorCustom {
333    fn size(&self) -> usize {
334        let mut size = 1; // flags
335        size += self.time_stamp_resolution.size();
336        size += self.ocr_resolution.size();
337        size += self.time_stamp_length.size();
338        size += self.ocr_length.size();
339        size += self.au_length.size();
340        size += self.instant_bitrate_length.size();
341        size += self.degradation_priority_length.size();
342        size += self.au_seq_num_length.size();
343        size += self.packet_seq_num_length.size();
344        size += self.reserved.size();
345        size += self.duration.size();
346
347        if let Some(time_stamps) = &self.time_stamps {
348            size += time_stamps.size(self.time_stamp_length);
349        }
350
351        size
352    }
353}
354
355/// Present in [`SLConfigDescriptorCustom`] when [`duration_flag`](SLConfigDescriptorCustom::duration_flag) is set.
356#[derive(Debug, PartialEq, Eq)]
357pub struct SLConfigDescriptorDuration {
358    /// Used to express the duration of access units and composition units. One second is evenly
359    /// divided in timeScale parts.
360    pub time_scale: u32,
361    /// The duration of an access unit is `accessUnitDuration * 1/timeScale` seconds.
362    pub access_unit_duration: u16,
363    /// The duration of a composition unit is `compositionUnitDuration * 1/timeScale` seconds.
364    pub composition_unit_duration: u16,
365}
366
367impl<'a> Deserialize<'a> for SLConfigDescriptorDuration {
368    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
369    where
370        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
371    {
372        Ok(Self {
373            time_scale: u32::deserialize(&mut reader)?,
374            access_unit_duration: u16::deserialize(&mut reader)?,
375            composition_unit_duration: u16::deserialize(&mut reader)?,
376        })
377    }
378}
379
380impl Serialize for SLConfigDescriptorDuration {
381    fn serialize<W>(&self, mut writer: W) -> std::io::Result<()>
382    where
383        W: std::io::Write,
384    {
385        self.time_scale.serialize(&mut writer)?;
386        self.access_unit_duration.serialize(&mut writer)?;
387        self.composition_unit_duration.serialize(&mut writer)?;
388        Ok(())
389    }
390}
391
392impl IsoSized for SLConfigDescriptorDuration {
393    fn size(&self) -> usize {
394        self.time_scale.size() + self.access_unit_duration.size() + self.composition_unit_duration.size()
395    }
396}
397
398/// Present in [`SLConfigDescriptorCustom`] when [`use_time_stamps_flag`](SLConfigDescriptorCustom::use_time_stamps_flag) is set.
399#[derive(Debug, PartialEq, Eq)]
400pub struct SLConfigDescriptorTimeStamps {
401    /// Conveys the time at which the first access unit of this elementary stream shall
402    /// be decoded. It is conveyed in the resolution specified by `timeStampResolution`.
403    pub start_decoding_time_stamp: u64,
404    /// Conveys the time at which the composition unit corresponding to the first
405    /// access unit of this elementary stream shall be decoded. It is conveyed in the resolution specified by
406    /// `timeStampResolution`.
407    pub start_composition_time_stamp: u64,
408}
409
410impl<'a> DeserializeSeed<'a, u8> for SLConfigDescriptorTimeStamps {
411    fn deserialize_seed<R>(mut reader: R, seed: u8) -> std::io::Result<Self>
412    where
413        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
414    {
415        let mut bit_reader = BitReader::new(reader.as_std());
416
417        Ok(Self {
418            start_decoding_time_stamp: bit_reader.read_bits(seed)?,
419            start_composition_time_stamp: bit_reader.read_bits(seed)?,
420        })
421    }
422}
423
424impl SLConfigDescriptorTimeStamps {
425    /// Serialize the timestamps using the given timestamp length
426    pub fn serialize<W>(&self, writer: W, time_stamp_length: u8) -> std::io::Result<()>
427    where
428        W: std::io::Write,
429    {
430        let mut bit_writer = BitWriter::new(writer);
431        bit_writer.write_bits(self.start_decoding_time_stamp, time_stamp_length)?;
432        bit_writer.write_bits(self.start_composition_time_stamp, time_stamp_length)?;
433        Ok(())
434    }
435
436    /// Calculate the size of the serialized timestamps based on the given timestamp length.
437    pub fn size(&self, time_stamp_length: u8) -> usize {
438        time_stamp_length as usize * 2
439    }
440}