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

Git pushed a commit to branch master
in repository ffmpeg.

commit 3776aadf4b12b82703eb01b3f4a1c0a2dd14e46d
Author:     James Almer <[email protected]>
AuthorDate: Tue Feb 11 12:57:40 2025 -0300
Commit:     James Almer <[email protected]>
CommitDate: Thu Aug 13 11:03:51 2026 -0300

    avcodec/encode: add a function to gracefully reconfigure an encoder
    
    In some cases there are compression and resource usage benefits from 
changing
    certain encoder values at runtime over of closing, freeing, allocating and
    initializing a whole new encoder. The most obvious case is rate control,
    quality settings, and so on. As such, this commit introduces a new function
    that attempts to reconfigure an opened encoder with a dictionary of options.
    
    Private options that can be changed are flagged with the runtime AVOption 
flag.
    Global options that can be changed, knowing that each encoder may support 
some
    but not others and as such can't be flagged in the global AVOptions struct,
    are signaled the same way through a new field in the FFCodecDefault struct.
    
    An encoder may provide a callback function that will be called for the
    reconfiguration process. Simple encoders that can work with only the 
AVOptions
    being reset and don't require any extra steps may just let the default 
function
    be called instead.
    
    Signed-off-by: James Almer <[email protected]>
---
 doc/APIchanges              |  4 ++
 libavcodec/avcodec.h        | 26 ++++++++++++
 libavcodec/codec.h          |  6 +++
 libavcodec/codec_internal.h |  8 ++++
 libavcodec/encode.c         | 98 +++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/encode.h         |  4 ++
 libavcodec/version.h        |  2 +-
 7 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 61e0d43735..a87764c6a1 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,10 @@ The last version increases of all libraries were on 2026-06-23.
 
 API changes, most recent first:
 
+2026-08-13 - xxxxxxxxxx - lavc 63.8.100 - avcodec.h codec.h
+  Add avcodec_encode_reconfigure.
+  Add AV_CODEC_CAP_RECONF.
+
 2026-08-xx - xxxxxxxxxx - lavf 63.6.100 - avformat.h
   Add AVFMT_FLAG_LEGACY_ID3V2_COMM_KEYS. The deprecated export of id3v2 COMM
   descriptors as bare metadata tag names is now opt-in through this flag,
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 6bce0d388d..4690d722fb 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2233,6 +2233,32 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
  */
 int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary 
**options);
 
+/**
+ * Try to reconfigure the encoder with the provided dictionary. May only be 
used
+ * if a codec with AV_CODEC_CAP_RECONF has been opened.
+ *
+ * Not all options can be changed, and it depends on the encoder. If any of the
+ * options can't be applied (Either because the option can't be changed, 
because
+ * invalid values for them were passed, or other errors), it is not guaranteed 
that
+ * the state of the encoder is the same as prior to calling this function, but 
in
+ * most cases it should.
+ * Unapplied options will remain in *dict, and owned by the caller.
+ *
+ * @param avctx   The context to reconfigure.
+ * @param options A dictionary filled with AVCodecContext and codec-private
+ *                options, which are set on top of the options already set in
+ *                avctx. Can't be NULL.
+ *
+ * @retval 0                         success
+ * @retval AVERROR_OPTION_NOT_FOUND  an entry with an invalid key was passed. 
The
+ *                                   context is untouched.
+ * @retval AVERROR(EINVAL)           an entry with an invalid value or an 
invalid
+ *                                   argument was passed.
+ * @retval AVERROR(ENOSYS)           unsupported encoder. The context is 
untouched.
+ * @retval "another negative error code" other errors.
+ */
+int avcodec_encode_reconfigure(AVCodecContext *avctx, AVDictionary **options);
+
 /**
  * Free all allocated data in the given subtitle struct.
  *
diff --git a/libavcodec/codec.h b/libavcodec/codec.h
index 0966d2e616..4fed2a23c5 100644
--- a/libavcodec/codec.h
+++ b/libavcodec/codec.h
@@ -47,6 +47,12 @@
  * avcodec_default_get_buffer2 or avcodec_default_get_encode_buffer.
  */
 #define AV_CODEC_CAP_DR1                 (1 <<  1)
+
+/**
+ * Encoder can be reconfigured by passing new initialization parameters.
+ */
+#define AV_CODEC_CAP_RECONF              (1 <<  2)
+
 /**
  * Encoder or decoder requires flushing with NULL input at the end in order to
  * give the complete and correct output.
diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
index 5cb65a06e2..6422c9996b 100644
--- a/libavcodec/codec_internal.h
+++ b/libavcodec/codec_internal.h
@@ -97,9 +97,11 @@
 typedef struct FFCodecDefault {
     const char *key;
     const char *value;
+    int flags;
 } FFCodecDefault;
 
 struct AVCodecContext;
+struct AVDictionary;
 struct AVSubtitle;
 struct AVPacket;
 
@@ -254,6 +256,12 @@ typedef struct FFCodec {
      */
     void (*flush)(struct AVCodecContext *);
 
