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]
