Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set optional EsdsBox in Mp4aBox. #23

Merged
merged 2 commits into from
Aug 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 44 additions & 16 deletions examples/mp4info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::Path;

use mp4::{Mp4Track, Result, TrackType};
use mp4::{Mp4Track, Result, TrackType, Error};

fn main() {
let args: Vec<String> = env::args().collect();
Expand All @@ -26,17 +26,23 @@ fn info<P: AsRef<Path>>(filename: &P) -> Result<()> {

let mp4 = mp4::Mp4Reader::read_header(reader, size)?;

println!("Metadata:");
println!(" size : {}", mp4.size());
println!(" major_brand : {}", mp4.major_brand());
println!("File:");
println!(" file size: {}", mp4.size());
println!(" major_brand: {}", mp4.major_brand());
let mut compatible_brands = String::new();
for brand in mp4.compatible_brands().iter() {
compatible_brands.push_str(&brand.to_string());
compatible_brands.push_str(",");
compatible_brands.push_str(" ");
}
println!(" compatible_brands: {}", compatible_brands);
println!("Duration: {:?}", mp4.duration());
println!(" compatible_brands: {}\n", compatible_brands);

println!("Movie:");
println!(" version: {}", mp4.moov.mvhd.version);
println!(" creation time: {}", creation_time(mp4.moov.mvhd.creation_time));
println!(" duration: {:?}", mp4.duration());
println!(" timescale: {:?}\n", mp4.timescale());

println!("Found {} Tracks", mp4.tracks().len());
for track in mp4.tracks().iter() {
let media_info = match track.track_type()? {
TrackType::Video => video_info(track)?,
Expand Down Expand Up @@ -68,13 +74,35 @@ fn video_info(track: &Mp4Track) -> Result<String> {
}

fn audio_info(track: &Mp4Track) -> Result<String> {
Ok(format!(
"{} ({}) ({:?}), {} Hz, {}, {} kb/s",
track.media_type()?,
track.audio_profile()?,
track.box_type()?,
track.sample_freq_index()?.freq(),
track.channel_config()?,
track.bitrate() / 1000
))
if let Some(ref mp4a) = track.trak.mdia.minf.stbl.stsd.mp4a {
if mp4a.esds.is_some() {
Ok(format!(
"{} ({}) ({:?}), {} Hz, {}, {} kb/s",
track.media_type()?,
track.audio_profile()?,
track.box_type()?,
track.sample_freq_index()?.freq(),
track.channel_config()?,
track.bitrate() / 1000
))
} else {
Ok(format!(
"{} ({:?}), {} kb/s",
track.media_type()?,
track.box_type()?,
track.bitrate() / 1000
))
}
} else {
Err(Error::InvalidData("mp4a box not found"))
}
}

fn creation_time(creation_time: u64) -> u64 {
// convert from MP4 epoch (1904-01-01) to Unix epoch (1970-01-01)
if creation_time >= 2082844800 {
creation_time - 2082844800
} else {
creation_time
}
}
67 changes: 47 additions & 20 deletions src/mp4box/mp4a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub struct Mp4aBox {
pub channelcount: u16,
pub samplesize: u16,
pub samplerate: FixedPointU16,
pub esds: EsdsBox,
pub esds: Option<EsdsBox>,
}

impl Default for Mp4aBox {
Expand All @@ -19,7 +19,7 @@ impl Default for Mp4aBox {
channelcount: 2,
samplesize: 16,
samplerate: FixedPointU16::new(48000),
esds: EsdsBox::default(),
esds: Some(EsdsBox::default()),
}
}
}
Expand All @@ -31,7 +31,7 @@ impl Mp4aBox {
channelcount: config.chan_conf as u16,
samplesize: 16,
samplerate: FixedPointU16::new(config.freq_index.freq() as u16),
esds: EsdsBox::new(config),
esds: Some(EsdsBox::new(config)),
}
}
}
Expand All @@ -42,7 +42,11 @@ impl Mp4Box for Mp4aBox {
}

fn box_size(&self) -> u64 {
HEADER_SIZE + 8 + 20 + self.esds.box_size()
let mut size = HEADER_SIZE + 8 + 20;
if let Some(ref esds) = self.esds {
size += esds.box_size();
}
size
}
}

Expand All @@ -62,21 +66,20 @@ impl<R: Read + Seek> ReadBox<&mut R> for Mp4aBox {

let header = BoxHeader::read(reader)?;
let BoxHeader { name, size: s } = header;

let mut esds = None;
if name == BoxType::EsdsBox {
let esds = EsdsBox::read_box(reader, s)?;

skip_bytes_to(reader, start + size)?;

Ok(Mp4aBox {
data_reference_index,
channelcount,
samplesize,
samplerate,
esds,
})
} else {
Err(Error::InvalidData("esds not found"))
esds = Some(EsdsBox::read_box(reader, s)?);
}
skip_bytes_to(reader, start + size)?;

Ok(Mp4aBox {
data_reference_index,
channelcount,
samplesize,
samplerate,
esds,
})
}
}

