avfilter: pool draining and self destruction support.
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 12 Jan 2012 01:32:41 +0000 (02:32 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 12 Jan 2012 15:32:54 +0000 (16:32 +0100)
This should fix a memleak.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
libavfilter/avfilter.c
libavfilter/defaults.c
libavfilter/internal.h

index 97f78e4..6e958e7 100644 (file)
@@ -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);
 }
 
index 5f18168..c083195 100644 (file)
@@ -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;
 }
index 227fe62..575bcff 100644 (file)
@@ -31,6 +31,8 @@
 typedef struct AVFilterPool {
     AVFilterBufferRef *pic[POOL_SIZE];
     int count;
+    int refcount;
+    int draining;
 } AVFilterPool;
 
 typedef struct AVFilterCommand {