vlc | branch: master | Francois Cartegnie <fcvlc...@free.fr> | Thu Apr 24 19:21:50 2014 +0200| [665f88b453dd7c8073b7b54448b9e7420026a973] | committer: Francois Cartegnie
demux: avi: lazy load indexes if not fastseekable refs #1532 > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=665f88b453dd7c8073b7b54448b9e7420026a973 --- modules/demux/avi/avi.c | 55 +++++++++++++++++++++++++++++++++++++++----- modules/demux/avi/libavi.c | 50 ++++++++++++++++++++++++++++++++++++++++ modules/demux/avi/libavi.h | 1 + 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/modules/demux/avi/avi.c b/modules/demux/avi/avi.c index 8c23d1e..b468bb1 100644 --- a/modules/demux/avi/avi.c +++ b/modules/demux/avi/avi.c @@ -175,6 +175,8 @@ struct demux_sys_t bool b_seekable; bool b_fastseekable; + bool b_indexloaded; /* if we read indexes from end of file before starting */ + uint32_t i_avih_flags; avi_chunk_t ck_root; bool b_odml; @@ -374,6 +376,7 @@ static int Open( vlc_object_t * p_this ) p_avih->i_flags&AVIF_TRUSTCKTYPE?" TRUST_CKTYPE":"" ); AVI_MetaLoad( p_demux, p_riff, p_avih ); + p_sys->i_avih_flags = p_avih->i_flags; /* now read info on each stream and create ES */ for( i = 0 ; i < i_track; i++ ) @@ -1426,19 +1429,48 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent ) if( p_sys->b_seekable ) { + int64_t i_pos_backup = stream_Tell( p_demux->s ); + + /* Check and lazy load indexes if it was not done (not fastseekable) */ + if ( !p_sys->b_indexloaded && ( p_sys->i_avih_flags & AVIF_HASINDEX ) ) + { + avi_chunk_t *p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0 ); + if (unlikely( !p_riff )) + return VLC_EGENERIC; + + int i_ret = AVI_ChunkFetchIndexes( p_demux->s, p_riff ); + if ( i_ret ) + { + /* Go back to position before index failure */ + if ( stream_Tell( p_demux->s ) - i_pos_backup ) + stream_Seek( p_demux->s, i_pos_backup ); + + if ( p_sys->i_avih_flags & AVIF_MUSTUSEINDEX ) + return VLC_EGENERIC; + } + else AVI_IndexLoad( p_demux ); + + p_sys->b_indexloaded = true; /* we don't want to try each time */ + } + if( !p_sys->i_length ) { avi_track_t *p_stream = NULL; unsigned i_stream = 0; int64_t i_pos; + if ( !p_sys->i_movi_lastchunk_pos && /* set when index is successfully loaded */ + ! ( p_sys->i_avih_flags & AVIF_ISINTERLEAVED ) ) + { + msg_Err( p_demux, "seeking without index at %d%%" + " only works for interleaved files", i_percent ); + goto failandresetpos; + } /* use i_percent to create a true i_date */ - msg_Warn( p_demux, "seeking without index at %d%%" - " only works for interleaved files", i_percent ); if( i_percent >= 100 ) { msg_Warn( p_demux, "cannot seek so far !" ); - return VLC_EGENERIC; + goto failandresetpos; } i_percent = __MAX( i_percent, 0 ); @@ -1460,14 +1492,14 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent ) if( p_stream == NULL ) { msg_Warn( p_demux, "cannot find any selected stream" ); - return VLC_EGENERIC; + goto failandresetpos; } /* be sure that the index exist */ if( AVI_StreamChunkSet( p_demux, i_stream, 0 ) ) { msg_Warn( p_demux, "cannot seek" ); - return VLC_EGENERIC; + goto failandresetpos; } while( i_pos >= p_stream->idx.p_entry[p_stream->i_idxposc].i_pos + @@ -1478,7 +1510,7 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent ) i_stream, p_stream->i_idxposc + 1 ) ) { msg_Warn( p_demux, "cannot seek" ); - return VLC_EGENERIC; + goto failandresetpos; } } @@ -1501,6 +1533,13 @@ static int Seek( demux_t *p_demux, mtime_t i_date, int i_percent ) p_sys->i_time = i_date; msg_Dbg( p_demux, "seek: %"PRId64" seconds", p_sys->i_time /1000000 ); return VLC_SUCCESS; + +failandresetpos: + /* Go back to position before index failure */ + if ( stream_Tell( p_demux->s ) - i_pos_backup ) + stream_Seek( p_demux->s, i_pos_backup ); + + return VLC_EGENERIC; } else { @@ -2296,6 +2335,8 @@ static int AVI_IndexLoad_idx1( demux_t *p_demux, if( AVI_IndexFind_idx1( p_demux, &p_idx1, &i_offset ) ) return VLC_EGENERIC; + p_sys->b_indexloaded = true; + for( unsigned i_index = 0; i_index < p_idx1->i_entry_count; i_index++ ) { unsigned i_cat; @@ -2325,6 +2366,8 @@ static void __Parse_indx( demux_t *p_demux, avi_index_t *p_index, off_t *pi_max_ { avi_entry_t index; + p_demux->p_sys->b_indexloaded = true; + msg_Dbg( p_demux, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse ); if( p_indx->i_indexsubtype == 0 ) { diff --git a/modules/demux/avi/libavi.c b/modules/demux/avi/libavi.c index d237cfa..c8a1eff 100644 --- a/modules/demux/avi/libavi.c +++ b/modules/demux/avi/libavi.c @@ -202,6 +202,56 @@ static int AVI_ChunkRead_list( stream_t *s, avi_chunk_t *p_container ) return VLC_SUCCESS; } +/* Allow to append indexes after starting playback */ +int AVI_ChunkFetchIndexes( stream_t *s, avi_chunk_t *p_riff ) +{ + avi_chunk_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 ); + if ( !p_movi ) + return VLC_EGENERIC; + + avi_chunk_t *p_chk; + uint64_t i_indexpos = 8 + p_movi->common.i_chunk_pos + p_movi->common.i_chunk_size; + bool b_seekable = false; + int i_ret = VLC_SUCCESS; + + stream_Control( s, STREAM_CAN_SEEK, &b_seekable ); + if ( !b_seekable || stream_Seek( s, i_indexpos ) ) + return VLC_EGENERIC; + + for( ; ; ) + { + p_chk = xmalloc( sizeof( avi_chunk_t ) ); + memset( p_chk, 0, sizeof( avi_chunk_t ) ); + if (unlikely( !p_riff->common.p_first )) + p_riff->common.p_first = p_chk; + else + p_riff->common.p_last->common.p_next = p_chk; + p_riff->common.p_last = p_chk; + + i_ret = AVI_ChunkRead( s, p_chk, p_riff ); + if( i_ret ) + break; + + if( p_chk->common.p_father->common.i_chunk_size > 0 && + ( stream_Tell( s ) > + (off_t)p_chk->common.p_father->common.i_chunk_pos + + (off_t)__EVEN( p_chk->common.p_father->common.i_chunk_size ) ) ) + { + break; + } + + /* If we can't seek then stop when we 've found any index */ + if( p_chk->common.i_chunk_fourcc == AVIFOURCC_indx || + p_chk->common.i_chunk_fourcc == AVIFOURCC_idx1 ) + { + break; + } + + } + + return i_ret; +} + #define AVI_READCHUNK_ENTER \ int64_t i_read = __EVEN(p_chk->common.i_chunk_size ) + 8; \ if( i_read > 100000000 ) \ diff --git a/modules/demux/avi/libavi.h b/modules/demux/avi/libavi.h index 2149223..83f004d 100644 --- a/modules/demux/avi/libavi.h +++ b/modules/demux/avi/libavi.h @@ -259,6 +259,7 @@ void *_AVI_ChunkFind ( avi_chunk_t *, vlc_fourcc_t, int ); int AVI_ChunkReadRoot( stream_t *, avi_chunk_t *p_root ); void AVI_ChunkFreeRoot( stream_t *, avi_chunk_t *p_chk ); +int AVI_ChunkFetchIndexes( stream_t *, avi_chunk_t *p_riff ); #define AVI_ChunkCount( p_chk, i_fourcc ) \ _AVI_ChunkCount( AVI_CHUNK(p_chk), i_fourcc ) _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits