@@ -211,12 +211,13 @@ impl Mp4Properties {
211
211
}
212
212
}
213
213
214
- struct TrakChildren {
214
+ struct AudioTrak {
215
215
mdhd : AtomInfo ,
216
216
minf : Option < AtomInfo > ,
217
217
}
218
218
219
- fn get_trak_children < R > ( reader : & mut AtomReader < R > , traks : & [ AtomInfo ] ) -> Result < TrakChildren >
219
+ /// Search through all the traks to find the first one with audio
220
+ fn find_audio_trak < R > ( reader : & mut AtomReader < R > , traks : & [ AtomInfo ] ) -> Result < AudioTrak >
220
221
where
221
222
R : Read + Seek ,
222
223
{
@@ -230,6 +231,9 @@ where
230
231
break ;
231
232
}
232
233
234
+ mdhd = None ;
235
+ minf = None ;
236
+
233
237
reader. seek ( SeekFrom :: Start ( mdia. start + 8 ) ) ?;
234
238
235
239
let mut read = 8 ;
@@ -284,44 +288,46 @@ where
284
288
err ! ( BadAtom ( "Expected atom \" trak.mdia.mdhd\" " ) ) ;
285
289
} ;
286
290
287
- Ok ( TrakChildren { mdhd, minf } )
291
+ Ok ( AudioTrak { mdhd, minf } )
288
292
}
289
293
290
294
struct Mdhd {
291
295
timescale : u32 ,
292
296
duration : u64 ,
293
297
}
294
298
295
- fn read_mdhd < R > ( reader : & mut AtomReader < R > ) -> Result < Mdhd >
296
- where
297
- R : Read + Seek ,
298
- {
299
- let version = reader. read_u8 ( ) ?;
300
- let _flags = reader. read_uint ( 3 ) ?;
299
+ impl Mdhd {
300
+ fn parse < R > ( reader : & mut AtomReader < R > ) -> Result < Self >
301
+ where
302
+ R : Read + Seek ,
303
+ {
304
+ let version = reader. read_u8 ( ) ?;
305
+ let _flags = reader. read_uint ( 3 ) ?;
301
306
302
- let ( timescale, duration) = if version == 1 {
303
- // We don't care about these two values
304
- let _creation_time = reader. read_u64 ( ) ?;
305
- let _modification_time = reader. read_u64 ( ) ?;
307
+ let ( timescale, duration) = if version == 1 {
308
+ // We don't care about these two values
309
+ let _creation_time = reader. read_u64 ( ) ?;
310
+ let _modification_time = reader. read_u64 ( ) ?;
306
311
307
- let timescale = reader. read_u32 ( ) ?;
308
- let duration = reader. read_u64 ( ) ?;
312
+ let timescale = reader. read_u32 ( ) ?;
313
+ let duration = reader. read_u64 ( ) ?;
309
314
310
- ( timescale, duration)
311
- } else {
312
- let _creation_time = reader. read_u32 ( ) ?;
313
- let _modification_time = reader. read_u32 ( ) ?;
315
+ ( timescale, duration)
316
+ } else {
317
+ let _creation_time = reader. read_u32 ( ) ?;
318
+ let _modification_time = reader. read_u32 ( ) ?;
314
319
315
- let timescale = reader. read_u32 ( ) ?;
316
- let duration = reader. read_u32 ( ) ?;
320
+ let timescale = reader. read_u32 ( ) ?;
321
+ let duration = reader. read_u32 ( ) ?;
317
322
318
- ( timescale, u64:: from ( duration) )
319
- } ;
323
+ ( timescale, u64:: from ( duration) )
324
+ } ;
320
325
321
- Ok ( Mdhd {
322
- timescale,
323
- duration,
324
- } )
326
+ Ok ( Mdhd {
327
+ timescale,
328
+ duration,
329
+ } )
330
+ }
325
331
}
326
332
327
333
// TODO: Estimate duration from stts?
@@ -334,76 +340,85 @@ struct SttsEntry {
334
340
sample_duration : u32 ,
335
341
}
336
342
337
- fn read_stts < R > ( reader : & mut R ) -> Result < Vec < SttsEntry > >
338
- where
339
- R : Read ,
340
- {
341
- let _version_and_flags = reader. read_uint :: < BigEndian > ( 4 ) ?;
343
+ #[ derive( Debug ) ]
344
+ struct Stts {
345
+ entries : Vec < SttsEntry > ,
346
+ }
342
347
343
- let entry_count = reader. read_u32 :: < BigEndian > ( ) ?;
344
- let mut entries = Vec :: try_with_capacity_stable ( entry_count as usize ) ?;
348
+ impl Stts {
349
+ fn parse < R > ( reader : & mut R ) -> Result < Self >
350
+ where
351
+ R : Read ,
352
+ {
353
+ let _version_and_flags = reader. read_uint :: < BigEndian > ( 4 ) ?;
345
354
346
- for _ in 0 ..entry_count {
347
- let sample_count = reader. read_u32 :: < BigEndian > ( ) ?;
348
- let sample_duration = reader. read_u32 :: < BigEndian > ( ) ?;
355
+ let entry_count = reader. read_u32 :: < BigEndian > ( ) ?;
356
+ let mut entries = Vec :: try_with_capacity_stable ( entry_count as usize ) ?;
349
357
350
- entries. push ( SttsEntry {
351
- _sample_count : sample_count,
352
- sample_duration,
353
- } ) ;
354
- }
358
+ for _ in 0 ..entry_count {
359
+ let sample_count = reader. read_u32 :: < BigEndian > ( ) ?;
360
+ let sample_duration = reader. read_u32 :: < BigEndian > ( ) ?;
355
361
356
- Ok ( entries)
362
+ entries. push ( SttsEntry {
363
+ _sample_count : sample_count,
364
+ sample_duration,
365
+ } ) ;
366
+ }
367
+
368
+ Ok ( Self { entries } )
369
+ }
357
370
}
358
371
359
372
struct Minf {
360
373
stsd_data : Vec < u8 > ,
361
- stts : Option < Vec < SttsEntry > > ,
374
+ stts : Option < Stts > ,
362
375
}
363
376
364
- fn read_minf < R > (
365
- reader : & mut AtomReader < R > ,
366
- len : u64 ,
367
- parse_mode : ParsingMode ,
368
- ) -> Result < Option < Minf > >
369
- where
370
- R : Read + Seek ,
371
- {
372
- let Some ( stbl) = find_child_atom ( reader, len, * b"stbl" , parse_mode) ? else {
373
- return Ok ( None ) ;
374
- } ;
377
+ impl Minf {
378
+ fn parse < R > (
379
+ reader : & mut AtomReader < R > ,
380
+ len : u64 ,
381
+ parse_mode : ParsingMode ,
382
+ ) -> Result < Option < Self > >
383
+ where
384
+ R : Read + Seek ,
385
+ {
386
+ let Some ( stbl) = find_child_atom ( reader, len, * b"stbl" , parse_mode) ? else {
387
+ return Ok ( None ) ;
388
+ } ;
375
389
376
- let mut stsd_data = None ;
377
- let mut stts = None ;
378
-
379
- let mut read = 8 ;
380
- while read < stbl. len {
381
- let Some ( atom) = reader. next ( ) ? else { break } ;
382
-
383
- read += atom. len ;
384
-
385
- if let AtomIdent :: Fourcc ( fourcc) = atom. ident {
386
- match & fourcc {
387
- b"stsd" => {
388
- let mut stsd = try_vec ! [ 0 ; ( atom. len - 8 ) as usize ] ;
389
- reader. read_exact ( & mut stsd) ?;
390
- stsd_data = Some ( stsd) ;
391
- } ,
392
- b"stts" => stts = Some ( read_stts ( reader) ?) ,
393
- _ => {
394
- skip_atom ( reader, atom. extended , atom. len ) ?;
395
- } ,
396
- }
390
+ let mut stsd_data = None ;
391
+ let mut stts = None ;
392
+
393
+ let mut read = 8 ;
394
+ while read < stbl. len {
395
+ let Some ( atom) = reader. next ( ) ? else { break } ;
396
+
397
+ read += atom. len ;
398
+
399
+ if let AtomIdent :: Fourcc ( fourcc) = atom. ident {
400
+ match & fourcc {
401
+ b"stsd" => {
402
+ let mut stsd = try_vec ! [ 0 ; ( atom. len - 8 ) as usize ] ;
403
+ reader. read_exact ( & mut stsd) ?;
404
+ stsd_data = Some ( stsd) ;
405
+ } ,
406
+ b"stts" => stts = Some ( Stts :: parse ( reader) ?) ,
407
+ _ => {
408
+ skip_atom ( reader, atom. extended , atom. len ) ?;
409
+ } ,
410
+ }
397
411
398
- continue ;
412
+ continue ;
413
+ }
399
414
}
400
- }
401
415
402
- let Some ( stsd_data) = stsd_data else {
403
- return Ok ( None ) ;
404
- } ;
416
+ let Some ( stsd_data) = stsd_data else {
417
+ return Ok ( None ) ;
418
+ } ;
405
419
406
- Ok ( Some ( Minf { stsd_data, stts } ) )
420
+ Ok ( Some ( Minf { stsd_data, stts } ) )
421
+ }
407
422
}
408
423
409
424
fn read_stsd < R > ( reader : & mut AtomReader < R > , properties : & mut Mp4Properties ) -> Result < ( ) >
@@ -467,13 +482,13 @@ where
467
482
R : Read + Seek ,
468
483
{
469
484
// We need the mdhd and minf atoms from the audio track
470
- let TrakChildren { mdhd, minf } = get_trak_children ( reader, traks) ?;
485
+ let AudioTrak { mdhd, minf } = find_audio_trak ( reader, traks) ?;
471
486
472
487
reader. seek ( SeekFrom :: Start ( mdhd. start + 8 ) ) ?;
473
488
let Mdhd {
474
489
timescale,
475
490
duration,
476
- } = read_mdhd ( reader) ?;
491
+ } = Mdhd :: parse ( reader) ?;
477
492
478
493
// We create the properties here, since it is possible the other information isn't available
479
494
let mut properties = Mp4Properties :: default ( ) ;
@@ -489,7 +504,7 @@ where
489
504
} ;
490
505
491
506
reader. seek ( SeekFrom :: Start ( minf_info. start + 8 ) ) ?;
492
- let Some ( Minf { stsd_data, stts } ) = read_minf ( reader, minf_info. len , parse_mode) ? else {
507
+ let Some ( Minf { stsd_data, stts } ) = Minf :: parse ( reader, minf_info. len , parse_mode) ? else {
493
508
return Ok ( properties) ;
494
509
} ;
495
510
@@ -505,7 +520,8 @@ where
505
520
let mdat_len = mdat_length ( reader) ?;
506
521
507
522
if let Some ( stts) = stts {
508
- let stts_specifies_duration = !( stts. len ( ) == 1 && stts[ 0 ] . sample_duration == 1 ) ;
523
+ let stts_specifies_duration =
524
+ !( stts. entries . len ( ) == 1 && stts. entries [ 0 ] . sample_duration == 1 ) ;
509
525
if stts_specifies_duration {
510
526
// We do a basic audio bitrate calculation below for each stream type.
511
527
// Up here, we can do a more accurate calculation if the duration is available.
0 commit comments