+    /**
+     * Reconfigure the encoder
+     * Called by avcodec_encode_reconfigure()
+     */
+    int (*reconf)(struct AVCodecContext *avctx, struct AVDictionary **dict);
+
     /**
      * Decoding only, a comma-separated list of bitstream filters to apply to
      * packets before decoding.
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 56b2f4362b..990ae43843 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -25,6 +25,7 @@
 #include "libavutil/internal.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
+#include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
 #include "libavutil/samplefmt.h"
 
@@ -595,6 +596,103 @@ int attribute_align_arg 
avcodec_receive_packet(AVCodecContext *avctx, AVPacket *
     return 0;
 }
 
+av_cold int ff_encode_reconf_parse_dict(AVCodecContext *avctx, AVDictionary 
**dict)
+{
+    const AVCodec *codec = avctx->codec;
+    const FFCodec *codec2 = ffcodec(codec);
+    const AVDictionaryEntry *t = NULL;
+    AVDictionary *copy = NULL;
+    int ret;
+
+    av_assert0(av_codec_is_encoder(codec) && (codec->capabilities & 
AV_CODEC_CAP_RECONF));
+
+    ret = av_dict_copy(&copy, *dict, 0);
+    if (ret < 0)
+        goto end;
+
+    // Remove the dictionary entries that would be applied to the private 
codec context
+    if (codec->priv_class) {
+        while ((t = av_dict_iterate(*dict, t))) {
+            if (av_opt_find(avctx->priv_data, t->key, NULL,
+                            AV_OPT_FLAG_RUNTIME_PARAM, 0))
+                av_dict_set(dict, t->key, NULL, 0);
+        }
+    }
+
+    // Ditto for global options
+    if (codec2->defaults) {
+        const FFCodecDefault *d = codec2->defaults;
+        while (d->key) {
+            if (d->flags & AV_OPT_FLAG_RUNTIME_PARAM)
+                av_dict_set(dict, d->key, NULL, 0);
+            d++;
+        }
+    }
+
+    // If any entry remains, then the requested option/s don't exist or are 
not settable.
+    if (av_dict_count(*dict)) {
+        ret = AVERROR_OPTION_NOT_FOUND;
+        goto end;
+    }
+
+    ret = av_dict_copy(dict, copy, 0);
+    if (ret < 0)
+        goto end;
+
+    // Do a dry run of applying the options, to ensure the encoder is 
unchanged in case
+    // one of them has an invalid value.
+    // This is done twice, once for avctx and once for the AVCodec, because 
using the
+    // search children flag in combination with the fake obj flag will iterate 
through
+    // the options from all compiled in codecs if you pass the avctx class.
+    if (codec->priv_class) {
+        ret = av_opt_set_dict2((void *)&codec->priv_class, &copy, 
AV_OPT_SEARCH_FAKE_OBJ);
+        if (ret < 0)
+            goto end;
+    }
+    ret = av_opt_set_dict2((void *)&avctx->av_class, &copy, 
AV_OPT_SEARCH_FAKE_OBJ);
+    if (ret < 0)
+        goto end;
+
+    // The dictionary should be empty.
+    av_assert0(!av_dict_count(copy));
+
+    ret = av_opt_set_dict2(avctx, dict, AV_OPT_SEARCH_CHILDREN);
+    if (ret < 0)
+        goto end;
+
+    // The dictionary should be empty.
+    av_assert0(!av_dict_count(*dict));
+
+    ret = 0;
+end:
+    av_dict_free(&copy);
+
+    return ret;
+}
+
+av_cold int avcodec_encode_reconfigure(AVCodecContext *avctx, AVDictionary 
**dict)
+{
+    const FFCodec *codec = ffcodec(avctx->codec);
+    int ret = AVERROR_BUG;
+
+    if (!dict || !*dict || !avcodec_is_open(avctx) || 
!av_codec_is_encoder(avctx->codec))
+        return AVERROR(EINVAL);
+
+    if (!(avctx->codec->capabilities & AV_CODEC_CAP_RECONF)) {
+        av_log(avctx, AV_LOG_ERROR, "This encoder does not support 
reconfiguration\n");
+        return AVERROR(ENOSYS);
+    }
+
+    if (codec->reconf)
+        ret = codec->reconf(avctx, dict);
+    else
+        ret = ff_encode_reconf_parse_dict(avctx, dict);
+    if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
 static int encode_preinit_video(AVCodecContext *avctx)
 {
     const AVCodec *c = avctx->codec;
diff --git a/libavcodec/encode.h b/libavcodec/encode.h
index b66b387030..0a9998062a 100644
--- a/libavcodec/encode.h
+++ b/libavcodec/encode.h
@@ -21,6 +21,8 @@
 #ifndef AVCODEC_ENCODE_H
 #define AVCODEC_ENCODE_H
 
+#include "libavutil/opt.h"
+#include "libavutil/dict.h"
 #include "libavutil/frame.h"
 
 #include "avcodec.h"
@@ -79,6 +81,8 @@ int ff_encode_reordered_opaque(AVCodecContext *avctx,
 int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
                         AVFrame *frame, int *got_packet);
 
+int ff_encode_reconf_parse_dict(AVCodecContext *avctx, AVDictionary **dict);
+
 /**
  * Add a CPB properties side data to an encoding context.
  */
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 7acb261bb3..37c4c39451 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 
 #include "version_major.h"
 
-#define LIBAVCODEC_VERSION_MINOR   7
+#define LIBAVCODEC_VERSION_MINOR   8
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \

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

Reply via email to