@@ -266,6 +266,8 @@ struct FileTypeBox {
266
266
/// Movie header box 'mvhd'.
267
267
#[ derive( Debug ) ]
268
268
struct MovieHeaderBox {
269
+ creation : u64 ,
270
+ modification : u64 ,
269
271
pub timescale : u32 ,
270
272
duration : u64 ,
271
273
}
@@ -777,9 +779,14 @@ pub enum XmlBox {
777
779
BinaryXmlBox ( TryVec < u8 > ) ,
778
780
}
779
781
782
+ #[ derive( Debug ) ]
783
+ pub struct UtcSecondsSince1904 ( pub u64 ) ;
784
+
780
785
/// Internal data structures.
781
786
#[ derive( Debug , Default ) ]
782
787
pub struct MediaContext {
788
+ pub creation : Option < UtcSecondsSince1904 > ,
789
+ pub modification : Option < UtcSecondsSince1904 > ,
783
790
pub timescale : Option < MediaTimeScale > ,
784
791
/// Tracks found in the file.
785
792
pub tracks : TryVec < Track > ,
@@ -2866,16 +2873,12 @@ pub fn read_mp4<T: Read>(f: &mut T) -> Result<MediaContext> {
2866
2873
context. ok_or ( Error :: NoMoov )
2867
2874
}
2868
2875
2869
- /// Parse a Movie Header Box
2870
- /// See ISOBMFF (ISO 14496-12:2015) § 8.2.2
2871
- fn parse_mvhd < T : Read > ( f : & mut BMFFBox < T > ) -> Result < Option < MediaTimeScale > > {
2872
- let mvhd = read_mvhd ( f) ?;
2873
- debug ! ( "{:?}" , mvhd) ;
2876
+ fn validate_timescale ( mvhd : & MovieHeaderBox ) -> Result < Option < MediaTimeScale > > {
2874
2877
if mvhd. timescale == 0 {
2875
- return Err ( Error :: InvalidData ( "zero timescale in mdhd" ) ) ;
2878
+ Err ( Error :: InvalidData ( "zero timescale in mdhd" ) )
2879
+ } else {
2880
+ Ok ( Some ( MediaTimeScale ( u64:: from ( mvhd. timescale ) ) ) )
2876
2881
}
2877
- let timescale = Some ( MediaTimeScale ( u64:: from ( mvhd. timescale ) ) ) ;
2878
- Ok ( timescale)
2879
2882
}
2880
2883
2881
2884
/// Parse a Movie Box
@@ -2885,6 +2888,8 @@ fn parse_mvhd<T: Read>(f: &mut BMFFBox<T>) -> Result<Option<MediaTimeScale>> {
2885
2888
/// such as with tests/test_case_1185230.mp4.
2886
2889
fn read_moov < T : Read > ( f : & mut BMFFBox < T > , context : Option < MediaContext > ) -> Result < MediaContext > {
2887
2890
let MediaContext {
2891
+ mut creation,
2892
+ mut modification,
2888
2893
mut timescale,
2889
2894
mut tracks,
2890
2895
mut mvex,
@@ -2898,7 +2903,11 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
2898
2903
while let Some ( mut b) = iter. next_box ( ) ? {
2899
2904
match b. head . name {
2900
2905
BoxType :: MovieHeaderBox => {
2901
- timescale = parse_mvhd ( & mut b) ?;
2906
+ let mvhd = read_mvhd ( & mut b) ?;
2907
+ debug ! ( "{:?}" , mvhd) ;
2908
+ creation = Some ( UtcSecondsSince1904 ( mvhd. creation ) ) ;
2909
+ modification = Some ( UtcSecondsSince1904 ( mvhd. modification ) ) ;
2910
+ timescale = validate_timescale ( & mvhd) ?;
2902
2911
}
2903
2912
BoxType :: TrackBox => {
2904
2913
let mut track = Track :: new ( tracks. len ( ) ) ;
@@ -2929,6 +2938,8 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>, context: Option<MediaContext>) -> Resu
2929
2938
}
2930
2939
2931
2940
Ok ( MediaContext {
2941
+ creation,
2942
+ modification,
2932
2943
timescale,
2933
2944
tracks,
2934
2945
mvex,
@@ -3204,33 +3215,39 @@ fn read_ftyp<T: Read>(src: &mut BMFFBox<T>) -> Result<FileTypeBox> {
3204
3215
/// Parse an mvhd box.
3205
3216
fn read_mvhd < T : Read > ( src : & mut BMFFBox < T > ) -> Result < MovieHeaderBox > {
3206
3217
let ( version, _) = read_fullbox_extra ( src) ?;
3218
+ let to_u64 = |n| {
3219
+ if n == std:: u32:: MAX {
3220
+ std:: u64:: MAX
3221
+ } else {
3222
+ u64:: from ( n)
3223
+ }
3224
+ } ;
3225
+ let creation;
3226
+ let modification;
3207
3227
match version {
3208
3228
// 64 bit creation and modification times.
3209
3229
1 => {
3210
- skip ( src, 16 ) ?;
3230
+ creation = be_u64 ( src) ?;
3231
+ modification = be_u64 ( src) ?;
3211
3232
}
3212
3233
// 32 bit creation and modification times.
3213
3234
0 => {
3214
- skip ( src, 8 ) ?;
3235
+ creation = to_u64 ( be_u32 ( src) ?) ;
3236
+ modification = to_u64 ( be_u32 ( src) ?) ;
3215
3237
}
3216
3238
_ => return Err ( Error :: InvalidData ( "unhandled mvhd version" ) ) ,
3217
3239
}
3218
3240
let timescale = be_u32 ( src) ?;
3219
3241
let duration = match version {
3220
3242
1 => be_u64 ( src) ?,
3221
- 0 => {
3222
- let d = be_u32 ( src) ?;
3223
- if d == std:: u32:: MAX {
3224
- std:: u64:: MAX
3225
- } else {
3226
- u64:: from ( d)
3227
- }
3228
- }
3243
+ 0 => to_u64 ( be_u32 ( src) ?) ,
3229
3244
_ => return Err ( Error :: InvalidData ( "unhandled mvhd version" ) ) ,
3230
3245
} ;
3231
3246
// Skip remaining fields.
3232
3247
skip ( src, 80 ) ?;
3233
3248
Ok ( MovieHeaderBox {
3249
+ creation,
3250
+ modification,
3234
3251
timescale,
3235
3252
duration,
3236
3253
} )
0 commit comments