1use super::ac3::Ac3ComponentType;
10use super::descriptor_body;
11use crate::error::{Error, Result};
12use dvb_common::{Parse, Serialize};
13
14pub const TAG: u8 = 0x7A;
16const HEADER_LEN: usize = 2;
17
18const FLAG_COMPONENT_TYPE: u8 = 0x80;
19const FLAG_BSID: u8 = 0x40;
20const FLAG_MAINID: u8 = 0x20;
21const FLAG_ASVC: u8 = 0x10;
22const FLAG_MIXINFO_EXISTS: u8 = 0x08;
23const FLAG_SUBSTREAM1: u8 = 0x04;
24const FLAG_SUBSTREAM2: u8 = 0x02;
25const FLAG_SUBSTREAM3: u8 = 0x01;
26
27#[derive(Debug, Clone, PartialEq, Eq)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize))]
30#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
31pub struct EnhancedAc3Descriptor<'a> {
32 pub component_type: Option<u8>,
34 pub bsid: Option<u8>,
36 pub mainid: Option<u8>,
38 pub asvc: Option<u8>,
40 pub mixinfoexists: bool,
43 pub substream1: Option<u8>,
45 pub substream2: Option<u8>,
47 pub substream3: Option<u8>,
49 pub additional_info: &'a [u8],
51}
52
53impl EnhancedAc3Descriptor<'_> {
54 #[must_use]
58 pub fn decoded_component_type(&self) -> Option<Ac3ComponentType> {
59 Some(Ac3ComponentType::from_byte(self.component_type?))
60 }
61}
62
63impl<'a> Parse<'a> for EnhancedAc3Descriptor<'a> {
64 type Error = crate::error::Error;
65 fn parse(bytes: &'a [u8]) -> Result<Self> {
66 let body = descriptor_body(
67 bytes,
68 TAG,
69 "EnhancedAc3Descriptor",
70 "unexpected tag for EAC-3 descriptor",
71 )?;
72 if body.is_empty() {
73 return Err(Error::InvalidDescriptor {
74 tag: TAG,
75 reason: "descriptor body is empty (length=0)",
76 });
77 }
78 let flags = body[0];
79 let mixinfoexists = (flags & FLAG_MIXINFO_EXISTS) != 0;
80 let mut pos = 1;
81 let mut read_one = |set: bool| -> Result<Option<u8>> {
82 if !set {
83 return Ok(None);
84 }
85 if pos >= body.len() {
86 return Err(Error::InvalidDescriptor {
87 tag: TAG,
88 reason: "enhanced AC-3 descriptor flags claim more bytes than length permits",
89 });
90 }
91 let b = body[pos];
92 pos += 1;
93 Ok(Some(b))
94 };
95
96 let component_type = read_one(flags & FLAG_COMPONENT_TYPE != 0)?;
97 let bsid = read_one(flags & FLAG_BSID != 0)?;
98 let mainid = read_one(flags & FLAG_MAINID != 0)?;
99 let asvc = read_one(flags & FLAG_ASVC != 0)?;
100 let substream1 = read_one(flags & FLAG_SUBSTREAM1 != 0)?;
101 let substream2 = read_one(flags & FLAG_SUBSTREAM2 != 0)?;
102 let substream3 = read_one(flags & FLAG_SUBSTREAM3 != 0)?;
103 let additional_info = &body[pos..];
104 Ok(Self {
105 component_type,
106 bsid,
107 mainid,
108 asvc,
109 mixinfoexists,
110 substream1,
111 substream2,
112 substream3,
113 additional_info,
114 })
115 }
116}
117
118impl Serialize for EnhancedAc3Descriptor<'_> {
119 type Error = crate::error::Error;
120 fn serialized_len(&self) -> usize {
121 HEADER_LEN
122 + 1
123 + usize::from(self.component_type.is_some())
124 + usize::from(self.bsid.is_some())
125 + usize::from(self.mainid.is_some())
126 + usize::from(self.asvc.is_some())
127 + usize::from(self.substream1.is_some())
128 + usize::from(self.substream2.is_some())
129 + usize::from(self.substream3.is_some())
130 + self.additional_info.len()
131 }
132
133 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
134 let len = self.serialized_len();
135 if buf.len() < len {
136 return Err(Error::OutputBufferTooSmall {
137 need: len,
138 have: buf.len(),
139 });
140 }
141 buf[0] = TAG;
142 buf[1] = (len - HEADER_LEN) as u8;
143 let mut flags: u8 = 0;
144 if self.component_type.is_some() {
145 flags |= FLAG_COMPONENT_TYPE;
146 }
147 if self.bsid.is_some() {
148 flags |= FLAG_BSID;
149 }
150 if self.mainid.is_some() {
151 flags |= FLAG_MAINID;
152 }
153 if self.asvc.is_some() {
154 flags |= FLAG_ASVC;
155 }
156 if self.mixinfoexists {
157 flags |= FLAG_MIXINFO_EXISTS;
158 }
159 if self.substream1.is_some() {
160 flags |= FLAG_SUBSTREAM1;
161 }
162 if self.substream2.is_some() {
163 flags |= FLAG_SUBSTREAM2;
164 }
165 if self.substream3.is_some() {
166 flags |= FLAG_SUBSTREAM3;
167 }
168 buf[2] = flags;
169 let mut pos = 3;
170 for b in [
171 self.component_type,
172 self.bsid,
173 self.mainid,
174 self.asvc,
175 self.substream1,
176 self.substream2,
177 self.substream3,
178 ]
179 .into_iter()
180 .flatten()
181 {
182 buf[pos] = b;
183 pos += 1;
184 }
185 buf[pos..pos + self.additional_info.len()].copy_from_slice(self.additional_info);
186 Ok(len)
187 }
188}
189impl<'a> crate::traits::DescriptorDef<'a> for EnhancedAc3Descriptor<'a> {
190 const TAG: u8 = TAG;
191 const NAME: &'static str = "ENHANCED_AC3";
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197 use crate::descriptors::ac3::{Ac3ChannelMode, Ac3ServiceType};
198
199 #[test]
200 fn parse_with_all_fields() {
201 let bytes = [
202 TAG,
203 8,
204 FLAG_COMPONENT_TYPE
205 | FLAG_BSID
206 | FLAG_MAINID
207 | FLAG_ASVC
208 | FLAG_MIXINFO_EXISTS
209 | FLAG_SUBSTREAM1
210 | FLAG_SUBSTREAM2
211 | FLAG_SUBSTREAM3,
212 0x11,
213 0x22,
214 0x33,
215 0x44,
216 0x55,
217 0x66,
218 0x77,
219 ];
220 let d = EnhancedAc3Descriptor::parse(&bytes).unwrap();
221 assert_eq!(d.component_type, Some(0x11));
222 assert_eq!(d.bsid, Some(0x22));
223 assert_eq!(d.mainid, Some(0x33));
224 assert_eq!(d.asvc, Some(0x44));
225 assert!(d.mixinfoexists);
226 assert_eq!(d.substream1, Some(0x55));
227 assert_eq!(d.substream2, Some(0x66));
228 assert_eq!(d.substream3, Some(0x77));
229 assert_eq!(d.additional_info, &[] as &[u8]);
230 }
231
232 #[test]
233 fn parse_with_only_component_type_and_mixinfoexists() {
234 let bytes = [TAG, 2, FLAG_COMPONENT_TYPE | FLAG_MIXINFO_EXISTS, 0x07];
235 let d = EnhancedAc3Descriptor::parse(&bytes).unwrap();
236 assert_eq!(d.component_type, Some(0x07));
237 assert!(d.mixinfoexists);
238 assert_eq!(d.bsid, None);
239 assert_eq!(d.substream1, None);
240 }
241
242 #[test]
243 fn parse_with_additional_info_only() {
244 let bytes = [TAG, 3, 0x00, 0xAA, 0xBB];
245 let d = EnhancedAc3Descriptor::parse(&bytes).unwrap();
246 assert_eq!(d.component_type, None);
247 assert!(!d.mixinfoexists);
248 assert_eq!(d.additional_info, &[0xAA, 0xBB]);
249 }
250
251 #[test]
252 fn decode_component_type_eac3_vi_stereo() {
253 let d = EnhancedAc3Descriptor {
257 component_type: Some(0x92),
258 bsid: None,
259 mainid: None,
260 asvc: None,
261 mixinfoexists: false,
262 substream1: None,
263 substream2: None,
264 substream3: None,
265 additional_info: &[],
266 };
267 let ct = d.decoded_component_type().unwrap();
268 assert!(ct.enhanced_ac3);
269 assert!(!ct.full_service);
270 assert_eq!(ct.service_type, Ac3ServiceType::VisuallyImpaired);
271 assert_eq!(ct.channels, Ac3ChannelMode::Stereo);
272 }
273
274 #[test]
275 fn decode_component_type_full_service_cm_stereo() {
276 let ct = Ac3ComponentType::from_byte(0x42);
279 assert!(!ct.enhanced_ac3);
280 assert!(ct.full_service);
281 assert_eq!(ct.service_type, Ac3ServiceType::CompleteMain);
282 assert_eq!(ct.channels, Ac3ChannelMode::Stereo);
283 }
284
285 #[test]
286 fn parse_rejects_wrong_tag() {
287 assert!(matches!(
288 EnhancedAc3Descriptor::parse(&[0x6A, 1, 0]).unwrap_err(),
289 Error::InvalidDescriptor { tag: 0x6A, .. }
290 ));
291 }
292
293 #[test]
294 fn parse_rejects_flags_past_length() {
295 let bytes = [TAG, 1, FLAG_COMPONENT_TYPE];
296 assert!(matches!(
297 EnhancedAc3Descriptor::parse(&bytes).unwrap_err(),
298 Error::InvalidDescriptor { .. }
299 ));
300 }
301
302 #[test]
303 fn parse_rejects_short_buffer() {
304 assert!(matches!(
305 EnhancedAc3Descriptor::parse(&[TAG]).unwrap_err(),
306 Error::BufferTooShort { .. }
307 ));
308 }
309
310 #[test]
311 fn serialize_round_trip() {
312 let d = EnhancedAc3Descriptor {
313 component_type: Some(0x40),
314 bsid: Some(8),
315 mainid: None,
316 asvc: None,
317 mixinfoexists: true,
318 substream1: Some(0xAA),
319 substream2: None,
320 substream3: None,
321 additional_info: &[0xFE, 0xED],
322 };
323 let mut buf = vec![0u8; d.serialized_len()];
324 d.serialize_into(&mut buf).unwrap();
325 assert_eq!(EnhancedAc3Descriptor::parse(&buf).unwrap(), d);
326 }
327
328 #[test]
329 fn serialize_round_trip_no_flags() {
330 let d = EnhancedAc3Descriptor {
331 component_type: None,
332 bsid: None,
333 mainid: None,
334 asvc: None,
335 mixinfoexists: false,
336 substream1: None,
337 substream2: None,
338 substream3: None,
339 additional_info: &[],
340 };
341 let mut buf = vec![0u8; d.serialized_len()];
342 d.serialize_into(&mut buf).unwrap();
343 assert_eq!(EnhancedAc3Descriptor::parse(&buf).unwrap(), d);
344 assert_eq!(buf, [TAG, 1, 0x00]);
345 }
346
347 #[test]
348 fn parse_rejects_empty_body() {
349 let bytes = [TAG, 0];
350 assert!(matches!(
351 EnhancedAc3Descriptor::parse(&bytes).unwrap_err(),
352 Error::InvalidDescriptor { .. }
353 ));
354 }
355}