aboutsummaryrefslogtreecommitdiffstats
path: root/nihav-mpeg/src/codecs/aac
diff options
context:
space:
mode:
authorKostya Shishkov <kostya.shishkov@gmail.com>2022-07-04 18:23:34 +0200
committerKostya Shishkov <kostya.shishkov@gmail.com>2022-07-04 18:23:34 +0200
commit9c3cd867ce7645f6f828675bd5d383033d6263f7 (patch)
treea3daea3e43f23a3178f7bc72be7c1212eca0f974 /nihav-mpeg/src/codecs/aac
parent03d914bb5e76c7e83cf98a501238472732bf11c8 (diff)
downloadnihav-9c3cd867ce7645f6f828675bd5d383033d6263f7.tar.gz
aac: support Program Config Element a bit
Diffstat (limited to 'nihav-mpeg/src/codecs/aac')
-rw-r--r--nihav-mpeg/src/codecs/aac/info.rs61
-rw-r--r--nihav-mpeg/src/codecs/aac/mod.rs2
2 files changed, 61 insertions, 2 deletions
diff --git a/nihav-mpeg/src/codecs/aac/info.rs b/nihav-mpeg/src/codecs/aac/info.rs
index e6e021b..648b356 100644
--- a/nihav-mpeg/src/codecs/aac/info.rs
+++ b/nihav-mpeg/src/codecs/aac/info.rs
@@ -168,7 +168,11 @@ impl M4AInfo {
}
let extension_flag = br.read_bool()?;
if self.channels == 0 {
- unimplemented!("program config element");
+ let (channels, sf_code) = skimp_through_program_config_element(&mut br)?;
+ validate!(channels > 0);
+ self.channels = channels;
+ validate!(AAC_SAMPLE_RATES[sf_code] != 0);
+ self.srate = AAC_SAMPLE_RATES[sf_code];
}
if (self.otype == M4AType::Scalable) || (self.otype == M4AType::ER_AAC_Scalable) {
let _layer = br.read(3)?;
@@ -260,6 +264,61 @@ impl M4AInfo {
}
}
+pub fn skimp_through_program_config_element(br: &mut BitReader) -> DecoderResult<(usize, usize)> {
+ let _id = br.read(4)?;
+ let _object_type = br.read(2)?;
+ let sampling_frequency_index = br.read(4)? as usize;
+ let num_front_channel_elements = br.read(4)? as usize;
+ let num_side_channel_elements = br.read(4)? as usize;
+ let num_back_channel_elements = br.read(4)? as usize;
+ let num_lfe_channel_elements = br.read(2)? as usize;
+ let num_assoc_data_elements = br.read(3)? as usize;
+ let num_valid_cc_elements = br.read(4)? as usize;
+ let mono_mixdown_present = br.read_bool()?;
+ if mono_mixdown_present {
+ let _mono_mixdown_element_number = br.read(4)?;
+ }
+ let stereo_mixdown_present = br.read_bool()?;
+ if stereo_mixdown_present {
+ let _stereo_mixdown_element_number = br.read(4)?;
+ }
+ let matrix_mixdown_idx_present = br.read_bool()?;
+ if matrix_mixdown_idx_present {
+ let _matrix_mixdown_idx = br.read(2)?;
+ let _pseudo_surround_enable = br.read_bool()?;
+ }
+ for _i in 0..num_front_channel_elements {
+ let _front_element_is_cpe = br.read_bool()?;
+ let _front_element_tag_select = br.read(4)?;
+ }
+ for _i in 0..num_side_channel_elements {
+ let _side_element_is_cpe = br.read_bool()?;
+ let _side_element_tag_select = br.read(4)?;
+ }
+ for _i in 0..num_back_channel_elements {
+ let _back_element_is_cpe = br.read_bool()?;
+ let _back_element_tag_select = br.read(4)?;
+ }
+ for _i in 0..num_lfe_channel_elements {
+ let _lfe_element_tag_select = br.read(4)?;
+ }
+ for _i in 0..num_assoc_data_elements {
+ let _assoc_data_element_tag_select = br.read(4)?;
+ }
+ for _i in 0..num_valid_cc_elements {
+ let _cc_element_is_ind_sw = br.read_bool()?;
+ let _valid_cc_element_tag_select = br.read(4)?;
+ }
+ br.align();
+ let comment_field_bytes = br.read(8)?;
+ br.skip(comment_field_bytes * 8)?;
+
+ Ok((num_front_channel_elements +
+ num_side_channel_elements +
+ num_back_channel_elements +
+ num_lfe_channel_elements, sampling_frequency_index))
+}
+
impl fmt::Display for M4AInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MPEG 4 Audio {}, {} Hz, {} channels, {} samples per frame",
diff --git a/nihav-mpeg/src/codecs/aac/mod.rs b/nihav-mpeg/src/codecs/aac/mod.rs
index 795464b..de9fbe5 100644
--- a/nihav-mpeg/src/codecs/aac/mod.rs
+++ b/nihav-mpeg/src/codecs/aac/mod.rs
@@ -570,7 +570,7 @@ impl AACDecoder {
br.skip(count * 8)?; // no SBR payload or such
},
5 => { // ID_PCE
- unimplemented!("program config");
+ skimp_through_program_config_element(br)?;
},
6 => { // ID_FIL
let mut count = br.read(4)? as usize;