[libav-devel] [PATCH 1/2] avcodec: move some AVCodecContext fields to an internal struct.

Justin Ruggles justin.ruggles at gmail.com
Wed Nov 16 23:30:52 CET 2011


A new field, AVCodecContext.internal is used to hold a new struct
AVCodecInternal, which has private fields that are not codec-specific and are
needed only by general libavcodec functions.

Moved user_buffer, user_buffer_count, and is_copy.
---
 doc/APIchanges         |    8 +++++
 libavcodec/avcodec.h   |   24 +++++++++++++--
 libavcodec/h264.c      |    3 +-
 libavcodec/internal.h  |   22 +++++++++++++
 libavcodec/mimic.c     |    4 ++-
 libavcodec/mpegvideo.c |    2 +-
 libavcodec/options.c   |    4 ++-
 libavcodec/pthread.c   |   16 +++++++--
 libavcodec/utils.c     |   79 +++++++++++++++++++++++++++--------------------
 libavcodec/version.h   |    5 ++-
 libavcodec/vp3.c       |    4 ++-
 libavcodec/vp8.c       |    3 +-
 12 files changed, 126 insertions(+), 48 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 5ef1fa5..4b375a4 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,14 @@ libavutil:   2011-04-18
 
 API changes, most recent first:
 
+2011-xx-xx - xxxxxxx - lavc 53.21.0
+  Move some AVCodecContext fields to a new private struct, AVCodecInternal,
+  which is accessed from a new field, AVCodecContext.internal.
+  - fields moved:
+      user_buffer
+      user_buffer_count
+      is_copy
+
 2011-11-06 - ba04ecf - lavu 51.14.0
   Add av_strcasecmp() and av_strncasecmp() to avstring.h.
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 7d506a1..67bbdf8 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1156,6 +1156,8 @@ typedef struct AVFrame {
     void *thread_opaque;
 } AVFrame;
 
+struct AVCodecInternal;
+
 /**
  * main external API structure.
  * New fields can be added to the end with minor version bumps.
@@ -1979,17 +1981,21 @@ typedef struct AVCodecContext {
      */
     int color_table_id;
 
+#if FF_API_INTERNAL_CONTEXT
     /**
      * internal_buffer count
      * Don't touch, used by libavcodec default_get_buffer().
+     * @deprecated this field was moved to an internal context
      */
-    int internal_buffer_count;
+    attribute_deprecated int internal_buffer_count;
 
     /**
      * internal_buffers
      * Don't touch, used by libavcodec default_get_buffer().
+     * @deprecated this field was moved to an internal context
      */
-    void *internal_buffer;
+    attribute_deprecated void *internal_buffer;
+#endif
 
     /**
      * Global quality for codecs which cannot change it per frame.
@@ -2875,14 +2881,18 @@ typedef struct AVCodecContext {
      */
     AVPacket *pkt;
 
+#if FF_API_INTERNAL_CONTEXT
     /**
      * Whether this is a copy of the context which had init() called on it.
      * This is used by multithreading - shared tables and picture pointers
      * should be freed from the original context only.
      * - encoding: Set by libavcodec.
      * - decoding: Set by libavcodec.
+     *
+     * @deprecated this field has been moved to an internal context
      */