Expand All @@ -95,7 +98,9 @@ impl<W: Write> WriteBox<&mut W> for Mp4aBox {
writer.write_u32::<BigEndian>(0)?; // reserved
writer.write_u32::<BigEndian>(self.samplerate.raw_value())?;

self.esds.write_box(writer)?;
if let Some(ref esds) = self.esds {
esds.write_box(writer)?;
}

Ok(size)
}
Expand Down Expand Up @@ -524,7 +529,7 @@ mod tests {
channelcount: 2,
samplesize: 16,
samplerate: FixedPointU16::new(48000),
esds: EsdsBox {
esds: Some(EsdsBox {
version: 0,
flags: 0,
es_desc: ESDescriptor {
Expand All @@ -544,7 +549,29 @@ mod tests {
},
sl_config: SLConfigDescriptor::default(),
},
},
}),
};
let mut buf = Vec::new();
src_box.write_box(&mut buf).unwrap();
assert_eq!(buf.len(), src_box.box_size() as usize);

let mut reader = Cursor::new(&buf);
let header = BoxHeader::read(&mut reader).unwrap();
assert_eq!(header.name, BoxType::Mp4aBox);
assert_eq!(src_box.box_size(), header.size);

let dst_box = Mp4aBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}

#[test]
fn test_mp4a_no_esds() {
let src_box = Mp4aBox {
data_reference_index: 1,
channelcount: 2,
samplesize: 16,
samplerate: FixedPointU16::new(48000),
esds: None,
};
let mut buf = Vec::new();
src_box.write_box(&mut buf).unwrap();
Expand Down
31 changes: 25 additions & 6 deletions src/track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl From<AacConfig> for TrackConfig {

#[derive(Debug)]
pub struct Mp4Track {
trak: TrakBox,
pub trak: TrakBox,
}

impl Mp4Track {
Expand Down Expand Up @@ -126,15 +126,23 @@ impl Mp4Track {

pub fn sample_freq_index(&self) -> Result<SampleFreqIndex> {
if let Some(ref mp4a) = self.trak.mdia.minf.stbl.stsd.mp4a {
SampleFreqIndex::try_from(mp4a.esds.es_desc.dec_config.dec_specific.freq_index)
if let Some(ref esds) = mp4a.esds {
SampleFreqIndex::try_from(esds.es_desc.dec_config.dec_specific.freq_index)
} else {
Err(Error::BoxInStblNotFound(self.track_id(), BoxType::EsdsBox))
}
} else {
Err(Error::BoxInStblNotFound(self.track_id(), BoxType::Mp4aBox))
}
}

pub fn channel_config(&self) -> Result<ChannelConfig> {
if let Some(ref mp4a) = self.trak.mdia.minf.stbl.stsd.mp4a {
ChannelConfig::try_from(mp4a.esds.es_desc.dec_config.dec_specific.chan_conf)
if let Some(ref esds) = mp4a.esds {
ChannelConfig::try_from(esds.es_desc.dec_config.dec_specific.chan_conf)
} else {
Err(Error::BoxInStblNotFound(self.track_id(), BoxType::EsdsBox))
}
} else {
Err(Error::BoxInStblNotFound(self.track_id(), BoxType::Mp4aBox))
}
Expand All @@ -156,7 +164,12 @@ impl Mp4Track {

pub fn bitrate(&self) -> u32 {
if let Some(ref mp4a) = self.trak.mdia.minf.stbl.stsd.mp4a {
mp4a.esds.es_desc.dec_config.avg_bitrate
if let Some(ref esds) = mp4a.esds {
esds.es_desc.dec_config.avg_bitrate
} else {
0
}
// mp4a.esds.es_desc.dec_config.avg_bitrate
} else {
let dur_sec = self.duration().as_secs();
if dur_sec > 0 {
Expand Down Expand Up @@ -215,7 +228,11 @@ impl Mp4Track {

pub fn audio_profile(&self) -> Result<AudioObjectType> {
if let Some(ref mp4a) = self.trak.mdia.minf.stbl.stsd.mp4a {
AudioObjectType::try_from(mp4a.esds.es_desc.dec_config.dec_specific.profile)
if let Some(ref esds) = mp4a.esds {
AudioObjectType::try_from(esds.es_desc.dec_config.dec_specific.profile)
} else {
Err(Error::BoxInStblNotFound(self.track_id(), BoxType::EsdsBox))
}
} else {
Err(Error::BoxInStblNotFound(self.track_id(), BoxType::Mp4aBox))
}
Expand Down Expand Up @@ -660,7 +677,9 @@ impl Mp4TrackWriter {

let max_sample_size = self.max_sample_size();
if let Some(ref mut mp4a) = self.trak.mdia.minf.stbl.stsd.mp4a {
mp4a.esds.es_desc.dec_config.buffer_size_db = max_sample_size;
if let Some(ref mut esds) = mp4a.esds {
esds.es_desc.dec_config.buffer_size_db = max_sample_size;
}
// TODO
// mp4a.esds.es_desc.dec_config.max_bitrate
// mp4a.esds.es_desc.dec_config.avg_bitrate
Expand Down