Skip to content

Commit

Permalink
Merge pull request #55 from alfredoyang/check_decoder_config
Browse files Browse the repository at this point in the history
parse program_config_element for channel counts
  • Loading branch information
rillian authored Jan 9, 2017
2 parents 067280b + a18a06e commit d0700aa
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 2 deletions.
2 changes: 1 addition & 1 deletion mp4parse/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ byteorder = "1.0.0"
afl = { version = "0.1.1", optional = true }
afl-plugin = { version = "0.1.1", optional = true }
abort_on_panic = { version = "1.0.0", optional = true }
bitreader = { version = "0.1.0" }
bitreader = { version = "0.2.0" }

[dev-dependencies]
test-assembler = "0.1.2"
Expand Down
57 changes: 56 additions & 1 deletion mp4parse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,52 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
},
};

let channel_counts: u16 = ReadInto::read(bit_reader, 4)?;
let mut channel_counts: u16 = ReadInto::read(bit_reader, 4)?;

// parsing GASpecificConfig
bit_reader.skip(1)?; // frameLengthFlag
let depend_on_core_order: u8 = ReadInto::read(bit_reader, 1)?;
if depend_on_core_order > 0 {
bit_reader.skip(14)?; // codeCoderDelay
}
bit_reader.skip(1)?; // extensionFlag

// When channel_counts is 0, we need to parse the program_config_element
// to calculate the channel counts.
if channel_counts == 0 {
log!("Parsing program_config_element for channel counts");

bit_reader.skip(4)?; // element_instance_tag
bit_reader.skip(2)?; // object_type
bit_reader.skip(4)?; // sampling_frequency_index
let num_front_channel: u8 = ReadInto::read(bit_reader, 4)?;
let num_side_channel: u8 = ReadInto::read(bit_reader, 4)?;
let num_back_channel:u8 = ReadInto::read(bit_reader, 4)?;
let num_lfe_channel: u8 = ReadInto::read(bit_reader, 2)?;
bit_reader.skip(3)?; // num_assoc_data
bit_reader.skip(4)?; // num_valid_cc

let mono_mixdown_present: bool = ReadInto::read(bit_reader, 1)?;
if mono_mixdown_present {
bit_reader.skip(4)?; // mono_mixdown_element_number
}

let stereo_mixdown_present: bool = ReadInto::read(bit_reader, 1)?;
if stereo_mixdown_present {
bit_reader.skip(4)?; // stereo_mixdown_element_number
}

let matrix_mixdown_idx_present: bool = ReadInto::read(bit_reader, 1)?;
if matrix_mixdown_idx_present {
bit_reader.skip(2)?; // matrix_mixdown_idx
bit_reader.skip(1)?; // pseudo_surround_enable
}

channel_counts += read_surround_channel_count(bit_reader, num_front_channel)?;
channel_counts += read_surround_channel_count(bit_reader, num_side_channel)?;
channel_counts += read_surround_channel_count(bit_reader, num_back_channel)?;
channel_counts += read_surround_channel_count(bit_reader, num_lfe_channel)?;
}

esds.audio_object_type = Some(audio_object_type);
esds.audio_sample_rate = sample_frequency;
Expand All @@ -1295,6 +1340,16 @@ fn read_ds_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
Ok(())
}

fn read_surround_channel_count(bit_reader: &mut BitReader, channels: u8) -> Result<u16> {
let mut count = 0;
for _ in 0..channels {
let is_cpe: bool = ReadInto::read(bit_reader, 1)?;
count += if is_cpe { 2 } else { 1 };
bit_reader.skip(4)?;
}
Ok(count)
}

fn read_dc_descriptor(data: &[u8], esds: &mut ES_Descriptor) -> Result<()> {
let des = &mut Cursor::new(data);
let object_profile = des.read_u8()?;
Expand Down
26 changes: 26 additions & 0 deletions mp4parse/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -858,3 +858,29 @@ fn read_qt_wave_atom() {
.expect("fail to read qt wave atom");
assert_eq!(track.codec_type, super::CodecType::MP3);
}

#[test]
fn read_esds() {
let aac_esds =
vec![
0x03, 0x24, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x40,
0x15, 0x00, 0x12, 0x00, 0x00, 0x01, 0xf4, 0x00,
0x00, 0x01, 0xf4, 0x00, 0x05, 0x0d, 0x13, 0x00,
0x05, 0x88, 0x05, 0x00, 0x48, 0x21, 0x10, 0x00,
0x56, 0xe5, 0x98, 0x06, 0x01, 0x02,
];
let mut stream = make_box(BoxSize::Auto, b"esds", |s| {
s.B32(0) // reserved
.append_bytes(aac_esds.as_slice())
});
let mut iter = super::BoxIter::new(&mut stream);
let mut stream = iter.next_box().unwrap().unwrap();

let es = super::read_esds(&mut stream).unwrap();

assert_eq!(es.audio_codec, super::CodecType::AAC);
assert_eq!(es.audio_object_type, Some(2));
assert_eq!(es.audio_sample_rate, Some(24000));
assert_eq!(es.audio_channel_count, Some(6));
assert_eq!(es.codec_esds, aac_esds);
}

0 comments on commit d0700aa

Please sign in to comment.