This implements filtered-caps negotiation for all the v4l*src elements, and removes...
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sat, 10 May 2003 14:36:34 +0000 (14:36 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Sat, 10 May 2003 14:36:34 +0000 (14:36 +0000)
Original commit message from CVS:
This implements filtered-caps negotiation for all the v4l*src elements, and removes the accompanying properties since they're no longer needed

sys/v4l/gstv4lmjpegsrc.c
sys/v4l/gstv4lmjpegsrc.h
sys/v4l/gstv4lsrc.c
sys/v4l/gstv4lsrc.h

index bcac299..92ef56f 100644 (file)
@@ -47,17 +47,16 @@ enum {
 /* arguments */
 enum {
   ARG_0,
+#if 0
   ARG_X_OFFSET,
   ARG_Y_OFFSET,
   ARG_F_WIDTH,
   ARG_F_HEIGHT,
-  ARG_H_DECIMATION,
-  ARG_V_DECIMATION,
-  ARG_WIDTH,
-  ARG_HEIGHT,
+  /* normally, we would want to use subframe capture, however,
+   * for the time being it's easier if we disable it first */
+#endif
   ARG_QUALITY,
   ARG_NUMBUFS,
-  ARG_BUFSIZE,
   ARG_USE_FIXED_FPS
 };
 
@@ -75,6 +74,8 @@ static gboolean              gst_v4lmjpegsrc_srcconvert   (GstPad         *pad,
 static GstPadLinkReturn      gst_v4lmjpegsrc_srcconnect   (GstPad         *pad,
                                                            GstCaps        *caps);
 static GstBuffer*            gst_v4lmjpegsrc_get          (GstPad         *pad);
+static GstCaps*              gst_v4lmjpegsrc_getcaps      (GstPad         *pad,
+                                                           GstCaps        *caps);
 
 /* get/set params */
 static void                  gst_v4lmjpegsrc_set_property (GObject        *object,
@@ -145,6 +146,7 @@ gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass *klass)
 
   parent_class = g_type_class_ref(GST_TYPE_V4LELEMENT);
 
+#if 0
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_X_OFFSET,
     g_param_spec_int("x_offset","x_offset","x_offset",
                      G_MININT,G_MAXINT,0,G_PARAM_WRITABLE));
@@ -157,20 +159,7 @@ gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass *klass)
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_F_HEIGHT,
     g_param_spec_int("frame_height","frame_height","frame_height",
                      G_MININT,G_MAXINT,0,G_PARAM_WRITABLE));
-
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_H_DECIMATION,
-    g_param_spec_int("h_decimation","h_decimation","h_decimation",
-                     G_MININT,G_MAXINT,0,G_PARAM_WRITABLE));
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_V_DECIMATION,
-    g_param_spec_int("v_decimation","v_decimation","v_decimation",
-                     G_MININT,G_MAXINT,0,G_PARAM_WRITABLE));
-
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_WIDTH,
-    g_param_spec_int("width","width","width",
-                     G_MININT,G_MAXINT,0,G_PARAM_READABLE));
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HEIGHT,
-    g_param_spec_int("height","height","height",
-                     G_MININT,G_MAXINT,0,G_PARAM_READABLE));
+#endif
 
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_QUALITY,
     g_param_spec_int("quality","quality","quality",
@@ -179,9 +168,6 @@ gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass *klass)
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NUMBUFS,
     g_param_spec_int("num_buffers","num_buffers","num_buffers",
                      G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFSIZE,
-    g_param_spec_int("buffer_size","buffer_size","buffer_size",
-                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
 
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_USE_FIXED_FPS,
     g_param_spec_boolean("use_fixed_fps", "Use Fixed FPS",
@@ -227,6 +213,7 @@ gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
   gst_element_add_pad(GST_ELEMENT(v4lmjpegsrc), v4lmjpegsrc->srcpad);
 
   gst_pad_set_get_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_get);
+  gst_pad_set_getcaps_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_getcaps);
   gst_pad_set_link_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_srcconnect);
   gst_pad_set_convert_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_srcconvert);
 
@@ -238,21 +225,16 @@ gst_v4lmjpegsrc_init (GstV4lMjpegSrc *v4lmjpegsrc)
                                        (GstBufferPoolBufferFreeFunction)gst_v4lmjpegsrc_buffer_free,
                                        v4lmjpegsrc);
 
+#if 0
   v4lmjpegsrc->frame_width = 0;
   v4lmjpegsrc->frame_height = 0;
   v4lmjpegsrc->x_offset = -1;
   v4lmjpegsrc->y_offset = -1;
