mirror of
https://github.com/alfg/mp4-rust.git
synced 2024-12-22 12:06:33 +00:00
Support profiles > 31 in DecoderSpecificDescriptor
(#69)
This commit is contained in:
parent
49f9ed0432
commit
12ba304023
3 changed files with 68 additions and 14 deletions
|
@ -53,11 +53,11 @@ impl Mp4aBox {
|
||||||
|
|
||||||
impl Mp4Box for Mp4aBox {
|
impl Mp4Box for Mp4aBox {
|
||||||
fn box_type(&self) -> BoxType {
|
fn box_type(&self) -> BoxType {
|
||||||
return self.get_type();
|
self.get_type()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn box_size(&self) -> u64 {
|
fn box_size(&self) -> u64 {
|
||||||
return self.get_size();
|
self.get_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_json(&self) -> Result<String> {
|
fn to_json(&self) -> Result<String> {
|
||||||
|
@ -159,8 +159,7 @@ impl Mp4Box for EsdsBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn summary(&self) -> Result<String> {
|
fn summary(&self) -> Result<String> {
|
||||||
let s = format!("");
|
Ok(String::new())
|
||||||
Ok(s)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,13 +470,45 @@ impl Descriptor for DecoderSpecificDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_chan_conf<R: Read + Seek>(reader: &mut R, byte_b: u8, freq_index: u8, extended_profile: bool) -> Result<u8> {
|
||||||
|
let chan_conf;
|
||||||
|
if freq_index == 15 {
|
||||||
|
// Skip the 24 bit sample rate
|
||||||
|
let sample_rate = reader.read_u24::<BigEndian>()?;
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
chan_conf = (byte_b >> 3) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(chan_conf)
|
||||||
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> ReadDesc<&mut R> for DecoderSpecificDescriptor {
|
impl<R: Read + Seek> ReadDesc<&mut R> for DecoderSpecificDescriptor {
|
||||||
fn read_desc(reader: &mut R, _size: u32) -> Result<Self> {
|
fn read_desc(reader: &mut R, _size: u32) -> Result<Self> {
|
||||||
let byte_a = reader.read_u8()?;
|
let byte_a = reader.read_u8()?;
|
||||||
let byte_b = reader.read_u8()?;
|
let byte_b = reader.read_u8()?;
|
||||||
let profile = byte_a >> 3;
|
let profile = get_audio_object_type(byte_a, byte_b);
|
||||||
let freq_index = ((byte_a & 0x07) << 1) + (byte_b >> 7);
|
let freq_index;
|
||||||
let chan_conf = (byte_b >> 3) & 0x0F;
|
let chan_conf;
|
||||||
|
if profile > 31 {
|
||||||
|
freq_index = (byte_b >> 1) & 0x0F;
|
||||||
|
chan_conf = get_chan_conf(reader, byte_b, freq_index, true)?;
|
||||||
|
} else {
|
||||||
|
freq_index = ((byte_a & 0x07) << 1) + (byte_b >> 7);
|
||||||
|
chan_conf = get_chan_conf(reader, byte_b, freq_index, false)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(DecoderSpecificDescriptor {
|
Ok(DecoderSpecificDescriptor {
|
||||||
profile,
|
profile,
|
||||||
|
|
37
tests/lib.rs
37
tests/lib.rs
|
@ -1,16 +1,11 @@
|
||||||
use mp4::{AudioObjectType, AvcProfile, ChannelConfig, MediaType, SampleFreqIndex, TrackType};
|
use mp4::{AudioObjectType, AvcProfile, ChannelConfig, MediaType, Mp4Reader, SampleFreqIndex, TrackType};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_read_mp4() {
|
fn test_read_mp4() {
|
||||||
let filename = "tests/samples/minimal.mp4";
|
let mut mp4 = get_reader("tests/samples/minimal.mp4");
|
||||||
let f = File::open(filename).unwrap();
|
|
||||||
let size = f.metadata().unwrap().len();
|
|
||||||
let reader = BufReader::new(f);
|
|
||||||
|
|
||||||
let mut mp4 = mp4::Mp4Reader::read_header(reader, size).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(2591, mp4.size());
|
assert_eq!(2591, mp4.size());
|
||||||
|
|
||||||
|
@ -119,3 +114,31 @@ fn test_read_mp4() {
|
||||||
assert_eq!(track2.channel_config().unwrap(), ChannelConfig::Mono);
|
assert_eq!(track2.channel_config().unwrap(), ChannelConfig::Mono);
|
||||||
assert_eq!(track2.bitrate(), 67695);
|
assert_eq!(track2.bitrate(), 67695);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_read_extended_audio_object_type() {
|
||||||
|
// Extended audio object type and sample rate index of 15
|
||||||
|
let mp4 = get_reader("tests/samples/extended_audio_object_type.mp4");
|
||||||
|
|
||||||
|
let track = mp4.tracks().get(&1).unwrap();
|
||||||
|
assert_eq!(track.track_type().unwrap(), TrackType::Audio);
|
||||||
|
assert_eq!(track.media_type().unwrap(), MediaType::AAC);
|
||||||
|
assert_eq!(
|
||||||
|
track.audio_profile().unwrap(),
|
||||||
|
AudioObjectType::AudioLosslessCoding
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
track.trak.mdia.minf.stbl.stsd.mp4a.as_ref().unwrap().esds.as_ref().unwrap().es_desc.dec_config.dec_specific.freq_index,
|
||||||
|
15
|
||||||
|
);
|
||||||
|
assert_eq!(track.channel_config().unwrap(), ChannelConfig::Stereo);
|
||||||
|
assert_eq!(track.bitrate(), 839250);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_reader(path: &str) -> Mp4Reader<BufReader<File>> {
|
||||||
|
let f = File::open(path).unwrap();
|
||||||
|
let f_size = f.metadata().unwrap().len();
|
||||||
|
let reader = BufReader::new(f);
|
||||||
|
|
||||||
|
mp4::Mp4Reader::read_header(reader, f_size).unwrap()
|
||||||
|
}
|
BIN
tests/samples/extended_audio_object_type.mp4
Normal file
BIN
tests/samples/extended_audio_object_type.mp4
Normal file
Binary file not shown.
Loading…
Reference in a new issue