From patchwork Thu Jul 18 21:35:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fu, Linjie" X-Patchwork-Id: 13981 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 4AB304468EC for ; Thu, 18 Jul 2019 12:36:17 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 261BA68AF10; Thu, 18 Jul 2019 12:36:17 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 95B2168ABD5 for ; Thu, 18 Jul 2019 12:36:10 +0300 (EEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Jul 2019 02:36:07 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,276,1559545200"; d="scan'208";a="367299111" Received: from icl-dev.sh.intel.com ([10.239.158.32]) by fmsmga006.fm.intel.com with ESMTP; 18 Jul 2019 02:36:06 -0700 From: Linjie Fu To: ffmpeg-devel@ffmpeg.org Date: Thu, 18 Jul 2019 17:35:28 -0400 Message-Id: <1563485728-6665-1-git-send-email-linjie.fu@intel.com> X-Mailer: git-send-email 2.7.4 Subject: [FFmpeg-devel] [PATCH] lavc/phtread_frame: update hwaccel_priv_data in time for multithread X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Linjie Fu MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" 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 --- 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 */