avi.c
来自「VLC媒体播放程序」· C语言 代码 · 共 2,041 行 · 第 1/5 页
C
2,041 行
/***************************************************************************** * Function to convert pts to chunk or byte *****************************************************************************/static mtime_t AVI_PTSToChunk( avi_track_t *tk, mtime_t i_pts ){ 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 ){ 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; 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( input_thread_t *p_input, unsigned int i_stream ){ demux_sys_t *p_sys = p_input->p_demux_data; avi_packet_t avi_pk; /* 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_input->s, p_sys->i_movi_lastchunk_pos ); if( AVI_PacketNext( p_input ) ) { return VLC_EGENERIC; } } else { stream_Seek( p_input->s, p_sys->i_movi_begin + 12 ); } for( ;; ) { if( p_input->b_die ) { return VLC_EGENERIC; } if( AVI_PacketGetHeader( p_input, &avi_pk ) ) { msg_Warn( p_input, "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_input ) ) { return VLC_EGENERIC; } } else { /* add this chunk to the index */ AVIIndexEntry_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_input ) ) { return VLC_EGENERIC; } } }}/* be sure that i_ck will be a valid index entry */static int AVI_StreamChunkSet( input_thread_t *p_input, unsigned int i_stream, unsigned int i_ck ){ demux_sys_t *p_sys = p_input->p_demux_data; 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_input, 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( input_thread_t *p_input, unsigned int i_stream, off_t i_byte ){ demux_sys_t *p_sys = p_input->p_demux_data; 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_input, 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( input_thread_t *p_input, int i_stream, mtime_t i_date ){ demux_sys_t *p_sys = p_input->p_demux_data; 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_input, i_stream, AVI_PTSToChunk( p_stream, i_date ) ) ) { return VLC_EGENERIC; } if( p_stream->i_cat == AUDIO_ES ) { unsigned int i; tk->i_blockno = 0; for( i = 0; i < tk->i_idxposc; i++ ) { if( tk->i_blocksize > 0 ) { tk->i_blockno += ( tk->p_index[i].i_length + tk->i_blocksize - 1 ) / tk->i_blocksize; } else { tk->i_blockno++; } } } msg_Dbg( p_input, "old:"I64Fd" %s new "I64Fd, i_oldpts, i_oldpts > i_date ? ">" : "<", i_date ); if( p_stream->i_cat == VIDEO_ES ) { /* search key frame */ if( i_date < i_oldpts ) { while( p_stream->i_idxposc > 0 && !( p_stream->p_index[p_stream->i_idxposc].i_flags & AVIIF_KEYFRAME ) ) { if( AVI_StreamChunkSet( p_input, i_stream, p_stream->i_idxposc - 1 ) ) { return VLC_EGENERIC; } } } else { while( p_stream->i_idxposc < p_stream->i_idxnb && !( p_stream->p_index[p_stream->i_idxposc].i_flags & AVIIF_KEYFRAME ) ) { if( AVI_StreamChunkSet( p_input, i_stream, p_stream->i_idxposc + 1 ) ) { return VLC_EGENERIC; } } } } } else { if( AVI_StreamBytesSet( p_input, i_stream, AVI_PTSToByte( p_stream, i_date ) ) ) { return VLC_EGENERIC; } } return VLC_SUCCESS;#undef p_stream}/**************************************************************************** * Return VLC_TRUE if it's a key frame ****************************************************************************/static int AVI_GetKeyFlag( vlc_fourcc_t i_fourcc, uint8_t *p_byte ){ switch( i_fourcc ) { case FOURCC_DIV1: /* we have: * startcode: 0x00000100 32bits * framenumber ? 5bits * piture type 0(I),1(P) 2bits */ if( GetDWBE( p_byte ) != 0x00000100 ) { /* it's not an msmpegv1 stream, strange...*/ return AVIIF_KEYFRAME; } else { return p_byte[4] & 0x06 ? 0 : AVIIF_KEYFRAME; } case FOURCC_DIV2: case FOURCC_DIV3: /* wmv1 also */ /* we have * picture type 0(I),1(P) 2bits */ return p_byte[0] & 0xC0 ? 0 : AVIIF_KEYFRAME; case FOURCC_mp4v: /* we should find first occurence of 0x000001b6 (32bits) * startcode: 0x000001b6 32bits * piture type 0(I),1(P) 2bits */ if( GetDWBE( p_byte ) != 0x000001b6 ) { /* not true , need to find the first VOP header */ return AVIIF_KEYFRAME; } else { return p_byte[4] & 0xC0 ? 0 : AVIIF_KEYFRAME; } default: /* I can't do it, so say yes */ return AVIIF_KEYFRAME; }}vlc_fourcc_t AVI_FourccGetCodec( unsigned int i_cat, vlc_fourcc_t i_codec ){ switch( i_cat ) { case AUDIO_ES: wf_tag_to_fourcc( i_codec, &i_codec, NULL ); return i_codec; case VIDEO_ES: /* XXX DIV1 <- msmpeg4v1, DIV2 <- msmpeg4v2, DIV3 <- msmpeg4v3, mp4v for mpeg4 */ switch( i_codec ) { case FOURCC_1: return VLC_FOURCC('m','r','l','e'); case FOURCC_DIV1: case FOURCC_div1: case FOURCC_MPG4: case FOURCC_mpg4: return FOURCC_DIV1; case FOURCC_DIV2: case FOURCC_div2: case FOURCC_MP42: case FOURCC_mp42: case FOURCC_MPG3: case FOURCC_mpg3: return FOURCC_DIV2; case FOURCC_div3: case FOURCC_MP43: case FOURCC_mp43: case FOURCC_DIV3: case FOURCC_DIV4: case FOURCC_div4: case FOURCC_DIV5: case FOURCC_div5: case FOURCC_DIV6: case FOURCC_div6: case FOURCC_AP41: case FOURCC_3IV1: case FOURCC_3iv1:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?