[FFmpeg-soc] [soc]: r316 - in libavfilter: avfilter.c avfilter.h filter_test.c vf_crop.c vo_sdl.c vsrc_dummy.c

koorogi subversion at mplayerhq.hu
Thu Jul 5 22:48:48 CEST 2007


Author: koorogi
Date: Thu Jul  5 22:48:48 2007
New Revision: 316

Log:
Rework filter initialization sequence.  Now supports passing user parameters,
querying supported colorspaces, etc.


Modified:
   libavfilter/avfilter.c
   libavfilter/avfilter.h
   libavfilter/filter_test.c
   libavfilter/vf_crop.c
   libavfilter/vo_sdl.c
   libavfilter/vsrc_dummy.c

Modified: libavfilter/avfilter.c
==============================================================================
--- libavfilter/avfilter.c	(original)
+++ libavfilter/avfilter.c	Thu Jul  5 22:48:48 2007
@@ -19,6 +19,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -91,6 +92,7 @@ int avfilter_link(AVFilterContext *src, 
                   AVFilterContext *dst, unsigned dstpad)
 {
     AVFilterLink *link;
+    int *fmts[2], i, j;
 
     if(src->outputs[srcpad] || dst->inputs[dstpad])
         return -1;
@@ -104,7 +106,29 @@ int avfilter_link(AVFilterContext *src, 
     link->dstpad = dstpad;
     link->cur_pic = NULL;
 
-    src->filter->outputs[dstpad].set_video_props(link);
+    /* find a format both filters support - TODO: auto-insert conversion filter */
+    fmts[0] = src->filter->outputs[srcpad].query_formats(link);
+    fmts[1] = dst->filter->inputs[dstpad].query_formats(link);
+    for(i = 0; fmts[0][i] != -1; i ++)
+        for(j = 0; fmts[1][j] != -1; j ++)
+            if(fmts[0][i] == fmts[1][j]) {
+                link->format = fmts[0][i];
+                goto format_done;
+            }
+
+format_done:
+    av_free(fmts[0]);
+    av_free(fmts[1]);
+    if(link->format == -1) {
+        /* failed to find a format.  fail at creating the link */
+        av_free(link);
+        src->outputs[srcpad] = NULL;
+        dst->inputs[dstpad]  = NULL;
+        return -1;
+    }
+
+    src->filter->outputs[srcpad].config_props(link);
+    dst->filter->inputs[dstpad].config_props(link);
     return 0;
 }
 
@@ -263,9 +287,21 @@ int avfilter_init_filter(AVFilterContext
 
     if(filter->filter->init)
         if((ret = filter->filter->init(filter, args))) return ret;
-    for(i = 0; i < pad_count(filter->filter->outputs); i ++)
-        if(filter->outputs[i])
-            filter->filter->outputs[i].set_video_props(filter->outputs[i]);
     return 0;
 }
 
+int *avfilter_make_format_list(int len, ...)
+{
+    int *ret, i;
+    va_list vl;
+
+    ret = av_malloc(sizeof(int) * (len + 1));
+    va_start(vl, len);
+    for(i = 0; i < len; i ++)
+        ret[i] = va_arg(vl, int);
+    va_end(vl);
+    ret[len] = -1;
+
+    return ret;
+}
+

Modified: libavfilter/avfilter.h
==============================================================================
--- libavfilter/avfilter.h	(original)
+++ libavfilter/avfilter.h	Thu Jul  5 22:48:48 2007
@@ -99,6 +99,13 @@ struct AVFilterPad
 #define AV_PAD_VIDEO 0
 
     /**
+     * Callback to get a list of supported formats.  The returned list should
+     * be terminated by -1.  This is used for both input and output pads and
+     * is required for both.
+     */
+    int *(*query_formats)(AVFilterLink *link);
+
+    /**
      * Callback called before passing the first slice of a new frame.  If
      * NULL, the filter layer will default to storing a reference to the
      * picture inside the link structure.
@@ -131,11 +138,15 @@ struct AVFilterPad
     void (*request_frame)(AVFilterLink *link);
 
     /**
-     * Callback to set properties of the link. Only for video output pads.
-     * XXX: this is not acceptable as is.  it needs reworked to allow for
-     * negotiation of colorspace, etc.
+     * Link configuration callback.  For output pads, this should set the link
+     * properties such as width/height.  NOTE: this should not set the format
+     * property - that is negotiated between filters by the filter system using
+     * the query_formats() callback.
+     *
+     * For input pads, this should check the properties of the link, and update
+     * the filter's internal state as necessary.
      */
-    int (*set_video_props)(AVFilterLink *link);
+    int (*config_props)(AVFilterLink *link);
 };
 
 /* the default implementations of start_frame() and end_frame() */
