summaryrefslogtreecommitdiff
path: root/libavfilter
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-01-12 02:32:41 +0100
committerMichael Niedermayer <michaelni@gmx.at>2012-01-12 16:32:54 +0100
commitf068ce570f7c378106bd7afdad6455b22ac28020 (patch)
treefb7b3a5b7d9e9ad3dbc7ec9fc8e1165c64e06f0a /libavfilter
parent4fd1e2e43233960f122a2c16841834d388d77c60 (diff)
avfilter: pool draining and self destruction support.
This should fix a memleak. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavfilter')
-rw-r--r--libavfilter/avfilter.c54
-rw-r--r--libavfilter/defaults.c6
-rw-r--r--libavfilter/internal.h2
3 files changed, 43 insertions, 19 deletions
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 97f78e4629..6e958e7141 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -81,12 +81,41 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
return ret;
}
+static void free_pool(AVFilterPool *pool)
+{
+ int i;
+
+ av_assert0(pool->refcount > 0);
+
+ for (i = 0; i < POOL_SIZE; i++) {
+ if (pool->pic[i]) {
+ AVFilterBufferRef *picref = pool->pic[i];
+ /* free buffer: picrefs stored in the pool are not
+ * supposed to contain a free callback */
+ av_freep(&picref->buf->data[0]);
+ av_freep(&picref->buf);
+
+ av_freep(&picref->audio);
+ av_freep(&picref->video);
+ av_freep(&pool->pic[i]);
+ pool->count--;
+ }
+ }
+ pool->draining = 1;
+
+ if (!--pool->refcount) {
+ av_assert0(!pool->count);
+ av_free(pool);
+ }
+}
+
static void store_in_pool(AVFilterBufferRef *ref)
{
int i;
AVFilterPool *pool= ref->buf->priv;
av_assert0(ref->buf->data[0]);
+ av_assert0(pool->refcount>0);
if (pool->count == POOL_SIZE) {
AVFilterBufferRef *ref1 = pool->pic[0];
@@ -107,6 +136,10 @@ static void store_in_pool(AVFilterBufferRef *ref)
break;
}
}
+ if (pool->draining) {
+ free_pool(pool);
+ } else
+ --pool->refcount;
}
void avfilter_unref_buffer(AVFilterBufferRef *ref)
@@ -181,24 +214,9 @@ void avfilter_link_free(AVFilterLink **link)
if (!*link)
return;
- if ((*link)->pool) {
- int i;
- for (i = 0; i < POOL_SIZE; i++) {
- if ((*link)->pool->pic[i]) {
- AVFilterBufferRef *picref = (*link)->pool->pic[i];
- /* free buffer: picrefs stored in the pool are not
- * supposed to contain a free callback */
- av_freep(&picref->buf->data[0]);
- av_freep(&picref->buf);
-
- av_freep(&picref->audio);
- av_freep(&picref->video);
- av_freep(&(*link)->pool->pic[i]);
- }
- }
- (*link)->pool->count = 0;
-// av_freep(&(*link)->pool);
- }
+ if ((*link)->pool)
+ free_pool((*link)->pool);
+
av_freep(link);
}
diff --git a/libavfilter/defaults.c b/libavfilter/defaults.c
index 5f18168374..c083195b4f 100644
--- a/libavfilter/defaults.c
+++ b/libavfilter/defaults.c
@@ -57,11 +57,14 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
pic->refcount = 1;
memcpy(picref->data, pic->data, sizeof(picref->data));
memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
+ pool->refcount++;
return picref;
}
}
- } else
+ } else {
pool = link->pool = av_mallocz(sizeof(AVFilterPool));
+ pool->refcount = 1;
+ }
// align: +2 is needed for swscaler, +16 to be SIMD-friendly
if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0)
@@ -77,6 +80,7 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
picref->buf->priv = pool;
picref->buf->free = NULL;
+ pool->refcount++;
return picref;
}
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 227fe6243d..575bcff364 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -31,6 +31,8 @@
typedef struct AVFilterPool {
AVFilterBufferRef *pic[POOL_SIZE];
int count;
+ int refcount;
+ int draining;
} AVFilterPool;
typedef struct AVFilterCommand {