From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id E4B2049D0A for ; Tue, 20 May 2025 02:09:29 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 01BBA68D213; Tue, 20 May 2025 05:09:25 +0300 (EEST) Received: from mail-vk1-f170.google.com (mail-vk1-f170.google.com [209.85.221.170]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id C1B3168C637 for ; Tue, 20 May 2025 05:09:19 +0300 (EEST) Received: by mail-vk1-f170.google.com with SMTP id 71dfb90a1353d-52413efd0d3so1479044e0c.2 for ; Mon, 19 May 2025 19:09:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747706958; x=1748311758; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=4pvLrqvUvrrGhoKtlWMunh46XT+moXJlDxcthNBQ/BY=; b=XwVFjFaqz0yczn6+JUju+m4IapJvtzTV5tok9LtLE5338JypHPRwgoomsI80kMf2W+ Y2EYs4qvVt3CDYYqovKbalEygKzmTUl3fL3YsYegiSaqgmZT4Yp6rRNbKjX4cY8HcQ9A 1BRHspdIQSsy9QPX8eJ9KIN3rLneliz+uHzOQpRlcJe5gEhlFR2HrCVJSSZ06NEBzhNT vpL9nV7IrzmUfW2xwvGS3Ak6GTd29QUvYk/foxfIvFruu+F8czjNtOtBJTgFV+Nto8Pe vuhtqcZQU0CVD+/oTK06qbgSZ4TMuL581GiRoDje9S+/svHM8khb6Jx/ykDpPbWggoai YoWQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747706958; x=1748311758; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=4pvLrqvUvrrGhoKtlWMunh46XT+moXJlDxcthNBQ/BY=; b=Wlg9CHLq/rAhvI0hjpvA3Q9n+xHjAWfO2cUJUHd6sFP8ox5NzFm5bWxs2nYMGYKFvK GjZijMBEA7rVhmUOIGnXP50krM6X0nrzt9iSMVHqE9Epwz/Y3Xo9ep/NSndvO/Lt6WjP BRPrlY0f0RpmQsT4M5oYLgLmnVLf0RPKbszne5uOYgHPgnx5rCGOi0IxsOxSbNQvXrO0 h5E8wrhfB9Cu48v6BVnGD1UAKcFUBgrdpnaE1wLQdbK/8gbQxQWJ4oh63AK60rPzsu5P d/V//K6yoGgebvLC5U7/YqBcnPb/ViOpwtdVwcoZu3Ai/UVymheqTjBDvrKigmLtpjS+ /TIQ== X-Gm-Message-State: AOJu0Yw0ztJInxsj2bMhSHhqOmQrUNFhx8LxdX3/qDkdCeT6BMirEhQO t501bwB40GAe1PfvbejisYq2fEEu2B5n4S0CP0wSZWdk15GSgcPRxB+06aNFdQ== X-Gm-Gg: ASbGncsGUCkBcPnua8X2A8ovwD/1kzQYBg0aWr+ksGd/gJ3O0fTnpF6y8AppTU8iis5 rusTWZgMDtuhx1lsdJUe5jX0oa831hmV7FW0umIS5CYkaB3IkcnOEB4Np62Su+Nw+9/eiy+L/V8 R329C6gk8QzAumEk/SKDk/PFMYV+NEMpuvdF9p6wSqoA7DJD9BV8ccLCIlknAm9IF31P+Si4tbI zsBu2MESbWKVK2x74W2N3O1XctCWq9Y6U+piZGT2PXInGBrMsth+t1oyZxnziPL8pVDDUqDBkN4 BPANTwMn+968KHokrgyaxtrxEfHdkNUk3vIrGSwXSGrhFRQaeiZ58uHSWMF9yhEvMUInQdE= X-Google-Smtp-Source: AGHT+IHr2+/vXSTA4Eej3gEDRF04w6AwPbU+iW/AXQMd3TCu4+S9qOyjFKR7Ss179HaRbtBfZc1f/Q== X-Received: by 2002:a05:6122:4b11:b0:52c:4eb0:118d with SMTP id 71dfb90a1353d-52dbcceb24fmr11722180e0c.4.1747706957835; Mon, 19 May 2025 19:09:17 -0700 (PDT) Received: from localhost.localdomain ([2800:2121:b000:82e:6173:9324:3616:deec]) by smtp.gmail.com with ESMTPSA id a1e0cc1a2514c-87bec12287esm6596317241.10.2025.05.19.19.09.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 May 2025 19:09:17 -0700 (PDT) From: James Almer To: ffmpeg-devel@ffmpeg.org Date: Mon, 19 May 2025 23:09:06 -0300 Message-ID: <20250520020906.1865-1-jamrial@gmail.com> X-Mailer: git-send-email 2.49.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avcodec/lcevcdec: don't try to write to output frames directly X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: The buffer references may not be writable at this point, as the decoder calls get_buffer2() with the AV_GET_BUFFER_FLAG_REF flag. Fixes races as reported by tsan, producing correct output regardless of threading choices. Signed-off-by: James Almer --- libavcodec/decode.c | 39 ++++++++++++++++++++---- libavcodec/lcevcdec.c | 69 ++++++++++++++++++++++++------------------- libavcodec/lcevcdec.h | 5 ++++ 3 files changed, 78 insertions(+), 35 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index c2b2dd6e3b..ef09568381 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -1590,22 +1590,49 @@ static void update_frame_props(AVCodecContext *avctx, AVFrame *frame) } } -static void attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) +static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) { AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); if (dc->lcevc_frame) { FrameDecodeData *fdd = frame->private_ref; + FFLCEVCFrame *frame_ctx; + int ret; - fdd->post_process_opaque = av_refstruct_ref(dc->lcevc); - fdd->post_process_opaque_free = ff_lcevc_unref; - fdd->post_process = ff_lcevc_process; + frame_ctx = av_mallocz(sizeof(*frame_ctx)); + if (!frame_ctx) + return AVERROR(ENOMEM); + + frame_ctx->frame = av_frame_alloc(); + if (!frame_ctx->frame) { + av_free(frame_ctx); + return AVERROR(ENOMEM); + } + + frame_ctx->lcevc = av_refstruct_ref(dc->lcevc); + frame_ctx->frame->width = frame->width; + frame_ctx->frame->height = frame->height; + frame_ctx->frame->format = frame->format; frame->width = dc->width; frame->height = dc->height; + + ret = avctx->get_buffer2(avctx, frame_ctx->frame, 0); + if (ret < 0) { + ff_lcevc_unref(frame_ctx); + return ret; + } + + validate_avframe_allocation(avctx, frame_ctx->frame); + + fdd->post_process_opaque = frame_ctx; + fdd->post_process_opaque_free = ff_lcevc_unref; + fdd->post_process = ff_lcevc_process; } dc->lcevc_frame = 0; + + return 0; } int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) @@ -1666,7 +1693,9 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags) if (ret < 0) goto fail; - attach_post_process_data(avctx, frame); + ret = attach_post_process_data(avctx, frame); + if (ret < 0) + goto fail; end: if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions && diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 2fe06b8800..102f6f32e9 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -47,7 +47,7 @@ static LCEVC_ColorFormat map_format(int format) return LCEVC_ColorFormat_Unknown; } -static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder, +static int alloc_base_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *frame, LCEVC_PictureHandle *picture) { LCEVC_PictureDesc desc; @@ -70,22 +70,22 @@ static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder, desc.sampleAspectRatioDen = frame->sample_aspect_ratio.den; /* Allocate LCEVC Picture */ - res = LCEVC_AllocPicture(decoder, &desc, picture); + res = LCEVC_AllocPicture(lcevc->decoder, &desc, picture); if (res != LCEVC_Success) { return AVERROR_EXTERNAL; } - res = LCEVC_LockPicture(decoder, *picture, LCEVC_Access_Write, &lock); + res = LCEVC_LockPicture(lcevc->decoder, *picture, LCEVC_Access_Write, &lock); if (res != LCEVC_Success) return AVERROR_EXTERNAL; - res = LCEVC_GetPicturePlaneCount(decoder, *picture, &planes); + res = LCEVC_GetPicturePlaneCount(lcevc->decoder, *picture, &planes); if (res != LCEVC_Success) return AVERROR_EXTERNAL; for (unsigned i = 0; i < planes; i++) { LCEVC_PicturePlaneDesc plane; - res = LCEVC_GetPictureLockPlaneDesc(decoder, lock, i, &plane); + res = LCEVC_GetPictureLockPlaneDesc(lcevc->decoder, lock, i, &plane); if (res != LCEVC_Success) return AVERROR_EXTERNAL; @@ -96,43 +96,43 @@ static int alloc_base_frame(void *logctx, LCEVC_DecoderHandle decoder, av_image_copy2(data, linesizes, frame->data, frame->linesize, frame->format, frame->width, frame->height); - res = LCEVC_UnlockPicture(decoder, lock); + res = LCEVC_UnlockPicture(lcevc->decoder, lock); if (res != LCEVC_Success) return AVERROR_EXTERNAL; return 0; } -static int alloc_enhanced_frame(void *logctx, LCEVC_DecoderHandle decoder, - const AVFrame *frame, LCEVC_PictureHandle *picture) +static int alloc_enhanced_frame(void *logctx, FFLCEVCFrame *frame_ctx, + LCEVC_PictureHandle *picture) { + FFLCEVCContext *lcevc = frame_ctx->lcevc; LCEVC_PictureDesc desc ; - LCEVC_ColorFormat fmt = map_format(frame->format); + LCEVC_ColorFormat fmt = map_format(frame_ctx->frame->format); LCEVC_PicturePlaneDesc planes[4] = { 0 }; - int width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1); - int height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1); LCEVC_ReturnCode res; - res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height); + res = LCEVC_DefaultPictureDesc(&desc, fmt, frame_ctx->frame->width, frame_ctx->frame->height); if (res != LCEVC_Success) return AVERROR_EXTERNAL; /* Set plane description */ for (int i = 0; i < 4; i++) { - planes[i].firstSample = frame->data[i]; - planes[i].rowByteStride = frame->linesize[i]; + planes[i].firstSample = frame_ctx->frame->data[i]; + planes[i].rowByteStride = frame_ctx->frame->linesize[i]; } /* Allocate LCEVC Picture */ - res = LCEVC_AllocPictureExternal(decoder, &desc, NULL, planes, picture); + res = LCEVC_AllocPictureExternal(lcevc->decoder, &desc, NULL, planes, picture); if (res != LCEVC_Success) { return AVERROR_EXTERNAL; } return 0; } -static int lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame *in) +static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame *in) { + FFLCEVCContext *lcevc = frame_ctx->lcevc; const AVFrameSideData *sd = av_frame_get_side_data(in, AV_FRAME_DATA_LCEVC); LCEVC_PictureHandle picture; LCEVC_ReturnCode res; @@ -145,7 +145,7 @@ static int lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame * if (res != LCEVC_Success) return AVERROR_EXTERNAL; - ret = alloc_base_frame(logctx, lcevc->decoder, in, &picture); + ret = alloc_base_frame(logctx, lcevc, in, &picture); if (ret < 0) return ret; @@ -154,7 +154,7 @@ static int lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame * return AVERROR_EXTERNAL; memset(&picture, 0, sizeof(picture)); - ret = alloc_enhanced_frame(logctx, lcevc->decoder, in, &picture); + ret = alloc_enhanced_frame(logctx, frame_ctx, &picture); if (ret < 0) return ret; @@ -165,8 +165,9 @@ static int lcevc_send_frame(void *logctx, FFLCEVCContext *lcevc, const AVFrame * return 0; } -static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out) +static int generate_output(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) { + FFLCEVCContext *lcevc = frame_ctx->lcevc; LCEVC_PictureDesc desc; LCEVC_DecodeInformation info; LCEVC_PictureHandle picture; @@ -186,6 +187,11 @@ static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out) out->crop_right = desc.cropRight; out->sample_aspect_ratio.num = desc.sampleAspectRatioNum; out->sample_aspect_ratio.den = desc.sampleAspectRatioDen; + + av_frame_copy_props(frame_ctx->frame, out); + av_frame_unref(out); + av_frame_move_ref(out, frame_ctx->frame); + out->width = desc.width + out->crop_left + out->crop_right; out->height = desc.height + out->crop_top + out->crop_bottom; @@ -196,13 +202,14 @@ static int generate_output(void *logctx, FFLCEVCContext *lcevc, AVFrame *out) return 0; } -static int lcevc_receive_frame(void *logctx, FFLCEVCContext *lcevc, AVFrame *out) +static int lcevc_receive_frame(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) { + FFLCEVCContext *lcevc = frame_ctx->lcevc; LCEVC_PictureHandle picture; LCEVC_ReturnCode res; int ret; - ret = generate_output(logctx, lcevc, out); + ret = generate_output(logctx, frame_ctx, out); if (ret < 0) return ret; @@ -249,12 +256,7 @@ static int lcevc_init(FFLCEVCContext *lcevc, void *logctx) #if CONFIG_LIBLCEVC_DEC LCEVC_AccelContextHandle dummy = { 0 }; const int32_t event = LCEVC_Log; -#endif - if (lcevc->initialized) - return 0; - -#if CONFIG_LIBLCEVC_DEC if (LCEVC_CreateDecoder(&lcevc->decoder, dummy) != LCEVC_Success) { av_log(logctx, AV_LOG_ERROR, "Failed to create LCEVC decoder\n"); return AVERROR_EXTERNAL; @@ -279,7 +281,8 @@ static int lcevc_init(FFLCEVCContext *lcevc, void *logctx) int ff_lcevc_process(void *logctx, AVFrame *frame) { FrameDecodeData *fdd = frame->private_ref; - FFLCEVCContext *lcevc = fdd->post_process_opaque; + FFLCEVCFrame *frame_ctx = fdd->post_process_opaque; + FFLCEVCContext *lcevc = frame_ctx->lcevc; int ret; if (!lcevc->initialized) { @@ -289,11 +292,14 @@ int ff_lcevc_process(void *logctx, AVFrame *frame) } #if CONFIG_LIBLCEVC_DEC - ret = lcevc_send_frame(logctx, lcevc, frame); + av_assert0(frame_ctx->frame); + + + ret = lcevc_send_frame(logctx, frame_ctx, frame); if (ret) return ret < 0 ? ret : 0; - lcevc_receive_frame(logctx, lcevc, frame); + lcevc_receive_frame(logctx, frame_ctx, frame); if (ret < 0) return ret; @@ -317,5 +323,8 @@ int ff_lcevc_alloc(FFLCEVCContext **plcevc) void ff_lcevc_unref(void *opaque) { - av_refstruct_unref(&opaque); + FFLCEVCFrame *lcevc = opaque; + av_refstruct_unref(&lcevc->lcevc); + av_frame_free(&lcevc->frame); + av_free(opaque); } diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h index b21d1073c4..62014132d9 100644 --- a/libavcodec/lcevcdec.h +++ b/libavcodec/lcevcdec.h @@ -35,6 +35,11 @@ typedef struct FFLCEVCContext { struct AVFrame; +typedef struct FFLCEVCFrame { + FFLCEVCContext *lcevc; + struct AVFrame *frame; +} FFLCEVCFrame; + int ff_lcevc_alloc(FFLCEVCContext **plcevc); int ff_lcevc_process(void *logctx, struct AVFrame *frame); void ff_lcevc_unref(void *opaque); -- 2.49.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".