diff mbox series

[FFmpeg-devel,1/2] lavc/videotoolbox: do not pass AVCodecContext to decoder output callback

Message ID 20220915135627.32230-1-anton@khirnov.net
State Accepted
Commit d7f4ad88a0df3c1339e142957bf2c40cd056b8ce
Headers show
Series [FFmpeg-devel,1/2] lavc/videotoolbox: do not pass AVCodecContext to decoder output callback | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov Sept. 15, 2022, 1:56 p.m. UTC
The opaque parameter for the callback is set in videotoolbox_start(),
called when the hwaccel is initialized. When frame threading is used,
avctx will be the context corresponding to the frame thread currently
doing the decoding. Using this same codec context in all subsequent
invocations of the decoder callback (even those triggered by a different
frame thread) is unsafe, and broken after
cc867f2c09d2b69cee8a0eccd62aff002cbbfe11, since each frame thread now
cleans up its hwaccel state after decoding each frame.

Fix this by passing hwaccel_priv_data as the opaque parameter, which
exists in a single instance forwarded between all frame threads.

The only other use of AVCodecContext in the decoder output callback is
as a logging context. For this purpose, store a logging context in
hwaccel_priv_data.
---
Initial version of this patch tested by Marvin on IRC.
Someone please test this final version, as I don't have the HW to do it
myself.
---
 libavcodec/videotoolbox.c | 10 ++++++----
 libavcodec/vt_internal.h  |  2 ++
 2 files changed, 8 insertions(+), 4 deletions(-)

Comments

Thilo Borgmann Sept. 15, 2022, 7:22 p.m. UTC | #1
Am 15.09.22 um 15:56 schrieb Anton Khirnov:
> The opaque parameter for the callback is set in videotoolbox_start(),
> called when the hwaccel is initialized. When frame threading is used,
> avctx will be the context corresponding to the frame thread currently
> doing the decoding. Using this same codec context in all subsequent
> invocations of the decoder callback (even those triggered by a different
> frame thread) is unsafe, and broken after
> cc867f2c09d2b69cee8a0eccd62aff002cbbfe11, since each frame thread now
> cleans up its hwaccel state after decoding each frame.
> 
> Fix this by passing hwaccel_priv_data as the opaque parameter, which
> exists in a single instance forwarded between all frame threads.
> 
> The only other use of AVCodecContext in the decoder output callback is
> as a logging context. For this purpose, store a logging context in
> hwaccel_priv_data.
> ---
> Initial version of this patch tested by Marvin on IRC.
> Someone please test this final version, as I don't have the HW to do it
> myself.
> ---
>   libavcodec/videotoolbox.c | 10 ++++++----
>   libavcodec/vt_internal.h  |  2 ++
>   2 files changed, 8 insertions(+), 4 deletions(-)

Confirmed, fixes the crash for me as well!

Thx,
Thilo
diff mbox series

Patch

diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
index ce83c2594a..d61d310600 100644
--- a/libavcodec/videotoolbox.c
+++ b/libavcodec/videotoolbox.c
@@ -690,8 +690,7 @@  static void videotoolbox_decoder_callback(void *opaque,
                                           CMTime pts,
                                           CMTime duration)
 {
-    AVCodecContext *avctx = opaque;
-    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
+    VTContext *vtctx = opaque;
 
     if (vtctx->frame) {
         CVPixelBufferRelease(vtctx->frame);
@@ -699,7 +698,8 @@  static void videotoolbox_decoder_callback(void *opaque,
     }
 
     if (!image_buffer) {
-        av_log(avctx, status ? AV_LOG_WARNING : AV_LOG_DEBUG, "vt decoder cb: output image buffer is null: %i\n", status);
+        av_log(vtctx->logctx, status ? AV_LOG_WARNING : AV_LOG_DEBUG,
+               "vt decoder cb: output image buffer is null: %i\n", status);
         return;
     }
 
@@ -949,7 +949,7 @@  static int videotoolbox_start(AVCodecContext *avctx)
                                                      videotoolbox->cv_pix_fmt_type);
 
     decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
-    decoder_cb.decompressionOutputRefCon   = avctx;
+    decoder_cb.decompressionOutputRefCon   = avctx->internal->hwaccel_priv_data;
 
     status = VTDecompressionSessionCreate(NULL,                      // allocator
                                           videotoolbox->cm_fmt_desc, // videoFormatDescription
@@ -1179,6 +1179,8 @@  int ff_videotoolbox_common_init(AVCodecContext *avctx)
     AVHWFramesContext *hw_frames;
     int err;
 
+    vtctx->logctx = avctx;
+
     // Old API - do nothing.
     if (avctx->hwaccel_context)
         return 0;
diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h
index 54a11fd1b5..9502d7c7dc 100644
--- a/libavcodec/vt_internal.h
+++ b/libavcodec/vt_internal.h
@@ -45,6 +45,8 @@  typedef struct VTContext {
     // Current H264 parameters (used to trigger decoder restart on SPS changes).
     uint8_t                     sps[3];
     bool                        reconfig_needed;
+
+    void *logctx;
 } VTContext;
 
 int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame);