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 EC94A44AF7 for ; Tue, 13 Jan 2026 00:49:19 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'SNG2DfVQkPzowVdEcgEWQTfPJyIlNSgMzPy+d+KrRa0=', expected b'bdrSy0SY7HArW3Kn2AeUtxD07UchZjN7exL/qJZGkZY=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1768265314; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=SNG2DfVQkPzowVdEcgEWQTfPJyIlNSgMzPy+d+KrRa0=; b=AVW8IzHrKm5YUGYlHvldUhYLU+cFpEPDW7BTnBr+Hpwj9GEzV+UF6ZWleq9mfnFky0LAo BNL4PfRO/AKZY+jMpd8EL6G2Yeh7yr444KIShvpxfDG+yGHESGklCIyK1veMvBj1Nkc9v3D Ev8ukv0RodNFj/UZTSAo5ZLTTvCdSc33wdKpnBd6GEcdaokL2ELndWrvlsDLnnoNVwvHibN e07t32eQ4ulCg6UpS9PHDj81UAtrHTsFhtOUBf77PZS7eKF18/MYmDjdZG1K5Pzpwg2YZt8 eKQt5Wz9EU9HB1iAkPYrAxKCDVIIkCOVFyoMy2+NcF75mptWsH3U3IWAXUZw== Received: from [172.20.0.4] (unknown [172.20.0.4]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id C77E2690E0F; Tue, 13 Jan 2026 02:48:34 +0200 (EET) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1768265291; b=CCKLAb0RHvWEd4HXadH8a6qChpD/uGCB6NTZl7kt5ZGIY01eCrFOZ3qMlDGjo7V8/bRhw qhB6BinSlVdsJZjjkrv7IZ1trBQ03n0YWx9C7VNCejDygivA9LsqM9SS0OEY4kFA2jAKnsm GtTKh+Ixfb4mQ+fDfdw0P5fBHc8T4aXmzi92OnDr2Thg9ZxV2BKhouPP6RILn7RpV/kHRi1 J8skvWn0Yqg8dkW8JS1NBROg6uJw2Xp2SO191+Jd0uRfbW4BNLvCQ62MmO3TRN4mQ2KF0V6 bwKCN5uUM2oITvILDsOMjc2RfIg2AWSNL6yfrYI2fJx0J+qdWzND/PUzdD7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1768265291; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=5bSh9qhOTNyLFjIn0wFnVA1qyh73AEzxHPohpooB7qs=; b=LU1IAu3CRV49v12iOcf6MohgTSWxjuRRH64lqx5AttTkkIkDRAELlj59q76mfyMXIXQVM G2ehb6rfoHHCplCOqIiEMDBhAPPk7lvOJNlZiL79x1NbWG2yhBHLPONQNImMGma5LP71bcc 6ORBrPCQKY/Do9Su7CxPKPdzqgGS86XpEwb7AHZu7VeVH02pd+h303ZG7+UPRtcKuiue0po hKoMNWDIEFZahZE1hbOzqVkl7qZ8Xyra02s2HjrZYXBNozhd1QjJHyrzGBUzxzebydOk7r/ JRkiXx/kmMpyoYq9mC0xXnNu/pzMLIbxcn0+bA8SYmydJRoac9oOD/ABRmHQ== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1768265279; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=bdrSy0SY7HArW3Kn2AeUtxD07UchZjN7exL/qJZGkZY=; b=aiQqeFwsYQqvjxj57F2QUgMsYgkfNnNzTqyVPbErRgzTeuR5ccjEVgVljVbrgq5w1+Hde wqgeNbc1K924TVotgYZ34Pz4kiiaAlhyKvIIwzVuYSNXA9oxSga6i7OdwRWb4usv5LywANS 2ZPb8y3Xpay7x3Ra9mC5jY58EXDU5HFsreI9qf8lWt/oTjUI26OiP9IHPcpQFdnvG3a/dZC ut9GklxnDVkE15Dzoir/hhhUy6v3RprPMmTTDNtYaWjNV5dXL9Tnd+PqEb+J1TJ0xprUnPf VxvDus2bMI4gy8SBQLDO8NyG+ofdw7hZBQwb093LhO78NzYJjC3ExeZhzRGQ== Received: from f7c34508609e (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 68B8D68EC69 for ; Tue, 13 Jan 2026 02:47:59 +0200 (EET) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Tue, 13 Jan 2026 00:47:58 -0000 Message-ID: <176826527967.25.17890061173258586806@4457048688e7> Message-ID-Hash: PL7S6MIBJZRO2WMITUNC2OWZ3L5VSUAM X-Message-ID-Hash: PL7S6MIBJZRO2WMITUNC2OWZ3L5VSUAM X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PR] [release/7.1] backport LCEVC fixes (PR #21443) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: James Almer via ffmpeg-devel Cc: James Almer Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #21443 opened by James Almer (jamrial) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21443 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21443.patch >>From 75c42f558bdd609ca8f625769c10afdb2c55779a Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 25 Aug 2025 10:36:10 -0300 Subject: [PATCH 01/10] avcodec/lcevcdec: support LCEVCdec version 4 Signed-off-by: James Almer --- libavcodec/lcevcdec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 601e97b3a1..ba1887499a 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -139,7 +139,11 @@ static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame if (!sd) return 1; +#ifdef LCEVC_DEC_VERSION_MAJOR + res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, sd->data, sd->size); +#else res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, 0, sd->data, sd->size); +#endif if (res != LCEVC_Success) return AVERROR_EXTERNAL; @@ -147,7 +151,11 @@ static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame if (ret < 0) return ret; +#ifdef LCEVC_DEC_VERSION_MAJOR + res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, picture, -1, NULL); +#else res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL); +#endif if (res != LCEVC_Success) return AVERROR_EXTERNAL; -- 2.49.1 >>From 4ef4474d65d7d5fde0805e6e0848a9a03ab97066 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 2 Nov 2025 15:29:59 +0100 Subject: [PATCH 02/10] avcodec/decode: Don't allocate LCEVC context for non-video Signed-off-by: Andreas Rheinhardt (cherry picked from commit 182b9c7a4a7117371d51caa917f26162db53cc56) --- libavcodec/decode.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index d8d3bd4d11..4f98945bcf 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -2084,9 +2084,11 @@ int ff_decode_preinit(AVCodecContext *avctx) return ret; if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_ENHANCEMENTS)) { - ret = ff_lcevc_alloc(&dc->lcevc); - if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) - return ret; + if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { + ret = ff_lcevc_alloc(&dc->lcevc); + if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) + return ret; + } } #if FF_API_DROPCHANGED -- 2.49.1 >>From 4fff1187ac31f151b3b153ff8b2f3250e1ee56b8 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 2 Nov 2025 16:00:06 +0100 Subject: [PATCH 03/10] avcodec/decode: Put lcevc fields into structure of their own Makes it easier to see that width and height in DecodeContext is actually a lcevc field. Signed-off-by: Andreas Rheinhardt (cherry picked from commit 2786e5a9ad32920fccee9352161e81c8e733563b) --- libavcodec/decode.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 4f98945bcf..9621f3dc7b 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -92,10 +92,12 @@ typedef struct DecodeContext { */ uint64_t side_data_pref_mask; - FFLCEVCContext *lcevc; - int lcevc_frame; - int width; - int height; + struct { + FFLCEVCContext *ctx; + int frame; + int width; + int height; + } lcevc; } DecodeContext; static DecodeContext *decode_ctx(AVCodecInternal *avci) @@ -1660,12 +1662,12 @@ static void update_frame_props(AVCodecContext *avctx, AVFrame *frame) AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); - dc->lcevc_frame = dc->lcevc && avctx->codec_type == AVMEDIA_TYPE_VIDEO && + dc->lcevc.frame = dc->lcevc.ctx && avctx->codec_type == AVMEDIA_TYPE_VIDEO && av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC); - if (dc->lcevc_frame) { - dc->width = frame->width; - dc->height = frame->height; + if (dc->lcevc.frame) { + dc->lcevc.width = frame->width; + dc->lcevc.height = frame->height; frame->width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1); frame->height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1); } @@ -1676,7 +1678,7 @@ static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); - if (dc->lcevc_frame) { + if (dc->lcevc.frame) { FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data; FFLCEVCFrame *frame_ctx; int ret; @@ -1691,13 +1693,13 @@ static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) return AVERROR(ENOMEM); } - frame_ctx->lcevc = ff_refstruct_ref(dc->lcevc); + frame_ctx->lcevc = ff_refstruct_ref(dc->lcevc.ctx); 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; + frame->width = dc->lcevc.width; + frame->height = dc->lcevc.height; ret = avctx->get_buffer2(avctx, frame_ctx->frame, 0); if (ret < 0) { @@ -1711,7 +1713,7 @@ static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) fdd->post_process_opaque_free = ff_lcevc_unref; fdd->post_process = ff_lcevc_process; } - dc->lcevc_frame = 0; + dc->lcevc.frame = 0; return 0; } @@ -2085,7 +2087,7 @@ int ff_decode_preinit(AVCodecContext *avctx) if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_ENHANCEMENTS)) { if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { - ret = ff_lcevc_alloc(&dc->lcevc); + ret = ff_lcevc_alloc(&dc->lcevc.ctx); if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) return ret; } @@ -2333,7 +2335,7 @@ void ff_decode_internal_sync(AVCodecContext *dst, const AVCodecContext *src) dst_dc->initial_pict_type = src_dc->initial_pict_type; dst_dc->intra_only_flag = src_dc->intra_only_flag; - ff_refstruct_replace(&dst_dc->lcevc, src_dc->lcevc); + ff_refstruct_replace(&dst_dc->lcevc.ctx, src_dc->lcevc.ctx); } void ff_decode_internal_uninit(AVCodecContext *avctx) @@ -2341,5 +2343,5 @@ void ff_decode_internal_uninit(AVCodecContext *avctx) AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); - ff_refstruct_unref(&dc->lcevc); + ff_refstruct_unref(&dc->lcevc.ctx); } -- 2.49.1 >>From 4007d2a532722e935675d5c9e0dc3de4dfaba1d5 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Sun, 2 Nov 2025 16:50:36 +0100 Subject: [PATCH 04/10] avcodec/decode: Optimize lcevc away if disabled Signed-off-by: Andreas Rheinhardt (cherry picked from commit 8e90f150ebccf3f30fe139245b7d22fd6f1ee4a9) --- libavcodec/Makefile | 2 +- libavcodec/decode.c | 12 ++++++++++++ libavcodec/lcevcdec.c | 10 ---------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 153a9e3881..9d1c1fc30f 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -46,7 +46,6 @@ OBJS = ac3_parser.o \ get_buffer.o \ imgconvert.o \ jni.o \ - lcevcdec.o \ mathtables.o \ mediacodec.o \ mpeg12framerate.o \ @@ -124,6 +123,7 @@ OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o OBJS-$(CONFIG_JNI) += ffjni.o jni.o OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o OBJS-$(CONFIG_LCMS2) += fflcms2.o +OBJS-$(CONFIG_LIBLCEVC_DEC) += lcevcdec.o OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 9621f3dc7b..0ab0f4bb4d 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -92,12 +92,14 @@ typedef struct DecodeContext { */ uint64_t side_data_pref_mask; +#if CONFIG_LIBLCEVC_DEC struct { FFLCEVCContext *ctx; int frame; int width; int height; } lcevc; +#endif } DecodeContext; static DecodeContext *decode_ctx(AVCodecInternal *avci) @@ -1659,6 +1661,7 @@ int ff_attach_decode_data(AVFrame *frame) static void update_frame_props(AVCodecContext *avctx, AVFrame *frame) { +#if CONFIG_LIBLCEVC_DEC AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); @@ -1671,10 +1674,12 @@ static void update_frame_props(AVCodecContext *avctx, AVFrame *frame) frame->width = frame->width * 2 / FFMAX(frame->sample_aspect_ratio.den, 1); frame->height = frame->height * 2 / FFMAX(frame->sample_aspect_ratio.num, 1); } +#endif } static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) { +#if CONFIG_LIBLCEVC_DEC AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); @@ -1714,6 +1719,7 @@ static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame) fdd->post_process = ff_lcevc_process; } dc->lcevc.frame = 0; +#endif return 0; } @@ -2087,9 +2093,11 @@ int ff_decode_preinit(AVCodecContext *avctx) if (!(avctx->export_side_data & AV_CODEC_EXPORT_DATA_ENHANCEMENTS)) { if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { +#if CONFIG_LIBLCEVC_DEC ret = ff_lcevc_alloc(&dc->lcevc.ctx); if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) return ret; +#endif } } @@ -2335,13 +2343,17 @@ void ff_decode_internal_sync(AVCodecContext *dst, const AVCodecContext *src) dst_dc->initial_pict_type = src_dc->initial_pict_type; dst_dc->intra_only_flag = src_dc->intra_only_flag; +#if CONFIG_LIBLCEVC_DEC ff_refstruct_replace(&dst_dc->lcevc.ctx, src_dc->lcevc.ctx); +#endif } void ff_decode_internal_uninit(AVCodecContext *avctx) { +#if CONFIG_LIBLCEVC_DEC AVCodecInternal *avci = avctx->internal; DecodeContext *dc = decode_ctx(avci); ff_refstruct_unref(&dc->lcevc.ctx); +#endif } diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index ba1887499a..41049f72fc 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -16,8 +16,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config_components.h" - #include "libavutil/avassert.h" #include "libavutil/frame.h" #include "libavutil/imgutils.h" @@ -26,7 +24,6 @@ #include "decode.h" #include "lcevcdec.h" -#if CONFIG_LIBLCEVC_DEC static LCEVC_ColorFormat map_format(int format) { switch (format) { @@ -255,11 +252,9 @@ static void lcevc_free(FFRefStructOpaque unused, void *obj) LCEVC_DestroyDecoder(lcevc->decoder); memset(lcevc, 0, sizeof(*lcevc)); } -#endif static int lcevc_init(FFLCEVCContext *lcevc, void *logctx) { -#if CONFIG_LIBLCEVC_DEC LCEVC_AccelContextHandle dummy = { 0 }; const int32_t event = LCEVC_Log; @@ -278,7 +273,6 @@ static int lcevc_init(FFLCEVCContext *lcevc, void *logctx) return AVERROR_EXTERNAL; } -#endif lcevc->initialized = 1; return 0; @@ -297,7 +291,6 @@ int ff_lcevc_process(void *logctx, AVFrame *frame) return ret; } -#if CONFIG_LIBLCEVC_DEC av_assert0(frame_ctx->frame); @@ -310,7 +303,6 @@ int ff_lcevc_process(void *logctx, AVFrame *frame) return ret; av_frame_remove_side_data(frame, AV_FRAME_DATA_LCEVC); -#endif return 0; } @@ -318,11 +310,9 @@ int ff_lcevc_process(void *logctx, AVFrame *frame) int ff_lcevc_alloc(FFLCEVCContext **plcevc) { FFLCEVCContext *lcevc = NULL; -#if CONFIG_LIBLCEVC_DEC lcevc = ff_refstruct_alloc_ext(sizeof(*lcevc), 0, NULL, lcevc_free); if (!lcevc) return AVERROR(ENOMEM); -#endif *plcevc = lcevc; return 0; } -- 2.49.1 >>From 044ca5f5ef0e7a7770069d10da86cc64bf9feaa1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 22 Dec 2025 21:53:47 -0300 Subject: [PATCH 05/10] avcodec/lcevcdec: avoid copying the input frame Based on the lcevc filter implementation. Signed-off-by: James Almer (cherry picked from commit b392d75cf72cca90b5476e0c1b2e0876f3aff4ab) --- libavcodec/lcevcdec.c | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 41049f72fc..5f0c41b52d 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -47,10 +47,7 @@ static int alloc_base_frame(void *logctx, FFLCEVCContext *lcevc, { LCEVC_PictureDesc desc; LCEVC_ColorFormat fmt = map_format(frame->format); - LCEVC_PictureLockHandle lock; - uint8_t *data[4] = { NULL }; - int linesizes[4] = { 0 }; - uint32_t planes; + LCEVC_PicturePlaneDesc planes[AV_VIDEO_MAX_PLANES] = { 0 }; LCEVC_ReturnCode res; res = LCEVC_DefaultPictureDesc(&desc, fmt, frame->width, frame->height); @@ -64,36 +61,16 @@ static int alloc_base_frame(void *logctx, FFLCEVCContext *lcevc, desc.sampleAspectRatioNum = frame->sample_aspect_ratio.num; desc.sampleAspectRatioDen = frame->sample_aspect_ratio.den; + for (int i = 0; i < AV_VIDEO_MAX_PLANES; i++) { + planes[i].firstSample = frame->data[i]; + planes[i].rowByteStride = frame->linesize[i]; + } + /* Allocate LCEVC Picture */ - res = LCEVC_AllocPicture(lcevc->decoder, &desc, picture); + res = LCEVC_AllocPictureExternal(lcevc->decoder, &desc, NULL, planes, picture); if (res != LCEVC_Success) { return AVERROR_EXTERNAL; } - res = LCEVC_LockPicture(lcevc->decoder, *picture, LCEVC_Access_Write, &lock); - if (res != LCEVC_Success) - return AVERROR_EXTERNAL; - - 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(lcevc->decoder, lock, i, &plane); - if (res != LCEVC_Success) - return AVERROR_EXTERNAL; - - data[i] = plane.firstSample; - linesizes[i] = plane.rowByteStride; - } - - av_image_copy2(data, linesizes, frame->data, frame->linesize, - frame->format, frame->width, frame->height); - - res = LCEVC_UnlockPicture(lcevc->decoder, lock); - if (res != LCEVC_Success) - return AVERROR_EXTERNAL; return 0; } -- 2.49.1 >>From 0d9b8bfc0ef68424630855feb93e1b19b517cecb Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 22 Dec 2025 21:54:43 -0300 Subject: [PATCH 06/10] avcodec/lcevcdec: fix input dimensions for the base picture Fixes crashes with some samples. Signed-off-by: James Almer (cherry picked from commit 4f86ebfe940cd11de8f5ccf39e2b45da8354269d) --- libavcodec/lcevcdec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 5f0c41b52d..cea396325e 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -48,9 +48,11 @@ static int alloc_base_frame(void *logctx, FFLCEVCContext *lcevc, LCEVC_PictureDesc desc; LCEVC_ColorFormat fmt = map_format(frame->format); LCEVC_PicturePlaneDesc planes[AV_VIDEO_MAX_PLANES] = { 0 }; + int width = frame->width - frame->crop_left - frame->crop_right; + int height = frame->height - frame->crop_top - frame->crop_bottom; LCEVC_ReturnCode res; - res = LCEVC_DefaultPictureDesc(&desc, fmt, frame->width, frame->height); + res = LCEVC_DefaultPictureDesc(&desc, fmt, width, height); if (res != LCEVC_Success) return AVERROR_EXTERNAL; -- 2.49.1 >>From c74b4512e09eb7cdbb05772faaef7bd4ce6be089 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 22 Dec 2025 21:56:09 -0300 Subject: [PATCH 07/10] avcodec/lcevcdec: free pictures on error Signed-off-by: James Almer (cherry picked from commit fe1dae1e1857ebda9624f4be3f93f447097ae942) --- libavcodec/lcevcdec.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index cea396325e..76bdbdbe07 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -132,8 +132,10 @@ static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame #else res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL); #endif - if (res != LCEVC_Success) + if (res != LCEVC_Success) { + LCEVC_FreePicture(lcevc->decoder, picture); return AVERROR_EXTERNAL; + } memset(&picture, 0, sizeof(picture)); ret = alloc_enhanced_frame(logctx, frame_ctx, &picture); @@ -141,8 +143,10 @@ static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame return ret; res = LCEVC_SendDecoderPicture(lcevc->decoder, picture); - if (res != LCEVC_Success) + if (res != LCEVC_Success) { + LCEVC_FreePicture(lcevc->decoder, picture); return AVERROR_EXTERNAL; + } return 0; } @@ -160,8 +164,10 @@ static int generate_output(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) return AVERROR_EXTERNAL; res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc); - if (res != LCEVC_Success) + if (res != LCEVC_Success) { + LCEVC_FreePicture(lcevc->decoder, picture); return AVERROR_EXTERNAL; + } out->crop_top = desc.cropTop; out->crop_bottom = desc.cropBottom; -- 2.49.1 >>From 0e1dd337013996536a1e136128f47e572d092c60 Mon Sep 17 00:00:00 2001 From: James Almer Date: Wed, 7 Jan 2026 12:16:27 -0300 Subject: [PATCH 08/10] avcodec/lcevc: attach a reference to the source frame to each passed in base picture This way we can ensure a frame reference will always exists for as long as the external library needs the base picture. Signed-off-by: James Almer (cherry picked from commit 188521c7ad9e2a82d913770c3102593ebcd3454d) --- libavcodec/lcevcdec.c | 59 +++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c index 76bdbdbe07..1bfb7c78c5 100644 --- a/libavcodec/lcevcdec.c +++ b/libavcodec/lcevcdec.c @@ -108,6 +108,7 @@ static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame { FFLCEVCContext *lcevc = frame_ctx->lcevc; const AVFrameSideData *sd = av_frame_get_side_data(in, AV_FRAME_DATA_LCEVC); + AVFrame *opaque; LCEVC_PictureHandle picture; LCEVC_ReturnCode res; int ret = 0; @@ -127,13 +128,27 @@ static int lcevc_send_frame(void *logctx, FFLCEVCFrame *frame_ctx, const AVFrame if (ret < 0) return ret; + opaque = av_frame_clone(in); + if (!opaque) { + LCEVC_FreePicture(lcevc->decoder, picture); + return AVERROR(ENOMEM); + } + + res = LCEVC_SetPictureUserData(lcevc->decoder, picture, opaque); + if (res != LCEVC_Success) { + LCEVC_FreePicture(lcevc->decoder, picture); + av_frame_free(&opaque); + return AVERROR_EXTERNAL; + } + #ifdef LCEVC_DEC_VERSION_MAJOR - res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, picture, -1, NULL); + res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, picture, -1, opaque); #else - res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, NULL); + res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, opaque); #endif if (res != LCEVC_Success) { LCEVC_FreePicture(lcevc->decoder, picture); + av_frame_free(&opaque); return AVERROR_EXTERNAL; } @@ -169,17 +184,16 @@ static int generate_output(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) return AVERROR_EXTERNAL; } + av_frame_unref(out); + av_frame_copy_props(frame_ctx->frame, (AVFrame *)info.baseUserData); + av_frame_move_ref(out, frame_ctx->frame); + out->crop_top = desc.cropTop; out->crop_bottom = desc.cropBottom; out->crop_left = desc.cropLeft; 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; @@ -190,18 +204,13 @@ static int generate_output(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) return 0; } -static int lcevc_receive_frame(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) +static int lcevc_flush_pictures(FFLCEVCContext *lcevc) { - FFLCEVCContext *lcevc = frame_ctx->lcevc; LCEVC_PictureHandle picture; LCEVC_ReturnCode res; - int ret; - - ret = generate_output(logctx, frame_ctx, out); - if (ret < 0) - return ret; while (1) { + AVFrame *base = NULL; res = LCEVC_ReceiveDecoderBase (lcevc->decoder, &picture); if (res != LCEVC_Success && res != LCEVC_Again) return AVERROR_EXTERNAL; @@ -209,6 +218,9 @@ static int lcevc_receive_frame(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *o if (res == LCEVC_Again) break; + LCEVC_GetPictureUserData(lcevc->decoder, picture, (void **)&base); + av_frame_free(&base); + res = LCEVC_FreePicture(lcevc->decoder, picture); if (res != LCEVC_Success) return AVERROR_EXTERNAL; @@ -217,6 +229,18 @@ static int lcevc_receive_frame(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *o return 0; } +static int lcevc_receive_frame(void *logctx, FFLCEVCFrame *frame_ctx, AVFrame *out) +{ + FFLCEVCContext *lcevc = frame_ctx->lcevc; + int ret; + + ret = generate_output(logctx, frame_ctx, out); + if (ret < 0) + return ret; + + return lcevc_flush_pictures(lcevc); +} + static void event_callback(LCEVC_DecoderHandle dec, LCEVC_Event event, LCEVC_PictureHandle pic, const LCEVC_DecodeInformation *info, const uint8_t *data, uint32_t size, void *logctx) @@ -233,8 +257,11 @@ static void event_callback(LCEVC_DecoderHandle dec, LCEVC_Event event, static void lcevc_free(FFRefStructOpaque unused, void *obj) { FFLCEVCContext *lcevc = obj; - if (lcevc->initialized) + if (lcevc->initialized) { + LCEVC_FlushDecoder(lcevc->decoder); + lcevc_flush_pictures(lcevc); LCEVC_DestroyDecoder(lcevc->decoder); + } memset(lcevc, 0, sizeof(*lcevc)); } @@ -283,7 +310,7 @@ int ff_lcevc_process(void *logctx, AVFrame *frame) if (ret) return ret < 0 ? ret : 0; - lcevc_receive_frame(logctx, frame_ctx, frame); + ret = lcevc_receive_frame(logctx, frame_ctx, frame); if (ret < 0) return ret; -- 2.49.1 >>From e95d47ad5f87fb681415e7ac45e5f26d4023c169 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 25 Aug 2025 10:36:26 -0300 Subject: [PATCH 09/10] avfilter/vf_lcevc: support LCEVCdec version 4 Signed-off-by: James Almer --- libavfilter/vf_lcevc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavfilter/vf_lcevc.c b/libavfilter/vf_lcevc.c index b83dc94e02..5fe8a0a868 100644 --- a/libavfilter/vf_lcevc.c +++ b/libavfilter/vf_lcevc.c @@ -139,7 +139,11 @@ static int send_frame(AVFilterLink *inlink, AVFrame *in) return ret; if (sd) { +#ifdef LCEVC_DEC_VERSION_MAJOR + res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, sd->data, sd->size); +#else res = LCEVC_SendDecoderEnhancementData(lcevc->decoder, in->pts, 0, sd->data, sd->size); +#endif if (res == LCEVC_Again) return AVERROR(EAGAIN); else if (res != LCEVC_Success) { @@ -148,7 +152,11 @@ static int send_frame(AVFilterLink *inlink, AVFrame *in) } } +#ifdef LCEVC_DEC_VERSION_MAJOR + res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, picture, -1, in); +#else res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, 0, picture, -1, in); +#endif if (res != LCEVC_Success) { av_log(ctx, AV_LOG_ERROR, "LCEVC_SendDecoderBase failed\n"); LCEVC_FreePicture(lcevc->decoder, picture); -- 2.49.1 >>From 09dc319bf3de78803f7f6a637e2cafdc441499e5 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 10 Jan 2026 15:48:46 -0300 Subject: [PATCH 10/10] avfilter/vf_lcevc: attach a reference to the source frame to each passed in base picture And free them once they are guaranteed to be no longer needed, instead of freeing them when returned with an enhanced output. Signed-off-by: James Almer (cherry picked from commit af136db1c3c5d72c4a71cedaf7b06d2f8ae3819e) --- libavfilter/vf_lcevc.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/libavfilter/vf_lcevc.c b/libavfilter/vf_lcevc.c index 5fe8a0a868..318b144374 100644 --- a/libavfilter/vf_lcevc.c +++ b/libavfilter/vf_lcevc.c @@ -152,6 +152,13 @@ static int send_frame(AVFilterLink *inlink, AVFrame *in) } } + res = LCEVC_SetPictureUserData(lcevc->decoder, picture, in); + if (res != LCEVC_Success) { + av_log(ctx, AV_LOG_ERROR, "LCEVC_SetPictureUserData failed\n"); + LCEVC_FreePicture(lcevc->decoder, picture); + return AVERROR_EXTERNAL; + } + #ifdef LCEVC_DEC_VERSION_MAJOR res = LCEVC_SendDecoderBase(lcevc->decoder, in->pts, picture, -1, in); #else @@ -223,8 +230,6 @@ static int generate_output(AVFilterLink *inlink, AVFrame *out) av_frame_copy_props(out, (AVFrame *)info.baseUserData); av_frame_remove_side_data(out, AV_FRAME_DATA_LCEVC); - av_frame_free((AVFrame **)&info.baseUserData); - res = LCEVC_GetPictureDesc(lcevc->decoder, picture, &desc); LCEVC_FreePicture(lcevc->decoder, picture); @@ -292,8 +297,12 @@ static void flush_bases(AVFilterContext *ctx) LCEVCContext *lcevc = ctx->priv; LCEVC_PictureHandle picture; - while (LCEVC_ReceiveDecoderBase(lcevc->decoder, &picture) == LCEVC_Success) + while (LCEVC_ReceiveDecoderBase(lcevc->decoder, &picture) == LCEVC_Success) { + AVFrame *base = NULL; + LCEVC_GetPictureUserData(lcevc->decoder, picture, (void **)&base); LCEVC_FreePicture(lcevc->decoder, picture); + av_frame_free(&base); + } } static int activate(AVFilterContext *ctx) @@ -407,6 +416,8 @@ static av_cold void uninit(AVFilterContext *ctx) { LCEVCContext *lcevc = ctx->priv; + LCEVC_FlushDecoder(lcevc->decoder); + flush_bases(ctx); LCEVC_DestroyDecoder(lcevc->decoder); } -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org