This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch release/8.1
in repository ffmpeg.

commit 9abdfda6f2cda9b397078ad4ce72741caf425ad1
Author:     James Almer <[email protected]>
AuthorDate: Mon Mar 9 20:22:27 2026 -0300
Commit:     James Almer <[email protected]>
CommitDate: Wed Mar 18 13:35:56 2026 -0300

    avcodec/lcevcdec: don't try to derive final dimensions from SAR
    
    Not only do some sources not provide an aspect ratio, as is the case of
    MPEG-TS, but also some enhanced streams have no change in dimensions, and 
this
    heuristic would generate bugus values.
    Instead, we need to parse the LCEVC bitstream for a Global Config process 
block
    in order to get the actual dimensions. This add a little overhead, but it 
can't
    be avoided.
    
    Signed-off-by: James Almer <[email protected]>
    (cherry picked from commit 49d75d81f6753623a3d1f5e8c5c6aa8bf669f744)
---
 libavcodec/decode.c        | 44 +++++++++++++++++++-------
 libavcodec/lcevcdec.c      | 79 +++++++++++++++++++++++++++++++++++++++++++++-
 libavcodec/lcevcdec.h      |  9 +++++-
 libavcodec/pthread_frame.c |  1 +
 4 files changed, 120 insertions(+), 13 deletions(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index ca1adfa386..5de5a84038 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -98,6 +98,8 @@ typedef struct DecodeContext {
     struct {
         FFLCEVCContext *ctx;
         int frame;
+        int base_width;
+        int base_height;
         int width;
         int height;
     } lcevc;
@@ -1661,7 +1663,7 @@ int ff_attach_decode_data(AVFrame *frame)
     return 0;
 }
 
-static void update_frame_props(AVCodecContext *avctx, AVFrame *frame)
+static int update_frame_props(AVCodecContext *avctx, AVFrame *frame)
 {
 #if CONFIG_LIBLCEVC_DEC
     AVCodecInternal    *avci = avctx->internal;
@@ -1671,12 +1673,23 @@ static void update_frame_props(AVCodecContext *avctx, 
AVFrame *frame)
                       av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC);
 
     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);
+        int ret = ff_lcevc_parse_frame(dc->lcevc.ctx, frame,
+                                       &dc->lcevc.width, &dc->lcevc.height, 
avctx);
+        if (ret < 0)
+            return ret;
+
+        // force get_buffer2() to allocate the base frame using the same 
dimensions
+        // as the final enhanced frame, in order to prevent reinitializing the 
buffer
+        // pools unnecessarely
+        if (dc->lcevc.width && dc->lcevc.height) {
+            dc->lcevc.base_width  = frame->width;
+            dc->lcevc.base_height = frame->height;
+            frame->width  = dc->lcevc.width;
+            frame->height = dc->lcevc.height;
+        }
     }
 #endif
+    return 0;
 }
 
 static int attach_post_process_data(AVCodecContext *avctx, AVFrame *frame)
@@ -1690,6 +1703,11 @@ static int attach_post_process_data(AVCodecContext 
*avctx, AVFrame *frame)
         FFLCEVCFrame *frame_ctx;
         int ret;
 
+        if (!dc->lcevc.width || !dc->lcevc.height) {
+            dc->lcevc.frame = 0;
+            return 0;
+        }
+
         frame_ctx = av_mallocz(sizeof(*frame_ctx));
         if (!frame_ctx)
             return AVERROR(ENOMEM);
@@ -1701,12 +1719,12 @@ static int attach_post_process_data(AVCodecContext 
*avctx, AVFrame *frame)
         }
 
         frame_ctx->lcevc = av_refstruct_ref(dc->lcevc.ctx);
-        frame_ctx->frame->width  = frame->width;
-        frame_ctx->frame->height = frame->height;
+        frame_ctx->frame->width  = dc->lcevc.width;
+        frame_ctx->frame->height = dc->lcevc.height;
         frame_ctx->frame->format = frame->format;
 
