Skip to main content

dvb_si/descriptors/
mpeg2_aac_audio.rs

1//! MPEG-2 AAC Audio Descriptor — ISO/IEC 13818-1 §2.6.68 (tag 0x2B).
2//!
3//! Identifies the profile, channel configuration, and additional
4//! information for an MPEG-2 AAC audio elementary stream.
5
6use super::aac_additional_info::AacAdditionalInfo;
7use super::descriptor_body;
8use crate::error::{Error, Result};
9use dvb_common::{Parse, Serialize};
10
11/// Descriptor tag for MPEG-2_AAC_audio_descriptor.
12pub const TAG: u8 = 0x2B;
13const HEADER_LEN: usize = 2;
14const BODY_LEN: u8 = 3;
15
16/// MPEG-2 AAC Audio Descriptor.
17#[derive(Debug, Clone, PartialEq, Eq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize))]
19#[cfg_attr(feature = "yoke", derive(yoke::Yokeable))]
20pub struct Mpeg2AacAudioDescriptor {
21    /// MPEG-2 AAC profile.
22    pub mpeg_2_aac_profile: u8,
23    /// MPEG-2 AAC channel configuration.
24    pub mpeg_2_aac_channel_configuration: u8,
25    /// MPEG-2 AAC additional information (Table 2-95).
26    pub mpeg_2_aac_additional_information: AacAdditionalInfo,
27}
28
29impl<'a> Parse<'a> for Mpeg2AacAudioDescriptor {
30    type Error = crate::error::Error;
31
32    fn parse(bytes: &'a [u8]) -> Result<Self> {
33        let body = descriptor_body(
34            bytes,
35            TAG,
36            "Mpeg2AacAudioDescriptor",
37            "unexpected tag for MPEG-2_AAC_audio_descriptor",
38        )?;
39        if body.len() < (BODY_LEN as usize) {
40            return Err(Error::InvalidDescriptor {
41                tag: TAG,
42                reason: "MPEG-2_AAC_audio_descriptor too short",
43            });
44        }
45        Ok(Self {
46            mpeg_2_aac_profile: body[0],
47            mpeg_2_aac_channel_configuration: body[1],
48            mpeg_2_aac_additional_information: AacAdditionalInfo::from_u8(body[2]),
49        })
50    }
51}
52
53impl Serialize for Mpeg2AacAudioDescriptor {
54    type Error = crate::error::Error;
55
56    fn serialized_len(&self) -> usize {
57        HEADER_LEN + (BODY_LEN as usize)
58    }
59
60    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
61        let len = self.serialized_len();
62        if buf.len() < len {
63            return Err(Error::OutputBufferTooSmall {
64                need: len,
65                have: buf.len(),
66            });
67        }
68        buf[0] = TAG;
69        buf[1] = BODY_LEN;
70        buf[HEADER_LEN] = self.mpeg_2_aac_profile;
71        buf[HEADER_LEN + 1] = self.mpeg_2_aac_channel_configuration;
72        buf[HEADER_LEN + 2] = self.mpeg_2_aac_additional_information.to_u8();
73        Ok(len)
74    }
75}
76
77impl<'a> crate::traits::DescriptorDef<'a> for Mpeg2AacAudioDescriptor {
78    const TAG: u8 = TAG;
79    const NAME: &'static str = "MPEG2_AAC_AUDIO";
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn round_trip() {
88        let orig = Mpeg2AacAudioDescriptor {
89            mpeg_2_aac_profile: 0x01,
90            mpeg_2_aac_channel_configuration: 0x02,
91            mpeg_2_aac_additional_information: AacAdditionalInfo::AacWithBandwidthExtension,
92        };
93        let mut buf = vec![0u8; orig.serialized_len()];
94        orig.serialize_into(&mut buf).unwrap();
95        let reparsed = Mpeg2AacAudioDescriptor::parse(&buf).unwrap();
96        assert_eq!(orig, reparsed);
97    }
98
99    #[test]
100    fn round_trip_reserved() {
101        let orig = Mpeg2AacAudioDescriptor {
102            mpeg_2_aac_profile: 0xAA,
103            mpeg_2_aac_channel_configuration: 0xBB,
104            mpeg_2_aac_additional_information: AacAdditionalInfo::Reserved(0xFE),
105        };
106        let mut buf = vec![0u8; orig.serialized_len()];
107        orig.serialize_into(&mut buf).unwrap();
108        let reparsed = Mpeg2AacAudioDescriptor::parse(&buf).unwrap();
109        assert_eq!(orig, reparsed);
110    }
111
112    #[test]
113    fn parse_rejects_wrong_tag() {
114        let err = Mpeg2AacAudioDescriptor::parse(&[0x02, 3, 0x00, 0x00, 0x00]).unwrap_err();
115        assert!(matches!(err, Error::InvalidDescriptor { tag: 0x02, .. }));
116    }
117
118    #[test]
119    fn parse_rejects_too_short() {
120        // present-but-short body (1 byte < BODY_LEN=3) → descriptor's own check.
121        let err = Mpeg2AacAudioDescriptor::parse(&[TAG, 1, 0x00]).unwrap_err();
122        assert!(matches!(err, Error::InvalidDescriptor { tag: TAG, .. }));
123    }
124}