[FFmpeg-devel] [PATCH] lavc/phtread_frame: update hwaccel_priv_data in time for multithread
Fu, Linjie
linjie.fu at intel.com
Fri Jul 19 19:32:27 EEST 2019
> -----Original Message-----
> From: Fu, Linjie
> Sent: Friday, July 19, 2019 05:35
> To: ffmpeg-devel at ffmpeg.org
> Cc: Fu, Linjie <linjie.fu at intel.com>
> Subject: [PATCH] lavc/phtread_frame: update hwaccel_priv_data in time for
> multithread
>
> When resolution/format changes, hwaccel_uninit/hwaccel_init will
> be called to destroy and re-create the hwaccel_priv_data. When output
> frame number meets the constraints for vframes, the hwaccel_priv_data
> modified in decoding thread won't be update to user-thread due to the
> delay mechanism. It will lead to:
> 1. memory leak in child-thread.
> 2. double free in user-thread while calling avcodec_close().
>
> Can be reproduced with a resolution change case, and use -vframes
> to terminate the decode during dynamic resolution changing:
>
> ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -v verbose
> -i ./reinit-large_420_8-to-small_420_8.h264 -pix_fmt nv12 -f rawvideo
> -vsync passthrough -vframes 45 -y out.yuv
>
> The root cause is the conflict between delay mechanism and -vframes.
> FFmpeg won't output a frame if it's still receiving the initial packets,
> so there is async between decode process and output. hwaccel_priv_data
> in user thread won't be updated until the resolution changing
> frame is output.
>
> As user context should reflect the state of the last frame that
> was output to the user, hwaccel_priv_data should be updated
> separately from decoding thread in time.
>
> Signed-off-by: Linjie Fu <linjie.fu at intel.com>
> ---
> libavcodec/pthread_frame.c | 11 +++++++++--
> 1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
> index 36ac0ac..cf7a575 100644
> --- a/libavcodec/pthread_frame.c
> +++ b/libavcodec/pthread_frame.c
> @@ -282,7 +282,6 @@ static int
> update_context_from_thread(AVCodecContext *dst, AVCodecContext *src,
> dst->sample_rate = src->sample_rate;
> dst->sample_fmt = src->sample_fmt;
> dst->channel_layout = src->channel_layout;
> - dst->internal->hwaccel_priv_data = src->internal->hwaccel_priv_data;
>
> if (!!dst->hw_frames_ctx != !!src->hw_frames_ctx ||
> (dst->hw_frames_ctx && dst->hw_frames_ctx->data != src-
> >hw_frames_ctx->data)) {
> @@ -410,6 +409,7 @@ static int submit_packet(PerThreadContext *p,
> AVCodecContext *user_avctx,
> pthread_mutex_unlock(&prev_thread->progress_mutex);
> }
>
> + p->avctx->internal->hwaccel_priv_data = prev_thread->avctx-
> >internal->hwaccel_priv_data;
> err = update_context_from_thread(p->avctx, prev_thread->avctx, 0);
> if (err) {
> pthread_mutex_unlock(&p->mutex);
> @@ -476,7 +476,7 @@ int ff_thread_decode_frame(AVCodecContext
> *avctx,
> FrameThreadContext *fctx = avctx->internal->thread_ctx;
> int finished = fctx->next_finished;
> PerThreadContext *p;
> - int err;
> + int err, cur_decoding;
>
> /* release the async lock, permitting blocked hwaccel threads to
> * go forward while we are in this function */
> @@ -544,6 +544,13 @@ int ff_thread_decode_frame(AVCodecContext
> *avctx,
>
> if (fctx->next_decoding >= avctx->thread_count) fctx->next_decoding = 0;
>
> + /* update hwaccel_priv_data from decoding thread */
> + cur_decoding = fctx->next_decoding - 1;
> + if (cur_decoding < 0) cur_decoding += avctx->thread_count;
> +
> + p = &fctx->threads[cur_decoding];
> + avctx->internal->hwaccel_priv_data = p->avctx->internal-
> >hwaccel_priv_data;
> +
> fctx->next_finished = finished;
>
> /* return the size of the consumed packet if no error occurred */
> --
> 2.7.4
Since previous concerns in https://patchwork.ffmpeg.org/patch/13723/
could be addressed in this version, ping for comments.
- linjie
More information about the ffmpeg-devel
mailing list