-        frame->width  = dc->lcevc.width;
-        frame->height = dc->lcevc.height;
+        frame->width  = dc->lcevc.base_width;
+        frame->height = dc->lcevc.base_height;
 
         ret = avctx->get_buffer2(avctx, frame_ctx->frame, 0);
         if (ret < 0) {
@@ -1771,7 +1789,9 @@ int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, 
int flags)
         }
     } else {
         avctx->sw_pix_fmt = avctx->pix_fmt;
-        update_frame_props(avctx, frame);
+        ret = update_frame_props(avctx, frame);
+        if (ret < 0)
+            goto fail;
     }
 
     ret = avctx->get_buffer2(avctx, frame, flags);
@@ -2091,7 +2111,7 @@ av_cold 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);
+            ret = ff_lcevc_alloc(&dc->lcevc.ctx, avctx);
             if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
                 return ret;
 #endif
@@ -2338,6 +2358,8 @@ av_cold void ff_decode_internal_sync(AVCodecContext *dst, 
const AVCodecContext *
     dst_dc->side_data_pref_mask = src_dc->side_data_pref_mask;
 #if CONFIG_LIBLCEVC_DEC
     av_refstruct_replace(&dst_dc->lcevc.ctx, src_dc->lcevc.ctx);
+    dst_dc->lcevc.width = src_dc->lcevc.width;
+    dst_dc->lcevc.height = src_dc->lcevc.height;
 #endif
 }
 
diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c
index 036b700775..69a73866fe 100644
--- a/libavcodec/lcevcdec.c
+++ b/libavcodec/lcevcdec.c
@@ -23,8 +23,12 @@
 #include "libavutil/mem.h"
 #include "libavutil/refstruct.h"
 
+#include "cbs.h"
+#include "cbs_lcevc.h"
 #include "decode.h"
+#include "lcevc_parse.h"
 #include "lcevcdec.h"
+#include "lcevctab.h"
 
 static LCEVC_ColorFormat map_format(int format)
 {
@@ -191,6 +195,15 @@ static int generate_output(void *logctx, FFLCEVCFrame 
*frame_ctx, AVFrame *out)
     out->width = desc.width + out->crop_left + out->crop_right;
     out->height = desc.height + out->crop_top + out->crop_bottom;
 
+    av_log(logctx, AV_LOG_DEBUG, "out PTS %"PRId64", %dx%d, "
+                                 "%zu/%zu/%zu/%zu, "
+                                 "SAR %d:%d, "
+                                 "hasEnhancement %d, enhanced %d\n",
+           out->pts, out->width, out->height,
+           out->crop_top, out->crop_bottom, out->crop_left, out->crop_right,
+           out->sample_aspect_ratio.num, out->sample_aspect_ratio.den,
+           info.hasEnhancement, info.enhanced);
+
     res = LCEVC_FreePicture(lcevc->decoder, picture);
     if (res != LCEVC_Success)
         return AVERROR_EXTERNAL;
@@ -256,6 +269,10 @@ static void lcevc_free(AVRefStructOpaque unused, void *obj)
         lcevc_flush_pictures(lcevc);
         LCEVC_DestroyDecoder(lcevc->decoder);
     }
+    if (lcevc->frag)
+        ff_cbs_fragment_free(lcevc->frag);
+    av_freep(&lcevc->frag);
+    ff_cbs_close(&lcevc->cbc);
     memset(lcevc, 0, sizeof(*lcevc));
 }
 
@@ -313,14 +330,74 @@ int ff_lcevc_process(void *logctx, AVFrame *frame)
     return 0;
 }
 
