[vlc-devel] [PATCH] rework the video frame skipping/dropping strategy in the avcodec decoder
Steve Lhomme
robux4 at videolabs.io
Fri Feb 27 09:48:34 CET 2015
One of the odd things about this bug, that you can see in the issue:
https://trac.videolan.org/vlc/ticket/10114
Is that `main warning: picture is too late to be displayed (missing 54 ms)`
The renderer has the picture already decoded but refuses to show it.
Just because it's late. I understand it might just show some
desynchronization with the sound (this file has no sound) but is it
better to not display anything when your CPU is overloaded ?
On Thu, Feb 26, 2015 at 5:28 PM, Steve Lhomme <robUx4 at videolabs.io> wrote:
> Fixes #10114
>
> When we are late for decoding we do the following:
> - skip non-ref frames outside of the decoder (decoded but not producing output)
>
> If we're still getting too late
> - skip non-key frames outside of the decoder (decoded but not producing output)
>
> If we're still too late
> - drop non-key frames packets before sending them to the decoder
>
> If we're still 5s late, the old drop packet method will be for many coming packets
>
> This strategy is more graceful than either skipping non-ref of just dropping any packet.
> ---
> modules/codec/avcodec/video.c | 78 +++++++++++++++++++------------------------
> 1 file changed, 34 insertions(+), 44 deletions(-)
>
> diff --git a/modules/codec/avcodec/video.c b/modules/codec/avcodec/video.c
> index 5ba6e2e..2c268c8 100644
> --- a/modules/codec/avcodec/video.c
> +++ b/modules/codec/avcodec/video.c
> @@ -464,7 +464,6 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
> {
> decoder_sys_t *p_sys = p_dec->p_sys;
> AVCodecContext *p_context = p_sys->p_context;
> - int b_drawpicture;
> block_t *p_block;
>
> if( !pp_block )
> @@ -529,53 +528,43 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
> return NULL;
> }
>
> - /* A good idea could be to decode all I pictures and see for the other */
> - if( !p_dec->b_pace_control &&
> - p_sys->b_hurry_up &&
> - (p_sys->i_late_frames > 4) )
> + if ( p_sys->b_hurry_up )
> {
> - b_drawpicture = 0;
> - if( p_sys->i_late_frames < 12 )
> + /* A good idea could be to decode all I pictures and see for the other */
> + if( !p_dec->b_pace_control &&
> + (p_sys->i_late_frames > 4) )
> {
> - p_context->skip_frame =
> - (p_sys->i_skip_frame <= AVDISCARD_NONREF) ?
> - AVDISCARD_NONREF : p_sys->i_skip_frame;
> + if ( p_sys->i_late_frames < 12 )
> + {
> + msg_Warn( p_dec, "More than 4 late frames, skip coming non-ref frames" );
> + p_context->skip_frame = __MAX( p_sys->i_skip_frame, AVDISCARD_NONREF );
> + }
> + else if ( p_sys->i_late_frames < 48 )
> + {
> + msg_Warn( p_dec, "More than 12 late frames, skip coming non-key frames" );
> + p_context->skip_frame = __MAX( p_sys->i_skip_frame, AVDISCARD_NONKEY );
> + }
> + else if ( !p_block ||
> + !( p_block->i_flags & ( BLOCK_FLAG_TYPE_I|BLOCK_FLAG_PREROLL ) ) )
> + {
> + /* picture too late, won't decode
> + * but break picture until a new I, and for mpeg4 ...*/
> + //p_sys->i_late_frames--; /* needed else it will never be decrease */
> + msg_Warn( p_dec, "More than 48 late frames, dropping non-key frame" );
> + if( p_block )
> + block_Release( p_block );
> + return NULL;
> + }
> }
> else
> {
> - /* picture too late, won't decode
> - * but break picture until a new I, and for mpeg4 ...*/
> - p_sys->i_late_frames--; /* needed else it will never be decrease */
> - if( p_block )
> - block_Release( p_block );
> - msg_Warn( p_dec, "More than 4 late frames, dropping frame" );
> - return NULL;
> - }
> - }
> - else
> - {
> - if( p_sys->b_hurry_up )
> p_context->skip_frame = p_sys->i_skip_frame;
> - if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
> - b_drawpicture = 1;
> - else
> - b_drawpicture = 0;
> - }
> + }
>
> - if( p_context->width <= 0 || p_context->height <= 0 )
> - {
> - if( p_sys->b_hurry_up )
> + if( p_context->width <= 0 || p_context->height <= 0 )
> + {
> p_context->skip_frame = p_sys->i_skip_frame;
> - }
> - else if( !b_drawpicture )
> - {
> - /* It creates broken picture
> - * FIXME either our parser or ffmpeg is broken */
> -#if 0
> - if( p_sys->b_hurry_up )
> - p_context->skip_frame = __MAX( p_context->skip_frame,
> - AVDISCARD_NONREF );
> -#endif
> + }
> }
>
> /*
> @@ -652,9 +641,8 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
>
> if( i_used < 0 )
> {
> - if( b_drawpicture )
> - msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
> - p_block->i_buffer );
> + msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
> + p_block->i_buffer );
> block_Release( p_block );
> return NULL;
> }
> @@ -732,9 +720,11 @@ static picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
> else
> {
> p_sys->i_late_frames = 0;
> + if ( p_sys->b_hurry_up )
> + p_context->skip_frame = p_sys->i_skip_frame;
> }
>
> - if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) )
> + if( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] )
> continue;
>
> if( p_sys->p_va != NULL || p_sys->p_ff_pic->opaque == NULL )
> --
> 2.2.2
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list