1use super::*;
3use alloc::vec::Vec;
4
5impl<'a> ExtensionBodyDef<'a> for DtsHd<'a> {
6 const TAG_EXTENSION: u8 = 0x0E;
7 const NAME: &'static str = "DTS_HD";
8}
9
10#[derive(Debug, Clone, PartialEq, Eq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize))]
13#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
14pub struct DtsHd<'a> {
15 pub substream_core_flag: bool,
17 pub substream_0_flag: bool,
19 pub substream_1_flag: bool,
21 pub substream_2_flag: bool,
23 pub substream_3_flag: bool,
25 pub reserved: u8,
27 pub substreams: Vec<SubstreamInfo>,
29 #[cfg_attr(feature = "serde", serde(borrow))]
31 pub additional_info: &'a [u8],
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize))]
37pub struct SubstreamInfo {
38 pub channel_count: u8,
40 pub lfe_flag: bool,
42 pub sampling_frequency: SamplingFrequency,
44 pub sample_resolution: bool,
46 pub reserved: u8,
48 pub assets: Vec<AssetInfo>,
50}
51
52#[derive(Debug, Clone, PartialEq, Eq)]
54#[cfg_attr(feature = "serde", derive(serde::Serialize))]
55pub struct AssetInfo {
56 pub asset_construction: u8,
58 pub vbr_flag: bool,
60 pub post_encode_br_scaling_flag: bool,
62 pub component_type_flag: bool,
64 pub language_code_flag: bool,
66 pub bit_rate_or_scaled: u16,
68 pub reserved: u8,
70 pub component_type: Option<u8>,
72 pub iso_639_language_code: Option<LangCode>,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78#[cfg_attr(feature = "serde", derive(serde::Serialize))]
79#[non_exhaustive]
80#[repr(u8)]
81pub enum SamplingFrequency {
82 Khz8 = 0,
84 Khz16 = 1,
86 Khz32 = 2,
88 Khz64 = 3,
90 Khz128 = 4,
92 Khz22_05 = 5,
94 Khz44_1 = 6,
96 Khz88_2 = 7,
98 Khz176_4 = 8,
100 Khz352_8 = 9,
102 Khz12 = 10,
104 Khz24 = 11,
106 Khz48 = 12,
108 Khz96 = 13,
110 Khz192 = 14,
112 Khz348 = 15,
114}
115
116impl SamplingFrequency {
117 #[must_use]
119 pub fn from_u8(v: u8) -> Self {
120 match v {
121 0 => SamplingFrequency::Khz8,
122 1 => SamplingFrequency::Khz16,
123 2 => SamplingFrequency::Khz32,
124 3 => SamplingFrequency::Khz64,
125 4 => SamplingFrequency::Khz128,
126 5 => SamplingFrequency::Khz22_05,
127 6 => SamplingFrequency::Khz44_1,
128 7 => SamplingFrequency::Khz88_2,
129 8 => SamplingFrequency::Khz176_4,
130 9 => SamplingFrequency::Khz352_8,
131 10 => SamplingFrequency::Khz12,
132 11 => SamplingFrequency::Khz24,
133 12 => SamplingFrequency::Khz48,
134 13 => SamplingFrequency::Khz96,
135 14 => SamplingFrequency::Khz192,
136 15 => SamplingFrequency::Khz348,
137 _ => SamplingFrequency::Khz48, }
139 }
140
141 #[must_use]
143 pub fn to_u8(self) -> u8 {
144 self as u8
145 }
146
147 #[must_use]
149 pub fn name(self) -> &'static str {
150 match self {
151 SamplingFrequency::Khz8 => "8 kHz",
152 SamplingFrequency::Khz16 => "16 kHz",
153 SamplingFrequency::Khz32 => "32 kHz",
154 SamplingFrequency::Khz64 => "64 kHz",
155 SamplingFrequency::Khz128 => "128 kHz",
156 SamplingFrequency::Khz22_05 => "22,05 kHz",
157 SamplingFrequency::Khz44_1 => "44,1 kHz",
158 SamplingFrequency::Khz88_2 => "88,2 kHz",
159 SamplingFrequency::Khz176_4 => "176,4 kHz",
160 SamplingFrequency::Khz352_8 => "352,8 kHz",
161 SamplingFrequency::Khz12 => "12 kHz",
162 SamplingFrequency::Khz24 => "24 kHz",
163 SamplingFrequency::Khz48 => "48 kHz",
164 SamplingFrequency::Khz96 => "96 kHz",
165 SamplingFrequency::Khz192 => "192 kHz",
166 SamplingFrequency::Khz348 => "348 kHz",
167 }
168 }
169}
170dvb_common::impl_spec_display!(SamplingFrequency);
171
172const MAX_CHANNEL_COUNT: u8 = 0x1F;
174const MAX_BIT_RATE: u16 = 0x1FFF;
176
177const SUBSTREAM_HEADER_LEN: usize = 3;
180const ASSET_FIXED_LEN: usize = 3;
183
184impl Serialize for SubstreamInfo {
185 type Error = crate::error::Error;
186 fn serialized_len(&self) -> usize {
187 let payload_len: usize = self
188 .assets
189 .iter()
190 .map(|a| {
191 ASSET_FIXED_LEN
192 + usize::from(a.component_type_flag)
193 + usize::from(a.language_code_flag) * ISO_639_LEN
194 })
195 .sum();
196 SUBSTREAM_HEADER_LEN + payload_len
197 }
198 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
199 let payload_len = self.serialized_len() - SUBSTREAM_HEADER_LEN;
200 let substream_length = payload_len;
201 if substream_length > 0xFF {
202 return Err(Error::ValueOutOfRange {
203 field: "substream_length",
204 reason: "substream payload exceeds 255 bytes",
205 });
206 }
207 if self.channel_count > MAX_CHANNEL_COUNT {
208 return Err(Error::ValueOutOfRange {
209 field: "channel_count",
210 reason: "exceeds 5-bit field",
211 });
212 }
213 buf[0] = substream_length as u8;
214 let num_assets = self.assets.len();
215 if num_assets == 0 {
216 return Err(Error::ValueOutOfRange {
217 field: "num_assets",
218 reason: "substream must have at least 1 asset",
219 });
220 }
221 let na = (num_assets - 1) as u8;
222 buf[1] = (na << 5) | (self.channel_count & MAX_CHANNEL_COUNT);
223 buf[2] = ((u8::from(self.lfe_flag)) << 7)
224 | ((self.sampling_frequency.to_u8() & 0x0F) << 3)
225 | ((u8::from(self.sample_resolution)) << 2)
226 | (self.reserved & 0x03);
227 let mut pos = SUBSTREAM_HEADER_LEN;
228 for a in &self.assets {
229 if a.bit_rate_or_scaled > MAX_BIT_RATE {
230 return Err(Error::ValueOutOfRange {
231 field: "bit_rate_or_scaled",
232 reason: "exceeds 13-bit field",
233 });
234 }
235 buf[pos] = (a.asset_construction << 3)
236 | ((u8::from(a.vbr_flag)) << 2)
237 | ((u8::from(a.post_encode_br_scaling_flag)) << 1)
238 | u8::from(a.component_type_flag);
239 buf[pos + 1] =
240 (u8::from(a.language_code_flag) << 7) | ((a.bit_rate_or_scaled >> 6) as u8 & 0x7F);
241 buf[pos + 2] = ((a.bit_rate_or_scaled as u8 & 0x3F) << 2) | (a.reserved & 0x03);
242 pos += ASSET_FIXED_LEN;
243 if a.component_type_flag {
244 buf[pos] = a.component_type.unwrap_or(0);
245 pos += 1;
246 }
247 if a.language_code_flag {
248 buf[pos..pos + ISO_639_LEN]
249 .copy_from_slice(&a.iso_639_language_code.unwrap_or(LangCode(*b" ")).0);
250 pos += ISO_639_LEN;
251 }
252 }
253 Ok(pos)
254 }
255}
256
257impl<'a> Parse<'a> for DtsHd<'a> {
258 type Error = crate::error::Error;
259 fn parse(sel: &'a [u8]) -> Result<Self> {
260 let first = *sel.first().ok_or(Error::BufferTooShort {
261 need: 1,
262 have: 0,
263 what: "DTS-HD descriptor body",
264 })?;
265 let substream_core_flag = (first & 0x80) != 0;
266 let substream_0_flag = (first & 0x40) != 0;
267 let substream_1_flag = (first & 0x20) != 0;
268 let substream_2_flag = (first & 0x10) != 0;
269 let substream_3_flag = (first & 0x08) != 0;
270 let reserved = first & 0x07;
271 let flags = [
272 substream_core_flag,
273 substream_0_flag,
274 substream_1_flag,
275 substream_2_flag,
276 substream_3_flag,
277 ];
278 let num_substreams = flags.iter().filter(|&&f| f).count();
279 let mut pos = 1;
280 let mut substreams = Vec::with_capacity(num_substreams);
281
282 for &present in &flags {
283 if !present {
284 continue;
285 }
286 let si = parse_substream_info(sel, &mut pos)?;
287 substreams.push(si);
288 }
289
290 Ok(DtsHd {
291 substream_core_flag,
292 substream_0_flag,
293 substream_1_flag,
294 substream_2_flag,
295 substream_3_flag,
296 reserved,
297 substreams,
298 additional_info: &sel[pos..],
299 })
300 }
301}
302
303fn parse_substream_info(sel: &[u8], pos: &mut usize) -> Result<SubstreamInfo> {
304 let need = *pos + SUBSTREAM_HEADER_LEN;
305 if sel.len() < need {
306 return Err(Error::BufferTooShort {
307 need,
308 have: sel.len(),
309 what: "substream_info header",
310 });
311 }
312 let substream_length = sel[*pos] as usize;
313 *pos += 1;
314 let end = *pos + substream_length;
315 if sel.len() < end {
316 return Err(Error::BufferTooShort {
317 need: end,
318 have: sel.len(),
319 what: "substream_info body",
320 });
321 }
322 let num_assets = ((sel[*pos] >> 5) & 0x07) as usize + 1;
323 let channel_count = sel[*pos] & 0x1F;
324 *pos += 1;
325 let lfe_flag = (sel[*pos] & 0x80) != 0;
326 let sampling_frequency = SamplingFrequency::from_u8((sel[*pos] >> 3) & 0x0F);
327 let sample_resolution = (sel[*pos] & 0x04) != 0;
328 let s_reserved = sel[*pos] & 0x03;
329 *pos += 1;
330
331 let mut assets = Vec::with_capacity(num_assets);
332 for _ in 0..num_assets {
333 let a = parse_asset_info(sel, pos)?;
334 assets.push(a);
335 }
336
337 Ok(SubstreamInfo {
338 channel_count,
339 lfe_flag,
340 sampling_frequency,
341 sample_resolution,
342 reserved: s_reserved,
343 assets,
344 })
345}
346
347fn parse_asset_info(sel: &[u8], pos: &mut usize) -> Result<AssetInfo> {
348 let need = *pos + ASSET_FIXED_LEN;
349 if sel.len() < need {
350 return Err(Error::BufferTooShort {
351 need,
352 have: sel.len(),
353 what: "asset_info",
354 });
355 }
356 let asset_construction = (sel[*pos] >> 3) & 0x1F;
357 let vbr_flag = (sel[*pos] & 0x04) != 0;
358 let post_encode_br_scaling_flag = (sel[*pos] & 0x02) != 0;
359 let component_type_flag = (sel[*pos] & 0x01) != 0;
360 *pos += 1;
361 let language_code_flag = (sel[*pos] & 0x80) != 0;
362 let bit_rate_or_scaled = ((u16::from(sel[*pos] & 0x7F)) << 6) | (u16::from(sel[*pos + 1]) >> 2);
363 *pos += 1;
364 let a_reserved = sel[*pos] & 0x03;
365 *pos += 1;
366
367 let component_type = if component_type_flag {
368 let ct = *sel.get(*pos).ok_or(Error::BufferTooShort {
369 need: *pos + 1,
370 have: sel.len(),
371 what: "asset_info component_type",
372 })?;
373 *pos += 1;
374 Some(ct)
375 } else {
376 None
377 };
378
379 let iso_639_language_code = if language_code_flag {
380 let need_lang = *pos + ISO_639_LEN;
381 let lang_bytes = sel.get(*pos..need_lang).ok_or(Error::BufferTooShort {
382 need: need_lang,
383 have: sel.len(),
384 what: "asset_info ISO_639_language_code",
385 })?;
386 *pos += ISO_639_LEN;
387 Some(LangCode([lang_bytes[0], lang_bytes[1], lang_bytes[2]]))
388 } else {
389 None
390 };
391
392 Ok(AssetInfo {
393 asset_construction,
394 vbr_flag,
395 post_encode_br_scaling_flag,
396 component_type_flag,
397 language_code_flag,
398 bit_rate_or_scaled,
399 reserved: a_reserved,
400 component_type,
401 iso_639_language_code,
402 })
403}
404
405impl Serialize for DtsHd<'_> {
406 type Error = crate::error::Error;
407 fn serialized_len(&self) -> usize {
408 1 + self
409 .substreams
410 .iter()
411 .map(|s| s.serialized_len())
412 .sum::<usize>()
413 + self.additional_info.len()
414 }
415 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
416 let len = self.serialized_len();
417 if buf.len() < len {
418 return Err(Error::OutputBufferTooSmall {
419 need: len,
420 have: buf.len(),
421 });
422 }
423 buf[0] = ((u8::from(self.substream_core_flag)) << 7)
424 | ((u8::from(self.substream_0_flag)) << 6)
425 | ((u8::from(self.substream_1_flag)) << 5)
426 | ((u8::from(self.substream_2_flag)) << 4)
427 | ((u8::from(self.substream_3_flag)) << 3)
428 | (self.reserved & 0x07);
429
430 let flags = [
431 self.substream_core_flag,
432 self.substream_0_flag,
433 self.substream_1_flag,
434 self.substream_2_flag,
435 self.substream_3_flag,
436 ];
437 let mut pos = 1;
438 let mut si = 0;
439 for &present in &flags {
440 if !present {
441 continue;
442 }
443 if si >= self.substreams.len() {
444 return Err(Error::ValueOutOfRange {
445 field: "DTS-HD substreams",
446 reason: "fewer substreams than flags indicate",
447 });
448 }
449 let written = self.substreams[si].serialize_into(&mut buf[pos..])?;
450 pos += written;
451 si += 1;
452 }
453 if si != self.substreams.len() {
454 return Err(Error::ValueOutOfRange {
455 field: "DTS-HD substreams",
456 reason: "more substreams than flags indicate",
457 });
458 }
459 buf[pos..len].copy_from_slice(self.additional_info);
460 Ok(len)
461 }
462}
463
464#[cfg(test)]
465mod tests {
466 use super::*;
467 use crate::descriptors::extension::test_support::*;
468 use crate::descriptors::extension::{ExtensionBody, ExtensionDescriptor};
469
470 #[test]
471 fn decodes_sampling_frequency() {
472 assert_eq!(SamplingFrequency::from_u8(12).name(), "48 kHz");
473 assert_eq!(SamplingFrequency::from_u8(0).name(), "8 kHz");
474 }
475
476 #[test]
477 fn parse_dts_hd_core_only() {
478 let sel = [
484 0x87, 0x06, 0x06, 0xE7, 0x09, 0x8B, 0xCF, 0x42, b'e', b'n', b'g', ];
492 let bytes = wrap(0x0E, &sel);
493 let d = ExtensionDescriptor::parse(&bytes).unwrap();
494 match &d.body {
495 ExtensionBody::DtsHd(b) => {
496 assert!(b.substream_core_flag);
497 assert!(!b.substream_0_flag);
498 assert!(!b.substream_1_flag);
499 assert!(!b.substream_2_flag);
500 assert!(!b.substream_3_flag);
501 assert_eq!(b.reserved, 7);
502 assert_eq!(b.substreams.len(), 1);
503 let s = &b.substreams[0];
504 assert_eq!(s.channel_count, 6);
505 assert!(s.lfe_flag);
506 assert_eq!(s.sampling_frequency, SamplingFrequency::Khz48);
507 assert!(s.sample_resolution);
508 assert_eq!(s.reserved, 3);
509 assert_eq!(s.assets.len(), 1);
510 let a = &s.assets[0];
511 assert_eq!(a.asset_construction, 1);
512 assert!(!a.vbr_flag);
513 assert!(!a.post_encode_br_scaling_flag);
514 assert!(a.component_type_flag);
515 assert!(a.language_code_flag);
516 assert_eq!(a.bit_rate_or_scaled, 755);
517 assert_eq!(a.reserved, 3);
518 assert_eq!(a.component_type, Some(0x42));
519 assert_eq!(a.iso_639_language_code, Some(LangCode(*b"eng")));
520 assert!(b.additional_info.is_empty());
521 }
522 other => panic!("expected DtsHd, got {other:?}"),
523 }
524 round_trip(&d);
525 }
526
527 #[test]
528 fn parse_dts_hd_flags_only() {
529 let sel = [0x00];
531 let bytes = wrap(0x0E, &sel);
532 let d = ExtensionDescriptor::parse(&bytes).unwrap();
533 match &d.body {
534 ExtensionBody::DtsHd(b) => {
535 assert!(!b.substream_core_flag);
536 assert!(b.substreams.is_empty());
537 }
538 other => panic!("expected DtsHd, got {other:?}"),
539 }
540 round_trip(&d);
541 }
542}