From 32674a6855259e35413a77a3ce33e15a815effca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Zeb=C3=BChr?= Date: Tue, 17 Oct 2023 14:31:08 +0700 Subject: [PATCH 1/2] mp4a: Make Descriptor::desc_size non-static Descriptions may require different amount of bytes to serialize depending on content of fields. In preparation of supporing reading and writing DecoderSpecificDescriptor::profiles (audio object type) values larger than 30. --- src/mp4box/mp4a.rs | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/mp4box/mp4a.rs b/src/mp4box/mp4a.rs index a80c6c4..3bb5a00 100644 --- a/src/mp4box/mp4a.rs +++ b/src/mp4box/mp4a.rs @@ -181,11 +181,12 @@ impl Mp4Box for EsdsBox { } fn box_size(&self) -> u64 { + let es_desc_size = self.es_desc.desc_size(); HEADER_SIZE + HEADER_EXT_SIZE + 1 - + size_of_length(ESDescriptor::desc_size()) as u64 - + ESDescriptor::desc_size() as u64 + + size_of_length(es_desc_size) as u64 + + es_desc_size as u64 } fn to_json(&self) -> Result { @@ -247,7 +248,7 @@ impl WriteBox<&mut W> for EsdsBox { trait Descriptor: Sized { fn desc_tag() -> u8; - fn desc_size() -> u32; + fn desc_size(&self) -> u32; } trait ReadDesc: Sized { @@ -325,13 +326,15 @@ impl Descriptor for ESDescriptor { 0x03 } - fn desc_size() -> u32 { + fn desc_size(&self) -> u32 { + let dec_config_size = self.dec_config.desc_size(); + let sl_config_size = self.sl_config.desc_size(); 3 + 1 - + size_of_length(DecoderConfigDescriptor::desc_size()) - + DecoderConfigDescriptor::desc_size() + + size_of_length(dec_config_size) + + dec_config_size + 1 - + size_of_length(SLConfigDescriptor::desc_size()) - + SLConfigDescriptor::desc_size() + + size_of_length(sl_config_size) + + sl_config_size } } @@ -373,7 +376,7 @@ impl ReadDesc<&mut R> for ESDescriptor { impl WriteDesc<&mut W> for ESDescriptor { fn write_desc(&self, writer: &mut W) -> Result { - let size = Self::desc_size(); + let size = self.desc_size(); write_desc(writer, Self::desc_tag(), size)?; writer.write_u16::(self.es_id)?; @@ -417,10 +420,9 @@ impl Descriptor for DecoderConfigDescriptor { 0x04 } - fn desc_size() -> u32 { - 13 + 1 - + size_of_length(DecoderSpecificDescriptor::desc_size()) - + DecoderSpecificDescriptor::desc_size() + fn desc_size(&self) -> u32 { + let dec_specific_size = self.dec_specific.desc_size(); + 13 + 1 + size_of_length(dec_specific_size) + dec_specific_size } } @@ -467,7 +469,7 @@ impl ReadDesc<&mut R> for DecoderConfigDescriptor { impl WriteDesc<&mut W> for DecoderConfigDescriptor { fn write_desc(&self, writer: &mut W) -> Result { - let size = Self::desc_size(); + let size = self.desc_size(); write_desc(writer, Self::desc_tag(), size)?; writer.write_u8(self.object_type_indication)?; @@ -504,7 +506,7 @@ impl Descriptor for DecoderSpecificDescriptor { 0x05 } - fn desc_size() -> u32 { + fn desc_size(&self) -> u32 { 2 } } @@ -564,7 +566,7 @@ impl ReadDesc<&mut R> for DecoderSpecificDescriptor { impl WriteDesc<&mut W> for DecoderSpecificDescriptor { fn write_desc(&self, writer: &mut W) -> Result { - let size = Self::desc_size(); + let size = self.desc_size(); write_desc(writer, Self::desc_tag(), size)?; writer.write_u8((self.profile << 3) + (self.freq_index >> 1))?; @@ -588,7 +590,7 @@ impl Descriptor for SLConfigDescriptor { 0x06 } - fn desc_size() -> u32 { + fn desc_size(&self) -> u32 { 1 } } @@ -603,7 +605,7 @@ impl ReadDesc<&mut R> for SLConfigDescriptor { impl WriteDesc<&mut W> for SLConfigDescriptor { fn write_desc(&self, writer: &mut W) -> Result { - let size = Self::desc_size(); + let size = self.desc_size(); write_desc(writer, Self::desc_tag(), size)?; writer.write_u8(2)?; // pre-defined From 0a3973b8278c5c58ac5758979f36c75b79fdaba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Zeb=C3=BChr?= Date: Tue, 17 Oct 2023 14:44:16 +0700 Subject: [PATCH 2/2] mp4a: Support DecoderSpecificDescriptor profiles > 30 Adds support for reading and writing AAC audio specific info when profile (object type) is larger than 30. --- src/mp4box/mp4a.rs | 65 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/src/mp4box/mp4a.rs b/src/mp4box/mp4a.rs index 3bb5a00..f83573b 100644 --- a/src/mp4box/mp4a.rs +++ b/src/mp4box/mp4a.rs @@ -507,14 +507,18 @@ impl Descriptor for DecoderSpecificDescriptor { } fn desc_size(&self) -> u32 { - 2 + if self.profile < 31 { + 2 + } else { + 3 + } } } fn get_audio_object_type(byte_a: u8, byte_b: u8) -> u8 { let mut profile = byte_a >> 3; if profile == 31 { - profile = 32 + ((byte_a & 7) | (byte_b >> 5)); + profile = 32 + ((byte_a & 7) << 3 | (byte_b >> 5)); } profile @@ -533,7 +537,7 @@ fn get_chan_conf( chan_conf = ((sample_rate >> 4) & 0x0F) as u8; } else if extended_profile { let byte_c = reader.read_u8()?; - chan_conf = (byte_b & 1) | (byte_c & 0xE0); + chan_conf = (byte_b & 1) << 3 | (byte_c >> 5); } else { chan_conf = (byte_b >> 3) & 0x0F; } @@ -569,8 +573,15 @@ impl WriteDesc<&mut W> for DecoderSpecificDescriptor { let size = self.desc_size(); write_desc(writer, Self::desc_tag(), size)?; - writer.write_u8((self.profile << 3) + (self.freq_index >> 1))?; - writer.write_u8((self.freq_index << 7) + (self.chan_conf << 3))?; + if self.profile < 31 { + writer.write_u8((self.profile << 3) | (self.freq_index >> 1))?; + writer.write_u8((self.freq_index << 7) | (self.chan_conf << 3))?; + } else { + let profile_minus_32 = self.profile - 32; + writer.write_u8(31u8 << 3 | profile_minus_32 >> 3)?; + writer.write_u8(profile_minus_32 << 5 | self.freq_index << 1 | self.chan_conf >> 7)?; + writer.write_u8((self.chan_conf & 7) << 5)?; + } Ok(size) } @@ -682,4 +693,48 @@ mod tests { let dst_box = Mp4aBox::read_box(&mut reader, header.size).unwrap(); assert_eq!(src_box, dst_box); } + + #[test] + fn test_decoder_specific_descriptor() { + let test_dec_spec = |src_dec_spec: DecoderSpecificDescriptor| { + let mut buf = Vec::new(); + let written = src_dec_spec.write_desc(&mut buf).unwrap(); + // expect two extra bytes for the tag and size fields + assert_eq!(buf.len(), written as usize + 2); + + let mut reader = Cursor::new(&buf); + let (tag, size) = read_desc(&mut reader).unwrap(); + assert_eq!(5, tag); + assert_eq!(size, written); + + let dst_dec_spec = DecoderSpecificDescriptor::read_desc(&mut reader, written).unwrap(); + assert_eq!(src_dec_spec, dst_dec_spec); + }; + + test_dec_spec(DecoderSpecificDescriptor { + profile: 2, // LC + freq_index: 4, // 44100 + chan_conf: 2, // Stereo + }); + test_dec_spec(DecoderSpecificDescriptor { + profile: 5, // SpectralBandReplication (HEv1) + freq_index: 3, // 48000 + chan_conf: 1, // Mono + }); + test_dec_spec(DecoderSpecificDescriptor { + profile: 29, // ParametricStereo (HEv2) + freq_index: 2, // 64000 + chan_conf: 7, // SevenOne + }); + test_dec_spec(DecoderSpecificDescriptor { + profile: 34, // MpegLayer3 + freq_index: 4, // 44100 + chan_conf: 2, // Stereo + }); + test_dec_spec(DecoderSpecificDescriptor { + profile: 42, // UnifiedSpeechAudioCoding (xHE) + freq_index: 11, // 8000 + chan_conf: 6, // FiveOne + }); + } }