Skip to content

Commit 3d9efdc

Browse files
authored
Merge pull request mozilla#263 from mozilla/fix-read_moov
Restore read_moov behavior allowing multiple moov boxes
2 parents 94fd2f1 + 67a2fb3 commit 3d9efdc

File tree

4 files changed

+34
-10
lines changed

4 files changed

+34
-10
lines changed

mp4parse/src/lib.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -738,12 +738,6 @@ pub struct MediaContext {
738738
pub userdata: Option<Result<UserdataBox>>,
739739
}
740740

741-
impl MediaContext {
742-
pub fn new() -> MediaContext {
743-
Default::default()
744-
}
745-
}
746-
747741
/// An ISOBMFF item as described by an iloc box. For the sake of avoiding copies,
748742
/// this can either be represented by the `Location` variant, which indicates
749743
/// where the data exists within a `MediaDataBox` stored separately, or the
@@ -2278,7 +2272,7 @@ pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> {
22782272
debug!("{:?}", ftyp);
22792273
}
22802274
BoxType::MovieBox => {
2281-
context = Some(read_moov(&mut b)?);
2275+
context = Some(read_moov(&mut b, context)?);
22822276
}
22832277
_ => skip_box_content(&mut b)?,
22842278
};
@@ -2301,6 +2295,8 @@ pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> {
23012295
context.ok_or(Error::NoMoov)
23022296
}
23032297

2298+
/// Parse a Movie Header Box
2299+
/// See ISOBMFF (ISO 14496-12:2015) § 8.2.2
23042300
fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
23052301
let mvhd = read_mvhd(f)?;
23062302
debug!("{:?}", mvhd);
@@ -2311,14 +2307,19 @@ fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
23112307
Ok(timescale)
23122308
}
23132309

2314-
fn read_moov<T: Read>(f: &mut BMFFBox<T>) -> Result<MediaContext> {
2310+
/// Parse a Movie Box
2311+
/// See ISOBMFF (ISO 14496-12:2015) § 8.2.1
2312+
/// Note that despite the spec indicating "exactly one" moov box should exist at
2313+
/// the file container level, we support reading and merging multiple moov boxes
2314+
/// such as with tests/test_case_1185230.mp4.
2315+
fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Result<MediaContext> {
23152316
let MediaContext {
23162317
mut timescale,
23172318
mut tracks,
23182319
mut mvex,
23192320
mut psshs,
23202321
mut userdata,
2321-
} = Default::default();
2322+
} = context.unwrap_or_default();
23222323

23232324
let mut iter = f.box_iter();
23242325
while let Some(mut b) = iter.next_box()? {
@@ -2396,6 +2397,8 @@ fn read_pssh<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSystemSpecificHe
23962397
})
23972398
}
23982399

2400+
/// Parse a Movie Extends Box
2401+
/// See ISOBMFF (ISO 14496-12:2015) § 8.8.1
23992402
fn read_mvex<T: Read>(src: &mut BMFFBox<T>) -> Result<MovieExtendsBox> {
24002403
let mut iter = src.box_iter();
24012404
let mut fragment_duration = None;
@@ -2421,6 +2424,8 @@ fn read_mehd<T: Read>(src: &mut BMFFBox<T>) -> Result<MediaScaledTime> {
24212424
Ok(MediaScaledTime(fragment_duration))
24222425
}
24232426

2427+
/// Parse a Track Box
2428+
/// See ISOBMFF (ISO 14496-12:2015) § 8.3.1.
24242429
fn read_trak<T: Read>(f: &mut BMFFBox<T>, track: &mut Track) -> Result<()> {
24252430
let mut iter = f.box_iter();
24262431
while let Some(mut b) = iter.next_box()? {
@@ -3940,6 +3945,7 @@ fn read_schm<T: Read>(src: &mut BMFFBox<T>) -> Result<SchemeTypeBox> {
39403945
}
39413946

39423947
/// Parse a metadata box inside a moov, trak, or mdia box.
3948+
/// See ISOBMFF (ISO 14496-12:2015) § 8.10.1.
39433949
fn read_udta<T: Read>(src: &mut BMFFBox<T>) -> Result<UserdataBox> {
39443950
let mut iter = src.box_iter();
39453951
let mut udta = UserdataBox { meta: None };

mp4parse/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1248,7 +1248,7 @@ fn read_invalid_pssh() {
12481248
let mut iter = super::BoxIter::new(&mut stream);
12491249
let mut stream = iter.next_box().unwrap().unwrap();
12501250

1251-
match super::read_moov(&mut stream) {
1251+
match super::read_moov(&mut stream, None) {
12521252
Err(Error::InvalidData(s)) => assert_eq!(s, "read_buf size exceeds BUF_SIZE_LIMIT"),
12531253
_ => panic!("unexpected result with invalid descriptor"),
12541254
}

mp4parse/tests/public.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,24 @@ fn public_video_av1() {
618618
}
619619
}
620620

621+
#[test]
622+
fn public_mp4_bug_1185230() {
623+
let input = &mut File::open("tests/test_case_1185230.mp4").expect("Unknown file");
624+
let context = mp4::read_mp4(input).expect("read_mp4 failed");
625+
let number_video_tracks = context
626+
.tracks
627+
.iter()
628+
.filter(|t| t.track_type == mp4::TrackType::Video)
629+
.count();
630+
let number_audio_tracks = context
631+
.tracks
632+
.iter()
633+
.filter(|t| t.track_type == mp4::TrackType::Audio)
634+
.count();
635+
assert_eq!(number_video_tracks, 2);
636+
assert_eq!(number_audio_tracks, 2);
637+
}
638+
621639
#[test]
622640
fn public_avif_primary_item() {
623641
let input = &mut File::open(IMAGE_AVIF).expect("Unknown file");

mp4parse/tests/test_case_1185230.mp4

3.17 KB
Binary file not shown.

0 commit comments

Comments
 (0)