Adds support for decoder-private options and makes setting other options
simpler.
---
 libavcodec/avcodec.h |   33 +++++++++++++++++++++++++++++++++
 libavcodec/options.c |   21 ++++++++++++++++++++-
 libavcodec/utils.c   |   21 ++++++++++++++++++++-
 3 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index e067ee0..a97f1f9 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -30,6 +30,7 @@
 #include "libavutil/samplefmt.h"
 #include "libavutil/avutil.h"
 #include "libavutil/cpu.h"
+#include "libavutil/meta.h"
 
 #include "libavcodec/version.h"
 
@@ -3612,6 +3613,38 @@ int avcodec_default_execute2(AVCodecContext *c, int 
(*func)(AVCodecContext *c2,
 int avcodec_open(AVCodecContext *avctx, AVCodec *codec);
 
 /**
+ * Initialize the AVCodecContext to use the given AVCodec. Prior to using this
+ * function the context has to be allocated with avcodec_alloc_context().
+ *
+ * The functions avcodec_find_decoder_by_name(), 
avcodec_find_encoder_by_name(),
+ * avcodec_find_decoder() and avcodec_find_encoder() provide an easy way for
+ * retrieving a codec.
+ *
+ * @warning This function is not thread safe!
+ *
+ * @code
+ * avcodec_register_all();
+ * avmeta_set(&opts, "b", "2.5M", 0);
+ * codec = avcodec_find_decoder(CODEC_ID_H264);
+ * if (!codec)
+ *     exit(1);
+ *
+ * context = avcodec_alloc_context();
+ *
+ * if (avcodec_open(context, codec, opts) < 0)
+ *     exit(1);
+ * @endcode
+ *
+ * @param avctx The context to initialize.
+ * @param options  Metadata filled with AVCodecContext and codec-private 
options.
+ *                 One return this object will be filled with options that 
were not found.
+ *
+ * @return zero on success, a negative value on error
+ * @see avcodec_alloc_context, avcodec_find_decoder, avcodec_find_encoder
+ */
+int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVMetadata **options);
+
+/**
  * Decode the audio frame of size avpkt->size from avpkt->data into samples.
  * Some decoders may support multiple frames in a single AVPacket, such
  * decoders would then just decode the first frame. In this case,
diff --git a/libavcodec/options.c b/libavcodec/options.c
index 8f9aec4..58292d7 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -37,6 +37,25 @@ static const char* context_to_name(void* ptr) {
         return "NULL";
 }
 
+static const AVOption *opt_find(void *obj, const char *name, const char *unit, 
int opt_flags, int search_flags)
+{
+    AVCodecContext *s = obj;
+    AVCodec        *c = NULL;
+
+    if (s->priv_data) {
+        if (s->codec->priv_class)
+            return avopt_find(s->priv_data, name, unit, opt_flags, 
search_flags);
+        return NULL;
+    }
+
+    while ((c = av_codec_next(c))) {
+        const AVOption *o;
+        if (c->priv_class && (o = avopt_find(&c->priv_class, name, unit, 
opt_flags, search_flags)))
+            return o;
+    }
+    return NULL;
+}
+
 #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
@@ -457,7 +476,7 @@ static const AVOption options[]={
 #undef D
 #undef DEFAULT
 
-static const AVClass av_codec_context_class = { "AVCodecContext", 
context_to_name, options, LIBAVUTIL_VERSION_INT, OFFSET(log_level_offset) };
+static const AVClass av_codec_context_class = { "AVCodecContext", 
context_to_name, options, LIBAVUTIL_VERSION_INT, OFFSET(log_level_offset), 
.opt_find = opt_find};
 
 void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType 
codec_type){
     int flags=0;
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 9e87994..dc21d96 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -32,6 +32,7 @@
 #include "libavutil/audioconvert.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/samplefmt.h"
+#include "libavutil/meta.h"
 #include "avcodec.h"
 #include "dsputil.h"
 #include "libavutil/opt.h"
@@ -463,7 +464,16 @@ AVFrame *avcodec_alloc_frame(void){
 
 int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
 {
+    return avcodec_open2(avctx, codec, NULL);
+}
+
+int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, 
AVMetadata **options)
+{
     int ret = 0;
+    AVMetadata *tmp = NULL;
+
+    if (options)
+        avmeta_copy(&tmp, *options, 0);
 
     /* If there is a user-supplied mutex locking routine, call it. */
     if (ff_lockmgr_cb) {
@@ -490,14 +500,18 @@ int attribute_align_arg avcodec_open(AVCodecContext 
*avctx, AVCodec *codec)
             ret = AVERROR(ENOMEM);
             goto end;
         }
-        if(codec->priv_class){ //this can be droped once all user apps use   
avcodec_get_context_defaults3()
+        if (codec->priv_class) {
             *(AVClass**)avctx->priv_data= codec->priv_class;
             av_opt_set_defaults(avctx->priv_data);
+            if ((ret = avopt_process(avctx->priv_data, &tmp)) < 0)
+                goto free_and_end;
         }
       }
     } else {
         avctx->priv_data = NULL;
     }
+    if ((ret = avopt_process(avctx, &tmp)) < 0)
+        goto free_and_end;
 
     if(avctx->coded_width && avctx->coded_height)
         avcodec_set_dimensions(avctx, avctx->coded_width, avctx->coded_height);
@@ -609,6 +623,11 @@ end:
     if (ff_lockmgr_cb) {
         (*ff_lockmgr_cb)(&codec_mutex, AV_LOCK_RELEASE);
     }
+    if (options) {
+        avmeta_free(options);
+        *options = tmp;
+    }
+
     return ret;
 free_and_end:
     av_freep(&avctx->priv_data);
-- 
1.7.5.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to