-int ff_lcevc_alloc(FFLCEVCContext **plcevc)
+int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const AVFrame *frame,
+                         int *width, int *height, void *logctx)
+{
+    LCEVCRawProcessBlock *block = NULL;
+    LCEVCRawGlobalConfig *gc = NULL;
+    AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_LCEVC);
+    int ret;
+
+    ret = ff_cbs_read(lcevc->cbc, lcevc->frag, sd->buf, sd->data, sd->size);
+    if (ret < 0) {
+        av_log(logctx, AV_LOG_ERROR, "Failed to parse Access Unit.\n");
+        goto end;
+    }
+
+    ret = ff_cbs_lcevc_find_process_block(lcevc->cbc, lcevc->frag,
+                                          LCEVC_PAYLOAD_TYPE_GLOBAL_CONFIG, 
&block);
+    if (ret < 0) {
+        ret = 0;
+        goto end;
+    }
+
+    gc = block->payload;
+    if (gc->resolution_type < 63) {
+        *width  = ff_lcevc_resolution_type[gc->resolution_type].width;
+        *height = ff_lcevc_resolution_type[gc->resolution_type].height;
+    } else {
+        *width  = gc->custom_resolution_width;
+        *height = gc->custom_resolution_height;
+    }
+
+    ret = 0;
+end:
+    ff_cbs_fragment_reset(lcevc->frag);
+
+    return ret;
+}
+
+static const CodedBitstreamUnitType decompose_unit_types[] = {
+    LCEVC_IDR_NUT,
+};
+
+int ff_lcevc_alloc(FFLCEVCContext **plcevc, void *logctx)
 {
     FFLCEVCContext *lcevc = NULL;
+    int ret;
+
     lcevc = av_refstruct_alloc_ext(sizeof(*lcevc), 0, NULL, lcevc_free);
     if (!lcevc)
         return AVERROR(ENOMEM);
+
+    lcevc->frag = av_mallocz(sizeof(*lcevc->frag));
+    if (!lcevc->frag) {
+        ret = AVERROR(ENOMEM);
+        goto fail;
+    }
+
+    ret = ff_cbs_init(&lcevc->cbc, AV_CODEC_ID_LCEVC, logctx);
+    if (ret < 0)
+        goto fail;
+
+    lcevc->cbc->decompose_unit_types    = decompose_unit_types;
+    lcevc->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
+
     *plcevc = lcevc;
     return 0;
+fail:
+    av_refstruct_unref(&lcevc);
+    return ret;
 }
 
 void ff_lcevc_unref(void *opaque)
diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h
index 62014132d9..a65214344d 100644
--- a/libavcodec/lcevcdec.h
+++ b/libavcodec/lcevcdec.h
@@ -28,8 +28,13 @@
 typedef uintptr_t LCEVC_DecoderHandle;
 #endif
 
+struct CodedBitstreamContext;
+struct CodedBitstreamFragment;
+
 typedef struct FFLCEVCContext {
     LCEVC_DecoderHandle decoder;
+    struct CodedBitstreamContext *cbc;
+    struct CodedBitstreamFragment *frag;
     int initialized;
 } FFLCEVCContext;
 
@@ -40,7 +45,9 @@ typedef struct FFLCEVCFrame {
     struct AVFrame *frame;
 } FFLCEVCFrame;
 
-int ff_lcevc_alloc(FFLCEVCContext **plcevc);
+int ff_lcevc_alloc(FFLCEVCContext **plcevc, void *logctx);
 int ff_lcevc_process(void *logctx, struct AVFrame *frame);
+int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const struct AVFrame *frame,
+                         int *width, int *height, void *logctx);
 void ff_lcevc_unref(void *opaque);
 #endif /* AVCODEC_LCEVCDEC_H */
diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c
index 2115d4204d..c2853086ce 100644
--- a/libavcodec/pthread_frame.c
+++ b/libavcodec/pthread_frame.c
@@ -403,6 +403,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
         dst->hwaccel_flags = src->hwaccel_flags;
 
         av_refstruct_replace(&dst->internal->pool, src->internal->pool);
+        ff_decode_internal_sync(dst, src);
     }
 
     if (for_user) {

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to