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 + -
显示快捷键?