Skip to content
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
1 change: 1 addition & 0 deletions mp4parse/src/boxes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ box_database!(
ProtectedVisualSampleEntry 0x656e6376, // "encv" - Need to check official name in spec.
ProtectedAudioSampleEntry 0x656e6361, // "enca" - Need to check official name in spec.
MovieExtendsBox 0x6d766578, // "mvex"
MovieExtendsHeaderBox 0x6d656864, // "mehd"
);
39 changes: 36 additions & 3 deletions mp4parse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,18 @@ pub struct OpusSpecificBox {
channel_mapping_table: Option<ChannelMappingTable>,
}

#[derive(Debug)]
pub struct MovieExtendsBox {
pub fragment_duration: Option<MediaScaledTime>,
}

/// Internal data structures.
#[derive(Debug, Default)]
pub struct MediaContext {
pub timescale: Option<MediaTimeScale>,
pub has_mvex: bool,
/// Tracks found in the file.
pub tracks: Vec<Track>,
pub mvex: Option<MovieExtendsBox>,
}

impl MediaContext {
Expand Down Expand Up @@ -555,8 +560,9 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: &mut MediaContext) -> Result<
context.tracks.push(track);
}
BoxType::MovieExtendsBox => {
context.has_mvex = true;
try!(skip_box_content(&mut b));
let mvex = try!(read_mvex(&mut b));
log!("{:?}", mvex);
context.mvex = Some(mvex);
}
_ => try!(skip_box_content(&mut b)),
};
Expand All @@ -565,6 +571,33 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: &mut MediaContext) -> Result<
Ok(())
}

fn read_mvex<T: Read>(src: &mut BMFFBox<T>) -> Result<MovieExtendsBox> {
let mut iter = src.box_iter();
let mut fragment_duration = None;
while let Some(mut b) = try!(iter.next_box()) {
match b.head.name {
BoxType::MovieExtendsHeaderBox => {
let duration = try!(read_mehd(&mut b));
fragment_duration = Some(duration);
},
_ => try!(skip_box_content(&mut b)),
}
}
Ok(MovieExtendsBox {
fragment_duration: fragment_duration,
})
}

fn read_mehd<T: Read>(src: &mut BMFFBox<T>) -> Result<MediaScaledTime> {
let (version, _) = try!(read_fullbox_extra(src));
let fragment_duration = match version {
1 => try!(be_u64(src)),
0 => try!(be_u32(src)) as u64,
_ => return Err(Error::InvalidData("unhandled mehd version")),
};
Ok(MediaScaledTime(fragment_duration))
}

fn read_trak<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
let mut iter = f.box_iter();
while let Some(mut b) = try!(iter.next_box()) {
Expand Down
35 changes: 34 additions & 1 deletion mp4parse_capi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ pub struct mp4parse_track_video_info {
// codec_specific_config
}

#[repr(C)]
pub struct mp4parse_fragment_info {
pub fragment_duration: u64,
// TODO:
// info in trex box.
}

// Even though mp4parse_parser is opaque to C, rusty-cheddar won't let us
// use more than one member, so we introduce *another* wrapper.
struct Wrap {
Expand Down Expand Up @@ -492,6 +499,32 @@ pub unsafe extern fn mp4parse_get_track_video_info(parser: *mut mp4parse_parser,
MP4PARSE_OK
}

#[no_mangle]
pub unsafe extern fn mp4parse_get_fragment_info(parser: *mut mp4parse_parser, info: *mut mp4parse_fragment_info) -> mp4parse_error {
if parser.is_null() || info.is_null() || (*parser).poisoned() {
return MP4PARSE_ERROR_BADARG;
}

let context = (*parser).context();
let info: &mut mp4parse_fragment_info = &mut *info;

info.fragment_duration = 0;

let duration = match context.mvex {
Some(ref mvex) => mvex.fragment_duration,
None => return MP4PARSE_ERROR_INVALID,
};

if let (Some(time), Some(scale)) = (duration, context.timescale) {
info.fragment_duration = match media_time_to_us(time, scale) {
Some(time_us) => time_us as u64,
None => return MP4PARSE_ERROR_INVALID,
}
}

MP4PARSE_OK
}

// A fragmented file needs mvex table and contains no data in stts, stsc, and stco boxes.
#[no_mangle]
pub unsafe extern fn mp4parse_is_fragmented(parser: *mut mp4parse_parser, track_id: u32, fragmented: *mut u8) -> mp4parse_error {
Expand All @@ -503,7 +536,7 @@ pub unsafe extern fn mp4parse_is_fragmented(parser: *mut mp4parse_parser, track_
let tracks = &context.tracks;
(*fragmented) = false as u8;

if !context.has_mvex {
if context.mvex.is_none() {
return MP4PARSE_OK;
}

Expand Down