From dc51a72ba45fbefb9f1c6c3ca5a5b2388d69b2da Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michaelni@gmx.at>
Date: Wed, 29 Sep 2010 15:05:47 +0000
Subject: [PATCH] Move allocation and init to defaults of the private codec
 contexts to avcodec_get_context_defaults3(). That way the user app can set
 codec specific parameters in the private context before opening it.

Originally committed as revision 25257 to svn://svn.ffmpeg.org/ffmpeg/trunk
---
 libavcodec/avcodec.h |  8 ++++++++
 libavcodec/options.c | 30 ++++++++++++++++++++++++++++++
 libavcodec/utils.c   |  6 ++++++
 3 files changed, 44 insertions(+)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index c12d4ebf555..3667e723d68 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -3330,6 +3330,10 @@ void avcodec_get_context_defaults(AVCodecContext *s);
  *  we WILL change its arguments and name a few times! */
 void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType);
 
+/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API!
+ *  we WILL change its arguments and name a few times! */
+int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec);
+
 /**
  * Allocate an AVCodecContext and set its fields to default values.  The
  * resulting struct can be deallocated by simply calling av_free().
@@ -3343,6 +3347,10 @@ AVCodecContext *avcodec_alloc_context(void);
  *  we WILL change its arguments and name a few times! */
 AVCodecContext *avcodec_alloc_context2(enum AVMediaType);
 
+/** THIS FUNCTION IS NOT YET PART OF THE PUBLIC API!
+ *  we WILL change its arguments and name a few times! */
+AVCodecContext *avcodec_alloc_context3(AVCodec *codec);
+
 /**
  * Copy the settings of the source AVCodecContext into the destination
  * AVCodecContext. The resulting destination codec context will be
diff --git a/libavcodec/options.c b/libavcodec/options.c
index d55d4fde264..6a6ac78e287 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -467,6 +467,36 @@ void avcodec_get_context_defaults2(AVCodecContext *s, enum AVMediaType codec_typ
     s->reordered_opaque= AV_NOPTS_VALUE;
 }
 
+int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec){
+    avcodec_get_context_defaults2(s, codec ? codec->type : AVMEDIA_TYPE_UNKNOWN);
+    if(codec && codec->priv_data_size){
+        if(!s->priv_data){
+            s->priv_data= av_mallocz(codec->priv_data_size);
+            if (!s->priv_data) {
+                return AVERROR(ENOMEM);
+            }
+        }
+        if(codec->priv_class){
+            *(AVClass**)s->priv_data= codec->priv_class;
+            av_opt_set_defaults(s->priv_data);
+        }
+    }
+    return 0;
+}
+
+AVCodecContext *avcodec_alloc_context3(AVCodec *codec){
+    AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
+
+    if(avctx==NULL) return NULL;
+
+    if(avcodec_get_context_defaults3(avctx, codec) < 0){
+        av_free(avctx);
+        return NULL;
+    }
+
+    return avctx;
+}
+
 AVCodecContext *avcodec_alloc_context2(enum AVMediaType codec_type){
     AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
 
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index ad80f0f4a30..7edff412ece 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -471,11 +471,17 @@ int attribute_align_arg avcodec_open(AVCodecContext *avctx, AVCodec *codec)
         goto end;
 
     if (codec->priv_data_size > 0) {
+      if(!avctx->priv_data){
         avctx->priv_data = av_mallocz(codec->priv_data_size);
         if (!avctx->priv_data) {
             ret = AVERROR(ENOMEM);
             goto end;
         }
+        if(codec->priv_class){ //this can be droped once all user apps use   avcodec_get_context_defaults3()
+            *(AVClass**)avctx->priv_data= codec->priv_class;
+            av_opt_set_defaults(avctx->priv_data);
+        }
+      }
     } else {
         avctx->priv_data = NULL;
     }
-- 
GitLab