[FFmpeg-cvslog] AVFilter: use picture pool to avoid malloc().

Michael Niedermayer git at videolan.org
Sat May 7 00:07:18 CEST 2011


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Fri May  6 23:53:06 2011 +0200| [39f66edbeae5ccabefe38b2fcb25d6c242d868c0] | committer: Michael Niedermayer

AVFilter: use picture pool to avoid malloc().
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=39f66edbeae5ccabefe38b2fcb25d6c242d868c0
---

 libavfilter/avfilter.c |   43 ++++++++++++++++++++++++++++++++++++++++++-
 libavfilter/avfilter.h |    2 ++
 libavfilter/defaults.c |   22 +++++++++++++++++++++-
 libavfilter/internal.h |    6 ++++++
 4 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 7b4d853..0518e6d 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -25,6 +25,7 @@
 #include "libavutil/rational.h"
 #include "libavutil/audioconvert.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/avassert.h"
 #include "avfilter.h"
 #include "internal.h"
 
@@ -69,12 +70,50 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
     return ret;
 }
 
+static void store_in_pool(AVFilterBufferRef *ref)
+{
+    int i;
+    AVFilterLink *link= ref->buf->priv;
+    AVFilterPool *pool;
+
+    av_assert0(ref->buf->data[0]);
+
+    if(!link->pool)
+        link->pool = av_mallocz(sizeof(AVFilterPool));
+    pool= link->pool;
+
+    if(pool->count == POOL_SIZE){
+        AVFilterBufferRef *ref1= pool->pic[0];
+        av_freep(&ref1->video);
+        av_freep(&ref1->audio);
+        av_freep(&ref1->buf->data[0]);
+        av_freep(&ref1->buf);
+        av_free(ref1);
+        memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1));
+        pool->count--;
+        pool->pic[POOL_SIZE-1] = NULL;
+    }
+
+    for(i=0; i<POOL_SIZE; i++){
+        if(!pool->pic[i]){
+            pool->pic[i]= ref;
+            pool->count++;
+            break;
+        }
+    }
+}
+
 void avfilter_unref_buffer(AVFilterBufferRef *ref)
 {
     if (!ref)
         return;
-    if (!(--ref->buf->refcount))
+    if (!(--ref->buf->refcount)){
+        if(!ref->buf->free){
+            store_in_pool(ref);
+            return;
+        }
         ref->buf->free(ref->buf);
+    }
     av_freep(&ref->video);
     av_freep(&ref->audio);
     av_free(ref);
@@ -646,6 +685,7 @@ void avfilter_free(AVFilterContext *filter)
         if ((link = filter->inputs[i])) {
             if (link->src)
                 link->src->outputs[link->srcpad - link->src->output_pads] = NULL;
+            av_freep(&link->pool);
             avfilter_formats_unref(&link->in_formats);
             avfilter_formats_unref(&link->out_formats);
         }
@@ -655,6 +695,7 @@ void avfilter_free(AVFilterContext *filter)
         if ((link = filter->outputs[i])) {
             if (link->dst)
                 link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
+            av_freep(&link->pool);
             avfilter_formats_unref(&link->in_formats);
             avfilter_formats_unref(&link->out_formats);
         }
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 5003152..1a69aa3 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -619,6 +619,8 @@ struct AVFilterLink {
      * input link is assumed to be an unchangeable property.
      */
     AVRational time_base;
+
+    struct AVFilterPool *pool;
 };
 
 /**
diff --git a/libavfilter/defaults.c b/libavfilter/defaults.c
index 1da2630..ef798dd 100644
--- a/libavfilter/defaults.c
+++ b/libavfilter/defaults.c
@@ -25,7 +25,6 @@
 #include "avfilter.h"
 #include "internal.h"
 
-/* TODO: buffer pool.  see comment for avfilter_default_get_video_buffer() */
 void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
 {
     av_free(ptr->data[0]);
@@ -39,7 +38,26 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
 {
     int linesize[4];
     uint8_t *data[4];
+    int i;
     AVFilterBufferRef *picref = NULL;
+    AVFilterPool *pool= link->pool;
+
+    if(pool) for(i=0; i<POOL_SIZE; i++){
+        picref= pool->pic[i];
+        if(picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h){
+            AVFilterBuffer *pic= picref->buf;
+            pool->pic[i]= NULL;
+            pool->count--;
+            picref->video->w = w;
+            picref->video->h = h;
+            picref->perms = perms | AV_PERM_READ;
+            picref->format= link->format;
+            pic->refcount = 1;
+            memcpy(picref->data,     pic->data,     sizeof(picref->data));
+            memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
+            return picref;
+        }
+    }
 
     // +2 is needed for swscaler, +16 to be SIMD-friendly
     if (av_image_alloc(data, linesize, w, h, link->format, 16) < 0)
@@ -51,6 +69,8 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
         av_free(data[0]);
         return NULL;
     }
+    picref->buf->priv= link;
+    picref->buf->free= NULL;
 
     return picref;
 }
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 188da87..159e979 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -27,6 +27,12 @@
 #include "avfilter.h"
 #include "avfiltergraph.h"
 
+#define POOL_SIZE 32
+typedef struct AVFilterPool {
+    AVFilterBufferRef *pic[POOL_SIZE];
+    int count;
+}AVFilterPool;
+
 /**
  * Check for the validity of graph.
  *



More information about the ffmpeg-cvslog mailing list