-
-  v4lmjpegsrc->horizontal_decimation = 4;
-  v4lmjpegsrc->vertical_decimation = 4;
-
-  v4lmjpegsrc->end_width = 0;
-  v4lmjpegsrc->end_height = 0;
+#endif
 
   v4lmjpegsrc->quality = 50;
 
   v4lmjpegsrc->numbufs = 64;
-  v4lmjpegsrc->bufsize = 256;
 
   /* no clock */
   v4lmjpegsrc->clock = NULL;
@@ -343,14 +325,44 @@ gst_v4lmjpegsrc_srcconvert (GstPad    *pad,
 }
 
 
+static inline gulong
+calc_bufsize (int hor_dec,
+              int ver_dec)
+{
+        guint8 div = hor_dec * ver_dec;
+        guint32 num = (1024 * 512) / (div);
+        guint32 result = 2;
+                                                                                
+        num--;
+        while (num) {
+                num >>= 1;
+                result <<= 1;
+        }
+                                                                                
+        if (result > (512 * 1024))
+                return (512 * 1024);
+        if (result < 8192)
+                return 8192;
+        return result;
+}
+
+#define gst_caps_get_int_range(caps, name, min, max) \
+  gst_props_entry_get_int_range(gst_props_get_entry((caps)->properties, \
+                                                    name), \
+                                min, max)
+
+
 static GstPadLinkReturn
 gst_v4lmjpegsrc_srcconnect (GstPad  *pad,
                             GstCaps *caps)
 {
   GstPadLinkReturn ret_val;
-  GstV4lMjpegSrc *v4lmjpegsrc;
-
-  v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad));
+  GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC(gst_pad_get_parent(pad));
+  gint hor_dec, ver_dec;
+  gint w, h;
+  gint max_w = GST_V4LELEMENT(v4lmjpegsrc)->vcap.maxwidth,
+       max_h = GST_V4LELEMENT(v4lmjpegsrc)->vcap.maxheight;
+  gulong bufsize;
 
   /* in case the buffers are active (which means that we already
    * did capsnego before and didn't clean up), clean up anyways */
@@ -370,11 +382,64 @@ gst_v4lmjpegsrc_srcconnect (GstPad  *pad,
    * our own mime type back and it'll work. Other properties are to be set
    * by the src, not by the opposite caps */
 
+  if (gst_caps_has_property(caps, "width")) {
+    if (gst_caps_has_fixed_property(caps, "width")) {
+      gst_caps_get_int(caps, "width", &w);
+    } else {
+      int max;
+      gst_caps_get_int_range(caps, "width", &w, &max);
+    }
+  }
+  if (gst_caps_has_property(caps, "height")) {
+    if (gst_caps_has_fixed_property(caps, "height")) {
+      gst_caps_get_int(caps, "height", &h);
+    } else {
+      int max;
+      gst_caps_get_int_range(caps, "height", &h, &max);
+    }
+  }
+
+  /* figure out decimation */
+  if (w >= max_w) {
+    hor_dec = 1;
+  } else if (w*2 >= max_w) {
+    hor_dec = 2;
+  } else {
+    hor_dec = 4;
+  }
+  if (h >= max_h) {
+    ver_dec = 1;
+  } else if (h*2 >= max_h) {
+    ver_dec = 2;
+  } else {
+    ver_dec = 4;
+  }
+
+  /* calculate bufsize */
+  bufsize = calc_bufsize(hor_dec, ver_dec);
+
   /* set buffer info */
-  if (!gst_v4lmjpegsrc_set_buffer(v4lmjpegsrc, v4lmjpegsrc->numbufs, v4lmjpegsrc->bufsize))
+  if (!gst_v4lmjpegsrc_set_buffer(v4lmjpegsrc,
+                                  v4lmjpegsrc->numbufs, bufsize)) {
     return GST_PAD_LINK_REFUSED;
+  }
 
   /* set capture parameters and mmap the buffers */
+  if (hor_dec == ver_dec) {
+    if (!gst_v4lmjpegsrc_set_capture(v4lmjpegsrc,
+                                     hor_dec,
+                                     v4lmjpegsrc->quality)) {
+      return GST_PAD_LINK_REFUSED;
+    }
+  } else {
+    if (!gst_v4lmjpegsrc_set_capture_m(v4lmjpegsrc,
+                                       0, 0, max_w, max_h,
+                                       hor_dec, ver_dec,
+                                       v4lmjpegsrc->quality)) {
+      return GST_PAD_LINK_REFUSED;
+    }
+  }
+#if 0
   if (!v4lmjpegsrc->frame_width && !v4lmjpegsrc->frame_height &&
        v4lmjpegsrc->x_offset < 0 && v4lmjpegsrc->y_offset < 0 &&
        v4lmjpegsrc->horizontal_decimation == v4lmjpegsrc->vertical_decimation)
@@ -392,6 +457,8 @@ gst_v4lmjpegsrc_srcconnect (GstPad  *pad,
          v4lmjpegsrc->quality))
       return GST_PAD_LINK_REFUSED;
   }
