@@ -394,7 +394,7 @@ impl FormatReader for AdtsReader<'_> {
394
394
395
395
fn approximate_frame_count ( mut source : & mut MediaSourceStream < ' _ > ) -> Result < Option < u64 > > {
396
396
let original_pos = source. pos ( ) ;
397
- let total_len = match source. byte_len ( ) {
397
+ let remaining_len = match source. byte_len ( ) {
398
398
Some ( len) => len - original_pos,
399
399
_ => return Ok ( None ) ,
400
400
} ;
@@ -428,34 +428,48 @@ fn approximate_frame_count(mut source: &mut MediaSourceStream<'_>) -> Result<Opt
428
428
else {
429
429
// The number of points to sample within the stream.
430
430
const NUM_SAMPLE_POINTS : u64 = 4 ;
431
+ const NUM_FRAMES : u32 = 100 ;
431
432
432
- let step = ( total_len - original_pos ) / NUM_SAMPLE_POINTS ;
433
+ let step = remaining_len / NUM_SAMPLE_POINTS ;
433
434
434
- // Skip the first sample point (start of file) since it is an outlier.
435
- for new_pos in ( original_pos..total_len - step) . step_by ( step as usize ) . skip ( 1 ) {
436
- let res = source. seek ( SeekFrom :: Start ( new_pos) ) ;
437
- if res. is_err ( ) {
438
- break ;
439
- }
435
+ // file can be small enough and not have enough NUM_FRAMES, but we can still read at least one header
436
+ if step > 0 {
437
+ for new_pos in ( original_pos..( original_pos + remaining_len) ) . step_by ( step as usize ) {
438
+ let mut cur_pos = new_pos;
439
+ if source. seek ( SeekFrom :: Start ( cur_pos) ) . is_err ( ) {
440
+ break ;
441
+ }
442
+
443
+ for _ in 0 ..NUM_FRAMES {
444
+ let header = match AdtsHeader :: read ( & mut source) {
445
+ Ok ( header) => header,
446
+ _ => break ,
447
+ } ;
440
448
441
- for _ in 0 ..=100 {
442
- let header = match AdtsHeader :: read ( & mut source) {
443
- Ok ( header) => header,
444
- _ => break ,
445
- } ;
449
+ parsed_n_frames += 1 ;
450
+ n_bytes += u64:: from ( header. frame_len ) ;
446
451
447
- parsed_n_frames += 1 ;
448
- n_bytes += u64:: from ( header. frame_len ) ;
452
+ // skip frame to avoid meeting sync word in the audio data and for quick sync()
453
+ cur_pos += u64:: from ( header. frame_len ) ;
454
+ if source. seek ( SeekFrom :: Start ( cur_pos) ) . is_err ( ) {
455
+ break ;
456
+ }
457
+ }
458
+
459
+ // if reading NUM_FRAMES frames overflow the next step position then break
460
+ if cur_pos > new_pos + step {
461
+ break ;
462
+ }
449
463
}
450
464
}
451
465
452
466
let _ = source. seek ( SeekFrom :: Start ( original_pos) ) ?;
453
467
}
454
468
455
- debug ! ( "adts: parsed {} of {} bytes to approximate duration" , n_bytes, total_len ) ;
469
+ debug ! ( "adts: parsed {} of {} bytes to approximate duration" , n_bytes, remaining_len ) ;
456
470
457
471
match parsed_n_frames {
458
472
0 => Ok ( None ) ,
459
- _ => Ok ( Some ( total_len / ( n_bytes / parsed_n_frames) * SAMPLES_PER_AAC_PACKET ) ) ,
473
+ _ => Ok ( Some ( remaining_len / ( n_bytes / parsed_n_frames) * SAMPLES_PER_AAC_PACKET ) ) ,
460
474
}
461
475
}
0 commit comments