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

Git pushed a commit to branch master
in repository ffmpeg.

commit e0e6ca1e29ef3f6b1e9b7d8656fe341eee8cf647
Author:     James Almer <[email protected]>
AuthorDate: Thu Oct 1 17:35:23 2026 -0300
Commit:     James Almer <[email protected]>
CommitDate: Thu Oct 8 11:15:10 2026 -0300

    avcodec/lcevcdec: add support for passing options
    
    Signed-off-by: James Almer <[email protected]>
---
 doc/codecs.texi               |  2 +
 libavcodec/avcodec_internal.h |  2 +
 libavcodec/decode.c           |  4 +-
 libavcodec/lcevcdec.c         | 88 +++++++++++++++++++++++++++++++++++++++----
 libavcodec/lcevcdec.h         | 15 +++++++-
 libavcodec/options_table.h    |  6 +++
 libavcodec/version.h          |  2 +-
 7 files changed, 107 insertions(+), 12 deletions(-)

diff --git a/doc/codecs.texi b/doc/codecs.texi
index 8f746dbc24..b85f405cf6 100644
--- a/doc/codecs.texi
+++ b/doc/codecs.texi
@@ -1041,6 +1041,8 @@ Note: The required alignment depends on if 
@code{AV_CODEC_FLAG_UNALIGNED} is set
 CPU. @code{AV_CODEC_FLAG_UNALIGNED} cannot be changed from the command line. 
Also hardware
 decoders will not apply left/top Cropping.
 
+@item lcevc-dec-params @var{string} (@emph{decoding,video})
+A :-separated list of key=value parameters passed to liblcevc-dec to 
initialize it.
 
 @end table
 
diff --git a/libavcodec/avcodec_internal.h b/libavcodec/avcodec_internal.h
index ebd9458120..d009138665 100644
--- a/libavcodec/avcodec_internal.h
+++ b/libavcodec/avcodec_internal.h
@@ -35,6 +35,8 @@ typedef struct FFCodecContext {
      * The public context.
      */
     AVCodecContext pub;
+
+    struct AVDictionary *lcevc_params;
 } FFCodecContext;
 
 static av_always_inline FFCodecContext *ffcodeccontext(AVCodecContext *avctx)
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 94dfc06a84..627ad9420a 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -2152,7 +2152,9 @@ 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, av_log_get_level() + 
avctx->log_level_offset);
+            FFCodecContext *ffavc = ffcodeccontext(avctx);
+            ret = ff_lcevc_alloc(&dc->lcevc.ctx, &ffavc->lcevc_params,
+                                 av_log_get_level() + avctx->log_level_offset);
             if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE))
                 return ret;
 #endif
diff --git a/libavcodec/lcevcdec.c b/libavcodec/lcevcdec.c
index d62adfba13..a2bda77b4a 100644
--- a/libavcodec/lcevcdec.c
+++ b/libavcodec/lcevcdec.c
@@ -21,6 +21,7 @@
 #include "libavutil/imgutils.h"
 #include "libavutil/log.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
 #include "libavutil/refstruct.h"
 
 #include "cbs.h"
