scuffle_mp4/object_description/
decoder_config.rs

1use isobmff::IsoSized;
2use nutype_enum::nutype_enum;
3use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, U24Be};
4use scuffle_bytes_util::{BitWriter, IoResultExt};
5
6use super::profile_level_indication_index::ProfileLevelIndicationIndexDescriptor;
7use super::{BaseDescriptor, DescriptorTag, UnknownDescriptor};
8
9nutype_enum! {
10    /// ObjectTypeIndication
11    ///
12    /// ISO/IEC 14496-1 - 7.2.6.6.2
13    pub enum ObjectTypeIndication(u8) {
14        /// Forbidden
15        Forbidden = 0x00,
16        /// Systems ISO/IEC 14496-1 a
17        Systems14496_1_a = 0x01,
18        /// Systems ISO/IEC 14496-1 b
19        Systems14496_1_b = 0x02,
20        /// Interaction Stream
21        InteractionStream = 0x03,
22        /// Systems ISO/IEC 14496-1 Extended BIFS Configuration
23        Systems14496_1_ExtendedBIFSConfiguration = 0x04,
24        /// Systems ISO/IEC 14496-1 AFX
25        Systems14496_1_AFX = 0x05,
26        /// Font Data Stream
27        FontDataStream = 0x06,
28        /// Synthesized Texture Stream
29        SynthesizedTextureStream = 0x07,
30        /// Streaming Text Stream
31        StreamingTextStream = 0x08,
32        /// Visual ISO/IEC 14496-2
33        Visual14496_2 = 0x20,
34        /// Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10
35        Visual14496_10 = 0x21,
36        /// Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10
37        ParameterSets_14496_10 = 0x22,
38        /// Audio ISO/IEC 14496-3
39        Audio14496_3 = 0x40,
40        /// Visual ISO/IEC 13818-2 Simple Profile
41        Visual13818_2_SimpleProfile = 0x60,
42        /// Visual ISO/IEC 13818-2 Main Profile
43        Visual13818_2_MainProfile = 0x61,
44        /// Visual ISO/IEC 13818-2 SNR Profile
45        Visual13818_2_SNRProfile = 0x62,
46        /// Visual ISO/IEC 13818-2 Spatial Profile
47        Visual13818_2_SpatialProfile = 0x63,
48        /// Visual ISO/IEC 13818-2 High Profile
49        Visual13818_2_HighProfile = 0x64,
50        /// Visual ISO/IEC 13818-2 422 Profile
51        Visual13818_2_422Profile = 0x65,
52        /// Audio ISO/IEC 13818-7 Main Profile
53        Audio13818_7_MainProfile = 0x66,
54        /// Audio ISO/IEC 13818-7 LowComplexity Profile
55        Audio13818_7_LowComplexityProfile = 0x67,
56        /// Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile
57        Audio13818_7_ScaleableSamplingRateProfile = 0x68,
58        /// Audio ISO/IEC 13818-3
59        Audio13818_3 = 0x69,
60        /// Visual ISO/IEC 11172-2
61        Visual11172_2 = 0x6A,
62        /// Audio ISO/IEC 11172-3
63        Audio11172_3 = 0x6B,
64        /// Visual ISO/IEC 10918-1
65        Visual10918_1 = 0x6C,
66        /// Visual ISO/IEC 15444-1
67        Visual15444_1 = 0x6E,
68        /// No object type specified
69        Unspecified = 0xFF,
70    }
71}
72
73impl<'a> Deserialize<'a> for ObjectTypeIndication {
74    fn deserialize<R>(reader: R) -> std::io::Result<Self>
75    where
76        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
77    {
78        u8::deserialize(reader).map(Into::into)
79    }
80}
81
82impl Serialize for ObjectTypeIndication {
83    fn serialize<W>(&self, writer: W) -> std::io::Result<()>
84    where
85        W: std::io::Write,
86    {
87        self.0.serialize(writer)
88    }
89}
90
91impl IsoSized for ObjectTypeIndication {
92    fn size(&self) -> usize {
93        1
94    }
95}
96
97nutype_enum! {
98    /// StreamType
99    ///
100    /// ISO/IEC 14496-1 - 7.2.6.6.2
101    pub enum StreamType(u8) {
102        /// Forbidden
103        Forbidden = 0x00,
104        /// ObjectDescriptorStream
105        ///
106        /// See ISO/IEC 14496-1 - 7.2.5
107        ObjectDescriptorStream = 0x01,
108        /// ClockReferenceStream
109        ///
110        /// See ISO/IEC 14496-1 - 7.3.2.5
111        ClockReferenceStream = 0x02,
112        /// SceneDescriptionStream
113        ///
114        /// See ISO/IEC 14496-11
115        SceneDescriptionStream = 0x03,
116        /// VisualStream
117        VisualStream = 0x04,
118        /// AudioStream
119        AudioStream = 0x05,
120        /// MPEG7Stream
121        MPEG7Stream = 0x06,
122        /// IPMPStream
123        ///
124        /// See ISO/IEC 14496-1 - 7.2.3.2
125        IPMPStream = 0x07,
126        /// ObjectContentInfoStream
127        ///
128        ///  See ISO/IEC 14496-1 - 7.2.4.2
129        ObjectContentInfoStream = 0x08,
130        /// MPEGJStream
131        MPEGJStream = 0x09,
132        /// Interaction Stream
133        InteractionStream = 0x0A,
134        /// IPMPToolStream
135        ///
136        /// See ISO/IEC 14496-13
137        IPMPToolStream = 0x0B,
138    }
139}
140
141/// Deocder Config Descriptor
142///
143/// ISO/IEC 14496-1 - 7.2.6.6
144#[derive(Debug, PartialEq, Eq)]
145pub struct DecoderConfigDescriptor<'a> {
146    /// An indication of the object or scene description type that needs to be supported
147    /// by the decoder for this elementary stream.
148    pub object_type_indication: ObjectTypeIndication,
149    /// Conveys the type of this elementary stream.
150    pub stream_type: StreamType,
151    /// Indicates that this stream is used for upstream information.
152    pub up_stream: bool,
153    /// Reserved bit.
154    pub reserved: bool,
155    /// Is the size of the decoding buffer for this elementary stream in bytes.
156    pub buffer_size_db: U24Be,
157    /// Is the maximum bitrate in bits per second of this elementary stream in any time window of
158    /// one second duration.
159    pub max_bitrate: u32,
160    /// Is the average bitrate in bits per second of this elementary stream. For streams with variable
161    /// bitrate this value shall be set to zero.
162    pub avg_bitrate: u32,
163    /// Decoder specific information.
164    pub dec_specific_info: Option<UnknownDescriptor<'a>>,
165    /// A list of [`ProfileLevelIndicationIndexDescriptor`]s.
166    pub profile_level_indication_index_descr: Vec<ProfileLevelIndicationIndexDescriptor>,
167    /// Any other unknown descriptors that are contained in this descriptor but not deserialized.
168    pub unknown_descriptors: Vec<UnknownDescriptor<'a>>,
169}
170
171impl DecoderConfigDescriptor<'_> {
172    fn payload_size(&self) -> usize {
173        let mut size = 0;
174        size += self.object_type_indication.size();
175        size += 1; // stream_type + up_stream + reserved
176        size += self.buffer_size_db.size();
177        size += self.max_bitrate.size();
178        size += self.avg_bitrate.size();
179
180        size += self.dec_specific_info.size();
181        size += self.profile_level_indication_index_descr.size();
182        size += self.unknown_descriptors.size();
183
184        size
185    }
186
187    /// Returns the base descriptor.
188    pub fn base_descriptor(&self) -> BaseDescriptor {
189        BaseDescriptor {
190            tag: DescriptorTag::DecoderConfigDescrTag,
191            size_of_instance: self.payload_size() as u32,
192        }
193    }
194}
195
196impl<'a> Deserialize<'a> for DecoderConfigDescriptor<'a> {
197    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
198    where
199        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
200    {
201        let base_descriptor = BaseDescriptor::deserialize(&mut reader)?;
202        let mut reader = reader.take(base_descriptor.size_of_instance as usize);
203
204        let object_type_indication = ObjectTypeIndication::deserialize(&mut reader)?;
205
206        let byte = u8::deserialize(&mut reader)?;
207        let stream_type = StreamType::from((byte & 0b111_1100) >> 2);
208        let up_stream = (byte & 0b0000_0010) != 0;
209        let reserved = (byte & 0b0000_0001) != 0;
210        let buffer_size_db = U24Be::deserialize(&mut reader)?;
211        let max_bitrate = u32::deserialize(&mut reader)?;
212        let avg_bitrate = u32::deserialize(&mut reader)?;
213
214        let mut dec_specific_info = None;
215        let mut profile_level_indication_index_descr = Vec::new();
216        let mut unknown_descriptors = Vec::new();
217
218        loop {
219            let Some(base_descriptor) = BaseDescriptor::deserialize(&mut reader).eof_to_none()? else {
220                break;
221            };
222
223            match base_descriptor.tag {
224                DescriptorTag::DecSpecificInfoTag => {
225                    let Some(descr) = UnknownDescriptor::deserialize_seed(&mut reader, base_descriptor).eof_to_none()?
226                    else {
227                        break;
228                    };
229                    dec_specific_info = Some(descr);
230                }
231                DescriptorTag::profileLevelIndicationIndexDescrTag => {
232                    let Some(descr) = ProfileLevelIndicationIndexDescriptor::deserialize_seed(&mut reader, base_descriptor)
233                        .eof_to_none()?
234                    else {
235                        break;
236                    };
237                    profile_level_indication_index_descr.push(descr);
238                }
239                _ => {
240                    let Some(descr) = UnknownDescriptor::deserialize_seed(&mut reader, base_descriptor).eof_to_none()?
241                    else {
242                        break;
243                    };
244                    unknown_descriptors.push(descr);
245                }
246            }
247        }
248
249        Ok(Self {
250            object_type_indication,
251            stream_type,
252            up_stream,
253            reserved,
254            buffer_size_db,
255            max_bitrate,
256            avg_bitrate,
257            dec_specific_info,
258            profile_level_indication_index_descr,
259            unknown_descriptors,
260        })
261    }
262}
263
264impl Serialize for DecoderConfigDescriptor<'_> {
265    fn serialize<W>(&self, writer: W) -> std::io::Result<()>
266    where
267        W: std::io::Write,
268    {
269        let mut bit_writer = BitWriter::new(writer);
270
271        self.base_descriptor().serialize(&mut bit_writer)?;
272        self.object_type_indication.serialize(&mut bit_writer)?;
273        bit_writer.write_bits(self.stream_type.0 as u64, 6)?;
274        bit_writer.write_bit(self.up_stream)?;
275        bit_writer.write_bit(self.reserved)?;
276        self.buffer_size_db.serialize(&mut bit_writer)?;
277        self.max_bitrate.serialize(&mut bit_writer)?;
278        self.avg_bitrate.serialize(&mut bit_writer)?;
279
280        if let Some(dec_specific_info) = &self.dec_specific_info {
281            dec_specific_info.serialize(&mut bit_writer)?;
282        }
283
284        for profile_level_indication_index_descr in &self.profile_level_indication_index_descr {
285            profile_level_indication_index_descr.serialize(&mut bit_writer)?;
286        }
287
288        for unknown_descriptor in &self.unknown_descriptors {
289            unknown_descriptor.serialize(&mut bit_writer)?;
290        }
291
292        Ok(())
293    }
294}
295
296impl IsoSized for DecoderConfigDescriptor<'_> {
297    fn size(&self) -> usize {
298        self.base_descriptor().size() + self.payload_size()
299    }
300}