Make avfilter_get_video_buffer() recursive.
authorStefano Sabatini <stefano.sabatini-lala@poste.it>
Sun, 18 Oct 2009 08:16:18 +0000 (08:16 +0000)
committerStefano Sabatini <stefano.sabatini-lala@poste.it>
Sun, 18 Oct 2009 08:16:18 +0000 (08:16 +0000)
When called on a link with a filter whose destination pad has not a
get_video_buffer callback defined, it will call
avfilter_get_video_buffer() on the first output link of the
destination filer, rather than use avfilter_default_get_buffer(), so
the video buffer can be allocated forward in the filterchain.

Also add the w and h parameters to avfilter_get_video_buffer(), as the
minimum width and height requested by each filter in the filterchain
may change, this allows for example a memcpy-less pad filter.

This change breaks API / ABI backward compatibility.

See the thread:
"[PATCH] Implement recusive avfilter_get_video_buffer()".

Originally committed as revision 20272 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/defaults.c

index 6088077..77c7571 100644 (file)
@@ -185,17 +185,20 @@ static void dprintf_link(void *ctx, AVFilterLink *link, int end)
 
 #define DPRINTF_START(ctx, func) dprintf(NULL, "%-16s: ", #func)
 
-AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms)
+AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
 {
     AVFilterPicRef *ret = NULL;
 
-    DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " perms:%d\n", perms);
+    DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " perms:%d w:%d h:%d\n", perms, w, h);
 
     if(link_dpad(link).get_video_buffer)
-        ret = link_dpad(link).get_video_buffer(link, perms);
+        ret = link_dpad(link).get_video_buffer(link, perms, w, h);
+
+    if(!ret && link->dst->output_count)
+        ret = avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
 
     if(!ret)
-        ret = avfilter_default_get_video_buffer(link, perms);
+        ret = avfilter_default_get_video_buffer(link, perms, w, h);
 
     DPRINTF_START(NULL, get_video_buffer); dprintf_link(NULL, link, 0); dprintf(NULL, " returning "); dprintf_picref(NULL, ret, 1);
 
@@ -251,7 +254,7 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
                 link_dpad(link).min_perms, link_dpad(link).rej_perms);
         */
 
-        link->cur_pic = avfilter_default_get_video_buffer(link, dst->min_perms);
+        link->cur_pic = avfilter_default_get_video_buffer(link, dst->min_perms, link->w, link->h);
         link->srcpic = picref;
         link->cur_pic->pts = link->srcpic->pts;
         link->cur_pic->pixel_aspect = link->srcpic->pixel_aspect;
index 9c282e2..2b17dea 100644 (file)
@@ -22,9 +22,9 @@
 #ifndef AVFILTER_AVFILTER_H
 #define AVFILTER_AVFILTER_H
 
-#define LIBAVFILTER_VERSION_MAJOR  0
-#define LIBAVFILTER_VERSION_MINOR  5
-#define LIBAVFILTER_VERSION_MICRO  1
+#define LIBAVFILTER_VERSION_MAJOR  1
+#define LIBAVFILTER_VERSION_MINOR  0
+#define LIBAVFILTER_VERSION_MICRO  0
 
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
                                                LIBAVFILTER_VERSION_MINOR, \
@@ -293,7 +293,7 @@ struct AVFilterPad
      *
      * Input video pads only.
      */
-    AVFilterPicRef *(*get_video_buffer)(AVFilterLink *link, int perms);
+    AVFilterPicRef *(*get_video_buffer)(AVFilterLink *link, int perms, int w, int h);
 
     /**
      * Callback called after the slices of a frame are completely sent. If
@@ -361,7 +361,7 @@ int avfilter_default_config_output_link(AVFilterLink *link);
 int avfilter_default_config_input_link (AVFilterLink *link);
 /** default handler for get_video_buffer() for video inputs */
 AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link,
-                                                  int perms);
+                                                  int perms, int w, int h);
 /**
  * A helper for query_formats() which sets all links to the same list of
  * formats. If there are no links hooked to this filter, the list of formats is
@@ -499,10 +499,13 @@ int avfilter_config_links(AVFilterContext *filter);
  * @param link  the output link to the filter from which the picture will
  *              be requested
  * @param perms the required access permissions
+ * @param w     the minimum width of the buffer to allocate
+ * @param h     the minimum height of the buffer to allocate
  * @return      A reference to the picture. This must be unreferenced with
  *              avfilter_unref_pic when you are finished with it.
  */
-AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms);
+AVFilterPicRef *avfilter_get_video_buffer(AVFilterLink *link, int perms,
+                                          int w, int h);
 
 /**
  * Requests an input frame from the filter at the other end of the link.
index dabb1d5..1983672 100644 (file)
@@ -32,7 +32,7 @@ void avfilter_default_free_video_buffer(AVFilterPic *pic)
 /* TODO: set the buffer's priv member to a context structure for the whole
  * filter chain.  This will allow for a buffer pool instead of the constant
  * alloc & free cycle currently implemented. */
-AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms)
+AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
 {
     AVFilterPic *pic = av_mallocz(sizeof(AVFilterPic));
     AVFilterPicRef *ref = av_mallocz(sizeof(AVFilterPicRef));
@@ -40,8 +40,8 @@ AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms)
     char *buf;
 
     ref->pic   = pic;
-    ref->w     = pic->w = link->w;
-    ref->h     = pic->h = link->h;
+    ref->w     = pic->w = w;
+    ref->h     = pic->h = h;
 
     /* make sure the buffer gets read permission or it's useless for output */
     ref->perms = perms | AV_PERM_READ;
@@ -72,7 +72,7 @@ void avfilter_default_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
         out = link->dst->outputs[0];
 
     if(out) {
-        out->outpic      = avfilter_get_video_buffer(out, AV_PERM_WRITE);
+        out->outpic      = avfilter_get_video_buffer(out, AV_PERM_WRITE, link->w, link->h);
         out->outpic->pts = picref->pts;
         avfilter_start_frame(out, avfilter_ref_pic(out->outpic, ~0));
     }