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

add creation and modification fields to MediaContext #321

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
55 changes: 36 additions & 19 deletions mp4parse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ struct FileTypeBox {
/// Movie header box 'mvhd'.
#[derive(Debug)]
struct MovieHeaderBox {
creation: u64,
modification: u64,
pub timescale: u32,
duration: u64,
}
Expand Down Expand Up @@ -777,9 +779,14 @@ pub enum XmlBox {
BinaryXmlBox(TryVec<u8>),
}

#[derive(Debug)]
pub struct UtcSecondsSince1904(pub u64);

/// Internal data structures.
#[derive(Debug, Default)]
pub struct MediaContext {
pub creation: Option<UtcSecondsSince1904>,
pub modification: Option<UtcSecondsSince1904>,
pub timescale: Option<MediaTimeScale>,
/// Tracks found in the file.
pub tracks: TryVec<Track>,
Expand Down Expand Up @@ -2866,16 +2873,12 @@ pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> {
context.ok_or(Error::NoMoov)
}

/// Parse a Movie Header Box
/// See ISOBMFF (ISO 14496-12:2015) § 8.2.2
fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
let mvhd = read_mvhd(f)?;
debug!("{:?}", mvhd);
fn validate_timescale(mvhd: &MovieHeaderBox) -> Result<Option<MediaTimeScale>> {
if mvhd.timescale == 0 {
return Err(Error::InvalidData("zero timescale in mdhd"));
Err(Error::InvalidData("zero timescale in mdhd"))
} else {
Ok(Some(MediaTimeScale(u64::from(mvhd.timescale))))
}
let timescale = Some(MediaTimeScale(u64::from(mvhd.timescale)));
Ok(timescale)
}

/// Parse a Movie Box
Expand All @@ -2885,6 +2888,8 @@ fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
/// such as with tests/test_case_1185230.mp4.
fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Result<MediaContext> {
let MediaContext {
mut creation,
mut modification,
mut timescale,
mut tracks,
mut mvex,
Expand All @@ -2898,7 +2903,11 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
while let Some(mut b) = iter.next_box()? {
match b.head.name {
BoxType::MovieHeaderBox => {
timescale = parse_mvhd(&mut b)?;
let mvhd = read_mvhd(&mut b)?;
debug!("{:?}", mvhd);
creation = Some(UtcSecondsSince1904(mvhd.creation));
modification = Some(UtcSecondsSince1904(mvhd.modification));
timescale = validate_timescale(&mvhd)?;
}
BoxType::TrackBox => {
let mut track = Track::new(tracks.len());
Expand Down Expand Up @@ -2929,6 +2938,8 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
}

Ok(MediaContext {
creation,
modification,
timescale,
tracks,
mvex,
Expand Down Expand Up @@ -3204,33 +3215,39 @@ fn read_ftyp<T: Read>(src: &mut BMFFBox<T>) -> Result<FileTypeBox> {
/// Parse an mvhd box.
fn read_mvhd<T: Read>(src: &mut BMFFBox<T>) -> Result<MovieHeaderBox> {
let (version, _) = read_fullbox_extra(src)?;
let to_u64 = |n| {
if n == std::u32::MAX {
std::u64::MAX
} else {
u64::from(n)
}
};
let creation;
let modification;
match version {
// 64 bit creation and modification times.
1 => {
skip(src, 16)?;
creation = be_u64(src)?;
modification = be_u64(src)?;
}
// 32 bit creation and modification times.
0 => {
skip(src, 8)?;
creation = to_u64(be_u32(src)?);
modification = to_u64(be_u32(src)?);
}
_ => return Err(Error::InvalidData("unhandled mvhd version")),
}
let timescale = be_u32(src)?;
let duration = match version {
1 => be_u64(src)?,
0 => {
let d = be_u32(src)?;
if d == std::u32::MAX {
std::u64::MAX
} else {
u64::from(d)
}
}
0 => to_u64(be_u32(src)?),
_ => return Err(Error::InvalidData("unhandled mvhd version")),
};
// Skip remaining fields.
skip(src, 80)?;
Ok(MovieHeaderBox {
creation,
modification,
timescale,
duration,
})
Expand Down
2 changes: 1 addition & 1 deletion mp4parse/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ fn read_mvhd_invalid_timescale() {
let mut stream = iter.next_box().unwrap().unwrap();
assert_eq!(stream.head.name, BoxType::MovieHeaderBox);
assert_eq!(stream.head.size, 120);
let r = super::parse_mvhd(&mut stream);
let r = super::validate_timescale(&super::read_mvhd(&mut stream).unwrap());
assert!(r.is_err());
}

Expand Down