+#endif
+
   /* we now have an actual width/height - *set it* */
   caps = gst_caps_new("v4lmjpegsrc_caps",
                       "video/jpeg",
@@ -520,6 +587,30 @@ gst_v4lmjpegsrc_get (GstPad *pad)
 }
 
 
+static GstCaps*
+gst_v4lmjpegsrc_getcaps (GstPad  *pad,
+                         GstCaps *_caps)
+{
+  GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC(gst_pad_get_parent(pad));
+  struct video_capability *vcap = &GST_V4LELEMENT(v4lmjpegsrc)->vcap;
+  GstCaps *caps;
+
+  if (!GST_V4L_IS_OPEN(GST_V4LELEMENT(v4lmjpegsrc))) {
+    return NULL;
+  }
+
+  caps = GST_CAPS_NEW("v4lmjpegsrc_jpeg_caps",
+                      "video/jpeg",
+                        "width",  GST_PROPS_INT_RANGE(vcap->maxwidth/4,
+                                                      vcap->maxwidth),
+                        "height", GST_PROPS_INT_RANGE(vcap->maxheight/4,
+                                                      vcap->maxheight),
+                        NULL);
+
+  return caps;
+}
+
+
 static void
 gst_v4lmjpegsrc_set_property (GObject      *object,
                               guint        prop_id,
@@ -532,6 +623,7 @@ gst_v4lmjpegsrc_set_property (GObject      *object,
   v4lmjpegsrc = GST_V4LMJPEGSRC(object);
 
   switch (prop_id) {
+#if 0
     case ARG_X_OFFSET:
       v4lmjpegsrc->x_offset = g_value_get_int(value);
       break;
@@ -544,21 +636,13 @@ gst_v4lmjpegsrc_set_property (GObject      *object,
     case ARG_F_HEIGHT:
       v4lmjpegsrc->frame_height = g_value_get_int(value);
       break;
-    case ARG_H_DECIMATION:
-      v4lmjpegsrc->horizontal_decimation = g_value_get_int(value);
-      break;
-    case ARG_V_DECIMATION:
-      v4lmjpegsrc->vertical_decimation = g_value_get_int(value);
-      break;
+#endif
     case ARG_QUALITY:
       v4lmjpegsrc->quality = g_value_get_int(value);
       break;
     case ARG_NUMBUFS:
       v4lmjpegsrc->numbufs = g_value_get_int(value);
       break;
-    case ARG_BUFSIZE:
-      v4lmjpegsrc->bufsize = g_value_get_int(value);
-      break;
     case ARG_USE_FIXED_FPS:
       if (!GST_V4L_IS_ACTIVE(GST_V4LELEMENT(v4lmjpegsrc))) {
         v4lmjpegsrc->use_fixed_fps = g_value_get_boolean(value);
@@ -583,12 +667,7 @@ gst_v4lmjpegsrc_get_property (GObject    *object,
   v4lmjpegsrc = GST_V4LMJPEGSRC(object);
 
   switch (prop_id) {
-    case ARG_WIDTH:
-      g_value_set_int(value, v4lmjpegsrc->end_width);
-      break;
-    case ARG_HEIGHT:
-      g_value_set_int(value, v4lmjpegsrc->end_height);
-      break;
+#if 0
     case ARG_X_OFFSET:
       g_value_set_int(value, v4lmjpegsrc->x_offset);
       break;
@@ -601,21 +680,13 @@ gst_v4lmjpegsrc_get_property (GObject    *object,
     case ARG_F_HEIGHT:
       g_value_set_int(value, v4lmjpegsrc->frame_height);
       break;
-    case ARG_H_DECIMATION:
-      g_value_set_int(value, v4lmjpegsrc->horizontal_decimation);
-      break;
-    case ARG_V_DECIMATION:
-      g_value_set_int(value, v4lmjpegsrc->vertical_decimation);
-      break;
+#endif
     case ARG_QUALITY:
       g_value_set_int(value, v4lmjpegsrc->quality);
       break;
     case ARG_NUMBUFS:
       g_value_set_int(value, v4lmjpegsrc->breq.count);
       break;
-    case ARG_BUFSIZE:
-      g_value_set_int(value, v4lmjpegsrc->breq.size);
-      break;
     case ARG_USE_FIXED_FPS:
       g_value_set_boolean(value, v4lmjpegsrc->use_fixed_fps);
       break;
index fea2a56..ccac3c5 100644 (file)
@@ -74,20 +74,19 @@ struct _GstV4lMjpegSrc {
   /* how are we going to push buffers? */
   gboolean use_fixed_fps;
 
+  /* end size */
+  gint end_width, end_height;
+
   /* caching values */
+#if 0
   gint x_offset;
   gint y_offset;
   gint frame_width;
   gint frame_height;
-  gint horizontal_decimation;
-  gint vertical_decimation;
-
-  gint end_width;
-  gint end_height;
+#endif
 
   gint quality;
   gint numbufs;
-  gint bufsize; /* in KB */
 };
 
 struct _GstV4lMjpegSrcClass {
index c42b482..898e87f 100644 (file)
@@ -48,10 +48,6 @@ enum {
 /* arguments */
 enum {
   ARG_0,
-  ARG_WIDTH,
-  ARG_HEIGHT,
-  ARG_PALETTE,
-  ARG_PALETTE_NAME,
   ARG_NUMBUFS,
   ARG_BUFSIZE,
   ARG_USE_FIXED_FPS
@@ -70,6 +66,8 @@ static gboolean              gst_v4lsrc_srcconvert   (GstPad         *pad,
                                                       gint64         *dest_value);
 static GstPadLinkReturn      gst_v4lsrc_srcconnect   (GstPad         *pad,
                                                       GstCaps        *caps);
+static GstCaps*                     gst_v4lsrc_getcaps      (GstPad         *pad,
+                                                      GstCaps        *caps);
 static GstBuffer*            gst_v4lsrc_get          (GstPad         *pad);
 
 /* get/set params */
@@ -98,11 +96,9 @@ static void                  gst_v4lsrc_buffer_free  (GstBufferPool  *pool,
 static void                  gst_v4lsrc_set_clock    (GstElement     *element,
                                                       GstClock       *clock);
 
+static GstPadTemplate *src_template = NULL;
 
-static GstCaps *capslist = NULL;
-static GstPadTemplate *src_template;
-
-static GstElementClass *parent_class = NULL;\
+static GstElementClass *parent_class = NULL;
 static guint gst_v4lsrc_signals[LAST_SIGNAL] = { 0 };
 
 
@@ -141,19 +137,6 @@ gst_v4lsrc_class_init (GstV4lSrcClass *klass)
 
   parent_class = g_type_class_ref(GST_TYPE_V4LELEMENT);
 
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_WIDTH,
-    g_param_spec_int("width", "Width", "Video width",
-                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_HEIGHT,
-    g_param_spec_int("height", "Height", "Video height",
-                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PALETTE,
-    g_param_spec_int("palette", "Palette", "Video palette",
-                     G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
-  g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PALETTE_NAME,
-    g_param_spec_string("palette_name", "Palette name",
-                        "Name of the current video palette",
-                        NULL, G_PARAM_READABLE));
   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NUMBUFS,
     g_param_spec_int("num_buffers","Num Buffers","Number of buffers",
                      G_MININT,G_MAXINT,0,G_PARAM_READABLE));
@@ -199,6 +182,7 @@ gst_v4lsrc_init (GstV4lSrc *v4lsrc)
   gst_element_add_pad(GST_ELEMENT(v4lsrc), v4lsrc->srcpad);
 
   gst_pad_set_get_function (v4lsrc->srcpad, gst_v4lsrc_get);
+  gst_pad_set_getcaps_function (v4lsrc->srcpad, gst_v4lsrc_getcaps);
   gst_pad_set_link_function (v4lsrc->srcpad, gst_v4lsrc_srcconnect);
   gst_pad_set_convert_function (v4lsrc->srcpad, gst_v4lsrc_srcconvert);
 
@@ -210,9 +194,6 @@ gst_v4lsrc_init (GstV4lSrc *v4lsrc)
                  (GstBufferPoolBufferFreeFunction)gst_v4lsrc_buffer_free,
                  v4lsrc);
 
-  v4lsrc->palette = 0; /* means 'any' - user can specify a specific palette */
-  v4lsrc->width = 160;
-  v4lsrc->height = 120;
   v4lsrc->buffer_size = 0;
 
   /* no clock */
@@ -303,6 +284,108 @@ gst_v4lsrc_srcconvert (GstPad    *pad,
   return TRUE;
 }
 
+static GstCaps *
+gst_v4lsrc_palette_to_caps (int            palette,
+                            GstPropsEntry *width,
+                            GstPropsEntry *height)
+{
+  guint32 fourcc;
+  GstCaps *caps;
+
+  switch (palette) {
+    case VIDEO_PALETTE_YUV422:
+    case VIDEO_PALETTE_YUYV:
+      fourcc = GST_MAKE_FOURCC('Y','U','Y','2');
+      break;
+    case VIDEO_PALETTE_YUV420P:
+      fourcc = GST_MAKE_FOURCC('I','4','2','0');
+      break;
+    case VIDEO_PALETTE_UYVY:
+      fourcc = GST_MAKE_FOURCC('U','Y','V','Y');
+      break;
+    case VIDEO_PALETTE_YUV411:
+      fourcc = GST_MAKE_FOURCC('Y','4','1','P');
+      break;
+    case VIDEO_PALETTE_RGB555:
+    case VIDEO_PALETTE_RGB565:
+    case VIDEO_PALETTE_RGB24:
+    case VIDEO_PALETTE_RGB32:
+      fourcc = GST_MAKE_FOURCC('R','G','B',' ');
+      break;
+    default:
+      return NULL;
+  }
+
+  if (fourcc == GST_MAKE_FOURCC('R','G','B',' ')) {
+    gint depth = 0;
+    guint32 r_mask = 0, g_mask = 0, b_mask = 0;
+
+    switch (palette) {
+      case VIDEO_PALETTE_RGB555:
+        depth = 15;
+        r_mask = 0x7c00; g_mask = 0x03e0; b_mask = 0x001f;
+        break;
+      case VIDEO_PALETTE_RGB565:
+        depth = 16;
+        r_mask = 0xf800; g_mask = 0x07f0; b_mask = 0x001f;
+        break;
+      case VIDEO_PALETTE_RGB24:
+        depth = 24;
+        r_mask = 0xff0000; g_mask = 0x00ff00; b_mask = 0x0000ff;
+        break;
+      case VIDEO_PALETTE_RGB32:
+        depth = 32;
+        r_mask = 0x00ff0000; g_mask = 0x0000ff00; b_mask = 0x000000ff;
+        break;
+      default:
+        g_assert_not_reached();
+        break;
+    }
+
+    caps = GST_CAPS_NEW("v4lsrc_rgb_caps",
+                        "video/raw",
+                          "format",     GST_PROPS_FOURCC(fourcc),
+                          "bpp",        GST_PROPS_INT((depth+1) & ~1),
+                          "depth",      GST_PROPS_INT(depth),
+                          "endianness", GST_PROPS_INT(G_BYTE_ORDER),
+                          "red_mask",   GST_PROPS_INT(r_mask),
+                          "green_mask", GST_PROPS_INT(g_mask),
+                          "blue_mask",  GST_PROPS_INT(b_mask),
+                          NULL);
+  } else {
+    caps = GST_CAPS_NEW("v4lsrc_yuv_caps",
+                        "video/raw",
+                          "format",     GST_PROPS_FOURCC(fourcc),
+                          NULL);
+  }
+
+  gst_props_add_entry(caps->properties, width);
+  gst_props_add_entry(caps->properties, height);
+
+  return caps;
+}
+
+#define gst_v4lsrc_palette_to_caps_fixed(palette, width, height) \
+  gst_v4lsrc_palette_to_caps(palette, \
+                             gst_props_entry_new("width", \
+                                                 GST_PROPS_INT(width)), \
+                             gst_props_entry_new("height", \
+                                                 GST_PROPS_INT(height)) \
+                            )
+#define gst_v4lsrc_palette_to_caps_range(palette, min_w, max_w, min_h, max_h) \
+  gst_v4lsrc_palette_to_caps(palette, \
+                             gst_props_entry_new("width", \
+                                                 GST_PROPS_INT_RANGE(min_w, \
+                                                                     max_w)), \
+                             gst_props_entry_new("height", \
+                                                 GST_PROPS_INT_RANGE(min_h, \
+                                                                     max_h)) \
+                            )
+
+#define gst_caps_get_int_range(caps, name, min, max) \
+  gst_props_entry_get_int_range(gst_props_get_entry((caps)->properties, \
+                                                    name), \
+                                min, max)
 
 static GstPadLinkReturn
 gst_v4lsrc_srcconnect (GstPad  *pad,
@@ -327,123 +410,76 @@ gst_v4lsrc_srcconnect (GstPad  *pad,
     return GST_PAD_LINK_DELAYED;
   }
 
-  palette = v4lsrc->palette;
-
   /* TODO: caps = gst_caps_normalize(capslist); */
   for (caps = vscapslist ; caps != NULL ; caps = vscapslist = vscapslist->next)
   {
     guint32 fourcc;
-    gint depth;
+    gint depth, w, h;
 
     gst_caps_get_fourcc_int (caps, "format", &fourcc);
-
-    if (v4lsrc->palette > 0)
-    {
-      switch (v4lsrc->palette)
-      {
-        case VIDEO_PALETTE_YUV420P:
-          if (fourcc != GST_MAKE_FOURCC('I','4','2','0') &&
-              fourcc != GST_MAKE_FOURCC('I','Y','U','V'))
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
-          goto try_caps;
-        case VIDEO_PALETTE_YUV422:
-        case VIDEO_PALETTE_YUYV:
-          if (fourcc != GST_MAKE_FOURCC('Y','U','Y','2'))
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          goto try_caps;
-        case VIDEO_PALETTE_UYVY:
-          if (fourcc != GST_MAKE_FOURCC('U','Y','V','Y'))
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          goto try_caps;
-        case VIDEO_PALETTE_YUV411:
-          if (fourcc != GST_MAKE_FOURCC('Y','4','1','P'))
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
-          goto try_caps;
-        case VIDEO_PALETTE_RGB555:
-         depth = gst_caps_get_int (caps, "depth", &depth);
-          if (fourcc != GST_MAKE_FOURCC('R','G','B',' ') ||
-              depth != 15)
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          goto try_caps;
-        case VIDEO_PALETTE_RGB565:
-         depth = gst_caps_get_int (caps, "depth", &depth);
-          if (fourcc != GST_MAKE_FOURCC('R','G','B',' ') ||
-              depth != 16)
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          goto try_caps;
-        case VIDEO_PALETTE_RGB24:
-         depth = gst_caps_get_int (caps, "depth", &depth);
-          if (fourcc != GST_MAKE_FOURCC('R','G','B',' ') ||
-              depth != 24)
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 3;
-          goto try_caps;
-        case VIDEO_PALETTE_RGB32:
-         depth = gst_caps_get_int (caps, "depth", &depth);
-          if (fourcc != GST_MAKE_FOURCC('R','G','B',' ') ||
-              depth != 32)
-            goto try_next;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 4;
-          goto try_caps;
-        default:
-          goto try_next;
+    if (gst_caps_has_property(caps, "width")) {
+      if (gst_caps_has_fixed_property(caps, "width")) {
+        gst_caps_get_int(caps, "width", &w);
+      } else {
+        int max;
+        gst_caps_get_int_range(caps, "width", &w, &max);
       }
     }
-    else
-    {
-      switch (fourcc)
-      {
-        case GST_MAKE_FOURCC('I','4','2','0'):
-        case GST_MAKE_FOURCC('I','Y','U','V'):
-          palette = VIDEO_PALETTE_YUV420P;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
-          goto try_caps;
-        case GST_MAKE_FOURCC('Y','U','Y','2'):
-          palette = VIDEO_PALETTE_YUV422;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          goto try_caps;
-        case GST_MAKE_FOURCC('U','Y','V','Y'):
-          palette = VIDEO_PALETTE_UYVY;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-          goto try_caps;
-        case GST_MAKE_FOURCC('Y','4','1','P'):
-          palette = VIDEO_PALETTE_YUV411;
-         v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 1.5;
-          goto try_caps;
-        case GST_MAKE_FOURCC('R','G','B',' '):
-         depth = gst_caps_get_int (caps, "depth", &depth);
-          switch (depth)
-          {
-            case 15:
-              palette = VIDEO_PALETTE_RGB555;
-             v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-              goto try_caps;
-            case 16:
-              palette = VIDEO_PALETTE_RGB565;
-             v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 2;
-              goto try_caps;
-            case 24:
-              palette = VIDEO_PALETTE_RGB24;
-             v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 3;
-              goto try_caps;
-            case 32:
-              palette = VIDEO_PALETTE_RGB32;
-             v4lsrc->buffer_size = v4lsrc->width * v4lsrc->height * 4;
-              goto try_caps;
-            default:
-              goto try_next;
-          }
-        default:
-          goto try_next;
+    if (gst_caps_has_property(caps, "height")) {
+      if (gst_caps_has_fixed_property(caps, "height")) {
+        gst_caps_get_int(caps, "height", &h);
+      } else {
+        int max;
+        gst_caps_get_int_range(caps, "height", &h, &max);
       }
     }
 
+    switch (fourcc)
+    {
+      case GST_MAKE_FOURCC('I','4','2','0'):
+      case GST_MAKE_FOURCC('I','Y','U','V'):
+        palette = VIDEO_PALETTE_YUV420P;
+        v4lsrc->buffer_size = ((w+1)&~1) * ((h+1)&~1) * 1.5;
+        goto try_caps;
+      case GST_MAKE_FOURCC('Y','U','Y','2'):
+        palette = VIDEO_PALETTE_YUV422;
+        v4lsrc->buffer_size = ((w+1)&~1) * h * 2;
+        goto try_caps;
+      case GST_MAKE_FOURCC('U','Y','V','Y'):
+        palette = VIDEO_PALETTE_UYVY;
+        v4lsrc->buffer_size = ((w+1)&~1) * h * 2;
+        goto try_caps;
+      case GST_MAKE_FOURCC('Y','4','1','P'):
+        palette = VIDEO_PALETTE_YUV411;
+        v4lsrc->buffer_size = ((w+3)&~3) * h * 1.5;
+        goto try_caps;
+      case GST_MAKE_FOURCC('R','G','B',' '):
+        depth = gst_caps_get_int (caps, "depth", &depth);
+        switch (depth)
+        {
+          case 15:
+            palette = VIDEO_PALETTE_RGB555;
+            v4lsrc->buffer_size = w * h * 2;
+            goto try_caps;
+          case 16:
+            palette = VIDEO_PALETTE_RGB565;
+            v4lsrc->buffer_size = w * h * 2;
+            goto try_caps;
+          case 24:
+            palette = VIDEO_PALETTE_RGB24;
+            v4lsrc->buffer_size = w * h * 3;
+            goto try_caps;
+          case 32:
+            palette = VIDEO_PALETTE_RGB32;
+            v4lsrc->buffer_size = w * h * 4;
+            goto try_caps;
+          default:
+            goto try_next;
+        }
+      default:
+        goto try_next;
+    }
+
   /* if this caps wasn't useful, try the next one */
   try_next:
     continue;
@@ -455,32 +491,7 @@ gst_v4lsrc_srcconnect (GstPad  *pad,
       continue;
 
     /* try to connect the pad/caps with the actual width/height */
-    if (palette >= VIDEO_PALETTE_RGB565 && palette <= VIDEO_PALETTE_RGB555) {
-       gint depth;
-       gint bpp;
-
-       gst_caps_get_int(caps, "bpp", &bpp),
-       gst_caps_get_int(caps, "depth", &depth),
-
-       newcaps = gst_caps_new("v4lsrc_caps",
-                              "video/raw",
-                              gst_props_new(
-                                 "format", GST_PROPS_FOURCC(fourcc),
-                                 "width",  GST_PROPS_INT(v4lsrc->width),
-                                 "height", GST_PROPS_INT(v4lsrc->height),
-                                 "bpp",    GST_PROPS_INT(bpp),
-                                 "depth",  GST_PROPS_INT(depth),
-                                 NULL      ) );
-    }
-    else {
-       newcaps = gst_caps_new("v4lsrc_caps",
-                              "video/raw",
-                              gst_props_new(
-                                 "format", GST_PROPS_FOURCC(fourcc),
-                                 "width",  GST_PROPS_INT(v4lsrc->width),
-                                 "height", GST_PROPS_INT(v4lsrc->height),
-                                 NULL      ) );
-    }
+    newcaps = gst_v4lsrc_palette_to_caps_fixed(palette, w, h);
 
     gst_caps_debug (newcaps, "new caps to set on v4lsrc's src pad");
 
@@ -489,7 +500,7 @@ gst_v4lsrc_srcconnect (GstPad  *pad,
     else if (ret_val == GST_PAD_LINK_DELAYED)
       return GST_PAD_LINK_DELAYED;
 
-    if (!gst_v4lsrc_set_capture(v4lsrc, v4lsrc->width, v4lsrc->height, palette))
+    if (!gst_v4lsrc_set_capture(v4lsrc, w, h, palette))
       return GST_PAD_LINK_REFUSED;
 
     if (!gst_v4lsrc_capture_init(v4lsrc))
@@ -503,6 +514,40 @@ gst_v4lsrc_srcconnect (GstPad  *pad,
 }
 
 
+static GstCaps *
+gst_v4lsrc_getcaps (GstPad  *pad,
+                    GstCaps *caps)
+{
+  GstCaps *list = NULL;
+  GstV4lSrc *v4lsrc = GST_V4LSRC(gst_pad_get_parent(pad));
+  int palette[] = {
+    VIDEO_PALETTE_YUV422,
+    VIDEO_PALETTE_YUV420P,
+    VIDEO_PALETTE_UYVY,
+    VIDEO_PALETTE_YUV411P,
+    VIDEO_PALETTE_RGB555,
+    VIDEO_PALETTE_RGB565,
+    VIDEO_PALETTE_RGB24,
+    VIDEO_PALETTE_RGB32,
+  }, i;
+  struct video_capability *vcap = &GST_V4LELEMENT(v4lsrc)->vcap;
+
+  if (!GST_V4L_IS_OPEN(GST_V4LELEMENT(v4lsrc))) {
+    return NULL;
+  }
+
+  for (i = 0; i < 8; i++) {
+    GstCaps *one;
+    one = gst_v4lsrc_palette_to_caps_range(palette[i],
+                                           vcap->minwidth,  vcap->maxwidth,
+                                           vcap->minheight, vcap->maxheight);
+    list = gst_caps_append(list, one);
+  }
+
+  return list;
+}
+
+
 static GstBuffer*
 gst_v4lsrc_get (GstPad *pad)
 {
@@ -611,18 +656,6 @@ gst_v4lsrc_set_property (GObject      *object,
   v4lsrc = GST_V4LSRC(object);
 
   switch (prop_id) {
-    case ARG_WIDTH:
-      v4lsrc->width = g_value_get_int(value);
-      break;
-
-    case ARG_HEIGHT:
-      v4lsrc->height = g_value_get_int(value);
-      break;
-
-    case ARG_PALETTE:
-      v4lsrc->palette = g_value_get_int(value);
-      break;
-
     case ARG_USE_FIXED_FPS:
       if (!GST_V4L_IS_ACTIVE(GST_V4LELEMENT(v4lsrc))) {
         v4lsrc->use_fixed_fps = g_value_get_boolean(value);
@@ -648,22 +681,6 @@ gst_v4lsrc_get_property (GObject    *object,
   v4lsrc = GST_V4LSRC(object);
 
   switch (prop_id) {
-    case ARG_WIDTH:
-      g_value_set_int(value, v4lsrc->mmap.width);
-      break;
-
-    case ARG_HEIGHT:
-      g_value_set_int(value, v4lsrc->mmap.height);
-      break;
-
-    case ARG_PALETTE:
-      g_value_set_int(value, v4lsrc->mmap.format);
-      break;
-
-    case ARG_PALETTE_NAME:
-      g_value_set_string(value, g_strdup(palette_name[v4lsrc->mmap.format]));
-      break;
-
     case ARG_NUMBUFS:
       g_value_set_int(value, v4lsrc->mbuf.frames);
       break;
@@ -804,57 +821,17 @@ plugin_init (GModule   *module,
              GstPlugin *plugin)
 {
   GstElementFactory *factory;
-  GstCaps *caps;
-  gint i;
-  gulong format[5] = { GST_MAKE_FOURCC('Y','U','Y','2'), /* VIDEO_PALETTE_YUV422/_YUYV */
-                       GST_MAKE_FOURCC('I','4','2','0'), /* VIDEO_PALETTE_YUV420P */
-                       GST_MAKE_FOURCC('I','Y','U','V'), /* VIDEO_PALETTE_YUV420P */
-                       GST_MAKE_FOURCC('U','Y','V','Y'), /* VIDEO_PALETTE_UYVY */
-                       GST_MAKE_FOURCC('Y','4','1','P')  /* VIDEO_PALETTE_YUV411 */
-                     };
-  gint rgb_bpp[4] = { 16, 16, 24, 32 };
-  gint rgb_depth[4] = { 15, 16, 24, 32 };
 
   /* create an elementfactory for the v4lsrc */
   factory = gst_element_factory_new("v4lsrc",GST_TYPE_V4LSRC,
                                    &gst_v4lsrc_details);
   g_return_val_if_fail(factory != NULL, FALSE);
 
-  /* make a list of all available caps - first the YUV formats */
-  for (i=0;i<5;i++)
-  {
-    caps = gst_caps_new ("v4lsrc_caps",
-                         "video/raw",
-                         gst_props_new (
-                            "format", GST_PROPS_FOURCC(format[i]),
-                            "width",  GST_PROPS_INT_RANGE (0, G_MAXINT),
-                            "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
-                            NULL       )
-                        );
-    capslist = gst_caps_append(capslist, caps);
-  }
-
-  /* now all the RGB formats */
-  for (i=0;i<4;i++)
-  {
-    caps = gst_caps_new ("v4lsrc_caps",
-                         "video/raw",
-                         gst_props_new (
-                            "format", GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
-                            "width",  GST_PROPS_INT_RANGE (0, G_MAXINT),
-                            "height", GST_PROPS_INT_RANGE (0, G_MAXINT),
-                            "bpp",    GST_PROPS_INT(rgb_bpp[i]),
-                            "depth",  GST_PROPS_INT(rgb_depth[i]),
-                            NULL       )
-                        );
-    capslist = gst_caps_append(capslist, caps);
-  }
-
   src_template = gst_pad_template_new (
                  "src",
                   GST_PAD_SRC,
                  GST_PAD_ALWAYS,
-                 capslist, NULL);
+                 NULL);
 
   gst_element_factory_add_pad_template (factory, src_template);
 
index 6a7d299..9c2070a 100644 (file)
@@ -85,11 +85,6 @@ struct _GstV4lSrc {
 
   /* how are we going to push buffers? */
   gboolean use_fixed_fps;
-
-  /* caching values */
-  gint width;
-  gint height;
-  gint palette;
 };
 
 struct _GstV4lSrcClass {