-    int is_copy;
+    attribute_deprecated int is_copy;
+#endif
 
     /**
      * Which multithreading methods to use.
@@ -2945,6 +2955,14 @@ typedef struct AVCodecContext {
 #define AV_EF_BITSTREAM (1<<1)
 #define AV_EF_BUFFER    (1<<2)
 #define AV_EF_EXPLODE   (1<<3)
+
+    /**
+     * Private context used for internal data.
+     *
+     * Unlike priv_data, this is not codec-specific. It is used in general
+     * libavcodec functions.
+     */
+    struct AVCodecInternal *internal;
 } AVCodecContext;
 
 /**
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index d959d56..7930525 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -1173,7 +1173,8 @@ static void copy_parameter_set(void **to, void **from, int count, int size)
 static int decode_init_thread_copy(AVCodecContext *avctx){
     H264Context *h= avctx->priv_data;
 
-    if (!avctx->is_copy) return 0;
+    if (!avctx->internal->is_copy)
+        return 0;
     memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
     memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
 
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 54d57d2..c88c991 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -27,6 +27,28 @@
 #include <stdint.h>
 #include "avcodec.h"
 
+typedef struct AVCodecInternal {
+    /**
+     * internal buffer count
+     * used by default get/release/reget_buffer().
+     */
+    int internal_buffer_count;
+
+    /**
+     * internal buffers
+     * used by default get/release/reget_buffer().
+     */
+    void *internal_buffer;
+
+    /**
+     * Whether the parent AVCodecContext is a copy of the context which had
+     * init() called on it.
+     * This is used by multithreading - shared tables and picture pointers
+     * should be freed from the original context only.
+     */
+    int is_copy;
+} AVCodecInternal;
+
 struct AVCodecDefault {
     const uint8_t *key;
     const uint8_t *value;
diff --git a/libavcodec/mimic.c b/libavcodec/mimic.c
index c0d8546..b93f51f 100644
--- a/libavcodec/mimic.c
+++ b/libavcodec/mimic.c
@@ -24,6 +24,7 @@
 #include <stdint.h>
 
 #include "avcodec.h"
+#include "internal.h"
 #include "get_bits.h"
 #include "bytestream.h"
 #include "dsputil.h"
@@ -405,7 +406,8 @@ static av_cold int mimic_decode_end(AVCodecContext *avctx)
 
     av_free(ctx->swap_buf);
 
-    if(avctx->is_copy) return 0;
+    if (avctx->internal->is_copy)
+        return 0;
 
     for(i = 0; i < 16; i++)
         if(ctx->buf_ptrs[i].data[0])
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 4c149f2..dcef706 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -858,7 +858,7 @@ void MPV_common_end(MpegEncContext *s)
     av_freep(&s->reordered_input_picture);
     av_freep(&s->dct_offset);
 
-    if(s->picture && !s->avctx->is_copy){
+    if(s->picture && !s->avctx->internal->is_copy){
         for(i=0; i<s->picture_count; i++){
             free_picture(s, &s->picture[i]);
         }
diff --git a/libavcodec/options.c b/libavcodec/options.c
index e747408..3ebb97b 100644
--- a/libavcodec/options.c
+++ b/libavcodec/options.c
@@ -329,7 +329,9 @@ static const AVOption options[]={
 {"ibias", "intra quant bias", OFFSET(intra_quant_bias), AV_OPT_TYPE_INT, {.dbl = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E},
 {"pbias", "inter quant bias", OFFSET(inter_quant_bias), AV_OPT_TYPE_INT, {.dbl = FF_DEFAULT_QUANT_BIAS }, INT_MIN, INT_MAX, V|E},
 {"color_table_id", NULL, OFFSET(color_table_id), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
+#if FF_API_INTERNAL_CONTEXT
 {"internal_buffer_count", NULL, OFFSET(internal_buffer_count), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
+#endif
 {"global_quality", NULL, OFFSET(global_quality), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
 {"coder", NULL, OFFSET(coder_type), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E, "coder"},
 {"vlc", "variable length coder / huffman coder", 0, AV_OPT_TYPE_CONST, {.dbl = FF_CODER_TYPE_VLC }, INT_MIN, INT_MAX, V|E, "coder"},
@@ -644,9 +646,9 @@ int avcodec_copy_context(AVCodecContext *dest, const AVCodecContext *src)
     dest->priv_data       = NULL;
     dest->codec           = NULL;
     dest->slice_offset    = NULL;
-    dest->internal_buffer = NULL;
     dest->hwaccel         = NULL;
     dest->thread_opaque   = NULL;
+    dest->internal        = NULL;
 
     /* reallocate values that should be allocated separately */
     dest->rc_eq           = NULL;
diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
index 7557e68..9fe9b8d 100644
--- a/libavcodec/pthread.c
+++ b/libavcodec/pthread.c
@@ -31,6 +31,7 @@
 
 #include "config.h"
 #include "avcodec.h"
+#include "internal.h"
 #include "thread.h"
 
 #if HAVE_PTHREADS
@@ -672,8 +673,10 @@ static void frame_thread_free(AVCodecContext *avctx, int thread_count)
         pthread_cond_destroy(&p->output_cond);
         av_freep(&p->avpkt.data);
 
-        if (i)
+        if (i) {
             av_freep(&p->avctx->priv_data);
+            av_freep(&p->avctx->internal);
+        }
 
         av_freep(&p->avctx);
     }
@@ -728,9 +731,15 @@ static int frame_thread_init(AVCodecContext *avctx)
 
             update_context_from_thread(avctx, copy, 1);
         } else {
-            copy->is_copy   = 1;
             copy->priv_data = av_malloc(codec->priv_data_size);
             memcpy(copy->priv_data, src->priv_data, codec->priv_data_size);
+            copy->internal = av_malloc(sizeof(AVCodecInternal));
+            if (!copy->internal) {
+                err = AVERROR(ENOMEM);
+                goto error;
+            }
+            *(copy->internal) = *(src->internal);
+            copy->internal->is_copy = 1;
 
             if (codec->init_thread_copy)
                 err = codec->init_thread_copy(copy);
@@ -862,8 +871,7 @@ void ff_thread_release_buffer(AVCodecContext *avctx, AVFrame *f)
     }
 
     if(avctx->debug & FF_DEBUG_BUFFERS)
-        av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p, %d buffers used\n",
-                                    f, f->owner->internal_buffer_count);
+        av_log(avctx, AV_LOG_DEBUG, "thread_release_buffer called on pic %p\n", f);
 
     fctx = p->parent;
     pthread_mutex_lock(&fctx->buffer_mutex);
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index cd8dce9..332272f 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -250,12 +250,13 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
     int h= s->height;
     InternalBuffer *buf;
     int *picture_number;
+    AVCodecInternal *avci = s->internal;
 
     if(pic->data[0]!=NULL) {
         av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n");
         return -1;
     }
-    if(s->internal_buffer_count >= INTERNAL_BUFFER_SIZE) {
+    if(avci->internal_buffer_count >= INTERNAL_BUFFER_SIZE) {
         av_log(s, AV_LOG_ERROR, "internal_buffer_count overflow (missing release_buffer?)\n");
         return -1;
     }
@@ -263,19 +264,13 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
     if(av_image_check_size(w, h, 0, s))
         return -1;
 
-    if(s->internal_buffer==NULL){
-        s->internal_buffer= av_mallocz((INTERNAL_BUFFER_SIZE+1)*sizeof(InternalBuffer));
+    if (!avci->internal_buffer) {
+        avci->internal_buffer = av_mallocz((INTERNAL_BUFFER_SIZE+1) *
+                                            sizeof(InternalBuffer));
     }
-#if 0
-    s->internal_buffer= av_fast_realloc(
-        s->internal_buffer,
-        &s->internal_buffer_size,
-        sizeof(InternalBuffer)*FFMAX(99,  s->internal_buffer_count+1)/*FIXME*/
-        );
-#endif
 
-    buf= &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
-    picture_number= &(((InternalBuffer*)s->internal_buffer)[INTERNAL_BUFFER_SIZE]).last_pic_num; //FIXME ugly hack
+    buf = &((InternalBuffer*)avci->internal_buffer)[avci->internal_buffer_count];
+    picture_number = &(((InternalBuffer*)avci->internal_buffer)[INTERNAL_BUFFER_SIZE]).last_pic_num; //FIXME ugly hack
     (*picture_number)++;
 
     if(buf->base[0] && (buf->width != w || buf->height != h || buf->pix_fmt != s->pix_fmt)){
@@ -366,14 +361,15 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
         pic->data[i]= buf->data[i];
         pic->linesize[i]= buf->linesize[i];
     }
-    s->internal_buffer_count++;
+    avci->internal_buffer_count++;
 
     if(s->pkt) pic->pkt_pts= s->pkt->pts;
     else       pic->pkt_pts= AV_NOPTS_VALUE;
     pic->reordered_opaque= s->reordered_opaque;
 
     if(s->debug&FF_DEBUG_BUFFERS)
-        av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d buffers used\n", pic, s->internal_buffer_count);
+        av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p, %d "
+               "buffers used\n", pic, avci->internal_buffer_count);
 
     return 0;
 }
@@ -381,22 +377,23 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){
 void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){
     int i;
     InternalBuffer *buf, *last;
+    AVCodecInternal *avci = s->internal;
 
     assert(pic->type==FF_BUFFER_TYPE_INTERNAL);
-    assert(s->internal_buffer_count);
-
-    if(s->internal_buffer){
-    buf = NULL; /* avoids warning */
-    for(i=0; i<s->internal_buffer_count; i++){ //just 3-5 checks so is not worth to optimize
-        buf= &((InternalBuffer*)s->internal_buffer)[i];
-        if(buf->data[0] == pic->data[0])
-            break;
-    }
-    assert(i < s->internal_buffer_count);
-    s->internal_buffer_count--;
-    last = &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];
+    assert(avci->internal_buffer_count);
+
+    if (avci->internal_buffer) {
+        buf = NULL; /* avoids warning */
+        for (i = 0; i < avci->internal_buffer_count; i++) { //just 3-5 checks so is not worth to optimize
+            buf = &((InternalBuffer*)avci->internal_buffer)[i];
+            if (buf->data[0] == pic->data[0])
+                break;
+        }
+        assert(i < avci->internal_buffer_count);
+        avci->internal_buffer_count--;
+        last = &((InternalBuffer*)avci->internal_buffer)[avci->internal_buffer_count];
 
-    FFSWAP(InternalBuffer, *buf, *last);
+        FFSWAP(InternalBuffer, *buf, *last);
     }
 
     for(i=0; i<4; i++){
@@ -406,7 +403,8 @@ void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){
 //printf("R%X\n", pic->opaque);
 
     if(s->debug&FF_DEBUG_BUFFERS)
-        av_log(s, AV_LOG_DEBUG, "default_release_buffer called on pic %p, %d buffers used\n", pic, s->internal_buffer_count);
+        av_log(s, AV_LOG_DEBUG, "default_release_buffer called on pic %p, %d "
+               "buffers used\n", pic, avci->internal_buffer_count);
 }
 
 int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic){
@@ -521,6 +519,14 @@ int attribute_align_arg avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVD
         goto end;
     }
 
+    if (!avctx->internal) {
+        avctx->internal = av_mallocz(sizeof(AVCodecInternal));
+        if (!avctx->internal) {
+            ret = AVERROR(ENOMEM);
+            goto end;
+        }
+    }
+
     if (codec->priv_data_size > 0) {
       if(!avctx->priv_data){
         avctx->priv_data = av_mallocz(codec->priv_data_size);
@@ -670,6 +676,7 @@ end:
 free_and_end:
     av_dict_free(&tmp);
     av_freep(&avctx->priv_data);
+    av_freep(&avctx->internal);
     avctx->codec= NULL;
     goto end;
 }
@@ -844,6 +851,7 @@ av_cold int avcodec_close(AVCodecContext *avctx)
         avctx->codec->close(avctx);
     avcodec_default_free_buffers(avctx);
     avctx->coded_frame = NULL;
+    av_freep(&avctx->internal);
     if (avctx->codec && avctx->codec->priv_class)
         av_opt_free(avctx->priv_data);
     av_opt_free(avctx);
@@ -1109,22 +1117,25 @@ void avcodec_flush_buffers(AVCodecContext *avctx)
 }
 
 void avcodec_default_free_buffers(AVCodecContext *s){
+    AVCodecInternal *avci = s->internal;
     int i, j;
 
-    if(s->internal_buffer==NULL) return;
+    if (!avci->internal_buffer)
+        return;
 
-    if (s->internal_buffer_count)
-        av_log(s, AV_LOG_WARNING, "Found %i unreleased buffers!\n", s->internal_buffer_count);
+    if (avci->internal_buffer_count)
+        av_log(s, AV_LOG_WARNING, "Found %i unreleased buffers!\n",
+               avci->internal_buffer_count);
     for(i=0; i<INTERNAL_BUFFER_SIZE; i++){
-        InternalBuffer *buf= &((InternalBuffer*)s->internal_buffer)[i];
+        InternalBuffer *buf= &((InternalBuffer*)avci->internal_buffer)[i];
         for(j=0; j<4; j++){
             av_freep(&buf->base[j]);
             buf->data[j]= NULL;
         }
     }
-    av_freep(&s->internal_buffer);
+    av_freep(&avci->internal_buffer);
 
-    s->internal_buffer_count=0;
+    avci->internal_buffer_count=0;
 }
 
 #if FF_API_OLD_FF_PICT_TYPES
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 356ecbb..35e8958 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -21,7 +21,7 @@
 #define AVCODEC_VERSION_H
 
 #define LIBAVCODEC_VERSION_MAJOR 53
-#define LIBAVCODEC_VERSION_MINOR 20
+#define LIBAVCODEC_VERSION_MINOR 21
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -104,5 +104,8 @@
 #ifndef FF_API_PARSE_FRAME
 #define FF_API_PARSE_FRAME (LIBAVCODEC_VERSION_MAJOR < 54)
 #endif
+#ifndef FF_API_INTERNAL_CONTEXT
+#define FF_API_INTERNAL_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 54)
+#endif
 
 #endif /* AVCODEC_VERSION_H */
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index 991ddce..a31ad4e 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -35,6 +35,7 @@
 
 #include "libavutil/imgutils.h"
 #include "avcodec.h"
+#include "internal.h"
 #include "dsputil.h"
 #include "get_bits.h"
 
@@ -2008,7 +2009,8 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx)
     av_free(s->motion_val[1]);
     av_free(s->edge_emu_buffer);
 
-    if (avctx->is_copy) return 0;
+    if (avctx->internal->is_copy)
+        return 0;
 
     for (i = 0; i < 16; i++) {
         free_vlc(&s->dc_vlc[i]);
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 836176d..d9be734 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -24,6 +24,7 @@
 
 #include "libavutil/imgutils.h"
 #include "avcodec.h"
+#include "internal.h"
 #include "vp8.h"
 #include "vp8data.h"
 #include "rectangle.h"
@@ -88,7 +89,7 @@ static void vp8_decode_flush_impl(AVCodecContext *avctx,
     VP8Context *s = avctx->priv_data;
     int i;
 
-    if (!avctx->is_copy) {
+    if (!avctx->internal->is_copy) {
         for (i = 0; i < 5; i++)
             if (s->frames[i].data[0])
                 vp8_release_frame(s, &s->frames[i], prefer_delayed_free, can_direct_free);
-- 
1.7.1



More information about the libav-devel mailing list