From 39f66edbeae5ccabefe38b2fcb25d6c242d868c0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 6 May 2011 23:53:06 +0200 Subject: [PATCH] AVFilter: use picture pool to avoid malloc(). Signed-off-by: Michael Niedermayer --- 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 7b4d853b69..0518e6d6c2 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; ipic[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 5003152069..1a69aa397c 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 1da2630471..ef798ddd8d 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; ipic[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 188da87099..159e979168 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. *