@@ -206,4 +217,6 @@ AVFilterContext *avfilter_create_by_name
 int avfilter_init_filter(AVFilterContext *filter, const char *args);
 void avfilter_destroy(AVFilterContext *filter);
 
+int *avfilter_make_format_list(int len, ...);
+
 #endif  /* FFMPEG_AVFILTER_H */

Modified: libavfilter/filter_test.c
==============================================================================
--- libavfilter/filter_test.c	(original)
+++ libavfilter/filter_test.c	Thu Jul  5 22:48:48 2007
@@ -36,12 +36,13 @@ int main()
     crop = avfilter_create_by_name("crop");
     out  = avfilter_create_by_name("sdl");
 
-    avfilter_link(src,  0, crop, 0);
-    avfilter_link(crop, 0, out,  0);
     avfilter_init_filter(src,  NULL);
     avfilter_init_filter(crop, "20:40:320:240");
     avfilter_init_filter(out,  NULL);
 
+    avfilter_link(src,  0, crop, 0);
+    avfilter_link(crop, 0, out,  0);
+
     for(i = 0; i < 10; i ++) {
         sdl_display(out);
         sleep(1);

Modified: libavfilter/vf_crop.c
==============================================================================
--- libavfilter/vf_crop.c	(original)
+++ libavfilter/vf_crop.c	Thu Jul  5 22:48:48 2007
@@ -27,22 +27,18 @@
 typedef struct
 {
     int x, y, w, h;
+    int cx, cy, cw, ch;
 } CropContext;
 
 static int init(AVFilterContext *ctx, const char *args)
 {
     CropContext *crop = ctx->priv;
 
-    if(ctx->inputs[0]->format != PIX_FMT_RGB24) {
-        av_log(ctx, AV_LOG_FATAL, "unsupported input format\n");
-        return -1;
-    }
-
     /* default parameters */
     crop->x = 0;
     crop->y = 0;
-    crop->w = 640;
-    crop->h = 480;
+    crop->w = -1;
+    crop->h = -1;
 
     if(args)
         sscanf(args, "%d:%d:%d:%d", &crop->x, &crop->y, &crop->w, &crop->h);
@@ -50,13 +46,37 @@ static int init(AVFilterContext *ctx, co
     return 0;
 }
 
-static int set_video_props(AVFilterLink *link)
+static int *query_in_formats(AVFilterLink *link)
+{
+    return avfilter_make_format_list(1, PIX_FMT_RGB24);
+}
+
+static int *query_out_formats(AVFilterLink *link)
+{
+    return avfilter_make_format_list(1, link->src->inputs[0]->format);
+}
+
+static int config_input(AVFilterLink *link)
+{
+    CropContext *crop = link->dst->priv;
+
+    crop->cx = FFMIN(crop->x, link->w - 1);
+    crop->cy = FFMIN(crop->y, link->h - 1);
+    crop->cw = FFMIN(crop->w, link->w - crop->cx);
+    crop->ch = FFMIN(crop->h, link->h - crop->cy);
+
+    if(crop->cw <= 0) crop->cw = link->w - crop->cx;
+    if(crop->ch <= 0) crop->ch = link->h - crop->cy;
+
+    return 0;
+}
+
+static int config_output(AVFilterLink *link)
 {
     CropContext *crop = link->src->priv;
 
-    link->w = crop->w;
-    link->h = crop->h;
-    link->format = link->src->inputs[0]->format;
+    link->w = crop->cw;
+    link->h = crop->ch;
 
     return 0;
 }
@@ -66,10 +86,10 @@ static void start_frame(AVFilterLink *li
     CropContext *crop = link->dst->priv;
     AVFilterPicRef *ref2 = avfilter_ref_pic(picref);
 
-    ref2->w = crop->w;
-    ref2->h = crop->h;
-    ref2->data[0] += crop->y * ref2->linesize[0];
-    ref2->data[0] += 3 * crop->x;
+    ref2->w = crop->cw;
+    ref2->h = crop->ch;
+    ref2->data[0] += crop->cy * ref2->linesize[0];
+    ref2->data[0] += crop->cx * 3;
 
     av_log(link->dst, AV_LOG_INFO, "start_frame()\n");
     avfilter_default_start_frame(link, picref);
@@ -97,20 +117,20 @@ static void draw_slice(AVFilterLink *lin
 
     av_log(link->dst, AV_LOG_INFO, "draw_slice()\n");
 
-    if(y >= crop->y + crop->h || y + h <= crop->y) return;
+    if(y >= crop->cy + crop->ch || y + h <= crop->cy) return;
 
     memcpy(src, data, sizeof(uint8_t *) * 4);
 
-    if(top < crop->y) {
-        height -=  crop->y - top;
-        src[0] += (crop->y - top) * pic->linesize[0];
-        top     =  crop->y;
+    if(top < crop->cy) {
+        height -=  crop->cy - top;
+        src[0] += (crop->cy - top) * pic->linesize[0];
+        top     =  crop->cy;
     }
-    if(top + height > crop->y + crop->h)
-        height = crop->y + crop->h - top;
-    src[0] += 3 * crop->x;
+    if(top + height > crop->cy + crop->ch)
+        height = crop->cy + crop->ch - top;
+    src[0] += 3 * crop->cx;
 
-    avfilter_draw_slice(ctx->outputs[0], src, top - crop->y, height);
+    avfilter_draw_slice(ctx->outputs[0], src, top - crop->cy, height);
 }
 
 /* XXX: maybe make the default implementation do this? */
@@ -131,12 +151,15 @@ AVFilter vf_crop =
                                     .type            = AV_PAD_VIDEO,
                                     .start_frame     = start_frame,
                                     .draw_slice      = draw_slice,
-                                    .end_frame       = end_frame, },
+                                    .end_frame       = end_frame,
+                                    .query_formats   = query_in_formats,
+                                    .config_props    = config_input, },
                                   { .name = NULL}},
     .outputs   = (AVFilterPad[]) {{ .name            = "default",
                                     .type            = AV_PAD_VIDEO,
                                     .request_frame   = request_frame,
-                                    .set_video_props = set_video_props},
+                                    .query_formats   = query_out_formats,
+                                    .config_props    = config_output, },
                                   { .name = NULL}},
 };
 

