@ -252,6 +252,13 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f)
ret = AVERROR ( ENOMEM ) ;
ret = AVERROR ( ENOMEM ) ;
goto fail ;
goto fail ;
}
}
// The duration here is always the difference between consecutive
// start times and doesn't even try to read the actual duration of the
// media fragments. This is what other smooth streaming tools tend to
// do too, but cannot express missing fragments, and the start times
// may not match the stream metadata we get from libavformat. Correct
// calculation would require parsing the tfxd atom (if present, it's
// not mandatory) or parsing the full moof atoms separately.
for ( i = 0 ; i < track - > chunks ; i + + ) {
for ( i = 0 ; i < track - > chunks ; i + + ) {
if ( version = = 1 ) {
if ( version = = 1 ) {
track - > offsets [ i ] . time = avio_rb64 ( f ) ;
track - > offsets [ i ] . time = avio_rb64 ( f ) ;
@ -270,9 +277,30 @@ static int read_tfra(struct Tracks *tracks, int start_index, AVIOContext *f)
track - > offsets [ i - 1 ] . duration = track - > offsets [ i ] . time -
track - > offsets [ i - 1 ] . duration = track - > offsets [ i ] . time -
track - > offsets [ i - 1 ] . time ;
track - > offsets [ i - 1 ] . time ;
}
}
if ( track - > chunks > 0 )
if ( track - > chunks > 0 ) {
track - > offsets [ track - > chunks - 1 ] . duration = track - > duration -
track - > offsets [ track - > chunks - 1 ] . duration = track - > offsets [ 0 ] . time +
track - > duration -
track - > offsets [ track - > chunks - 1 ] . time ;
track - > offsets [ track - > chunks - 1 ] . time ;
if ( track - > offsets [ track - > chunks - 1 ] . duration < = 0 ) {
fprintf ( stderr , " Calculated last chunk duration for track %d "
" was non-positive (% " PRId64 " ), probably due to missing "
" fragments " , track - > track_id ,
track - > offsets [ track - > chunks - 1 ] . duration ) ;
if ( track - > chunks > 1 ) {
track - > offsets [ track - > chunks - 1 ] . duration =
track - > offsets [ track - > chunks - 2 ] . duration ;
} else {
track - > offsets [ track - > chunks - 1 ] . duration = 1 ;
}
fprintf ( stderr , " corrected to % " PRId64 " \n " ,
track - > offsets [ track - > chunks - 1 ] . duration ) ;
track - > duration = track - > offsets [ track - > chunks - 1 ] . time +
track - > offsets [ track - > chunks - 1 ] . duration -
track - > offsets [ 0 ] . time ;
fprintf ( stderr , " Track duration corrected to % " PRId64 " \n " ,
track - > duration ) ;
}
}
ret = 0 ;
ret = 0 ;
fail :
fail :
@ -524,6 +552,7 @@ static void print_track_chunks(FILE *out, struct Tracks *tracks, int main,
const char * type )
const char * type )
{
{
int i , j ;
int i , j ;
int64_t pos = 0 ;
struct Track * track = tracks - > tracks [ main ] ;
struct Track * track = tracks - > tracks [ main ] ;
int should_print_time_mismatch = 1 ;
int should_print_time_mismatch = 1 ;
@ -543,8 +572,18 @@ static void print_track_chunks(FILE *out, struct Tracks *tracks, int main,
}
}
}
}
}
}
fprintf ( out , " \t \t <c n= \" %d \" d= \" % " PRId64 " \" /> \n " ,
fprintf ( out , " \t \t <c n= \" %d \" d= \" % " PRId64 " \" " ,
i , track - > offsets [ i ] . duration ) ;
i , track - > offsets [ i ] . duration ) ;
if ( pos ! = track - > offsets [ i ] . time ) {
// With the current logic for calculation of durations from
// chunk start times, this branch can only be hit on the first
// chunk - but that's still useful and this will keep working
// if the duration calculation is improved.
fprintf ( out , " t= \" % " PRId64 " \" " , track - > offsets [ i ] . time ) ;
pos = track - > offsets [ i ] . time ;
}
pos + = track - > offsets [ i ] . duration ;
fprintf ( out , " /> \n " ) ;
}
}
}
}