1use super::descriptor_body;
18use crate::error::{Error, Result};
19use dvb_common::{Parse, Serialize};
20
21pub const TAG: u8 = 0x7B;
23const HEADER_LEN: usize = 2;
24const FIXED_LEN: usize = 5;
26
27const SAMPLE_RATE_CODE_MAX: u8 = 0x0F; const BIT_RATE_CODE_MAX: u8 = 0x3F; const NBLKS_MAX: u8 = 0x7F; const FSIZE_MAX: u16 = 0x3FFF; const SURROUND_MODE_MAX: u8 = 0x3F; const EXTENDED_SURROUND_MAX: u8 = 0x03; #[derive(Debug, Clone, PartialEq, Eq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize))]
37#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
38pub struct DtsDescriptor<'a> {
39 pub sample_rate_code: u8,
41 pub bit_rate_code: u8,
44 pub nblks: u8,
46 pub fsize: u16,
48 pub surround_mode: u8,
50 pub lfe_flag: bool,
52 pub extended_surround_flag: u8,
54 pub additional_info: &'a [u8],
56}
57
58impl DtsDescriptor<'_> {
59 #[must_use]
63 pub fn sample_rate_hz(&self) -> Option<u32> {
64 match self.sample_rate_code {
65 0x01 => Some(8_000),
66 0x02 => Some(16_000),
67 0x03 => Some(32_000),
68 0x04 => Some(64_000),
69 0x05 => Some(128_000),
70 0x06 => Some(11_025),
71 0x07 => Some(22_050),
72 0x08 => Some(44_100),
73 0x09 => Some(88_020),
74 0x0A => Some(176_400),
75 0x0B => Some(12_000),
76 0x0C => Some(24_000),
77 0x0D => Some(48_000),
78 0x0E => Some(96_000),
79 0x0F => Some(192_000),
80 _ => None,
81 }
82 }
83
84 #[must_use]
87 pub fn sample_rate_name(&self) -> Option<&'static str> {
88 match self.sample_rate_code {
89 0x00 => Some("invalid"),
90 0x01 => Some("8 kHz"),
91 0x02 => Some("16 kHz"),
92 0x03 => Some("32 kHz"),
93 0x04 => Some("64 kHz"),
94 0x05 => Some("128 kHz"),
95 0x06 => Some("11.025 kHz"),
96 0x07 => Some("22.05 kHz"),
97 0x08 => Some("44.1 kHz"),
98 0x09 => Some("88.02 kHz"),
100 0x0A => Some("176.4 kHz"),
101 0x0B => Some("12 kHz"),
102 0x0C => Some("24 kHz"),
103 0x0D => Some("48 kHz"),
104 0x0E => Some("96 kHz"),
105 0x0F => Some("192 kHz"),
106 _ => None,
107 }
108 }
109
110 #[must_use]
115 pub fn bit_rate_kbits(&self) -> Option<u32> {
116 match self.bit_rate_code & 0x1F {
117 0x05 => Some(128),
118 0x06 => Some(192),
119 0x07 => Some(224),
120 0x08 => Some(256),
121 0x09 => Some(320),
122 0x0A => Some(384),
123 0x0B => Some(448),
124 0x0C => Some(512),
125 0x0D => Some(576),
126 0x0E => Some(640),
127 0x0F => Some(768),
128 0x10 => Some(960),
129 0x11 => Some(1_024),
130 0x12 => Some(1_152),
131 0x13 => Some(1_280),
132 0x14 => Some(1_344),
133 0x15 => Some(1_408),
134 0x16 => Some(1_411),
135 0x17 => Some(1_472),
136 0x18 => Some(1_536),
137 0x19 => Some(1_920),
138 0x1A => Some(2_048),
139 0x1B => Some(3_072),
140 0x1C => Some(3_840),
141 0x1D => None, 0x1E => None, 0x1F => None, _ => None,
145 }
146 }
147
148 #[must_use]
150 pub fn bit_rate_name(&self) -> Option<&'static str> {
151 match self.bit_rate_code & 0x1F {
152 0x05 => Some("128 kbit/s"),
153 0x06 => Some("192 kbit/s"),
154 0x07 => Some("224 kbit/s"),
155 0x08 => Some("256 kbit/s"),
156 0x09 => Some("320 kbit/s"),
157 0x0A => Some("384 kbit/s"),
158 0x0B => Some("448 kbit/s"),
159 0x0C => Some("512 kbit/s"),
160 0x0D => Some("576 kbit/s"),
161 0x0E => Some("640 kbit/s"),
162 0x0F => Some("768 kbit/s"),
163 0x10 => Some("960 kbit/s"),
164 0x11 => Some("1024 kbit/s"),
165 0x12 => Some("1152 kbit/s"),
166 0x13 => Some("1280 kbit/s"),
167 0x14 => Some("1344 kbit/s"),
168 0x15 => Some("1408 kbit/s"),
169 0x16 => Some("1411.2 kbit/s"),
170 0x17 => Some("1472 kbit/s"),
171 0x18 => Some("1536 kbit/s"),
172 0x19 => Some("1920 kbit/s"),
173 0x1A => Some("2048 kbit/s"),
174 0x1B => Some("3072 kbit/s"),
175 0x1C => Some("3840 kbit/s"),
176 0x1D => Some("open"),
177 0x1E => Some("variable"),
178 0x1F => Some("lossless"),
179 _ => None,
180 }
181 }
182
183 #[must_use]
187 pub fn surround_mode_name(&self) -> Option<&'static str> {
188 match self.surround_mode {
189 0x00 => Some("1 / mono"),
190 0x02 => Some("2 / L+R (stereo)"),
191 0x03 => Some("2 / (L+R)+(L-R) (sum-difference)"),
192 0x04 => Some("2 / LT+RT (left and right total)"),
193 0x05 => Some("3 / C+L+R"),
194 0x06 => Some("3 / L+R+S"),
195 0x07 => Some("4 / C+L+R+S"),
196 0x08 => Some("4 / L+R+SL+SR"),
197 0x09 => Some("5 / C+L+R+SL+SR"),
198 0x0A..=0x0F => None, 0x10..=0x3F => None, _ => None,
201 }
202 }
203
204 #[must_use]
207 pub fn extended_surround_name(&self) -> &'static str {
208 match self.extended_surround_flag {
209 0x00 => "no extended surround",
210 0x01 => "matrixed extended surround",
211 0x02 => "discrete extended surround",
212 0x03 => "undefined",
213 _ => "unknown",
214 }
215 }
216}
217
218impl<'a> Parse<'a> for DtsDescriptor<'a> {
219 type Error = crate::error::Error;
220 fn parse(bytes: &'a [u8]) -> Result<Self> {
221 let body = descriptor_body(
222 bytes,
223 TAG,
224 "DtsDescriptor",
225 "unexpected tag for DTS_descriptor",
226 )?;
227 if body.len() < FIXED_LEN {
228 return Err(Error::InvalidDescriptor {
229 tag: TAG,
230 reason: "DTS_descriptor body shorter than 5 bytes",
231 });
232 }
233 let packed: u64 = (u64::from(body[0]) << 32)
235 | (u64::from(body[1]) << 24)
236 | (u64::from(body[2]) << 16)
237 | (u64::from(body[3]) << 8)
238 | u64::from(body[4]);
239 let sample_rate_code = ((packed >> 36) & 0x0F) as u8;
240 let bit_rate_code = ((packed >> 30) & 0x3F) as u8;
241 let nblks = ((packed >> 23) & 0x7F) as u8;
242 let fsize = ((packed >> 9) & 0x3FFF) as u16;
243 let surround_mode = ((packed >> 3) & 0x3F) as u8;
244 let lfe_flag = ((packed >> 2) & 0x01) != 0;
245 let extended_surround_flag = (packed & 0x03) as u8;
246 let additional_info = &body[FIXED_LEN..];
247 Ok(Self {
248 sample_rate_code,
249 bit_rate_code,
250 nblks,
251 fsize,
252 surround_mode,
253 lfe_flag,
254 extended_surround_flag,
255 additional_info,
256 })
257 }
258}
259
260impl Serialize for DtsDescriptor<'_> {
261 type Error = crate::error::Error;
262 fn serialized_len(&self) -> usize {
263 HEADER_LEN + FIXED_LEN + self.additional_info.len()
264 }
265
266 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
267 if self.sample_rate_code > SAMPLE_RATE_CODE_MAX {
268 return Err(Error::InvalidDescriptor {
269 tag: TAG,
270 reason: "sample_rate_code exceeds 4 bits",
271 });
272 }
273 if self.bit_rate_code > BIT_RATE_CODE_MAX {
274 return Err(Error::InvalidDescriptor {
275 tag: TAG,
276 reason: "bit_rate_code exceeds 6 bits",
277 });
278 }
279 if self.nblks > NBLKS_MAX {
280 return Err(Error::InvalidDescriptor {
281 tag: TAG,
282 reason: "nblks exceeds 7 bits",
283 });
284 }
285 if self.fsize > FSIZE_MAX {
286 return Err(Error::InvalidDescriptor {
287 tag: TAG,
288 reason: "fsize exceeds 14 bits",
289 });
290 }
291 if self.surround_mode > SURROUND_MODE_MAX {
292 return Err(Error::InvalidDescriptor {
293 tag: TAG,
294 reason: "surround_mode exceeds 6 bits",
295 });
296 }
297 if self.extended_surround_flag > EXTENDED_SURROUND_MAX {
298 return Err(Error::InvalidDescriptor {
299 tag: TAG,
300 reason: "extended_surround_flag exceeds 2 bits",
301 });
302 }
303 if FIXED_LEN + self.additional_info.len() > u8::MAX as usize {
304 return Err(Error::InvalidDescriptor {
305 tag: TAG,
306 reason: "DTS_descriptor body exceeds 255 bytes",
307 });
308 }
309 let len = self.serialized_len();
310 if buf.len() < len {
311 return Err(Error::OutputBufferTooSmall {
312 need: len,
313 have: buf.len(),
314 });
315 }
316 buf[0] = TAG;
317 buf[1] = (FIXED_LEN + self.additional_info.len()) as u8;
318 let packed: u64 = ((u64::from(self.sample_rate_code) & 0x0F) << 36)
319 | ((u64::from(self.bit_rate_code) & 0x3F) << 30)
320 | ((u64::from(self.nblks) & 0x7F) << 23)
321 | ((u64::from(self.fsize) & 0x3FFF) << 9)
322 | ((u64::from(self.surround_mode) & 0x3F) << 3)
323 | (u64::from(self.lfe_flag) << 2)
324 | (u64::from(self.extended_surround_flag) & 0x03);
325 buf[2] = (packed >> 32) as u8;
326 buf[3] = (packed >> 24) as u8;
327 buf[4] = (packed >> 16) as u8;
328 buf[5] = (packed >> 8) as u8;
329 buf[6] = packed as u8;
330 buf[HEADER_LEN + FIXED_LEN..len].copy_from_slice(self.additional_info);
331 Ok(len)
332 }
333}
334impl<'a> crate::traits::DescriptorDef<'a> for DtsDescriptor<'a> {
335 const TAG: u8 = TAG;
336 const NAME: &'static str = "DTS";
337}
338
339#[cfg(test)]
340mod tests {
341 use super::*;
342
343 #[test]
344 fn parse_no_additional_info() {
345 let d_in = DtsDescriptor {
348 sample_rate_code: 0b1101,
349 bit_rate_code: 0b001010,
350 nblks: 8,
351 fsize: 1024,
352 surround_mode: 0b000010,
353 lfe_flag: true,
354 extended_surround_flag: 0b01,
355 additional_info: &[],
356 };
357 let mut buf = vec![0u8; d_in.serialized_len()];
358 d_in.serialize_into(&mut buf).unwrap();
359 let d = DtsDescriptor::parse(&buf).unwrap();
360 assert_eq!(d, d_in);
361 assert_eq!(buf[1], 5);
362 }
363
364 #[test]
365 fn parse_with_additional_info() {
366 let d_in = DtsDescriptor {
367 sample_rate_code: 0b1000,
368 bit_rate_code: 0b011010,
369 nblks: 127,
370 fsize: 0x3FFF,
371 surround_mode: 0b001001,
372 lfe_flag: false,
373 extended_surround_flag: 0b10,
374 additional_info: &[0xAA, 0xBB, 0xCC],
375 };
376 let mut buf = vec![0u8; d_in.serialized_len()];
377 d_in.serialize_into(&mut buf).unwrap();
378 let d = DtsDescriptor::parse(&buf).unwrap();
379 assert_eq!(d.additional_info, &[0xAA, 0xBB, 0xCC]);
380 assert_eq!(d, d_in);
381 }
382
383 #[test]
384 fn decode_sample_rate() {
385 let d = DtsDescriptor {
386 sample_rate_code: 0x0D,
387 bit_rate_code: 0,
388 nblks: 0,
389 fsize: 0,
390 surround_mode: 0,
391 lfe_flag: false,
392 extended_surround_flag: 0,
393 additional_info: &[],
394 };
395 assert_eq!(d.sample_rate_hz(), Some(48_000));
396 assert_eq!(d.sample_rate_name(), Some("48 kHz"));
397 }
398
399 #[test]
400 fn decode_sample_rate_invalid() {
401 let d = DtsDescriptor {
402 sample_rate_code: 0x00,
403 bit_rate_code: 0,
404 nblks: 0,
405 fsize: 0,
406 surround_mode: 0,
407 lfe_flag: false,
408 extended_surround_flag: 0,
409 additional_info: &[],
410 };
411 assert_eq!(d.sample_rate_hz(), None);
412 assert_eq!(d.sample_rate_name(), Some("invalid"));
413 }
414
415 #[test]
416 fn decode_bit_rate_384() {
417 let d = DtsDescriptor {
419 sample_rate_code: 0,
420 bit_rate_code: 0x0A,
421 nblks: 0,
422 fsize: 0,
423 surround_mode: 0,
424 lfe_flag: false,
425 extended_surround_flag: 0,
426 additional_info: &[],
427 };
428 assert_eq!(d.bit_rate_kbits(), Some(384));
429 assert_eq!(d.bit_rate_name(), Some("384 kbit/s"));
430 }
431
432 #[test]
433 fn decode_bit_rate_128() {
434 let d = DtsDescriptor {
436 sample_rate_code: 0,
437 bit_rate_code: 0x05,
438 nblks: 0,
439 fsize: 0,
440 surround_mode: 0,
441 lfe_flag: false,
442 extended_surround_flag: 0,
443 additional_info: &[],
444 };
445 assert_eq!(d.bit_rate_kbits(), Some(128));
446 }
447
448 #[test]
449 fn decode_bit_rate_lossless() {
450 let d = DtsDescriptor {
452 sample_rate_code: 0,
453 bit_rate_code: 0x3F,
454 nblks: 0,
455 fsize: 0,
456 surround_mode: 0,
457 lfe_flag: false,
458 extended_surround_flag: 0,
459 additional_info: &[],
460 };
461 assert_eq!(d.bit_rate_kbits(), None);
462 assert_eq!(d.bit_rate_name(), Some("lossless"));
463 }
464
465 #[test]
466 fn decode_bit_rate_reserved_msb_ignored() {
467 let d_low = DtsDescriptor {
471 sample_rate_code: 0,
472 bit_rate_code: 0x0A,
473 nblks: 0,
474 fsize: 0,
475 surround_mode: 0,
476 lfe_flag: false,
477 extended_surround_flag: 0,
478 additional_info: &[],
479 };
480 let d_high = DtsDescriptor {
481 sample_rate_code: 0,
482 bit_rate_code: 0x2A,
483 nblks: 0,
484 fsize: 0,
485 surround_mode: 0,
486 lfe_flag: false,
487 extended_surround_flag: 0,
488 additional_info: &[],
489 };
490 assert_eq!(d_low.bit_rate_kbits(), d_high.bit_rate_kbits());
491 assert_eq!(d_low.bit_rate_name(), d_high.bit_rate_name());
492 }
493
494 #[test]
495 fn decode_surround_mode() {
496 let d = DtsDescriptor {
497 sample_rate_code: 0,
498 bit_rate_code: 0,
499 nblks: 0,
500 fsize: 0,
501 surround_mode: 0x09,
502 lfe_flag: false,
503 extended_surround_flag: 0,
504 additional_info: &[],
505 };
506 assert_eq!(d.surround_mode_name(), Some("5 / C+L+R+SL+SR"));
507 }
508
509 #[test]
510 fn decode_surround_mode_user_defined() {
511 let d = DtsDescriptor {
512 sample_rate_code: 0,
513 bit_rate_code: 0,
514 nblks: 0,
515 fsize: 0,
516 surround_mode: 0x20,
517 lfe_flag: false,
518 extended_surround_flag: 0,
519 additional_info: &[],
520 };
521 assert_eq!(d.surround_mode_name(), None);
522 }
523
524 #[test]
525 fn decode_extended_surround() {
526 let d = DtsDescriptor {
527 sample_rate_code: 0,
528 bit_rate_code: 0,
529 nblks: 0,
530 fsize: 0,
531 surround_mode: 0,
532 lfe_flag: false,
533 extended_surround_flag: 0x02,
534 additional_info: &[],
535 };
536 assert_eq!(d.extended_surround_name(), "discrete extended surround");
537 }
538
539 #[test]
540 fn parse_rejects_wrong_tag() {
541 let bytes = [0x7C, 5, 0, 0, 0, 0, 0];
542 assert!(matches!(
543 DtsDescriptor::parse(&bytes).unwrap_err(),
544 Error::InvalidDescriptor { tag: 0x7C, .. }
545 ));
546 }
547
548 #[test]
549 fn parse_rejects_body_too_short() {
550 let bytes = [TAG, 4, 0, 0, 0, 0];
551 assert!(matches!(
552 DtsDescriptor::parse(&bytes).unwrap_err(),
553 Error::InvalidDescriptor { .. }
554 ));
555 }
556
557 #[test]
558 fn parse_rejects_length_overrunning_buffer() {
559 let bytes = [TAG, 5, 0, 0, 0];
560 assert!(matches!(
561 DtsDescriptor::parse(&bytes).unwrap_err(),
562 Error::BufferTooShort { .. }
563 ));
564 }
565
566 #[test]
567 fn serialize_round_trip_max_fields() {
568 let d = DtsDescriptor {
569 sample_rate_code: 0x0F,
570 bit_rate_code: 0x3F,
571 nblks: 0x7F,
572 fsize: 0x3FFF,
573 surround_mode: 0x3F,
574 lfe_flag: true,
575 extended_surround_flag: 0x03,
576 additional_info: &[0x01],
577 };
578 let mut buf = vec![0u8; d.serialized_len()];
579 d.serialize_into(&mut buf).unwrap();
580 assert_eq!(DtsDescriptor::parse(&buf).unwrap(), d);
581 }
582
583 #[test]
584 fn serialize_rejects_fsize_over_range() {
585 let d = DtsDescriptor {
586 sample_rate_code: 0,
587 bit_rate_code: 0,
588 nblks: 0,
589 fsize: 0x4000,
590 surround_mode: 0,
591 lfe_flag: false,
592 extended_surround_flag: 0,
593 additional_info: &[],
594 };
595 let mut buf = vec![0u8; d.serialized_len()];
596 assert!(matches!(
597 d.serialize_into(&mut buf).unwrap_err(),
598 Error::InvalidDescriptor { .. }
599 ));
600 }
601
602 #[test]
603 fn serialize_rejects_bit_rate_code_over_range() {
604 let d = DtsDescriptor {
605 sample_rate_code: 0,
606 bit_rate_code: 0x40,
607 nblks: 0,
608 fsize: 0,
609 surround_mode: 0,
610 lfe_flag: false,
611 extended_surround_flag: 0,
612 additional_info: &[],
613 };
614 let mut buf = vec![0u8; d.serialized_len()];
615 assert!(matches!(
616 d.serialize_into(&mut buf).unwrap_err(),
617 Error::InvalidDescriptor { .. }
618 ));
619 }
620
621 #[cfg(feature = "serde")]
622 #[test]
623 fn serde_serializes_to_stable_json() {
624 let d = DtsDescriptor {
627 sample_rate_code: 0b1101,
628 bit_rate_code: 0b001010,
629 nblks: 16,
630 fsize: 2048,
631 surround_mode: 0b001000,
632 lfe_flag: true,
633 extended_surround_flag: 0b01,
634 additional_info: &[0x99],
635 };
636 let j = serde_json::to_string(&d).unwrap();
637 let _v: serde_json::Value = serde_json::from_str(&j).unwrap();
640 assert!(j.contains("sample_rate_code"));
641 }
642}