@@ -956,6 +956,8 @@ impl FileTypeBox {
956
956
/// Movie header box 'mvhd'.
957
957
#[ derive( Debug ) ]
958
958
struct MovieHeaderBox {
959
+ creation : u64 ,
960
+ modification : u64 ,
959
961
pub timescale : u32 ,
960
962
#[ allow( dead_code) ] // See https://github.com/mozilla/mp4parse-rust/issues/340
961
963
duration : u64 ,
@@ -1503,9 +1505,14 @@ pub enum XmlBox {
1503
1505
BinaryXmlBox ( TryVec < u8 > ) ,
1504
1506
}
1505
1507
1508
+ #[ derive( Debug ) ]
1509
+ pub struct UtcSecondsSince1904 ( pub u64 ) ;
1510
+
1506
1511
/// Internal data structures.
1507
1512
#[ derive( Debug , Default ) ]
1508
1513
pub struct MediaContext {
1514
+ pub creation : Option < UtcSecondsSince1904 > ,
1515
+ pub modification : Option < UtcSecondsSince1904 > ,
1509
1516
pub timescale : Option < MediaTimeScale > ,
1510
1517
/// Tracks found in the file.
1511
1518
pub tracks : TryVec < Track > ,
@@ -4115,16 +4122,12 @@ pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> {
4115
4122
context. ok_or ( Error :: MoovMissing )
4116
4123
}
4117
4124
4118
- /// Parse a Movie Header Box
4119
- /// See ISOBMFF (ISO 14496-12:2020) § 8.2.2
4120
- fn parse_mvhd < T : Read > ( f : & mut BMFFBox < T > ) -> Result < Option < MediaTimeScale > > {
4121
- let mvhd = read_mvhd ( f) ?;
4122
- debug ! ( "{:?}" , mvhd) ;
4125
+ fn validate_timescale ( mvhd : & MovieHeaderBox ) -> Result < Option < MediaTimeScale > > {
4123
4126
if mvhd. timescale == 0 {
4124
- return Status :: MvhdBadTimescale . into ( ) ;
4127
+ Err ( Error :: InvalidData ( Status :: MdhdBadTimescale ) )
4128
+ } else {
4129
+ Ok ( Some ( MediaTimeScale ( u64:: from ( mvhd. timescale ) ) ) )
4125
4130
}
4126
- let timescale = Some ( MediaTimeScale ( u64:: from ( mvhd. timescale ) ) ) ;
4127
- Ok ( timescale)
4128
4131
}
4129
4132
4130
4133
/// Parse a Movie Box
@@ -4134,6 +4137,8 @@ fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
4134
4137
/// such as with tests/test_case_1185230.mp4.
4135
4138
fn read_moov < T : Read > ( f : & mut BMFFBox < T > , context : Option < MediaContext > ) -> Result < MediaContext > {
4136
4139
let MediaContext {
4140
+ mut creation,
4141
+ mut modification,
4137
4142
mut timescale,
4138
4143
mut tracks,
4139
4144
mut mvex,
@@ -4147,7 +4152,11 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
4147
4152
while let Some ( mut b) = iter. next_box ( ) ? {
4148
4153
match b. head . name {
4149
4154
BoxType :: MovieHeaderBox => {
4150
- timescale = parse_mvhd ( & mut b) ?;
4155
+ let mvhd = read_mvhd ( & mut b) ?;
4156
+ debug ! ( "{:?}" , mvhd) ;
4157
+ creation = Some ( UtcSecondsSince1904 ( mvhd. creation ) ) ;
4158
+ modification = Some ( UtcSecondsSince1904 ( mvhd. modification ) ) ;
4159
+ timescale = validate_timescale ( & mvhd) ?;
4151
4160
}
4152
4161
BoxType :: TrackBox => {
4153
4162
let mut track = Track :: new ( tracks. len ( ) ) ;
@@ -4178,6 +4187,8 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
4178
4187
}
4179
4188
4180
4189
Ok ( MediaContext {
4190
+ creation,
4191
+ modification,
4181
4192
timescale,
4182
4193
tracks,
4183
4194
mvex,
@@ -4490,28 +4501,32 @@ fn read_ftyp<T: Read>(src: &mut BMFFBox<T>) -> Result<FileTypeBox> {
4490
4501
/// Parse an mvhd box.
4491
4502
fn read_mvhd < T : Read > ( src : & mut BMFFBox < T > ) -> Result < MovieHeaderBox > {
4492
4503
let ( version, _) = read_fullbox_extra ( src) ?;
4504
+ let to_u64 = |n| {
4505
+ if n == std:: u32:: MAX {
4506
+ std:: u64:: MAX
4507
+ } else {
4508
+ u64:: from ( n)
4509
+ }
4510
+ } ;
4511
+ let creation;
4512
+ let modification;
4493
4513
match version {
4494
4514
// 64 bit creation and modification times.
4495
4515
1 => {
4496
- skip ( src, 16 ) ?;
4516
+ creation = be_u64 ( src) ?;
4517
+ modification = be_u64 ( src) ?;
4497
4518
}
4498
4519
// 32 bit creation and modification times.
4499
4520
0 => {
4500
- skip ( src, 8 ) ?;
4521
+ creation = to_u64 ( be_u32 ( src) ?) ;
4522
+ modification = to_u64 ( be_u32 ( src) ?) ;
4501
4523
}
4502
4524
_ => return Status :: MvhdBadVersion . into ( ) ,
4503
4525
}
4504
4526
let timescale = be_u32 ( src) ?;
4505
4527
let duration = match version {
4506
4528
1 => be_u64 ( src) ?,
4507
- 0 => {
4508
- let d = be_u32 ( src) ?;
4509
- if d == u32:: MAX {
4510
- u64:: MAX
4511
- } else {
4512
- u64:: from ( d)
4513
- }
4514
- }
4529
+ 0 => to_u64 ( be_u32 ( src) ?) ,
4515
4530
_ => unreachable ! ( "Should have returned Status::MvhdBadVersion" ) ,
4516
4531
} ;
4517
4532
// Skip remaining valid fields.
@@ -4520,6 +4535,8 @@ fn read_mvhd<T: Read>(src: &mut BMFFBox<T>) -> Result<MovieHeaderBox> {
4520
4535
// Padding could be added in some contents.
4521
4536
skip_box_remain ( src) ?;
4522
4537
Ok ( MovieHeaderBox {
4538
+ creation,
4539
+ modification,
4523
4540
timescale,
4524
4541
duration,
4525
4542
} )
0 commit comments