⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decoder.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
static void optimize_video_pts( decoder_t *p_dec ){    picture_t * oldest_pict = NULL;    picture_t * youngest_pict = NULL;    int i;    input_thread_t * p_input = p_dec->p_owner->p_input;    vout_thread_t * p_vout = p_dec->p_owner->p_vout;    input_thread_private_t * p_priv = p_input->p;    /* Enable with --auto-adjust-pts-delay */    if( !p_priv->pts_adjust.auto_adjust ) return;    for( i = 0; i < I_RENDERPICTURES; i++ )    {        picture_t * pic = PP_RENDERPICTURE[i];        if( pic->i_status != READY_PICTURE )            continue;        if( !oldest_pict || pic->date < oldest_pict->date )            oldest_pict = pic;        if( !youngest_pict || pic->date > youngest_pict->date )            youngest_pict = pic;    }    if( !youngest_pict || !oldest_pict )        return;    /* Try to find if we can reduce the pts     * This first draft is way to simple, and we can't say if the     * algo will converge. It's also full of constants.     * But this simple algo allows to reduce the latency     * to the minimum.     * The whole point of this, is to bypass the pts_delay set     * by the access but also the delay arbitraly set by     * the remote server.     * Actually the remote server's muxer may set up a     * pts<->dts delay in the muxed stream. That is     * why we may end up in having a negative pts_delay,     * to compensate that artificial delay. */    mtime_t buffer_size = youngest_pict->date - oldest_pict->date;    int64_t pts_slide = 0;    if( buffer_size < 10000 )    {        if( p_priv->pts_adjust.i_num_faulty > 10 )        {            pts_slide = __MAX(p_input->i_pts_delay *3 / 2, 10000);            p_priv->pts_adjust.i_num_faulty = 0;        }        if( p_priv->pts_adjust.to_high )        {            p_priv->pts_adjust.to_high = !p_priv->pts_adjust.to_high;            p_priv->pts_adjust.i_num_faulty = 0;        }        p_priv->pts_adjust.i_num_faulty++;    }    else if( buffer_size > 100000 )    {        if( p_priv->pts_adjust.i_num_faulty > 25 )        {            pts_slide = -buffer_size/2;            p_priv->pts_adjust.i_num_faulty = 0;        }        if( p_priv->pts_adjust.to_high )        {            p_priv->pts_adjust.to_high = !p_priv->pts_adjust.to_high;            p_priv->pts_adjust.i_num_faulty = 0;        }        p_priv->pts_adjust.i_num_faulty++;    }    if( pts_slide )    {        mtime_t origi_delay = p_input->i_pts_delay;        p_input->i_pts_delay += pts_slide;        /* Don't play with the pts delay for more than -2<->3sec */        if( p_input->i_pts_delay < -2000000 )            p_input->i_pts_delay = -2000000;        else if( p_input->i_pts_delay > 3000000 )            p_input->i_pts_delay = 3000000;        pts_slide = p_input->i_pts_delay - origi_delay;        msg_Dbg( p_input, "Sliding the pts by %dms pts delay at %dms picture buffer was %dms",            (int)pts_slide/1000, (int)p_input->i_pts_delay/1000, (int)buffer_size/1000);        vlc_mutex_lock( &p_vout->picture_lock );        /* Slide all the picture */        for( i = 0; i < I_RENDERPICTURES; i++ )            PP_RENDERPICTURE[i]->date += pts_slide;        /* FIXME: slide aout/spu */        vlc_mutex_unlock( &p_vout->picture_lock );    }}static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block ){    input_thread_t *p_input = p_dec->p_owner->p_input;    picture_t      *p_pic;    while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )    {        vout_thread_t  *p_vout = p_dec->p_owner->p_vout;        if( p_dec->b_die )        {            /* It prevent freezing VLC in case of broken decoder */            VoutDisplayedPicture( p_vout, p_pic );            if( p_block )                block_Release( p_block );            break;        }        vlc_mutex_lock( &p_input->p->counters.counters_lock );        stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_video, 1, NULL );        vlc_mutex_unlock( &p_input->p->counters.counters_lock );        if( p_pic->date < p_dec->p_owner->i_preroll_end )        {            VoutDisplayedPicture( p_vout, p_pic );            continue;        }        if( p_dec->p_owner->i_preroll_end > 0 )        {            msg_Dbg( p_dec, "End of video preroll" );            if( p_vout )                VoutFlushPicture( p_vout );            /* */            p_dec->p_owner->i_preroll_end = -1;        }        if( ( !p_dec->p_owner->p_packetizer || !p_dec->p_owner->p_packetizer->pf_get_cc ) && p_dec->pf_get_cc )            DecoderGetCc( p_dec, p_dec );        vout_DatePicture( p_vout, p_pic, p_pic->date );        optimize_video_pts( p_dec );        vout_DisplayPicture( p_vout, p_pic );    }}/** * Decode a block * * \param p_dec the decoder object * \param p_block the block to decode * \return VLC_SUCCESS or an error code */static int DecoderDecode( decoder_t *p_dec, block_t *p_block ){    decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;    const int i_rate = p_block ? p_block->i_rate : INPUT_RATE_DEFAULT;    if( p_block && p_block->i_buffer <= 0 )    {        block_Release( p_block );        return VLC_SUCCESS;    }#ifdef ENABLE_SOUT    if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )    {        block_t *p_sout_block;        while( ( p_sout_block =                     p_dec->pf_packetize( p_dec, p_block ? &p_block : 0 ) ) )        {            if( !p_dec->p_owner->p_sout_input )            {                es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );                p_dec->p_owner->sout.i_group = p_dec->fmt_in.i_group;                p_dec->p_owner->sout.i_id = p_dec->fmt_in.i_id;                if( p_dec->fmt_in.psz_language )                {                    if( p_dec->p_owner->sout.psz_language )                        free( p_dec->p_owner->sout.psz_language );                    p_dec->p_owner->sout.psz_language =                        strdup( p_dec->fmt_in.psz_language );                }                p_dec->p_owner->p_sout_input =                    sout_InputNew( p_dec->p_owner->p_sout,                                   &p_dec->p_owner->sout );                if( p_dec->p_owner->p_sout_input == NULL )                {                    msg_Err( p_dec, "cannot create packetizer output (%4.4s)",                             (char *)&p_dec->p_owner->sout.i_codec );                    p_dec->b_error = true;                    while( p_sout_block )                    {                        block_t *p_next = p_sout_block->p_next;                        block_Release( p_sout_block );                        p_sout_block = p_next;                    }                    break;                }            }            while( p_sout_block )            {                block_t *p_next = p_sout_block->p_next;                p_sout_block->p_next = NULL;                p_sout_block->i_rate = i_rate;                sout_InputSendBuffer( p_dec->p_owner->p_sout_input,                                      p_sout_block );                p_sout_block = p_next;            }            /* For now it's enough, as only sout impact on this flag */            if( p_dec->p_owner->p_sout->i_out_pace_nocontrol > 0 &&                p_dec->p_owner->p_input->p->b_out_pace_control )            {                msg_Dbg( p_dec, "switching to sync mode" );                p_dec->p_owner->p_input->p->b_out_pace_control = false;            }            else if( p_dec->p_owner->p_sout->i_out_pace_nocontrol <= 0 &&                     !p_dec->p_owner->p_input->p->b_out_pace_control )            {                msg_Dbg( p_dec, "switching to async mode" );                p_dec->p_owner->p_input->p->b_out_pace_control = true;            }        }    }    else#endif    if( p_dec->fmt_in.i_cat == AUDIO_ES )    {        if( p_block )            DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );        if( p_dec->p_owner->p_packetizer )        {            block_t *p_packetized_block;            decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;            while( (p_packetized_block =                    p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )            {                if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )                {                    es_format_Clean( &p_dec->fmt_in );                    es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );                }                while( p_packetized_block )                {                    block_t *p_next = p_packetized_block->p_next;                    p_packetized_block->p_next = NULL;                    p_packetized_block->i_rate = i_rate;                    DecoderDecodeAudio( p_dec, p_packetized_block );                    p_packetized_block = p_next;                }            }        }        else if( p_block )        {            DecoderDecodeAudio( p_dec, p_block );        }    }    else if( p_dec->fmt_in.i_cat == VIDEO_ES )    {        if( p_block )            DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );        if( p_dec->p_owner->p_packetizer )        {            block_t *p_packetized_block;            decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;            while( (p_packetized_block =                    p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )            {                if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )                {                    es_format_Clean( &p_dec->fmt_in );                    es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );                }                if( p_packetizer->pf_get_cc )                    DecoderGetCc( p_dec, p_packetizer );                while( p_packetized_block )                {                    block_t *p_next = p_packetized_block->p_next;                    p_packetized_block->p_next = NULL;                    p_packetized_block->i_rate = i_rate;                    DecoderDecodeVideo( p_dec, p_packetized_block );                    p_packetized_block = p_next;                }            }        }        else if( p_block )        {            DecoderDecodeVideo( p_dec, p_block );        }    }    else if( p_dec->fmt_in.i_cat == SPU_ES )    {        input_thread_t *p_input = p_dec->p_owner->p_input;        vout_thread_t *p_vout;        subpicture_t *p_spu;        if( p_block )            DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );        while( (p_spu = p_dec->pf_decode_sub( p_dec, p_block ? &p_block : NULL ) ) )        {            vlc_mutex_lock( &p_input->p->counters.counters_lock );            stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );            vlc_mutex_unlock( &p_input->p->counters.counters_lock );            p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );            if( p_vout && p_sys->p_spu_vout == p_vout )            {                /* Prerool does not work very well with subtitle */                if( p_spu->i_start < p_dec->p_owner->i_preroll_end &&                    ( p_spu->i_stop <= 0 || p_spu->i_stop < p_dec->p_owner->i_preroll_end ) )                    spu_DestroySubpicture( p_vout->p_spu, p_spu );                else                    spu_DisplaySubpicture( p_vout->p_spu, p_spu );            }            else            {                msg_Warn( p_dec, "no vout found, leaking subpicture" );            }            if( p_vout )                vlc_object_release( p_vout );        }    }    else    {        msg_Err( p_dec, "unknown ES format" );        p_dec->b_error = 1;    }    return p_dec->b_error ? VLC_EGENERIC : VLC_SUCCESS;}/** * Destroys a decoder object * * \param p_dec the decoder object * \return nothing */static void DeleteDecoder( decoder_t * p_dec ){    msg_Dbg( p_dec, "killing decoder fourcc `%4.4s', %u PES in FIFO",             (char*)&p_dec->fmt_in.i_codec,             (unsigned)block_FifoCount( p_dec->p_owner->p_fifo ) );    /* Free all packets still in the decoder fifo. */    block_FifoEmpty( p_dec->p_owner->p_fifo );    block_FifoRelease( p_dec->p_owner->p_fifo );    /* Cleanup */    if( p_dec->p_owner->p_aout_input )

⌨️ 快捷键说明

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