Skip to content

Commit e1ec2f3

Browse files
committed
mp4a: Support DecoderSpecificDescriptor profiles > 30
Adds support for reading and writing AAC audio specific info when profile (object type) is larger than 30.
1 parent 32674a6 commit e1ec2f3

File tree

1 file changed

+60
-5
lines changed

1 file changed

+60
-5
lines changed

src/mp4box/mp4a.rs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -507,14 +507,18 @@ impl Descriptor for DecoderSpecificDescriptor {
507507
}
508508

509509
fn desc_size(&self) -> u32 {
510-
2
510+
if self.profile < 31 {
511+
2
512+
} else {
513+
3
514+
}
511515
}
512516
}
513517

514518
fn get_audio_object_type(byte_a: u8, byte_b: u8) -> u8 {
515519
let mut profile = byte_a >> 3;
516520
if profile == 31 {
517-
profile = 32 + ((byte_a & 7) | (byte_b >> 5));
521+
profile = 32 + ((byte_a & 7) << 3 | (byte_b >> 5));
518522
}
519523

520524
profile
@@ -533,7 +537,7 @@ fn get_chan_conf<R: Read + Seek>(
533537
chan_conf = ((sample_rate >> 4) & 0x0F) as u8;
534538
} else if extended_profile {
535539
let byte_c = reader.read_u8()?;
536-
chan_conf = (byte_b & 1) | (byte_c & 0xE0);
540+
chan_conf = (byte_b & 1) << 3 | (byte_c >> 5);
537541
} else {
538542
chan_conf = (byte_b >> 3) & 0x0F;
539543
}
@@ -569,8 +573,15 @@ impl<W: Write> WriteDesc<&mut W> for DecoderSpecificDescriptor {
569573
let size = self.desc_size();
570574
write_desc(writer, Self::desc_tag(), size)?;
571575

572-
writer.write_u8((self.profile << 3) + (self.freq_index >> 1))?;
573-
writer.write_u8((self.freq_index << 7) + (self.chan_conf << 3))?;
576+
if self.profile < 31 {
577+
writer.write_u8((self.profile << 3) | (self.freq_index >> 1))?;
578+
writer.write_u8((self.freq_index << 7) | (self.chan_conf << 3))?;
579+
} else {
580+
let profile_minus_32 = self.profile - 32;
581+
writer.write_u8(31u8 << 3 | profile_minus_32 >> 3)?;
582+
writer.write_u8(profile_minus_32 << 5 | self.freq_index << 1 | self.chan_conf >> 7)?;
583+
writer.write_u8((self.chan_conf & 7) << 5)?;
584+
}
574585

575586
Ok(size)
576587
}
@@ -682,4 +693,48 @@ mod tests {
682693
let dst_box = Mp4aBox::read_box(&mut reader, header.size).unwrap();
683694
assert_eq!(src_box, dst_box);
684695
}
696+
697+
#[test]
698+
fn test_decoder_specific_descriptor() {
699+
let test_dec_spec = |src_dec_spec: DecoderSpecificDescriptor| {
700+
let mut buf = Vec::new();
701+
let written = src_dec_spec.write_desc(&mut buf).unwrap();
702+
// expect two extra bytes for the tag and size fields
703+
assert_eq!(buf.len(), written as usize + 2);
704+
705+
let mut reader = Cursor::new(&buf);
706+
let (tag, size) = read_desc(&mut reader).unwrap();
707+
assert_eq!(5, tag);
708+
assert_eq!(size, written);
709+
710+
let dst_dec_spec = DecoderSpecificDescriptor::read_desc(&mut reader, written).unwrap();
711+
assert_eq!(src_dec_spec, dst_dec_spec);
712+
};
713+
714+
test_dec_spec(DecoderSpecificDescriptor {
715+
profile: 2, // LC
716+
freq_index: 4, // 44100
717+
chan_conf: 2, // Stereo
718+
});
719+
test_dec_spec(DecoderSpecificDescriptor {
720+
profile: 5, // SpectralBandReplication (HEv1)
721+
freq_index: 3, // 48000
722+
chan_conf: 1, // Mono
723+
});
724+
test_dec_spec(DecoderSpecificDescriptor {
725+
profile: 29, // ParametricStereo (HEv2)
726+
freq_index: 2, // 64000
727+
chan_conf: 7, // SevenOne
728+
});
729+
test_dec_spec(DecoderSpecificDescriptor {
730+
profile: 34, // MpegLayer3 (xHE)
731+
freq_index: 4, // 44100
732+
chan_conf: 2, // Stereo
733+
});
734+
test_dec_spec(DecoderSpecificDescriptor {
735+
profile: 42, // UnifiedSpeechAudioCoding (xHE)
736+
freq_index: 11, // 8000
737+
chan_conf: 6, // FiveOne
738+
});
739+
}
685740
}

0 commit comments

Comments
 (0)