MP4: Read the Audio Specific Config's channel config

This commit is contained in:
Serial 2022-03-25 20:27:50 -04:00
parent a4f901368e
commit 559b5a4e34
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
2 changed files with 32 additions and 8 deletions

View file

@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **ID3v2**: `FrameValue::Popularimeter`
### Changed
- **MP4**: Sample rates are now retrieved from the [audio specific config](https://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config) (if possible).
- **MP4**: Sample rates and channels are now retrieved from the [audio specific config](https://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config) (if possible).
If the information is invalid or unavailable, the existing value from the `mp4a` box will be used instead.
- **Vorbis Comments**: Support non-PNG/JPEG images in `PictureInformation::from_picture`
- The method still only supports PNG and JPEG, but rather than error when it encounters an unknown image, it will return

View file

@ -435,11 +435,12 @@ where
// if (frequency index == 15)
// 24 bits: frequency
// 4 bits: channel configuration
// TODO: Channels
let byte_a = stsd.read_u8()?;
let byte_b = stsd.read_u8()?;
let mut object_type = byte_a >> 3;
let mut frequency_index = (byte_a << 5) | (byte_b >> 7);
let mut frequency_index = ((byte_a & 0x07) << 1) | (byte_b >> 7);
let mut channel_conf = (byte_b >> 3) & 0x0F;
let mut extended_object_type = false;
if object_type == 31 {
@ -455,21 +456,44 @@ where
match frequency_index {
// 15 means the sample rate is stored in the next 24 bits
0x0F => {
let sample_rate;
let explicit_sample_rate = stsd.read_u24::<BigEndian>()?;
if extended_object_type {
let remaining_sample_rate = stsd.read_u24::<BigEndian>()?;
properties.sample_rate =
(remaining_sample_rate >> 1) | u32::from(byte_b & 1);
sample_rate = explicit_sample_rate >> 1;
channel_conf = ((explicit_sample_rate >> 4) & 0x0F) as u8;
} else {
properties.sample_rate = stsd.read_uint::<BigEndian>(3)? as u32
sample_rate = explicit_sample_rate << 1;
let byte_c = stsd.read_u8()?;
channel_conf = ((explicit_sample_rate & 0x80) as u8
| (byte_c >> 1)) & 0x0F;
}
// Just use the sample rate we already read above if this is invalid
if sample_rate > 0 {
properties.sample_rate = sample_rate;
}
},
i if i < SAMPLE_RATES.len() as u8 => {
properties.sample_rate = SAMPLE_RATES[i as usize]
properties.sample_rate = SAMPLE_RATES[i as usize];
if extended_object_type {
let byte_c = stsd.read_u8()?;
channel_conf = (byte_b & 1) | (byte_c & 0xE0);
} else {
channel_conf = (byte_b >> 3) & 0x0F;
}
},
// Keep the sample rate we read above
_ => {},
}
// The channel configuration isn't always set, at least when testing with
// the Audio Lossless Coding reference software
if channel_conf > 0 {
properties.channels = channel_conf;
}
// We just check for ALS here, might extend it for more codes eventually
if object_type == 36 {
let mut ident = [0; 5];