avi.c

来自「VLC媒体播放程序」· C语言 代码 · 共 2,041 行 · 第 1/5 页

C
2,041
字号
                case FOURCC_3IVD:                case FOURCC_3ivd:                case FOURCC_3VID:                case FOURCC_3vid:                    return FOURCC_DIV3;                case FOURCC_DIVX:                case FOURCC_divx:                case FOURCC_MP4S:                case FOURCC_mp4s:                case FOURCC_M4S2:                case FOURCC_m4s2:                case FOURCC_xvid:                case FOURCC_XVID:                case FOURCC_XviD:                case FOURCC_DX50:                case FOURCC_dx50:                case FOURCC_mp4v:                case FOURCC_4:                case FOURCC_3IV2:                case FOURCC_3iv2:                    return FOURCC_mp4v;            }        default:            return VLC_FOURCC( 'u', 'n', 'd', 'f' );    }}/**************************************************************************** * ****************************************************************************/static void AVI_ParseStreamHeader( vlc_fourcc_t i_id,                                   int *pi_number, int *pi_type ){#define SET_PTR( p, v ) if( p ) *(p) = (v);    int c1, c2;    c1 = ((uint8_t *)&i_id)[0];    c2 = ((uint8_t *)&i_id)[1];    if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' )    {        SET_PTR( pi_number, 100 ); /* > max stream number */        SET_PTR( pi_type, UNKNOWN_ES );    }    else    {        SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) );        switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) )        {            case AVITWOCC_wb:                SET_PTR( pi_type, AUDIO_ES );                break;            case AVITWOCC_dc:            case AVITWOCC_db:                SET_PTR( pi_type, VIDEO_ES );                break;            default:                SET_PTR( pi_type, UNKNOWN_ES );                break;        }    }#undef SET_PTR}/**************************************************************************** * ****************************************************************************/static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk ){    uint8_t  *p_peek;    if( stream_Peek( p_input->s, &p_peek, 16 ) < 16 )    {        return VLC_EGENERIC;    }    p_pk->i_fourcc  = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] );    p_pk->i_size    = GetDWLE( p_peek + 4 );    p_pk->i_pos     = stream_Tell( p_input->s );    if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF )    {        p_pk->i_type = VLC_FOURCC( p_peek[8],  p_peek[9],                                   p_peek[10], p_peek[11] );    }    else    {        p_pk->i_type = 0;    }    memcpy( p_pk->i_peek, p_peek + 8, 8 );    AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat );    return VLC_SUCCESS;}static int AVI_PacketNext( input_thread_t *p_input ){    avi_packet_t    avi_ck;    int             i_skip = 0;    if( AVI_PacketGetHeader( p_input, &avi_ck ) )    {        return VLC_EGENERIC;    }    if( avi_ck.i_fourcc == AVIFOURCC_LIST &&        ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) )    {        i_skip = 12;    }    else if( avi_ck.i_fourcc == AVIFOURCC_RIFF &&             avi_ck.i_type == AVIFOURCC_AVIX )    {        i_skip = 24;    }    else    {        i_skip = __EVEN( avi_ck.i_size ) + 8;    }    if( stream_Read( p_input->s, NULL, i_skip ) != i_skip )    {        return VLC_EGENERIC;    }    return VLC_SUCCESS;}static int AVI_PacketRead( input_thread_t   *p_input,                           avi_packet_t     *p_pk,                           block_t          **pp_frame ){    size_t i_size;    i_size = __EVEN( p_pk->i_size + 8 );    if( ( *pp_frame = stream_Block( p_input->s, i_size ) ) == NULL )    {        return VLC_EGENERIC;    }    (*pp_frame)->p_buffer += 8;    (*pp_frame)->i_buffer -= 8;    if( i_size != p_pk->i_size + 8 )    {        (*pp_frame)->i_buffer--;    }    return VLC_SUCCESS;}static int AVI_PacketSearch( input_thread_t *p_input ){    demux_sys_t     *p_sys = p_input->p_demux_data;    avi_packet_t    avi_pk;    int             i_count = 0;    for( ;; )    {        if( stream_Read( p_input->s, NULL, 1 ) != 1 )        {            return VLC_EGENERIC;        }        AVI_PacketGetHeader( p_input, &avi_pk );        if( avi_pk.i_stream < p_sys->i_track &&            ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) )        {            return VLC_SUCCESS;        }        switch( avi_pk.i_fourcc )        {            case AVIFOURCC_JUNK:            case AVIFOURCC_LIST:            case AVIFOURCC_RIFF:            case AVIFOURCC_idx1:                return VLC_SUCCESS;        }        /* 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 (not that we care much anyway because         * this code is called only on broken files). */        if( !(++i_count % 1024) )        {            if( p_input->b_die ) return VLC_EGENERIC;            msleep( 10000 );            if( !(i_count % (1024 * 10)) )                msg_Warn( p_input, "trying to resync..." );        }    }}/**************************************************************************** * Index stuff. ****************************************************************************/static void AVI_IndexAddEntry( demux_sys_t *p_sys,                               int i_stream,                               AVIIndexEntry_t *p_index){    avi_track_t *tk = p_sys->track[i_stream];    /* Update i_movi_lastchunk_pos */    if( p_sys->i_movi_lastchunk_pos < p_index->i_pos )    {        p_sys->i_movi_lastchunk_pos = p_index->i_pos;    }    /* add the entry */    if( tk->i_idxnb >= tk->i_idxmax )    {        tk->i_idxmax += 16384;        tk->p_index = realloc( tk->p_index,                               tk->i_idxmax * sizeof( AVIIndexEntry_t ) );        if( tk->p_index == NULL )        {            return;        }    }    /* calculate cumulate length */    if( tk->i_idxnb > 0 )    {        p_index->i_lengthtotal =            tk->p_index[tk->i_idxnb - 1].i_length +                tk->p_index[tk->i_idxnb - 1].i_lengthtotal;    }    else    {        p_index->i_lengthtotal = 0;    }    tk->p_index[tk->i_idxnb++] = *p_index;}static int AVI_IndexLoad_idx1( input_thread_t *p_input ){    demux_sys_t *p_sys = p_input->p_demux_data;    avi_chunk_list_t    *p_riff;    avi_chunk_list_t    *p_movi;    avi_chunk_idx1_t    *p_idx1;    unsigned int i_stream;    unsigned int i_index;    off_t        i_offset;    unsigned int i;    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);    p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0);    p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0);    if( !p_idx1 )    {        msg_Warn( p_input, "cannot find idx1 chunk, no index defined" );        return VLC_EGENERIC;    }    /* *** calculate offset *** */    /* Well, avi is __SHIT__ so test more than one entry     * (needed for some avi files) */    i_offset = 0;    for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ )    {        if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos )        {            i_offset = p_movi->i_chunk_pos + 8;            break;        }    }    for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ )    {        unsigned int i_cat;        AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc,                               &i_stream,                               &i_cat );        if( i_stream < p_sys->i_track &&            i_cat == p_sys->track[i_stream]->i_cat )        {            AVIIndexEntry_t index;            index.i_id      = p_idx1->entry[i_index].i_fourcc;            index.i_flags   =                p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME);            index.i_pos     = p_idx1->entry[i_index].i_pos + i_offset;            index.i_length  = p_idx1->entry[i_index].i_length;            AVI_IndexAddEntry( p_sys, i_stream, &index );        }    }    return VLC_SUCCESS;}static void __Parse_indx( input_thread_t    *p_input,                          int               i_stream,                          avi_chunk_indx_t  *p_indx ){    demux_sys_t         *p_sys    = p_input->p_demux_data;    AVIIndexEntry_t     index;    int32_t             i;    msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse );    if( p_indx->i_indexsubtype == 0 )    {        for( i = 0; i < p_indx->i_entriesinuse; i++ )        {            index.i_id      = p_indx->i_id;            index.i_flags   = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8;            index.i_length  = p_indx->idx.std[i].i_size&0x7fffffff;            AVI_IndexAddEntry( p_sys, i_stream, &index );        }    }    else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD )    {        for( i = 0; i < p_indx->i_entriesinuse; i++ )        {            index.i_id      = p_indx->i_id;            index.i_flags   = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME;            index.i_pos     = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8;            index.i_length  = p_indx->idx.field[i].i_size;            AVI_IndexAddEntry( p_sys, i_stream, &index );        }    }    else    {        msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype );    }}static void AVI_IndexLoad_indx( input_thread_t *p_input ){    demux_sys_t         *p_sys = p_input->p_demux_data;    unsigned int        i_stream;    int32_t             i;    avi_chunk_list_t    *p_riff;    avi_chunk_list_t    *p_hdrl;    p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0);    p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 );    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )    {        avi_chunk_list_t    *p_strl;        avi_chunk_indx_t    *p_indx;#define p_stream  p_sys->track[i_stream]        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream );        p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 );        if( !p_indx )        {            msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" );            continue;        }        if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS )        {            __Parse_indx( p_input, i_stream, p_indx );        }        else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES )        {            avi_chunk_indx_t    ck_sub;            for( i = 0; i < p_indx->i_entriesinuse; i++ )            {                if( stream_Seek( p_input->s, p_indx->idx.super[i].i_offset )||                    AVI_ChunkRead( p_input->s, &ck_sub, NULL  ) )                {                    break;                }                __Parse_indx( p_input, i_stream, &ck_sub );            }        }        else        {            msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype );        }#undef p_stream    }}static void AVI_IndexLoad( input_thread_t *p_input ){    demux_sys_t *p_sys = p_input->p_demux_data;    unsigned int i_stream;    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )    {        p_sys->track[i_stream]->i_idxnb  = 0;        p_sys->track[i_stream]->i_idxmax = 0;        p_sys->track[i_stream]->p_index  = NULL;    }    if( p_sys->b_odml )    {        AVI_IndexLoad_indx( p_input );    }    else  if( AVI_IndexLoad_idx1( p_input ) )    {        /* try indx if idx1 failed as some "normal" file have indx too */        AVI_IndexLoad_indx( p_input );    }    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )    {        msg_Dbg( p_input, "s

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?