1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Default)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5pub struct Esds {
6 pub es_desc: EsDescriptor,
7}
8
9impl AtomExt for Esds {
10 type Ext = ();
11
12 const KIND_EXT: FourCC = FourCC::new(b"esds");
13
14 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
15 let mut es_desc = None;
16
17 while let Some(desc) = Descriptor::decode_maybe(buf)? {
18 match desc {
19 Descriptor::EsDescriptor(desc) => es_desc = Some(desc),
20 Descriptor::Unknown(tag, _) => {
21 tracing::warn!("unknown descriptor: {:02X}", tag)
22 }
23 _ => return Err(Error::UnexpectedDescriptor(desc.tag())),
24 }
25 }
26
27 Ok(Esds {
28 es_desc: es_desc.ok_or(Error::MissingDescriptor(EsDescriptor::TAG))?,
29 })
30 }
31
32 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
33 encode_descriptor(EsDescriptor::TAG, &self.es_desc, buf)
34 }
35}
36
37fn decode_descriptor_body<T: Decode, B: Buf>(buf: &mut B, size: usize) -> Result<T> {
48 if buf.remaining() < size {
49 return Err(Error::OutOfBounds);
50 }
51 let mut inner = buf.slice(size);
52 let res = T::decode(&mut inner)?;
53 buf.advance(size);
54 Ok(res)
55}
56
57fn encode_descriptor<T: Encode, B: BufMut>(tag: u8, body: &T, buf: &mut B) -> Result<()> {
61 tag.encode(buf)?;
62
63 let mut tmp = Vec::new();
65 body.encode(&mut tmp)?;
66
67 let size = tmp.len() as u32;
72 let mut groups = 1;
73 let mut s = size >> 7;
74 while s > 0 {
75 groups += 1;
76 s >>= 7;
77 }
78 for i in (0..groups).rev() {
79 let mut b = ((size >> (7 * i)) & 0x7F) as u8;
80 if i > 0 {
81 b |= 0x80;
82 }
83 b.encode(buf)?;
84 }
85
86 tmp.encode(buf)
87}
88
89macro_rules! descriptors {
90 ($($name:ident,)*) => {
91 #[derive(Debug, Clone, PartialEq, Eq)]
92 pub enum Descriptor {
93 $(
94 $name($name),
95 )*
96 Unknown(u8, Vec<u8>),
97 }
98
99 impl Decode for Descriptor {
100 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
101 let tag = u8::decode(buf)?;
102
103 let mut size: u32 = 0;
105 for i in 0..4 {
106 let b = u8::decode(buf)?;
107 size = (size << 7) | (b & 0x7F) as u32;
108 if b & 0x80 == 0 {
109 break;
110 }
111 if i == 3 {
112 return Err(Error::InvalidSize);
113 }
114 }
115
116 match tag {
117 $(
118 $name::TAG => Ok(decode_descriptor_body::<$name, _>(buf, size as _)?.into()),
119 )*
120 _ => Ok(Descriptor::Unknown(tag, Vec::decode_exact(buf, size as _)?)),
121 }
122 }
123 }
124
125 impl DecodeMaybe for Descriptor {
126 fn decode_maybe<B: Buf>(buf: &mut B) -> Result<Option<Self>> {
127 match buf.has_remaining() {
128 true => Descriptor::decode(buf).map(Some),
129 false => Ok(None),
130 }
131 }
132 }
133
134 impl Encode for Descriptor {
135 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
136 match self {
137 $(
138 Descriptor::$name(t) => encode_descriptor($name::TAG, t, buf),
139 )*
140 Descriptor::Unknown(tag, data) => encode_descriptor(*tag, data, buf),
141 }
142 }
143 }
144
145 impl Descriptor {
146 pub const fn tag(&self) -> u8 {
147 match self {
148 $(
149 Descriptor::$name(_) => $name::TAG,
150 )*
151 Descriptor::Unknown(tag, _) => *tag,
152 }
153 }
154 }
155
156 $(
157 impl From<$name> for Descriptor {
158 fn from(desc: $name) -> Self {
159 Descriptor::$name(desc)
160 }
161 }
162 )*
163 };
164}
165
166descriptors! {
167 EsDescriptor,
168 DecoderConfig,
169 DecoderSpecific,
170 SLConfig,
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Default)]
174#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175pub struct EsDescriptor {
176 pub es_id: u16,
177 pub depends_on_es_id: Option<u16>,
179 pub url: Option<Vec<u8>>,
181 pub ocr_es_id: Option<u16>,
183 pub stream_priority: u8,
185
186 pub dec_config: DecoderConfig,
187 pub sl_config: SLConfig,
188}
189
190impl EsDescriptor {
191 pub const TAG: u8 = 0x03;
192}
193
194impl Decode for EsDescriptor {
195 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
196 let es_id = u16::decode(buf)?;
197
198 let flags = u8::decode(buf)?;
200 let depends_on_es_id = match flags & 0x80 {
201 0 => None,
202 _ => Some(u16::decode(buf)?),
203 };
204 let url = match flags & 0x40 {
205 0 => None,
206 _ => {
207 let len = u8::decode(buf)?;
208 Some(Vec::decode_exact(buf, len as usize)?)
209 }
210 };
211 let ocr_es_id = match flags & 0x20 {
212 0 => None,
213 _ => Some(u16::decode(buf)?),
214 };
215
216 let mut dec_config = None;
217 let mut sl_config = None;
218
219 while let Some(desc) = Descriptor::decode_maybe(buf)? {
220 match desc {
221 Descriptor::DecoderConfig(desc) => dec_config = Some(desc),
222 Descriptor::SLConfig(desc) => sl_config = Some(desc),
223 Descriptor::Unknown(tag, _) => tracing::warn!("unknown descriptor: {:02X}", tag),
224 desc => return Err(Error::UnexpectedDescriptor(desc.tag())),
225 }
226 }
227
228 Ok(EsDescriptor {
229 es_id,
230 depends_on_es_id,
231 url,
232 ocr_es_id,
233 stream_priority: flags & 0x1F,
234 dec_config: dec_config.ok_or(Error::MissingDescriptor(DecoderConfig::TAG))?,
235 sl_config: sl_config.ok_or(Error::MissingDescriptor(SLConfig::TAG))?,
236 })
237 }
238}
239
240impl Encode for EsDescriptor {
241 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
242 if self.stream_priority > 0x1F {
243 return Err(Error::InvalidCombination(
244 "ES descriptor stream priority exceeds 5 bits",
245 ));
246 }
247 let url_len =
248 match &self.url {
249 Some(url) => Some(u8::try_from(url.len()).map_err(|_| {
250 Error::InvalidCombination("ES descriptor URL exceeds 255 bytes")
251 })?),
252 None => None,
253 };
254
255 self.es_id.encode(buf)?;
256
257 let mut flags = self.stream_priority;
258 if self.depends_on_es_id.is_some() {
259 flags |= 0x80;
260 }
261 if self.url.is_some() {
262 flags |= 0x40;
263 }
264 if self.ocr_es_id.is_some() {
265 flags |= 0x20;
266 }
267 flags.encode(buf)?;
268
269 self.depends_on_es_id.encode(buf)?;
270 if let (Some(len), Some(url)) = (url_len, &self.url) {
271 len.encode(buf)?;
272 url.encode(buf)?;
273 }
274 self.ocr_es_id.encode(buf)?;
275
276 encode_descriptor(DecoderConfig::TAG, &self.dec_config, buf)?;
277 encode_descriptor(SLConfig::TAG, &self.sl_config, buf)?;
278
279 Ok(())
280 }
281}
282
283#[derive(Debug, Clone, PartialEq, Eq, Default)]
284#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
285pub struct DecoderConfig {
286 pub object_type_indication: u8,
287 pub stream_type: u8,
288 pub up_stream: u8,
289 pub buffer_size_db: u24,
290 pub max_bitrate: u32,
291 pub avg_bitrate: u32,
292 pub dec_specific: Option<DecoderSpecific>,
298}
299
300impl DecoderConfig {
301 pub const TAG: u8 = 0x04;
302}
303
304impl Decode for DecoderConfig {
305 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
306 let object_type_indication = u8::decode(buf)?;
307 let byte_a = u8::decode(buf)?;
308 let stream_type = (byte_a & 0xFC) >> 2;
309 let up_stream = byte_a & 0x02;
310 let buffer_size_db = u24::decode(buf)?;
311 let max_bitrate = u32::decode(buf)?;
312 let avg_bitrate = u32::decode(buf)?;
313
314 let mut dec_specific = None;
315
316 while let Some(desc) = Descriptor::decode_maybe(buf)? {
317 match desc {
318 Descriptor::DecoderSpecific(desc) => dec_specific = Some(desc),
319 Descriptor::Unknown(tag, _) => tracing::warn!("unknown descriptor: {:02X}", tag),
320 desc => return Err(Error::UnexpectedDescriptor(desc.tag())),
321 }
322 }
323
324 Ok(DecoderConfig {
325 object_type_indication,
326 stream_type,
327 up_stream,
328 buffer_size_db,
329 max_bitrate,
330 avg_bitrate,
331 dec_specific,
332 })
333 }
334}
335
336impl Encode for DecoderConfig {
337 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
338 self.object_type_indication.encode(buf)?;
339 ((self.stream_type << 2) + (self.up_stream & 0x02) + 1).encode(buf)?; self.buffer_size_db.encode(buf)?;
341 self.max_bitrate.encode(buf)?;
342 self.avg_bitrate.encode(buf)?;
343
344 if let Some(dec_specific) = &self.dec_specific {
345 encode_descriptor(DecoderSpecific::TAG, dec_specific, buf)?;
346 }
347
348 Ok(())
349 }
350}
351
352#[derive(Debug, Clone, PartialEq, Eq, Default)]
353#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
354pub struct DecoderSpecific {
355 pub profile: u8,
356 pub freq_index: u8,
357 pub chan_conf: u8,
358 pub raw: Vec<u8>,
367}
368
369impl DecoderSpecific {
370 pub const TAG: u8 = 0x05;
371}
372
373fn parse_audio_specific_config(raw: &[u8]) -> (u8, u8, u8) {
378 if raw.len() < 2 {
379 return (0, 0, 0);
380 }
381 let byte_a = raw[0];
382 let byte_b = raw[1];
383
384 let mut profile = byte_a >> 3;
385 if profile == 31 {
386 profile = 32 + (((byte_a & 7) << 3) | (byte_b >> 5));
388 }
389
390 let freq_index = if profile > 31 {
391 (byte_b >> 1) & 0x0F
392 } else {
393 ((byte_a & 0x07) << 1) + (byte_b >> 7)
394 };
395
396 let chan_conf = if freq_index == 15 {
397 if raw.len() >= 5 {
399 let sample_rate =
400 (u32::from(raw[2]) << 16) | (u32::from(raw[3]) << 8) | u32::from(raw[4]);
401 ((sample_rate >> 4) & 0x0F) as u8
402 } else {
403 0
404 }
405 } else if profile > 31 {
406 if raw.len() >= 3 {
407 ((byte_b & 1) << 3) | (raw[2] >> 5)
409 } else {
410 0
411 }
412 } else {
413 (byte_b >> 3) & 0x0F
414 };
415
416 (profile, freq_index, chan_conf)
417}
418
419impl Decode for DecoderSpecific {
420 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
421 let raw = Vec::decode(buf)?;
425 let (profile, freq_index, chan_conf) = parse_audio_specific_config(&raw);
426
427 Ok(DecoderSpecific {
428 profile,
429 freq_index,
430 chan_conf,
431 raw,
432 })
433 }
434}
435
436impl Encode for DecoderSpecific {
437 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
438 if self.raw.is_empty() {
439 ((self.profile << 3) + (self.freq_index >> 1)).encode(buf)?;
442 ((self.freq_index << 7) + (self.chan_conf << 3)).encode(buf)?;
443 } else {
444 self.raw.encode(buf)?;
446 }
447
448 Ok(())
449 }
450}
451
452#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
453#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
454pub struct SLConfig {}
455
456impl SLConfig {
457 pub const TAG: u8 = 0x06;
458}
459
460impl Decode for SLConfig {
461 fn decode<B: Buf>(buf: &mut B) -> Result<Self> {
462 u8::decode(buf)?; Ok(SLConfig {})
464 }
465}
466
467impl Encode for SLConfig {
468 fn encode<B: BufMut>(&self, buf: &mut B) -> Result<()> {
469 2u8.encode(buf)?; Ok(())
471 }
472}
473
474#[cfg(test)]
475mod tests {
476 use super::*;
477
478 fn es_descriptor() -> EsDescriptor {
479 EsDescriptor {
480 es_id: 0x1234,
481 depends_on_es_id: Some(0x5678),
482 url: Some(b"https://example.com/audio".to_vec()),
483 ocr_es_id: Some(0x9ABC),
484 stream_priority: 17,
485 dec_config: DecoderConfig::default(),
486 sl_config: SLConfig::default(),
487 }
488 }
489
490 #[test]
493 fn test_es_descriptor_optional_fields_roundtrip() {
494 let mut flagged = es_descriptor();
495 for _ in 0..2 {
496 let mut buf = Vec::new();
497 Descriptor::from(flagged.clone()).encode(&mut buf).unwrap();
498 assert_eq!(
499 Descriptor::decode(&mut buf.as_slice()).unwrap(),
500 Descriptor::from(flagged.clone())
501 );
502
503 flagged.depends_on_es_id = None;
505 flagged.url = None;
506 flagged.ocr_es_id = None;
507 }
508 }
509
510 #[test]
511 fn test_es_descriptor_rejects_unencodable_fields() {
512 let mut desc = es_descriptor();
513 desc.stream_priority = 0x20;
514 assert!(desc.encode(&mut Vec::new()).is_err());
515
516 let mut desc = es_descriptor();
517 desc.url = Some(vec![b'a'; 256]);
518 assert!(desc.encode(&mut Vec::new()).is_err());
519 }
520
521 #[test]
522 fn test_descriptor_size_rejects_fifth_byte() {
523 let buf = [0x7F, 0x80, 0x80, 0x80, 0x80, 0x00];
524 assert!(matches!(
525 Descriptor::decode(&mut buf.as_slice()),
526 Err(Error::InvalidSize)
527 ));
528 }
529
530 const ESDS_2BYTE_SLCONFIG: &[u8] = &[
538 0x00, 0x00, 0x00, 0x28, b'e', b's', b'd', b's', 0x00, 0x00, 0x00, 0x00, 0x03, 0x1a, 0x00, 0x01, 0x00, 0x04, 0x11, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x02, 0x11, 0x90, 0x06, 0x02, 0x02, 0x15, ];
548
549 #[test]
550 fn test_esds_two_byte_slconfig() {
551 let esds =
552 Esds::decode(&mut &ESDS_2BYTE_SLCONFIG[..]).expect("2-byte SLConfig must be tolerated");
553 let dec = esds
554 .es_desc
555 .dec_config
556 .dec_specific
557 .expect("DecoderSpecificInfo present");
558 assert_eq!(dec.profile, 2, "AAC-LC");
559 assert_eq!(dec.freq_index, 3, "48 kHz");
560 }
561
562 const ESDS_NO_DEC_SPECIFIC: &[u8] = &[
569 0x00, 0x00, 0x00, 0x23, b'e', b's', b'd', b's', 0x00, 0x00, 0x00, 0x00, 0x03, 0x15, 0x00, 0x01, 0x00, 0x04, 0x0d, 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, ];
578
579 #[test]
580 fn test_esds_missing_dec_specific() {
581 let esds = Esds::decode(&mut &ESDS_NO_DEC_SPECIFIC[..])
582 .expect("a DecoderConfig without a DecoderSpecificInfo must be tolerated");
583 assert_eq!(esds.es_desc.dec_config.object_type_indication, 0x40);
584 assert!(
585 esds.es_desc.dec_config.dec_specific.is_none(),
586 "no tag-5 child decodes to None, not an error"
587 );
588
589 let mut buf = Vec::new();
591 esds.encode(&mut buf).unwrap();
592 let again = Esds::decode(&mut buf.as_slice()).unwrap();
593 assert_eq!(again, esds);
594 }
595
596 #[test]
601 fn test_unknown_descriptor_empty_body_roundtrips() {
602 let mut buf = Vec::new();
603 Descriptor::Unknown(0x7F, Vec::new())
604 .encode(&mut buf)
605 .unwrap();
606 Descriptor::from(SLConfig {}).encode(&mut buf).unwrap();
609
610 assert_eq!(&buf[..2], &[0x7F, 0x00], "empty body still emits a length");
611
612 let mut cur = buf.as_slice();
613 assert_eq!(
614 Descriptor::decode(&mut cur).unwrap(),
615 Descriptor::Unknown(0x7F, Vec::new())
616 );
617 assert_eq!(
618 Descriptor::decode(&mut cur).unwrap().tag(),
619 SLConfig::TAG,
620 "the following descriptor is intact"
621 );
622 }
623
624 #[test]
628 fn test_descriptor_multibyte_length_roundtrips() {
629 let body = vec![0xABu8; 200];
630 let mut buf = Vec::new();
631 Descriptor::Unknown(0x7F, body.clone())
632 .encode(&mut buf)
633 .unwrap();
634 assert_eq!(
635 &buf[..3],
636 &[0x7F, 0x81, 0x48],
637 "length 200, MSB group first"
638 );
639
640 let mut cur = buf.as_slice();
641 assert_eq!(
642 Descriptor::decode(&mut cur).unwrap(),
643 Descriptor::Unknown(0x7F, body)
644 );
645 }
646
647 #[test]
652 fn test_asc_escape_bit_packing() {
653 let (profile, freq_index, chan_conf) = parse_audio_specific_config(&[0xF9, 0x49, 0x20]);
654 assert_eq!(profile, 42, "32 + ((0xF9 & 7) << 3 | 0x49 >> 5)");
655 assert_eq!(freq_index, 4, "(0x49 >> 1) & 0x0F");
656 assert_eq!(chan_conf, 9, "((0x49 & 1) << 3) | (0x20 >> 5)");
657 }
658}