📄 avi.c
字号:
p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time ); } }#if 1 if( p_sys->i_time ) { i_date = p_sys->i_time; } /* seek for bytes based streams */ for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { if( p_stream->b_activated && p_stream->i_samplesize ) { AVI_TrackSeek( p_demux, i_stream, i_date );/* p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time );*/ } } msg_Dbg( p_demux, "seek: "I64Fd" seconds", p_sys->i_time /1000000 ); /* set true movie time */#endif if( !p_sys->i_time ) { p_sys->i_time = i_date; }#undef p_stream return VLC_SUCCESS; } else { msg_Err( p_demux, "shouldn't yet be executed" ); return VLC_EGENERIC; }}/***************************************************************************** * Control: ***************************************************************************** * *****************************************************************************/static double ControlGetPosition( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; if( p_sys->i_length > 0 ) { return (double)p_sys->i_time / (double)( p_sys->i_length * (mtime_t)1000000 ); } else if( stream_Size( p_demux->s ) > 0 ) { unsigned int i; int64_t i_tmp; int64_t i64 = 0; /* search the more advanced selected es */ for( i = 0; i < p_sys->i_track; i++ ) { avi_track_t *tk = p_sys->track[i]; if( tk->b_activated && tk->i_idxposc < tk->i_idxnb ) { i_tmp = tk->p_index[tk->i_idxposc].i_pos + tk->p_index[tk->i_idxposc].i_length + 8; if( i_tmp > i64 ) { i64 = i_tmp; } } } return (double)i64 / stream_Size( p_demux->s ); } return 0.0;}static int Control( demux_t *p_demux, int i_query, va_list args ){ demux_sys_t *p_sys = p_demux->p_sys; int i; double f, *pf; int64_t i64, *pi64; vlc_meta_t **pp_meta; switch( i_query ) { case DEMUX_GET_POSITION: pf = (double*)va_arg( args, double * ); *pf = ControlGetPosition( p_demux ); return VLC_SUCCESS; case DEMUX_SET_POSITION: f = (double)va_arg( args, double ); if( p_sys->b_seekable ) { i64 = (mtime_t)(1000000.0 * p_sys->i_length * f ); return Seek( p_demux, i64, (int)(f * 100) ); } else { int64_t i_pos = stream_Size( p_demux->s ) * f; return stream_Seek( p_demux->s, i_pos ); } case DEMUX_GET_TIME: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_time; return VLC_SUCCESS; case DEMUX_SET_TIME: { int i_percent = 0; i64 = (int64_t)va_arg( args, int64_t ); if( p_sys->i_length > 0 ) { i_percent = 100 * i64 / (p_sys->i_length*1000000); } else if( p_sys->i_time > 0 ) { i_percent = (int)( 100.0 * ControlGetPosition( p_demux ) * (double)i64 / (double)p_sys->i_time ); } return Seek( p_demux, i64, i_percent ); } case DEMUX_GET_LENGTH: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = p_sys->i_length * (mtime_t)1000000; return VLC_SUCCESS; case DEMUX_GET_FPS: pf = (double*)va_arg( args, double * ); *pf = 0.0; for( i = 0; i < (int)p_sys->i_track; i++ ) { avi_track_t *tk = p_sys->track[i]; if( tk->i_cat == VIDEO_ES && tk->i_scale > 0) { *pf = (float)tk->i_rate / (float)tk->i_scale; break; } } return VLC_SUCCESS; case DEMUX_GET_META: pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); *pp_meta = vlc_meta_Duplicate( p_sys->meta ); return VLC_SUCCESS; default: return VLC_EGENERIC; }}/***************************************************************************** * Function to convert pts to chunk or byte *****************************************************************************/static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts ){ if( !tk->i_scale ) return (mtime_t)0; return (mtime_t)((int64_t)i_pts * (int64_t)tk->i_rate / (int64_t)tk->i_scale / (int64_t)1000000 );}static mtime_t AVI_PTSToByte( avi_track_t *tk, mtime_t i_pts ){ if( !tk->i_scale || !tk->i_samplesize ) return (mtime_t)0; return (mtime_t)((int64_t)i_pts * (int64_t)tk->i_rate / (int64_t)tk->i_scale / (int64_t)1000000 * (int64_t)tk->i_samplesize );}static mtime_t AVI_GetDPTS( avi_track_t *tk, int64_t i_count ){ mtime_t i_dpts = 0; if( !tk->i_rate ) return i_dpts; i_dpts = (mtime_t)( (int64_t)1000000 * (int64_t)i_count * (int64_t)tk->i_scale / (int64_t)tk->i_rate ); if( tk->i_samplesize ) { return i_dpts / tk->i_samplesize; } return i_dpts;}static mtime_t AVI_GetPTS( avi_track_t *tk ){ if( tk->i_samplesize ) { int64_t i_count = 0; /* we need a valid entry we will emulate one */ if( tk->i_idxposc == tk->i_idxnb ) { if( tk->i_idxposc ) { /* use the last entry */ i_count = tk->p_index[tk->i_idxnb - 1].i_lengthtotal + tk->p_index[tk->i_idxnb - 1].i_length; } } else { i_count = tk->p_index[tk->i_idxposc].i_lengthtotal; } return AVI_GetDPTS( tk, i_count + tk->i_idxposb ); } else { if( tk->i_cat == AUDIO_ES ) { return AVI_GetDPTS( tk, tk->i_blockno ); } else { return AVI_GetDPTS( tk, tk->i_idxposc ); } }}static int AVI_StreamChunkFind( demux_t *p_demux, unsigned int i_stream ){ demux_sys_t *p_sys = p_demux->p_sys; avi_packet_t avi_pk; int i_loop_count = 0; /* find first chunk of i_stream that isn't in index */ if( p_sys->i_movi_lastchunk_pos >= p_sys->i_movi_begin + 12 ) { stream_Seek( p_demux->s, p_sys->i_movi_lastchunk_pos ); if( AVI_PacketNext( p_demux ) ) { return VLC_EGENERIC; } } else { stream_Seek( p_demux->s, p_sys->i_movi_begin + 12 ); } for( ;; ) { if( p_demux->b_die ) return VLC_EGENERIC; if( AVI_PacketGetHeader( p_demux, &avi_pk ) ) { msg_Warn( p_demux, "cannot get packet header" ); return VLC_EGENERIC; } if( avi_pk.i_stream >= p_sys->i_track || ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) ) { if( AVI_PacketNext( p_demux ) ) { return VLC_EGENERIC; } /* Prevents from eating all the CPU with broken files. * This value should be low enough so that it doesn't * affect the reading speed too much. */ if( !(++i_loop_count % 1024) ) { if( p_demux->b_die ) return VLC_EGENERIC; msleep( 10000 ); if( !(i_loop_count % (1024 * 10)) ) msg_Warn( p_demux, "don't seem to find any data..." ); } } else { /* add this chunk to the index */ avi_entry_t index; index.i_id = avi_pk.i_fourcc; index.i_flags = AVI_GetKeyFlag(p_sys->track[avi_pk.i_stream]->i_codec, avi_pk.i_peek); index.i_pos = avi_pk.i_pos; index.i_length = avi_pk.i_size; AVI_IndexAddEntry( p_sys, avi_pk.i_stream, &index ); if( avi_pk.i_stream == i_stream ) { return VLC_SUCCESS; } if( AVI_PacketNext( p_demux ) ) { return VLC_EGENERIC; } } }}/* be sure that i_ck will be a valid index entry */static int AVI_StreamChunkSet( demux_t *p_demux, unsigned int i_stream, unsigned int i_ck ){ demux_sys_t *p_sys = p_demux->p_sys; avi_track_t *p_stream = p_sys->track[i_stream]; p_stream->i_idxposc = i_ck; p_stream->i_idxposb = 0; if( i_ck >= p_stream->i_idxnb ) { p_stream->i_idxposc = p_stream->i_idxnb - 1; do { p_stream->i_idxposc++; if( AVI_StreamChunkFind( p_demux, i_stream ) ) { return VLC_EGENERIC; } } while( p_stream->i_idxposc < i_ck ); } return VLC_SUCCESS;}/* XXX FIXME up to now, we assume that all chunk are one after one */static int AVI_StreamBytesSet( demux_t *p_demux, unsigned int i_stream, off_t i_byte ){ demux_sys_t *p_sys = p_demux->p_sys; avi_track_t *p_stream = p_sys->track[i_stream]; if( ( p_stream->i_idxnb > 0 ) &&( i_byte < p_stream->p_index[p_stream->i_idxnb - 1].i_lengthtotal + p_stream->p_index[p_stream->i_idxnb - 1].i_length ) ) { /* index is valid to find the ck */ /* uses dichototmie to be fast enougth */ int i_idxposc = __MIN( p_stream->i_idxposc, p_stream->i_idxnb - 1 ); int i_idxmax = p_stream->i_idxnb; int i_idxmin = 0; for( ;; ) { if( p_stream->p_index[i_idxposc].i_lengthtotal > i_byte ) { i_idxmax = i_idxposc ; i_idxposc = ( i_idxmin + i_idxposc ) / 2 ; } else { if( p_stream->p_index[i_idxposc].i_lengthtotal + p_stream->p_index[i_idxposc].i_length <= i_byte) { i_idxmin = i_idxposc ; i_idxposc = (i_idxmax + i_idxposc ) / 2 ; } else { p_stream->i_idxposc = i_idxposc; p_stream->i_idxposb = i_byte - p_stream->p_index[i_idxposc].i_lengthtotal; return VLC_SUCCESS; } } } } else { p_stream->i_idxposc = p_stream->i_idxnb - 1; p_stream->i_idxposb = 0; do { p_stream->i_idxposc++; if( AVI_StreamChunkFind( p_demux, i_stream ) ) { return VLC_EGENERIC; } } while( p_stream->p_index[p_stream->i_idxposc].i_lengthtotal + p_stream->p_index[p_stream->i_idxposc].i_length <= i_byte ); p_stream->i_idxposb = i_byte - p_stream->p_index[p_stream->i_idxposc].i_lengthtotal; return VLC_SUCCESS; }}static int AVI_TrackSeek( demux_t *p_demux, int i_stream, mtime_t i_date ){ demux_sys_t *p_sys = p_demux->p_sys; avi_track_t *tk = p_sys->track[i_stream];#define p_stream p_sys->track[i_stream] mtime_t i_oldpts; i_oldpts = AVI_GetPTS( p_stream ); if( !p_stream->i_samplesize ) { if( AVI_StreamChunkSet( p_demux, i_stream, AVI_PTSToChunk( p_stream, i_date ) ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -