[vlc-devel] [PATCH 4/4] avcodec: fix deadlock when closing with mt
Rémi Denis-Courmont
remi at remlab.net
Tue Nov 17 20:03:54 CET 2015
Le 2015-11-17 21:34, Thomas Guillem a écrit :
> lavc_GetFrame can be stuck in decoder_GetPicture when decoder is
> closing.
> ---
> modules/codec/avcodec/video.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/modules/codec/avcodec/video.c
> b/modules/codec/avcodec/video.c
> index 69d6f6e..8ebc21c 100644
> --- a/modules/codec/avcodec/video.c
> +++ b/modules/codec/avcodec/video.c
> @@ -74,6 +74,7 @@ struct decoder_sys_t
>
> /* */
> bool b_flush;
> + atomic_bool flushing_buffers;
>
> /* VA API */
> vlc_va_t *p_va;
> @@ -458,6 +459,7 @@ int InitVideoDec( decoder_t *p_dec,
> AVCodecContext *p_context,
> p_sys->b_first_frame = true;
> p_sys->b_flush = false;
> p_sys->i_late_frames = 0;
> + atomic_init( &p_sys->flushing_buffers, false );
>
> /* Set output properties */
> p_dec->fmt_out.i_cat = VIDEO_ES;
> @@ -536,7 +538,11 @@ static picture_t *DecodeVideo( decoder_t *p_dec,
> block_t **pp_block )
> /* NOTE: data is good only the timeline changed so do
> not flush decoder */
> post_mt( p_sys );
> if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
> + {
> + atomic_store( &p_sys->flushing_buffers, true );
This assumes that libavcodec won't need new buffers while flushing. I
don't know if that is currently the case, and in any case, that seems
like an implementation detail of libavcodec (threaded) decoders that we
cannot rely on.
> avcodec_flush_buffers( p_context );
> + atomic_store( &p_sys->flushing_buffers, false );
> + }
> wait_mt( p_sys );
> #endif
> if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
> @@ -858,7 +864,10 @@ void EndVideoDec( decoder_t *p_dec )
>
> /* do not flush buffers if codec hasn't been opened
> (theora/vorbis/VC1) */
> if( p_sys->p_context->codec )
> + {
> + atomic_store( &p_sys->flushing_buffers, true );
This is racy.
> avcodec_flush_buffers( p_sys->p_context );
> + }
>
> wait_mt( p_sys );
>
> @@ -1065,6 +1074,12 @@ static int lavc_GetFrame(struct AVCodecContext
> *ctx, AVFrame *frame, int flags)
> frame->opaque = NULL;
>
> wait_mt(sys);
> + if (atomic_load(&sys->flushing_buffers))
> + {
> + /* If decoder is flushing buffers, abort current
> lavc_GetFrame call */
> + post_mt(sys);
> + return -1;
> + }
> if (sys->p_va == NULL)
> {
> if (!sys->b_direct_rendering)
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list