scuffle_mp4/object_description/
es.rs

1use isobmff::IsoSized;
2use scuffle_bytes_util::zero_copy::{Deserialize, DeserializeSeed, Serialize, ZeroCopyReader};
3use scuffle_bytes_util::{BitWriter, IoResultExt, StringCow};
4
5use super::decoder_config::DecoderConfigDescriptor;
6use super::sl_config::SLConfigDescriptor;
7use super::{BaseDescriptor, DescriptorTag, UnknownDescriptor};
8
9/// ES Descriptor
10///
11/// ISO/IEC 14496-1 - 7.2.6.5
12#[derive(Debug, PartialEq, Eq)]
13pub struct ESDescriptor<'a> {
14    /// Provides a unique label for each elementary stream within its name scope. The
15    /// values 0 and 0xFFFF are reserved.
16    pub es_id: u16,
17    /// Indicates a relative measure for the priority of this elementary stream. An elementary stream with a
18    /// higher `streamPriority` is more important than one with a lower `streamPriority`. The absolute values of
19    /// `streamPriority` are not normatively defined.
20    pub stream_priority: u8,
21    /// Is the `ES_ID` of another elementary stream on which this elementary stream depends.
22    /// The stream with `dependsOn_ES_ID` shall also be associated to the same object descriptor as the current
23    /// ES_Descriptor.
24    pub depends_on_es_id: Option<u16>,
25    /// Points to the location of an SL-packetized stream by name.
26    /// The parameters of the SL-packetized stream that is retrieved from the URL are
27    /// fully specified in this ES_Descriptor. See also 7.2.7.3.3. Permissible URLs may be constrained by profile
28    /// and levels as well as by specific delivery layers.
29    pub url_string: Option<StringCow<'a>>,
30    /// Indicates the `ES_ID` of the elementary stream within the name scope (see 7.2.7.2.4) from
31    /// which the time base for this elementary stream is derived. Circular references between elementary streams
32    /// are not permitted.
33    pub ocr_es_id: Option<u16>,
34    /// A [`DecoderConfigDescriptor`].
35    pub dec_config_descr: DecoderConfigDescriptor<'a>,
36    /// An [`SLConfigDescriptor`].
37    pub sl_config_descr: Option<SLConfigDescriptor>, /* (IMPORTANT) TODO: The spec says that this is required and NOT optional. */
38    /// A list of descriptors that are contained in this descriptor but not deserialized.
39    ///
40    /// Could be any of:
41    /// - `IPI_DescrPointer`
42    /// - `IP_IdentificationDataSet`
43    /// - `IPMP_DescriptorPointer`
44    /// - `LanguageDescriptor`
45    /// - `QoS_Descriptor`
46    /// - `RegistrationDescriptor`
47    /// - `ExtensionDescriptor`
48    pub unknown_descriptors: Vec<UnknownDescriptor<'a>>,
49}
50
51impl ESDescriptor<'_> {
52    /// Returns the base descriptor of this `ESDescriptor`.
53    pub fn base_descriptor(&self) -> BaseDescriptor {
54        BaseDescriptor {
55            tag: DescriptorTag::ES_DescrTag,
56            size_of_instance: self.payload_size() as u32,
57        }
58    }
59
60    fn payload_size(&self) -> usize {
61        let mut size = 0;
62        size += self.es_id.size(); // es_id
63        size += 1; // flags + stream_priority
64
65        size += self.depends_on_es_id.size();
66
67        if let Some(url_string) = self.url_string.as_ref() {
68            size += 1; // url_length
69            size += url_string.size();
70        }
71
72        size += self.ocr_es_id.size();
73        size += self.dec_config_descr.size();
74        size += self.sl_config_descr.size();
75        size += self.unknown_descriptors.size();
76
77        size
78    }
79}
80
81impl<'a> Deserialize<'a> for ESDescriptor<'a> {
82    fn deserialize<R>(mut reader: R) -> std::io::Result<Self>
83    where
84        R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
85    {
86        let base_descriptor = BaseDescriptor::deserialize(&mut reader)?;
87        let mut reader = reader.take(base_descriptor.size_of_instance as usize);
88
89        let es_id = u16::deserialize(&mut reader)?;
90
91        let byte = u8::deserialize(&mut reader)?;
92        let stream_dependence_flag = (byte & 0b1000_0000) != 0;
93        let url_flag = (byte & 0b0100_0000) != 0;
94        let ocr_stream_flag = (byte & 0b0010_0000) != 0;
95        let stream_priority = byte & 0b0001_1111;
96
97        let depends_on_es_id = if stream_dependence_flag {
98            Some(u16::deserialize(&mut reader)?)
99        } else {
100            None
101        };
102
103        let url_string = if url_flag {
104            let url_length = u8::deserialize(&mut reader)?;
105            let url_string = reader.try_read(url_length as usize)?;
106            Some(url_string.try_into().map_err(|e| {
107                std::io::Error::new(std::io::ErrorKind::InvalidData, format!("URLString must be valid UTF-8: {e}"))
108            })?)
109        } else {
110            None
111        };
112
113        let ocr_es_id = if ocr_stream_flag {
114            Some(u16::deserialize(&mut reader)?)
115        } else {
116            None
117        };
118
119        let dec_config_descr = DecoderConfigDescriptor::deserialize(&mut reader)?;
120        let sl_config_descr = SLConfigDescriptor::deserialize(&mut reader).eof_to_none()?;
121
122        let mut unknown_descriptors = Vec::new();
123
124        loop {
125            let Some(base_descriptor) = BaseDescriptor::deserialize(&mut reader).eof_to_none()? else {
126                break;
127            };
128
129            let Some(descr) = UnknownDescriptor::deserialize_seed(&mut reader, base_descriptor).eof_to_none()? else {
130                break;
131            };
132            unknown_descriptors.push(descr);
133        }
134
135        Ok(Self {
136            es_id,
137            stream_priority,
138            depends_on_es_id,
139            url_string,
140            ocr_es_id,
141            dec_config_descr,
142            sl_config_descr,
143            unknown_descriptors,
144        })
145    }
146}
147
148impl Serialize for ESDescriptor<'_> {
149    fn serialize<W>(&self, writer: W) -> std::io::Result<()>
150    where
151        W: std::io::Write,
152    {
153        let mut bit_writer = BitWriter::new(writer);
154
155        self.base_descriptor().serialize(&mut bit_writer)?;
156        self.es_id.serialize(&mut bit_writer)?;
157        bit_writer.write_bit(self.depends_on_es_id.is_some())?;
158        bit_writer.write_bit(self.url_string.is_some())?;
159        bit_writer.write_bit(self.ocr_es_id.is_some())?;
160        bit_writer.write_bits(self.stream_priority as u64, 5)?;
161
162        if let Some(depends_on_es_id) = self.depends_on_es_id {
163            depends_on_es_id.serialize(&mut bit_writer)?;
164        }
165
166        if let Some(url_string) = &self.url_string {
167            let url_length = url_string.len() as u8;
168            url_length.serialize(&mut bit_writer)?;
169            url_string.serialize(&mut bit_writer)?;
170        }
171
172        if let Some(ocr_es_id) = self.ocr_es_id {
173            ocr_es_id.serialize(&mut bit_writer)?;
174        }
175
176        self.dec_config_descr.serialize(&mut bit_writer)?;
177
178        if let Some(sl_config_descr) = &self.sl_config_descr {
179            sl_config_descr.serialize(&mut bit_writer)?;
180        }
181
182        for unknown_descriptor in &self.unknown_descriptors {
183            unknown_descriptor.serialize(&mut bit_writer)?;
184        }
185
186        Ok(())
187    }
188}
189
190impl IsoSized for ESDescriptor<'_> {
191    fn size(&self) -> usize {
192        self.base_descriptor().size() + self.payload_size()
193    }
194}