avfilter: pool draining and self destruction support.

This should fix a memleak.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
pull/3/head
Michael Niedermayer 13 years ago
parent 4fd1e2e432
commit f068ce570f
  1. 52
      libavfilter/avfilter.c
  2. 6
      libavfilter/defaults.c
  3. 2
      libavfilter/internal.h

@ -81,12 +81,41 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
return ret; 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) static void store_in_pool(AVFilterBufferRef *ref)
{ {
int i; int i;
AVFilterPool *pool= ref->buf->priv; AVFilterPool *pool= ref->buf->priv;
av_assert0(ref->buf->data[0]); av_assert0(ref->buf->data[0]);
av_assert0(pool->refcount>0);
if (pool->count == POOL_SIZE) { if (pool->count == POOL_SIZE) {
AVFilterBufferRef *ref1 = pool->pic[0]; AVFilterBufferRef *ref1 = pool->pic[0];
@ -107,6 +136,10 @@ static void store_in_pool(AVFilterBufferRef *ref)
break; break;
} }
} }
if (pool->draining) {
free_pool(pool);
} else
--pool->refcount;
} }
void avfilter_unref_buffer(AVFilterBufferRef *ref) void avfilter_unref_buffer(AVFilterBufferRef *ref)
@ -181,24 +214,9 @@ void avfilter_link_free(AVFilterLink **link)
if (!*link) if (!*link)
return; return;
if ((*link)->pool) { if ((*link)->pool)
int i; free_pool((*link)->pool);
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);
}
av_freep(link); av_freep(link);
} }

@ -57,11 +57,14 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
pic->refcount = 1; pic->refcount = 1;
memcpy(picref->data, pic->data, sizeof(picref->data)); memcpy(picref->data, pic->data, sizeof(picref->data));
memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize)); memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
pool->refcount++;
return picref; return picref;
} }
} }
} else } else {
pool = link->pool = av_mallocz(sizeof(AVFilterPool)); pool = link->pool = av_mallocz(sizeof(AVFilterPool));
pool->refcount = 1;
}
// align: +2 is needed for swscaler, +16 to be SIMD-friendly // align: +2 is needed for swscaler, +16 to be SIMD-friendly
if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0) 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->priv = pool;
picref->buf->free = NULL; picref->buf->free = NULL;
pool->refcount++;
return picref; return picref;
} }

@ -31,6 +31,8 @@
typedef struct AVFilterPool { typedef struct AVFilterPool {
AVFilterBufferRef *pic[POOL_SIZE]; AVFilterBufferRef *pic[POOL_SIZE];
int count; int count;
int refcount;
int draining;
} AVFilterPool; } AVFilterPool;
typedef struct AVFilterCommand { typedef struct AVFilterCommand {

Loading…
Cancel
Save