avi.c

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

C
2,041
字号
        b_stream = VLC_TRUE; /* at least one read succeed */        p_frame->i_pts =            input_ClockGetTS( p_input,                              p_input->stream.p_selected_program,                              p_frame->i_pts * 9/100);        if( tk->i_cat != VIDEO_ES )            p_frame->i_dts = p_frame->i_pts;        else        {            p_frame->i_dts = p_frame->i_pts;            p_frame->i_pts = 0;        }        //p_pes->i_rate = p_input->stream.control.i_rate;        es_out_Send( p_input->p_es_out, tk->p_es, p_frame );    }}/***************************************************************************** * Demux_UnSeekable: reads and demuxes data packets for unseekable file ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/static int Demux_UnSeekable( input_thread_t *p_input ){    demux_sys_t     *p_sys = p_input->p_demux_data;    avi_track_t *p_stream_master = NULL;    vlc_bool_t b_audio;    unsigned int i_stream;    unsigned int i_packet;    /* Check if we need to send the audio data to decoder */    b_audio = !p_input->stream.control.b_mute;    input_ClockManageRef( p_input,                          p_input->stream.p_selected_program,                          p_sys->i_pcr );    /* *** find master stream for data packet skipping algo *** */    /* *** -> first video, if any, or first audio ES *** */    for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )    {        avi_track_t *tk = p_sys->track[i_stream];        vlc_bool_t  b;        es_out_Control( p_input->p_es_out, ES_OUT_GET_ES_STATE, tk->p_es, &b );        if( b && tk->i_cat == VIDEO_ES )        {            p_stream_master = tk;        }        else if( b )        {            p_stream_master = tk;        }    }    if( !p_stream_master )    {        msg_Warn( p_input, "no more stream selected" );        return( 0 );    }    p_sys->i_pcr = AVI_GetPTS( p_stream_master ) * 9 / 100;    for( i_packet = 0; i_packet < 10; i_packet++)    {#define p_stream    p_sys->track[avi_pk.i_stream]        avi_packet_t    avi_pk;        if( AVI_PacketGetHeader( p_input, &avi_pk ) )        {            return( 0 );        }        if( avi_pk.i_stream >= p_sys->i_track ||            ( avi_pk.i_cat != AUDIO_ES && avi_pk.i_cat != VIDEO_ES ) )        {            /* we haven't found an audio or video packet:             *  - we have seek, found first next packet             *  - others packets could be found, skip them             */            switch( avi_pk.i_fourcc )            {                case AVIFOURCC_JUNK:                case AVIFOURCC_LIST:                case AVIFOURCC_RIFF:                    return( !AVI_PacketNext( p_input ) ? 1 : 0 );                case AVIFOURCC_idx1:                    if( p_sys->b_odml )                    {                        return( !AVI_PacketNext( p_input ) ? 1 : 0 );                    }                    return( 0 );    /* eof */                default:                    msg_Warn( p_input,                              "seems to have lost position, resync" );                    if( AVI_PacketSearch( p_input ) )                    {                        msg_Err( p_input, "resync failed" );                        return( -1 );                    }            }        }        else        {            /* do will send this packet to decoder ? */            if( !b_audio && avi_pk.i_cat == AUDIO_ES )            {                if( AVI_PacketNext( p_input ) )                {                    return( 0 );                }            }            else            {                /* it's a selected stream, check for time */                if( __ABS( AVI_GetPTS( p_stream ) -                            AVI_GetPTS( p_stream_master ) )< 600*1000 )                {                    /* load it and send to decoder */                    block_t *p_frame;                    if( AVI_PacketRead( p_input, &avi_pk, &p_frame ) || p_frame == NULL )                    {                        return( -1 );                    }                    p_frame->i_pts =                        input_ClockGetTS( p_input,                                          p_input->stream.p_selected_program,                                          AVI_GetPTS( p_stream ) * 9/100);                    if( avi_pk.i_cat != VIDEO_ES )                        p_frame->i_dts = p_frame->i_pts;                    else                    {                        p_frame->i_dts = p_frame->i_pts;                        p_frame->i_pts = 0;                    }                    //p_pes->i_rate = p_input->stream.control.i_rate;                    es_out_Send( p_input->p_es_out, p_stream->p_es, p_frame );                }                else                {                    if( AVI_PacketNext( p_input ) )                    {                        return( 0 );                    }                }            }            /* *** update stream time position *** */            if( p_stream->i_samplesize )            {                p_stream->i_idxposb += avi_pk.i_size;            }            else            {                if( p_stream->i_cat == AUDIO_ES )                {                    p_stream->i_blockno += p_stream->i_blocksize > 0 ? ( avi_pk.i_size + p_stream->i_blocksize - 1 ) / p_stream->i_blocksize : 1;                }                p_stream->i_idxposc++;            }        }#undef p_stream    }    return( 1 );}/***************************************************************************** * Seek: goto to i_date or i_percent ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/static int Seek( input_thread_t *p_input, mtime_t i_date, int i_percent ){    demux_sys_t *p_sys = p_input->p_demux_data;    unsigned int i_stream;    msg_Dbg( p_input,             "seek requested: "I64Fd" secondes %d%%",             i_date / 1000000,             i_percent );    if( p_sys->b_seekable )    {        if( !p_sys->i_length )        {            avi_track_t *p_stream;            int64_t i_pos;            /* use i_percent to create a true i_date */            msg_Warn( p_input,                      "mmh, seeking without index at %d%%"                      " work only for interleaved file", i_percent );            if( i_percent >= 100 )            {                msg_Warn( p_input, "cannot seek so far !" );                return( -1 );            }            i_percent = __MAX( i_percent, 0 );            /* try to find chunk that is at i_percent or the file */            i_pos = __MAX( i_percent *                           stream_Size( p_input->s ) / 100,                           p_sys->i_movi_begin );            /* search first selected stream */            for( i_stream = 0, p_stream = NULL;                        i_stream < p_sys->i_track; i_stream++ )            {                p_stream = p_sys->track[i_stream];                if( p_stream->b_activated )                {                    break;                }            }            if( !p_stream || !p_stream->b_activated )            {                msg_Warn( p_input, "cannot find any selected stream" );                return( -1 );            }            /* be sure that the index exist */            if( AVI_StreamChunkSet( p_input,                                    i_stream,                                    0 ) )            {                msg_Warn( p_input, "cannot seek" );                return( -1 );            }            while( i_pos >= p_stream->p_index[p_stream->i_idxposc].i_pos +               p_stream->p_index[p_stream->i_idxposc].i_length + 8 )            {                /* search after i_idxposc */                if( AVI_StreamChunkSet( p_input,                                        i_stream, p_stream->i_idxposc + 1 ) )                {                    msg_Warn( p_input, "cannot seek" );                    return( -1 );                }            }            i_date = AVI_GetPTS( p_stream );            /* TODO better support for i_samplesize != 0 */            msg_Dbg( p_input, "estimate date "I64Fd, i_date );        }#define p_stream    p_sys->track[i_stream]        p_sys->i_time = 0;        /* seek for chunk based streams */        for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ )        {            if( p_stream->b_activated && !p_stream->i_samplesize )/*            if( p_stream->b_activated ) */            {                AVI_TrackSeek( p_input, i_stream, i_date );                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_input, i_stream, i_date );/*                p_sys->i_time = __MAX( AVI_GetPTS( p_stream ), p_sys->i_time );*/            }        }        msg_Dbg( p_input, "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( 1 );    }    else    {        msg_Err( p_input, "shouldn't yet be executed" );        return( -1 );    }}/***************************************************************************** * Control: ***************************************************************************** * *****************************************************************************/static double ControlGetPosition( input_thread_t *p_input ){    demux_sys_t *p_sys = p_input->p_demux_data;    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_input->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 / (double)stream_Size( p_input->s );    }    return 0.0;}static int    Control( input_thread_t *p_input, int i_query, va_list args ){    demux_sys_t *p_sys = p_input->p_demux_data;    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_input );            return VLC_SUCCESS;        case DEMUX_SET_POSITION:            if( p_sys->b_seekable )            {                f = (double)va_arg( args, double );                i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );                return Seek( p_input, i64, (int)(f * 100) ) < 0 ? VLC_EGENERIC : VLC_SUCCESS;            }            return demux_vaControlDefault( p_input, i_query, args );        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_input ) *                                   (double)i64 / (double)p_sys->i_time );            }            return Seek( p_input, 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 demux_vaControlDefault( p_input, i_query, args );    }    return VLC_EGENERIC;}

⌨️ 快捷键说明

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