Skip to content
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
87 changes: 84 additions & 3 deletions mp4parse_capi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1727,9 +1727,19 @@ fn get_indice_table(
_ => None,
};

let empty_duration: Option<CheckedInteger<_>> = match &track.empty_duration {
&Some(e) => i64::try_from(e.0).ok().map(Into::into),
_ => None,
let empty_duration: Option<CheckedInteger<_>> = match track.empty_duration {
Some(duration) => {
let movie_timescale = context.timescale.ok_or(Mp4parseStatus::Invalid)?;
let track_timescale = track.timescale.ok_or(Mp4parseStatus::Invalid)?;
let duration = rational_scale(duration.0, movie_timescale.0, track_timescale.0)
.ok_or(Mp4parseStatus::Invalid)?;
Some(
i64::try_from(duration)
.map_err(|_| Mp4parseStatus::Invalid)?
.into(),
)
}
None => None,
};

// Find the track start offset time from 'elst'.
Expand Down Expand Up @@ -2376,3 +2386,74 @@ fn parse_no_timescale() {
assert_eq!(rv, Mp4parseStatus::Invalid);
};
}

#[cfg(test)]
mod edit_list_tests {
use super::*;
use mp4parse::{MediaScaledTime, MediaTimeScale, TrackScaledTime, TrackTimeScale};

fn context() -> MediaContext {
let mut file = std::fs::File::open("tests/video_colr_nclx_hdr10.mp4").unwrap();
let mut context = mp4parse::read_mp4(&mut file, ParseStrictness::Normal).unwrap();
context.tracks[0].ctts = None;
context.tracks[0].media_time = Some(TrackScaledTime(0, 0));
context
}

#[test]
fn empty_edit_uses_movie_timescale() {
for (movie_scale, track_scale, duration, media_time, expected) in [
(57600, 60, 960, 0, 1),
(60, 57600, 960, 0, 921600),
(60, 60, 960, 0, 960),
(57600, 60, 960, 2, -1),
(4, 1, u64::MAX - 3, 0, (u64::MAX / 4) as i64),
] {
let mut context = context();
context.timescale = Some(MediaTimeScale(movie_scale));
let track = &mut context.tracks[0];
track.timescale = Some(TrackTimeScale(track_scale, 0));
track.empty_duration = Some(MediaScaledTime(duration));
track.media_time = Some(TrackScaledTime(media_time, 0));
let track_id = track.track_id.unwrap();
let mut cache = TryHashMap::default();
let mut indices = Mp4parseByteData::default();
assert_eq!(
get_indice_table(&context, &mut cache, track_id, &mut indices),
Ok(())
);
assert!(indices.length > 0);
assert!(!indices.indices.is_null());
let first = unsafe { &*indices.indices };
assert_eq!(first.start_composition.0, expected);
assert_eq!(first.start_decode.0, 0);
}
}

#[test]
fn invalid_empty_edit_timescale() {
for (movie_scale, track_scale, duration) in [
(None, Some(60), 960),
(Some(57600), None, 960),
(Some(0), Some(60), 960),
(Some(1), Some(2), u64::MAX),
(Some(1), Some(1), u64::MAX),
] {
let mut context = context();
context.timescale = movie_scale.map(MediaTimeScale);
let track = &mut context.tracks[0];
track.timescale = track_scale.map(|scale| TrackTimeScale(scale, 0));
track.empty_duration = Some(MediaScaledTime(duration));
let track_id = track.track_id.unwrap();
assert_eq!(
get_indice_table(
&context,
&mut TryHashMap::default(),
track_id,
&mut Mp4parseByteData::default()
),
Err(Mp4parseStatus::Invalid)
);
}
}
}
18 changes: 9 additions & 9 deletions mp4parse_capi/tests/test_sample_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,20 @@ fn parse_sample_table() {
rv = mp4parse_get_indice_table(parser, track_info.track_id, &mut indice);
assert_eq!(rv, Mp4parseStatus::Ok);

// Compare the last few data from stagefright.
// The 95-tick empty edit at 1000 Hz adds 8550 ticks at 90000 Hz.
let video_indice_291 = Indice {
start_offset: 280_226.into(),
end_offset: 280_855.into(),
start_composition: 876995.into(),
end_composition: 879996.into(),
start_composition: 885450.into(),
end_composition: 888451.into(),
start_decode: 873900.into(),
sync: false,
};
let video_indice_292 = Indice {
start_offset: 280_855.into(),
end_offset: 281_297.into(),
start_composition: 873996.into(),
end_composition: 876995.into(),
start_composition: 882451.into(),
end_composition: 885450.into(),
start_decode: 873901.into(),
sync: false,
};
Expand All @@ -105,16 +105,16 @@ fn parse_sample_table() {
let video_indice_295 = Indice {
start_offset: 282_391.into(),
end_offset: 283_032.into(),
start_composition: 888995.into(),
end_composition: 888996.into(),
start_composition: 897450.into(),
end_composition: 897451.into(),
start_decode: 885900.into(),
sync: false,
};
let video_indice_296 = Indice {
start_offset: 283_092.into(),
end_offset: 283_526.into(),
start_composition: 885996.into(),
end_composition: 888995.into(),
start_composition: 894451.into(),
end_composition: 897450.into(),
start_decode: 885901.into(),
sync: false,
};
Expand Down
Loading