avi.c

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

C
2,041
字号
    {        avi_track_t         *tk = p_sys->track[i];        avi_chunk_list_t    *p_strl;        avi_chunk_strh_t    *p_strh;        avi_chunk_strf_auds_t    *p_auds;        if( tk->i_cat != AUDIO_ES )        {            continue;        }        if( tk->i_idxnb < 1 ||            tk->i_scale != 1 ||            tk->i_samplesize != 0 )        {            continue;        }        p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i );        p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 );        p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 );        if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM &&            (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec )        {            int64_t i_track_length =                tk->p_index[tk->i_idxnb-1].i_length +                tk->p_index[tk->i_idxnb-1].i_lengthtotal;            mtime_t i_length = (mtime_t)p_avih->i_totalframes *                               (mtime_t)p_avih->i_microsecperframe;            if( i_length == 0 )            {                msg_Warn( p_input, "track[%d] cannot be fixed (BeOS MediaKit generated)", i );                continue;            }            tk->i_samplesize = 1;            tk->i_rate       = i_track_length  * (int64_t)1000000/ i_length;            msg_Warn( p_input, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale );        }    }    if( p_sys->i_length )    {        p_input->stream.i_mux_rate =            stream_Size( p_input->s ) / 50 / p_sys->i_length;    }    if( p_sys->b_seekable )    {        /* we have read all chunk so go back to movi */        stream_Seek( p_input->s, p_movi->i_chunk_pos );    }    /* Skip movi header */    stream_Read( p_input->s, NULL, 12 );    p_sys->i_movi_begin = p_movi->i_chunk_pos;    return VLC_SUCCESS;error:    if( p_sys->meta )    {        vlc_meta_Delete( p_sys->meta );    }    AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );    free( p_sys );    return VLC_EGENERIC;}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close ( vlc_object_t * p_this ){    input_thread_t *    p_input = (input_thread_t *)p_this;    unsigned int i;    demux_sys_t *p_sys = p_input->p_demux_data  ;    for( i = 0; i < p_sys->i_track; i++ )    {        if( p_sys->track[i] )        {            FREE( p_sys->track[i]->p_index );            free( p_sys->track[i] );        }    }    FREE( p_sys->track );    AVI_ChunkFreeRoot( p_input->s, &p_sys->ck_root );    vlc_meta_Delete( p_sys->meta );    free( p_sys );}/***************************************************************************** * Demux_Seekable: reads and demuxes data packets for stream seekable ***************************************************************************** * AVIDemux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/typedef struct{    vlc_bool_t b_ok;    int i_toread;    off_t i_posf; /* where we will read :                   if i_idxposb == 0 : begining of chunk (+8 to acces data)                   else : point on data directly */} avi_track_toread_t;static int Demux_Seekable( input_thread_t *p_input ){    demux_sys_t *p_sys = p_input->p_demux_data;    unsigned int i_track_count = 0;    unsigned int i_track;    vlc_bool_t b_stream;    /* cannot be more than 100 stream (dcXX or wbXX) */    avi_track_toread_t toread[100];    /* detect new selected/unselected streams */    for( i_track = 0; i_track < p_sys->i_track; i_track++ )    {        avi_track_t *tk = p_sys->track[i_track];        vlc_bool_t  b;        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );        if( b && !tk->b_activated )        {            if( p_sys->b_seekable)            {                AVI_TrackSeek( p_input, i_track, p_sys->i_time );            }            tk->b_activated = VLC_TRUE;        }        else if( !b && tk->b_activated )        {            tk->b_activated = VLC_FALSE;        }        if( b )        {            i_track_count++;        }    }    if( i_track_count <= 0 )    {        msg_Warn( p_input, "no track selected, exiting..." );        return( 0 );    }    /* wait for the good time */    p_sys->i_pcr = p_sys->i_time * 9 / 100;    input_ClockManageRef( p_input,                          p_input->stream.p_selected_program,                          p_sys->i_pcr );    p_sys->i_time += 25*1000;  /* read 25ms */    /* init toread */    for( i_track = 0; i_track < p_sys->i_track; i_track++ )    {        avi_track_t *tk = p_sys->track[i_track];        mtime_t i_dpts;        toread[i_track].b_ok = tk->b_activated;        if( tk->i_idxposc < tk->i_idxnb )        {            toread[i_track].i_posf = tk->p_index[tk->i_idxposc].i_pos;           if( tk->i_idxposb > 0 )           {                toread[i_track].i_posf += 8 + tk->i_idxposb;           }        }        else        {            toread[i_track].i_posf = -1;        }        i_dpts = p_sys->i_time - AVI_GetPTS( tk  );        if( tk->i_samplesize )        {            toread[i_track].i_toread = AVI_PTSToByte( tk, __ABS( i_dpts ) );        }        else        {            toread[i_track].i_toread = AVI_PTSToChunk( tk, __ABS( i_dpts ) );        }        if( i_dpts < 0 )        {            toread[i_track].i_toread *= -1;        }    }    b_stream = VLC_FALSE;    for( ;; )    {        avi_track_t     *tk;        vlc_bool_t       b_done;        block_t         *p_frame;        off_t i_pos;        unsigned int i;        size_t i_size;        /* search for first chunk to be read */        for( i = 0, b_done = VLC_TRUE, i_pos = -1; i < p_sys->i_track; i++ )        {            if( !toread[i].b_ok ||                AVI_GetDPTS( p_sys->track[i],                             toread[i].i_toread ) <= -25 * 1000 )            {                continue;            }            if( toread[i].i_toread > 0 )            {                b_done = VLC_FALSE; /* not yet finished */            }            if( toread[i].i_posf > 0 )            {                if( i_pos == -1 || i_pos > toread[i_track].i_posf )                {                    i_track = i;                    i_pos = toread[i].i_posf;                }            }        }        if( b_done )        {            return( 1 );        }        if( i_pos == -1 )        {            /* no valid index, we will parse directly the stream             * in case we fail we will disable all finished stream */            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( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );                }            }            else            {                stream_Seek( p_input->s, p_sys->i_movi_begin + 12 );            }            for( ;; )            {                avi_packet_t avi_pk;                if( AVI_PacketGetHeader( p_input, &avi_pk ) )                {                    msg_Warn( p_input,                             "cannot get packet header, track disabled" );                    return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );                }                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 ) )                    {                        msg_Warn( p_input,                                  "cannot skip packet, track disabled" );                        return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );                    }                    continue;                }                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 );                    i_track = avi_pk.i_stream;                    tk = p_sys->track[i_track];                    /* do we will read this data ? */                    if( AVI_GetDPTS( tk, toread[i_track].i_toread ) > -25*1000 )                    {                        break;                    }                    else                    {                        if( AVI_PacketNext( p_input ) )                        {                            msg_Warn( p_input,                                      "cannot skip packet, track disabled" );                            return( AVI_TrackStopFinishedStreams( p_input ) ? 0 : 1 );                        }                    }                }            }        }        else        {            stream_Seek( p_input->s, i_pos );        }        /* Set the track to use */        tk = p_sys->track[i_track];        /* read thoses data */        if( tk->i_samplesize )        {            unsigned int i_toread;            if( ( i_toread = toread[i_track].i_toread ) <= 0 )            {                if( tk->i_samplesize > 1 )                {                    i_toread = tk->i_samplesize;                }                else                {                    i_toread = __MAX( AVI_PTSToByte( tk, 20 * 1000 ), 100 );                }            }            i_size = __MIN( tk->p_index[tk->i_idxposc].i_length -                                tk->i_idxposb,                            i_toread );        }        else        {            i_size = tk->p_index[tk->i_idxposc].i_length;        }        if( tk->i_idxposb == 0 )        {            i_size += 8; /* need to read and skip header */        }        if( ( p_frame = stream_Block( p_input->s, __EVEN( i_size ) ) )==NULL )        {            msg_Warn( p_input, "failled reading data" );            tk->b_activated = VLC_FALSE;            toread[i_track].b_ok = VLC_FALSE;            continue;        }        if( i_size % 2 )    /* read was padded on word boundary */        {            p_frame->i_buffer--;        }        /* skip header */        if( tk->i_idxposb == 0 )        {            p_frame->p_buffer += 8;            p_frame->i_buffer -= 8;        }        p_frame->i_pts = AVI_GetPTS( tk );        /* read data */        if( tk->i_samplesize )        {            if( tk->i_idxposb == 0 )            {                i_size -= 8;            }            toread[i_track].i_toread -= i_size;            tk->i_idxposb += i_size;            if( tk->i_idxposb >=                    tk->p_index[tk->i_idxposc].i_length )            {                tk->i_idxposb = 0;                tk->i_idxposc++;            }        }        else        {            int i_length = tk->p_index[tk->i_idxposc].i_length;            tk->i_idxposc++;            if( tk->i_cat == AUDIO_ES )            {                tk->i_blockno += tk->i_blocksize > 0 ? ( i_length + tk->i_blocksize - 1 ) / tk->i_blocksize : 1;            }            toread[i_track].i_toread--;        }        if( tk->i_idxposc < tk->i_idxnb)        {            toread[i_track].i_posf =                tk->p_index[tk->i_idxposc].i_pos;            if( tk->i_idxposb > 0 )            {                toread[i_track].i_posf += 8 + tk->i_idxposb;            }        }        else        {            toread[i_track].i_posf = -1;        }

⌨️ 快捷键说明

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