vlc | branch: master | Francois Cartegnie <[email protected]> | Fri Oct 28 23:10:50 2016 +0200| [daca57aeccb49009cdbabcc04d60d55242880a33] | committer: Francois Cartegnie
demux: mp4: fix and improve interleaving detection On compressed content, all chunks are separate > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=daca57aeccb49009cdbabcc04d60d55242880a33 --- modules/demux/mp4/mp4.c | 84 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 22 deletions(-) diff --git a/modules/demux/mp4/mp4.c b/modules/demux/mp4/mp4.c index 15fbb59..4b98566 100644 --- a/modules/demux/mp4/mp4.c +++ b/modules/demux/mp4/mp4.c @@ -124,7 +124,6 @@ static uint64_t MP4_TrackGetPos ( mp4_track_t * ); static uint32_t MP4_TrackGetReadSize( mp4_track_t *, uint32_t * ); static int MP4_TrackNextSample( demux_t *, mp4_track_t *, uint32_t ); static void MP4_TrackSetELST( demux_t *, mp4_track_t *, int64_t ); -static bool MP4_TrackIsInterleaved( const mp4_track_t * ); static void MP4_UpdateSeekpoint( demux_t * ); @@ -401,6 +400,64 @@ static block_t * MP4_EIA608_Convert( block_t * p_block ) return p_newblock; } +/* Analyzes chunks to find max interleave length + * sets flat flag if no interleaving is in use */ +static void MP4_GetInterleaving( demux_t *p_demux, uint64_t *pi_max_contiguous, bool *pb_flat ) +{ + demux_sys_t *p_sys = p_demux->p_sys; + *pi_max_contiguous = 0; + *pb_flat = true; + + /* Find first recorded chunk */ + mp4_track_t *tk = NULL; + uint64_t i_duration = 0; + for( unsigned i=0; i < p_sys->i_tracks; i++ ) + { + mp4_track_t *cur = &p_sys->track[i]; + if( !cur->i_chunk_count ) + continue; + + if( tk == NULL || cur->chunk[0].i_offset < tk->chunk[0].i_offset ) + tk = cur; + } + + for( ; tk != NULL; ) + { + i_duration += tk->chunk[tk->i_chunk].i_duration; + tk->i_chunk++; + + /* Find next chunk in data order */ + mp4_track_t *nexttk = NULL; + for( unsigned i=0; i < p_sys->i_tracks; i++ ) + { + mp4_track_t *cur = &p_sys->track[i]; + if( cur->i_chunk == cur->i_chunk_count ) + continue; + + if( nexttk == NULL || + cur->chunk[cur->i_chunk].i_offset < nexttk->chunk[nexttk->i_chunk].i_offset ) + nexttk = cur; + } + + if( tk != nexttk ) + { + i_duration = i_duration * CLOCK_FREQ / tk->i_timescale; + if( i_duration > *pi_max_contiguous ) + *pi_max_contiguous = i_duration; + i_duration = 0; + + if( tk->i_chunk != tk->i_chunk_count ) + *pb_flat = false; + } + + tk = nexttk; + } + + /* reset */ + for( unsigned i=0; i < p_sys->i_tracks; i++ ) + p_sys->track[i].i_chunk = 0; +} + static block_t * MP4_Block_Read( demux_t *p_demux, const mp4_track_t *p_track, int i_size ) { block_t *p_block = vlc_stream_Block( p_demux->s, i_size ); @@ -844,15 +901,13 @@ static int Open( vlc_object_t * p_this ) if( !p_sys->b_fragmented && p_sys->i_tracks > 1 && p_sys->b_seekable && !p_sys->b_seekmode ) { - for( unsigned i = 0; i < p_sys->i_tracks; i++ ) + uint64_t i_max_continuity; + bool b_flat; + MP4_GetInterleaving( p_demux, &i_max_continuity, &b_flat ); + if( b_flat ) { - mp4_track_t *tk = &p_sys->track[i]; - if( !MP4_TrackIsInterleaved( tk ) ) - { msg_Warn( p_demux, "that media doesn't look interleaved, will need to seek"); p_sys->b_seekmode = true; - break; - } } } @@ -1942,21 +1997,6 @@ static void LoadChapter( demux_t *p_demux ) } } -static bool MP4_TrackIsInterleaved( const mp4_track_t *p_track ) -{ - const MP4_Box_t *p_stsc = MP4_BoxGet( p_track->p_stbl, "stsc" ); - const MP4_Box_t *p_stsz = MP4_BoxGet( p_track->p_stbl, "stsz" ); - if( p_stsc && BOXDATA(p_stsc) && p_stsz && BOXDATA(p_stsz) ) - { - if( BOXDATA(p_stsc)->i_entry_count == 1 && - BOXDATA(p_stsz)->i_sample_count > 1 && - BOXDATA(p_stsc)->i_samples_per_chunk[0] == BOXDATA(p_stsz)->i_sample_count ) - return false; - } - - return true; -} - /* now create basic chunk data, the rest will be filled by MP4_CreateSamplesIndex */ static int TrackCreateChunksIndex( demux_t *p_demux, mp4_track_t *p_demux_track ) _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