Modified: libavfilter/vo_sdl.c
==============================================================================
--- libavfilter/vo_sdl.c	(original)
+++ libavfilter/vo_sdl.c	Thu Jul  5 22:48:48 2007
@@ -34,24 +34,32 @@ static int init(AVFilterContext *ctx, co
 {
     SDLContext *sdl = ctx->priv;
 
-    if(ctx->inputs[0]->format != PIX_FMT_RGB24) {
-        av_log(ctx, AV_LOG_FATAL, "unsupported input format\n");
-        return -1;
-    }
-
     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE)) {
         av_log(ctx, AV_LOG_FATAL, "unable to initialize SDL: %s\n",
                SDL_GetError());
         return -1;
     }
 
-    sdl->surface = SDL_SetVideoMode(ctx->inputs[0]->w,
-                                    ctx->inputs[0]->h,
-                                    24, SDL_HWSURFACE | SDL_DOUBLEBUF);
-
     return 0;
 }
 
+static int *query_formats(AVFilterLink *link)
+{
+    return avfilter_make_format_list(1, PIX_FMT_RGB24);
+}
+
+static int config_props(AVFilterLink *link)
+{
+    SDLContext *sdl = link->dst->priv;
+
+    /* SDL docs claim that calling this a second time to resize the
+     * surface will automatically free the old surface for us */
+    sdl->surface = SDL_SetVideoMode(link->w, link->h, 24,
+                                    SDL_HWSURFACE | SDL_DOUBLEBUF);
+
+    return !sdl->surface;
+}
+
 static void uninit(AVFilterContext *ctx)
 {
     SDL_QuitSubSystem(SDL_INIT_VIDEO);
@@ -117,7 +125,9 @@ AVFilter vo_sdl =
                                     .type        = AV_PAD_VIDEO,
                                     .start_frame = start_frame,
                                     .end_frame   = end_frame,
-                                    .draw_slice  = draw_slice, },
+                                    .draw_slice  = draw_slice,
+                                    .query_formats = query_formats,
+                                    .config_props  = config_props, },
                                   { .name = NULL}},
     .outputs   = (AVFilterPad[]) {{ .name = NULL}},
 };

Modified: libavfilter/vsrc_dummy.c
==============================================================================
--- libavfilter/vsrc_dummy.c	(original)
+++ libavfilter/vsrc_dummy.c	Thu Jul  5 22:48:48 2007
@@ -27,11 +27,15 @@
 #define GREEN   0x60
 #define BLUE    0xC0
 
-static int set_video_props(AVFilterLink *link)
+static int *query_formats(AVFilterLink *link)
+{
+    return avfilter_make_format_list(1, PIX_FMT_RGB24);
+}
+
+static int config_props(AVFilterLink *link)
 {
     link->w = 640;
     link->h = 480;
-    link->format = PIX_FMT_RGB24;
 
     return 0;
 }
@@ -73,7 +77,8 @@ AVFilter vsrc_dummy =
     .outputs   = (AVFilterPad[]) {{ .name            = "default",
                                     .type            = AV_PAD_VIDEO,
                                     .request_frame   = request_frame,
-                                    .set_video_props = set_video_props, },
+                                    .query_formats   = query_formats,
+                                    .config_props    = config_props, },
                                   { .name = NULL}},
 };
 



More information about the FFmpeg-soc mailing list