@@ -320,7 +321,7 @@ static void event_callback(LCEVC_DecoderHandle dec, 
LCEVC_Event event,
 static void lcevc_free(AVRefStructOpaque unused, void *obj)
 {
     FFLCEVCContext *lcevc = obj;
-    if (lcevc->initialized) {
+    if (lcevc->initialized == FF_LCEVCDEC_INIT) {
         LCEVC_FlushDecoder(lcevc->decoder);
         lcevc_flush_pictures(lcevc);
         LCEVC_DestroyDecoder(lcevc->decoder);
@@ -380,16 +381,52 @@ static int lcevc_init(FFLCEVCContext *lcevc)
 {
     LCEVC_AccelContextHandle dummy = { 0 };
     const int32_t event = LCEVC_Log;
+    LCEVC_ReturnCode res;
     int level;
 
+    lcevc->initialized = FF_LCEVCDEC_FAIL;
+
     if (LCEVC_CreateDecoder(&lcevc->decoder, dummy) != LCEVC_Success) {
         av_log(lcevc, AV_LOG_ERROR, "Failed to create LCEVC decoder\n");
         return AVERROR_EXTERNAL;
     }
 
+    if (lcevc->pipeline) {
+        res = LCEVC_ConfigureDecoderString(lcevc->decoder, "pipeline", 
lcevc->pipeline);
+        if (res != LCEVC_Success) {
+            av_log(lcevc, AV_LOG_ERROR, "Failed to set pipeline to \"%s\"\n", 
lcevc->pipeline);
+            LCEVC_DestroyDecoder(lcevc->decoder);
+            return AVERROR_EXTERNAL;
+        }
+    }
+
     level = get_log_level(lcevc->loglevel);
 
     LCEVC_ConfigureDecoderInt(lcevc->decoder, "log_level", level);
+    res = LCEVC_ConfigureDecoderInt(lcevc->decoder, "threads", lcevc->threads);
+    if (res != LCEVC_Success) {
+        av_log(lcevc, AV_LOG_ERROR, "Failed to set threads to %d\n", 
lcevc->threads);
+        LCEVC_DestroyDecoder(lcevc->decoder);
+        return AVERROR_EXTERNAL;
+    }
+    res = LCEVC_ConfigureDecoderInt(lcevc->decoder, "passthrough_mode", 
lcevc->passthrough_mode);
+    if (res != LCEVC_Success) {
+        av_log(lcevc, AV_LOG_ERROR, "Failed to set passthrough_mode to %d\n", 
lcevc->passthrough_mode);
+        LCEVC_DestroyDecoder(lcevc->decoder);
+        return AVERROR_EXTERNAL;
+    }
+    res = LCEVC_ConfigureDecoderBool(lcevc->decoder, "allow_dithering", 
lcevc->allow_dithering);
+    if (res != LCEVC_Success) {
+        av_log(lcevc, AV_LOG_ERROR, "Failed to set allow_dithering to %d\n", 
lcevc->allow_dithering);
+        LCEVC_DestroyDecoder(lcevc->decoder);
+        return AVERROR_EXTERNAL;
+    }
+    res = LCEVC_ConfigureDecoderBool(lcevc->decoder, "highlight_residuals", 
lcevc->highlight_residuals);
+    if (res != LCEVC_Success) {
+        av_log(lcevc, AV_LOG_ERROR, "Failed to set highlight_residuals to 
%d\n", lcevc->highlight_residuals);
+        LCEVC_DestroyDecoder(lcevc->decoder);
+        return AVERROR_EXTERNAL;
+    }
     LCEVC_ConfigureDecoderIntArray(lcevc->decoder, "events", 1, &event);
     LCEVC_SetDecoderEventCallback(lcevc->decoder, event_callback, lcevc);
 
@@ -399,7 +436,7 @@ static int lcevc_init(FFLCEVCContext *lcevc)
         return AVERROR_EXTERNAL;
     }
 
-    lcevc->initialized = 1;
+    lcevc->initialized = FF_LCEVCDEC_INIT;
 
     return 0;
 }
@@ -411,11 +448,12 @@ int ff_lcevc_process(void *logctx, AVFrame *frame)
     FFLCEVCContext *lcevc = frame_ctx->lcevc;
     int ret;
 
-    if (!lcevc->initialized) {
+    if (lcevc->initialized == FF_LCEVCDEC_UNINIT) {
         ret = lcevc_init(lcevc);
         if (ret < 0)
             return ret;
-    }
+    } else if (lcevc->initialized == FF_LCEVCDEC_FAIL)
+        return 0;
 
     av_assert0(frame_ctx->frame);
 
@@ -477,23 +515,60 @@ static const CodedBitstreamUnitType 
decompose_unit_types[] = {
     LCEVC_NON_IDR_NUT,
 };
 
+#define OFFSET(x) offsetof(FFLCEVCContext, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_DECODING_PARAM)
+static const AVOption lcevc_opts[] = {
+    { "passthrough_mode", "Set passthrough mode", OFFSET(passthrough_mode), 
AV_OPT_TYPE_INT,
+            { .i64 = 0 }, -1, 2, FLAGS, .unit = "passthrough_mode" },
+        { "disable", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, .unit = 
"passthrough_mode" },
+        { "allow",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 },  .unit = 
"passthrough_mode" },
+        { "force",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 },  .unit = 
"passthrough_mode" },
+        { "scale",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 2 },  .unit = 
"passthrough_mode" },
+    { "allow_dithering", "Allow dithering", OFFSET(allow_dithering), 
AV_OPT_TYPE_BOOL,
+            { .i64 = 1 }, 0, 1, FLAGS },
+    { "highlight_residuals", "Highlight residuals", 
OFFSET(highlight_residuals), AV_OPT_TYPE_BOOL,
+            { .i64 = 0 }, 0, 1, FLAGS },
+    { "threads", "Thread count", OFFSET(threads), AV_OPT_TYPE_INT,
+            { .i64 = 1 }, 0, INT_MAX, FLAGS },
+    { "pipeline", "Decoding pipeline", OFFSET(pipeline), AV_OPT_TYPE_STRING,
+            { .str = NULL }, 0, 0, FLAGS },
+    { NULL },
+};
+#undef OFFSET
+#undef FLAGS
 
 static const AVClass lcevcdec_context_class = {
     .class_name     = "liblcevc_dec",
     .item_name      = av_default_item_name,
+    .option         = lcevc_opts,
     .version        = LIBAVUTIL_VERSION_INT,
     .category       = AV_CLASS_CATEGORY_DECODER,
 };
 
-int ff_lcevc_alloc(FFLCEVCContext **plcevc, int loglevel)
+int ff_lcevc_alloc(FFLCEVCContext **plcevc, AVDictionary **options, int 
loglevel)
 {
     FFLCEVCContext *lcevc = NULL;
+    const AVDictionaryEntry *t;
     int ret;
 
     lcevc = av_refstruct_alloc_ext(sizeof(*lcevc), 0, NULL, lcevc_free);
     if (!lcevc)
         return AVERROR(ENOMEM);
 
+    lcevc->class = &lcevcdec_context_class;
+    av_opt_set_defaults(lcevc);
+
+    lcevc->loglevel = loglevel;
+
+    ret = av_opt_set_dict2(lcevc, options, 0);
+    if (ret < 0)
+        return ret;
+
+    if (t = av_dict_iterate(*options, NULL)) {
+        av_log(NULL, AV_LOG_FATAL, "liblcevc-dec option %s not found.\n", 
t->key);
+        return AVERROR_OPTION_NOT_FOUND;
+    }
+
     lcevc->frag = av_mallocz(sizeof(*lcevc->frag));
     if (!lcevc->frag) {
         ret = AVERROR(ENOMEM);
@@ -516,9 +591,6 @@ int ff_lcevc_alloc(FFLCEVCContext **plcevc, int loglevel)
         goto fail;
     }
 
-    lcevc->class = &lcevcdec_context_class;
-    lcevc->loglevel = loglevel;
-
     *plcevc = lcevc;
     return 0;
 fail:
diff --git a/libavcodec/lcevcdec.h b/libavcodec/lcevcdec.h
index b53547f112..b757acc3f9 100644
--- a/libavcodec/lcevcdec.h
+++ b/libavcodec/lcevcdec.h
@@ -22,7 +22,7 @@
 #include "config.h"
 
 #include "libavutil/log.h"
-#include "libavutil/pixfmt.h"
+#include "libavutil/dict.h"
 
 #include <stdint.h>
 #if CONFIG_LIBLCEVC_DEC
@@ -34,6 +34,12 @@ typedef uintptr_t LCEVC_DecoderHandle;
 struct CodedBitstreamContext;
 struct CodedBitstreamFragment;
 
+enum {
+    FF_LCEVCDEC_UNINIT = 0,
+    FF_LCEVCDEC_INIT,
+    FF_LCEVCDEC_FAIL,
+};
+
 typedef struct FFLCEVCContext {
     const AVClass *class;
     LCEVC_DecoderHandle decoder;
@@ -42,6 +48,11 @@ typedef struct FFLCEVCContext {
     struct AVRefStructPool *frame_pool; ///< pool of FFLCEVCFrame
     int64_t last_pts;
     int loglevel;
+    int threads;
+    int passthrough_mode;
+    int allow_dithering;
+    int highlight_residuals;
+    uint8_t *pipeline;
     int initialized;
 } FFLCEVCContext;
 
@@ -52,7 +63,7 @@ typedef struct FFLCEVCFrame {
     struct AVFrame *frame;
 } FFLCEVCFrame;
 
-int ff_lcevc_alloc(FFLCEVCContext **plcevc, int loglevel);
+int ff_lcevc_alloc(FFLCEVCContext **plcevc, AVDictionary **options, int 
loglevel);
 int ff_lcevc_process(void *logctx, struct AVFrame *frame);
 int ff_lcevc_parse_frame(FFLCEVCContext *lcevc, const struct AVFrame *frame,
                          enum AVPixelFormat *format, int *width, int *height);
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index a329a84db1..83f362a556 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -30,8 +30,10 @@
 
 #include "libavutil/opt.h"
 #include "avcodec.h"
+#include "avcodec_internal.h"
 #include "version_major.h"
 
+#define FFOFFSET(x) offsetof(FFCodecContext,x)
 #define OFFSET(x) offsetof(AVCodecContext,x)
 #define DEFAULT 0 //should be NAN but it does not work as it is not a constant 
in glibc as required by ANSI/ISO C
 //these names are too long to be readable
@@ -420,6 +422,9 @@ static const AVOption avcodec_options[] = {
     {"content_light_level",         .default_val.i64 = 
AV_PKT_DATA_CONTENT_LIGHT_LEVEL,         .type = AV_OPT_TYPE_CONST, .flags = 
A|D, .unit = "side_data_pkt" },
     {"icc_profile",                 .default_val.i64 = 
AV_PKT_DATA_ICC_PROFILE,                 .type = AV_OPT_TYPE_CONST, .flags = 
A|D, .unit = "side_data_pkt" },
     {"exif",                        .default_val.i64 = AV_PKT_DATA_EXIF,       
                 .type = AV_OPT_TYPE_CONST, .flags = A|D, .unit = 
"side_data_pkt" },
+
+// FFCodecContext options
+{"lcevc-dec-params", "Configure liblcevc-dec using a :-separated list of 
key=value parameters", FFOFFSET(lcevc_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, 
V|D },
 {NULL},
 };
 
@@ -431,5 +436,6 @@ static const AVOption avcodec_options[] = {
 #undef CC
 #undef DEFAULT
 #undef OFFSET
+#undef FFOFFSET
 
 #endif /* AVCODEC_OPTIONS_TABLE_H */
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 65bc52fb24..d8604fd00c 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
 #include "version_major.h"
 
 #define LIBAVCODEC_VERSION_MINOR  18
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \

-- 
To stop receiving notification emails like this one, please contact
[email protected].
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to