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/v4l2/gstv4l2src.c
sys/v4l2/gstv4l2src.h
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index c3b52dc..92ca209 100644 (file)
@@ -44,10 +44,6 @@ enum {
 /* arguments */
 enum {
        ARG_0,
-       ARG_WIDTH,
-       ARG_HEIGHT,
-       ARG_PALETTE,
-       ARG_PALETTE_NAMES,
        ARG_NUMBUFS,
        ARG_BUFSIZE,
        ARG_USE_FIXED_FPS
@@ -148,20 +144,6 @@ gst_v4l2src_class_init (GstV4l2SrcClass *klass)
 
        parent_class = g_type_class_ref(GST_TYPE_V4L2ELEMENT);
 
-       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_READWRITE));
-       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_READWRITE));
-
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PALETTE,
-               g_param_spec_int("palette","palette","palette",
-                                G_MININT,G_MAXINT,0,G_PARAM_READWRITE));
-       g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PALETTE_NAMES,
-               g_param_spec_pointer("palette_name","palette_name","palette_name",
-                                    G_PARAM_READABLE));
-
        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));
@@ -227,9 +209,6 @@ gst_v4l2src_init (GstV4l2Src *v4l2src)
                                        gst_v4l2src_buffer_free,
                                        v4l2src);
 
-       v4l2src->palette = 0; /* means 'any' - user can specify a specific palette */
-       v4l2src->width = 160;
-       v4l2src->height = 120;
        v4l2src->breq.count = 0;
 
        v4l2src->formats = NULL;
@@ -341,302 +320,296 @@ gst_v4l2src_srcconvert (GstPad    *pad,
 
 
 static GstCaps *
-gst_v4l2src_v4l2fourcc_to_caps (guint32  fourcc,
-                                gint     width,
-                                gint     height,
-                                gboolean compressed)
+gst_v4l2src_v4l2fourcc_to_caps (guint32        fourcc,
+                                GstPropsEntry *width,
+                                GstPropsEntry *height,
+                               gboolean       compressed)
 {
-       GstCaps *capslist = NULL, *caps;
+       GstCaps *caps = NULL;
 
        switch (fourcc) {
-               case V4L2_PIX_FMT_MJPEG: /* v4l2_fourcc('M','J','P','G') */
-                       caps = gst_caps_new("v4l2src_caps",
-                                       "video/jpeg",
-                                       gst_props_new(
-                                               "width",        GST_PROPS_INT(width),
-                                               "height",       GST_PROPS_INT(height),
-                                               NULL));
-                       capslist = gst_caps_append(capslist, caps);
+       case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */
+       case V4L2_PIX_FMT_JPEG:  /* JFIF JPEG */
+               caps = GST_CAPS_NEW("v4l2src_caps",
+                                   "video/jpeg",
+                                     NULL);
                        break;
+       case V4L2_PIX_FMT_RGB332:
+       case V4L2_PIX_FMT_RGB555:
+       case V4L2_PIX_FMT_RGB555X:
+       case V4L2_PIX_FMT_RGB565:
+       case V4L2_PIX_FMT_RGB565X:
+       case V4L2_PIX_FMT_RGB24:
+       case V4L2_PIX_FMT_BGR24:
+       case V4L2_PIX_FMT_RGB32:
+       case V4L2_PIX_FMT_BGR32: {
+               guint depth=0, bpp=0;
+               gint endianness = 0;
+               guint32 r_mask = 0, b_mask = 0, g_mask = 0;
+               guint32 fcc = GST_MAKE_FOURCC('R','G','B',' ');
+
+               switch (fourcc) {
                case V4L2_PIX_FMT_RGB332:
+                       bpp = depth = 8;
+                       endianness = G_BYTE_ORDER; /* 'like, whatever' */
+                       r_mask = 0xe0; g_mask = 0x1c; b_mask = 0x03;
+                       break;
                case V4L2_PIX_FMT_RGB555:
                case V4L2_PIX_FMT_RGB555X:
+                       bpp = 16; depth = 15;
+                       endianness = (fourcc == V4L2_PIX_FMT_RGB332) ?
+                                    G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+                       r_mask = 0x7c00; g_mask = 0x03e0; b_mask = 0x001f;
+                       break;
                case V4L2_PIX_FMT_RGB565:
                case V4L2_PIX_FMT_RGB565X:
+                       bpp = depth = 16;
+                       endianness = (fourcc == V4L2_PIX_FMT_RGB565) ?
+                                    G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+                       r_mask = 0xf800; g_mask = 0x07e0; b_mask = 0x001f;
+                       break;
                case V4L2_PIX_FMT_RGB24:
                case V4L2_PIX_FMT_BGR24:
+                       bpp = depth = 24;
+                       endianness = (fourcc == V4L2_PIX_FMT_BGR24) ?
+                                    G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+                       r_mask = 0xff0000; g_mask = 0x00ff00; b_mask = 0x0000ff;
+                       break;
                case V4L2_PIX_FMT_RGB32:
-               case V4L2_PIX_FMT_BGR32: {
-                       guint depth=0, bpp=0;
-                       gint endianness=0;
-                       gulong r_mask=0, b_mask=0, g_mask=0;
-                       switch (fourcc) {
-                               case V4L2_PIX_FMT_RGB332:
-                                       bpp = depth = 8;
-                                       endianness = G_BYTE_ORDER; /* 'like, whatever' */
-                                       r_mask = 0xe0; g_mask = 0x1c; b_mask = 0x03;
-                                       break;
-                               case V4L2_PIX_FMT_RGB555:
-                                       bpp = 16; depth = 15;
-                                       endianness = G_LITTLE_ENDIAN;
-                                       r_mask = 0x7c00; g_mask = 0x03e0; b_mask = 0x001f;
-                                       break;
-                               case V4L2_PIX_FMT_RGB555X:
-                                       bpp = 16; depth = 15;
-                                       endianness = G_BIG_ENDIAN;
-                                       r_mask = 0x7c00; g_mask = 0x03e0; b_mask = 0x001f;
-                                       break;
-                               case V4L2_PIX_FMT_RGB565:
-                                       bpp = depth = 16;
-                                       endianness = G_LITTLE_ENDIAN;
-                                       r_mask = 0xf800; g_mask = 0x07e0; b_mask = 0x001f;
-                                       break;
-                               case V4L2_PIX_FMT_RGB565X:
-                                       bpp = depth = 16;
-                                       endianness = G_BIG_ENDIAN;
-                                       r_mask = 0xf800; g_mask = 0x07e0; b_mask = 0x001f;
-                                       break;
-                               case V4L2_PIX_FMT_RGB24:
-                                       bpp = depth = 24;
-                                       endianness = G_BIG_ENDIAN;
-                                       r_mask = 0xff0000; g_mask = 0x00ff00; b_mask = 0x0000ff;
-                                       break;
-                               case V4L2_PIX_FMT_BGR24:
-                                       bpp = depth = 24;
-                                       endianness = G_LITTLE_ENDIAN;
-                                       r_mask = 0xff0000; g_mask = 0x00ff00; b_mask = 0x0000ff;
-                                       break;
-                               case V4L2_PIX_FMT_RGB32:
-                                       bpp = depth = 32;
-                                       endianness = G_BIG_ENDIAN;
-                                       r_mask = 0x00ff0000; g_mask = 0x0000ff00; b_mask = 0x000000ff;
-                                       break;
-                               case V4L2_PIX_FMT_BGR32:
-                                       endianness = G_LITTLE_ENDIAN;
-                                       bpp = depth = 32;
-                                       r_mask = 0x00ff0000; g_mask = 0x0000ff00; b_mask = 0x000000ff;
-                                       break;
-                       }
-                       caps = gst_caps_new("v4l2src_caps",
-                                       "video/raw",
-                                       gst_props_new(
-                                               "format",       GST_PROPS_FOURCC(GST_MAKE_FOURCC('R','G','B',' ')),
-                                               "width",        GST_PROPS_INT(width),
-                                               "height",       GST_PROPS_INT(height),
-                                               "bpp",          GST_PROPS_INT(bpp),
-                                               "depth",        GST_PROPS_INT(depth),
-                                               "red_mask",     GST_PROPS_INT(r_mask),
-                                               "green_mask",   GST_PROPS_INT(g_mask),
-                                               "blue_mask",    GST_PROPS_INT(b_mask),
-                                               "endianness",   GST_PROPS_INT(endianness),
-                                               NULL));
-                       capslist = gst_caps_append(capslist, caps);
-                       break; }
-               case V4L2_PIX_FMT_YUV420: /* I420/IYUV */
-                       caps = gst_caps_new("v4l2src_caps",
-                               "video/raw",
-                               gst_props_new(
-                                       "format",       GST_PROPS_FOURCC(GST_MAKE_FOURCC('I','4','2','0')),
-                                       "width",        GST_PROPS_INT(width),
-                                       "height",       GST_PROPS_INT(height),
-                                       NULL));
-                       capslist = gst_caps_append(capslist, caps);
-                       caps = gst_caps_new("v4l2src_caps",
-                               "video/raw",
-                               gst_props_new(
-                                       "format",       GST_PROPS_FOURCC(GST_MAKE_FOURCC('I','Y','U','V')),
-                                       "width",        GST_PROPS_INT(width),
-                                       "height",       GST_PROPS_INT(height),
-                                       NULL));
-                       capslist = gst_caps_append(capslist, caps);
+               case V4L2_PIX_FMT_BGR32:
+                       bpp = depth = 32;
+                       endianness = (fourcc == V4L2_PIX_FMT_BGR32) ?
+                                    G_LITTLE_ENDIAN : G_BIG_ENDIAN;
+                       r_mask = 0x00ff0000; g_mask = 0x0000ff00; b_mask = 0x000000ff;
+                       break;
+               default:
+                       g_assert_not_reached();
+                       break;
+               }
+
+               caps = GST_CAPS_NEW("v4l2src_caps",
+                                   "video/raw",
+                                     "format",     GST_PROPS_FOURCC(fcc),
+                                     "bpp",        GST_PROPS_INT(bpp),
+                                     "depth",      GST_PROPS_INT(depth),
+                                     "red_mask",   GST_PROPS_INT(r_mask),
+                                     "green_mask", GST_PROPS_INT(g_mask),
+                                     "blue_mask",  GST_PROPS_INT(b_mask),
+                                     "endianness", GST_PROPS_INT(endianness),
+                                     NULL);
+               break;
+       }
+       case V4L2_PIX_FMT_YUV420: /* I420/IYUV */
+       case V4L2_PIX_FMT_YUYV:
+       case V4L2_PIX_FMT_YVU420:
+       case V4L2_PIX_FMT_UYVY:
+       case V4L2_PIX_FMT_Y41P: {
+               guint32 fcc = 0;
+
+               switch (fourcc) {
+               case V4L2_PIX_FMT_YUV420:
+                       fcc = GST_MAKE_FOURCC('I','4','2','0');
                        break;
                case V4L2_PIX_FMT_YUYV:
-                       caps = gst_caps_new("v4l2src_caps",
-                               "video/raw",
-                               gst_props_new(
-                                       "format",       GST_PROPS_FOURCC(GST_MAKE_FOURCC('Y','U','Y','2')),
-                                       "width",        GST_PROPS_INT(width),
-                                       "height",       GST_PROPS_INT(height),
-                                       NULL));
-                       capslist = gst_caps_append(capslist, caps);
+                       fcc = GST_MAKE_FOURCC('Y','U','Y','2');
+                       break;
+               case V4L2_PIX_FMT_YVU420:
+                       fcc = GST_MAKE_FOURCC('Y','V','1','2');
+                       break;
+               case V4L2_PIX_FMT_UYVY:
+                       fcc = GST_MAKE_FOURCC('U','Y','V','Y');
+                       break;
+               case V4L2_PIX_FMT_Y41P:
+                       fcc = GST_MAKE_FOURCC('Y','4','1','P');
                        break;
                default:
+                       g_assert_not_reached();
                        break;
+               }
+
+               caps = GST_CAPS_NEW("v4l2src_caps",
+                                   "video/raw",
+                                     "format", GST_PROPS_FOURCC(fcc),
+                                     NULL);
+               break;
        }
+       default:
+               GST_DEBUG(GST_CAT_PLUGIN_INFO,
+                         "Unknown fourcc 0x%08x " GST_FOURCC_FORMAT ", trying default",
+                         fourcc, GST_FOURCC_ARGS(fourcc));
+
+               /* add the standard one */
+               if (compressed) {
+                       guint32 print_format = GUINT32_FROM_LE(fourcc);
+                       gchar *print_format_str = (gchar *) &print_format, *string_format;
+                       gint i;
 
-       /* add the standard one */
-       if (compressed) {
-               guint32 print_format = GUINT32_FROM_LE(fourcc);
-               gchar *print_format_str = (gchar *) &print_format, *string_format;
-               gint i;
-               for (i=0;i<4;i++)
-                       print_format_str[i] = g_ascii_tolower(print_format_str[i]);
-               string_format = g_strdup_printf("video/%4.4s", print_format_str);
-               caps = gst_caps_new("v4l2src_caps",
-                               string_format,
-                               gst_props_new(
-                                       "width",        GST_PROPS_INT(width),
-                                       "height",       GST_PROPS_INT(height),
-                                       NULL));
-               capslist = gst_caps_append(capslist, caps);
-               g_free(string_format);
-       } else {
-               caps = gst_caps_new("v4l2src_caps",
-                               "video/raw",
-                               gst_props_new(
-                                       "format",       GST_PROPS_FOURCC(fourcc),
-                                       "width",        GST_PROPS_INT(width),
-                                       "height",       GST_PROPS_INT(height),
-                                       NULL));
-               capslist = gst_caps_append(capslist, caps);
+                       for (i=0;i<4;i++) {
+                               print_format_str[i] =
+                                       g_ascii_tolower(print_format_str[i]);
+                       }
+                       string_format = g_strdup_printf("video/%4.4s",
+                                                       print_format_str);
+                       caps = GST_CAPS_NEW("v4l2src_caps",
+                                           string_format,
+                                             NULL);
+                       g_free(string_format);
+               } else {
+                       caps = GST_CAPS_NEW("v4l2src_caps",
+                                           "video/raw",
+                                             "format",GST_PROPS_FOURCC(fourcc),
+                                             NULL);
+               }
+               break;
        }
 
-       return capslist;
-}
+       if (!caps->properties)
+               caps->properties = gst_props_empty_new();
+       gst_props_add_entry(caps->properties, width);
+       gst_props_add_entry(caps->properties, height);
 
+       return caps;
+}
 
-static GList *
+#define gst_v4l2src_v4l2fourcc_to_caps_fixed(f, width, height,c) \
+       gst_v4l2src_v4l2fourcc_to_caps(f, \
+                                      gst_props_entry_new("width", \
+                                                          GST_PROPS_INT(width)), \
+                                      gst_props_entry_new("height", \
+                                                          GST_PROPS_INT(height)), \
+                                      c)
+
+#define gst_v4l2src_v4l2fourcc_to_caps_range(f, min_w, max_w, min_h, max_h, c) \
+       gst_v4l2src_v4l2fourcc_to_caps(f, \
+                                      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)), \
+                                      c)
+
+static struct v4l2_fmtdesc *
 gst_v4l2_caps_to_v4l2fourcc (GstV4l2Src *v4l2src,
-                             GstCaps    *capslist)
+                             GstCaps    *caps)
 {
-       GList *fourcclist = NULL;
-       GstCaps *caps;
-       guint32 fourcc;
        gint i;
-
-       for (caps = capslist;caps != NULL; caps = caps->next) {
-               const gchar *format = gst_caps_get_mime(caps);
-
-               if (!strcmp(format, "video/raw")) {
-                       /* non-compressed */
-                       gst_caps_get_fourcc_int(caps, "format", &fourcc);
-                       switch (fourcc) {
-                               case GST_MAKE_FOURCC('I','4','2','0'):
-                               case GST_MAKE_FOURCC('I','Y','U','V'):
-                                       fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_YUV420);
-                                       break;
-                               case GST_MAKE_FOURCC('Y','U','Y','2'):
-                                       fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_YUYV);
-                                       break;
-                               case GST_MAKE_FOURCC('R','G','B',' '): {
-                                       gint depth, endianness;
-                                       gst_caps_get_int(caps, "depth", &depth);
-                                       gst_caps_get_int(caps, "endianness", &endianness);
-                                       if (depth == 8) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB332);
-                                       } else if (depth == 15 && endianness == G_LITTLE_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB555);
-                                       } else if (depth == 15 && endianness == G_BIG_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB555X);
-                                       } else if (depth == 16 && endianness == G_LITTLE_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB565);
-                                       } else if (depth == 16 && endianness == G_BIG_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB565X);
-                                       } else if (depth == 24 && endianness == G_LITTLE_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_BGR24);
-                                       } else if (depth == 24 && endianness == G_BIG_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB24);
-                                       } else if (depth == 32 && endianness == G_LITTLE_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_BGR32);
-                                       } else if (depth == 32 && endianness == G_BIG_ENDIAN) {
-                                               fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_RGB32);
-                                       }
-                                       break; }
-                       }
-
-                       for (i=0;i<g_list_length(v4l2src->formats);i++) {
-                               struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *) g_list_nth_data(v4l2src->formats, i);
-                               if (fmt->pixelformat == fourcc)
-                                       fourcclist = g_list_append(fourcclist, (gpointer)fourcc);
+       guint32 fourcc = 0;
+       struct v4l2_fmtdesc *end_fmt = NULL;
+       const gchar *format = gst_caps_get_mime(caps);
+
+       if (!strcmp(format, "video/raw")) {
+               /* non-compressed */
+               gst_caps_get_fourcc_int(caps, "format", &fourcc);
+
+               switch (fourcc) {
+               case GST_MAKE_FOURCC('I','4','2','0'):
+               case GST_MAKE_FOURCC('I','Y','U','V'):
+                       fourcc = V4L2_PIX_FMT_YUV420;
+                       break;
+               case GST_MAKE_FOURCC('Y','U','Y','2'):
+                       fourcc = V4L2_PIX_FMT_YUYV;
+                       break;
+               case GST_MAKE_FOURCC('Y','4','1','P'):
+                       fourcc = V4L2_PIX_FMT_Y41P;
+                       break;
+               case GST_MAKE_FOURCC('U','Y','V','Y'):
+                       fourcc = V4L2_PIX_FMT_UYVY;
+                       break;
+               case GST_MAKE_FOURCC('Y','V','1','2'):
+                       fourcc = V4L2_PIX_FMT_YVU420;
+                       break;
+               case GST_MAKE_FOURCC('R','G','B',' '): {
+                       gint depth, endianness;
+
+                       gst_caps_get_int(caps, "depth", &depth);
+                       gst_caps_get_int(caps, "endianness", &endianness);
+
+                       switch (depth) {
+                       case 8:
+                               fourcc = V4L2_PIX_FMT_RGB332;
+                               break;
+                       case 15:
+                               fourcc = (endianness == G_LITTLE_ENDIAN) ?
+                                        V4L2_PIX_FMT_RGB555 :
+                                        V4L2_PIX_FMT_RGB555X;
+                               break;
+                       case 16:
+                               fourcc = (endianness == G_LITTLE_ENDIAN) ?
+                                        V4L2_PIX_FMT_RGB565 :
+                                        V4L2_PIX_FMT_RGB565X;
+                               break;
+                       case 24:
+                               fourcc = (endianness == G_LITTLE_ENDIAN) ?
+                                        V4L2_PIX_FMT_BGR24 :
+                                        V4L2_PIX_FMT_RGB24;
+                               break;
+                       case 32:
+                               fourcc = (endianness == G_LITTLE_ENDIAN) ?
+                                        V4L2_PIX_FMT_BGR32 :
+                                        V4L2_PIX_FMT_RGB32;
+                               break;
                        }
-               } else {
-                       /* compressed */
-                       gchar *format_us;
-                       gint i;
-                       if (strncmp(format, "video/", 6))
-                               continue;
-                       format = &format[6];
-                       if (strlen(format) != 4)
-                               continue;
-                       format_us = g_strdup(format);
-                       for (i=0;i<4;i++)
-                               format_us[i] = g_ascii_toupper(format_us[i]);
-                       fourcc = GST_MAKE_FOURCC(format_us[0],format_us[1],format_us[2],format_us[3]);
-                       switch (fourcc) {
-                               case GST_MAKE_FOURCC('J','P','E','G'):
-                                       fourcclist = g_list_append(fourcclist, (gpointer)V4L2_PIX_FMT_MJPEG);
-                                       break;
+               }
+               default:
+                       break;
+               }
+               for (i=0;i<g_list_length(v4l2src->formats);i++) {
+                       struct v4l2_fmtdesc *fmt;
+                       fmt = (struct v4l2_fmtdesc *)
+                               g_list_nth_data(v4l2src->formats, i);
+                       if (fmt->pixelformat == fourcc) {
+                               end_fmt = fmt;
+                               break;
                        }
-                       fourcclist = g_list_append(fourcclist, (gpointer)fourcc);
                }
-       }
-
-       return fourcclist;
-}
-
-
-static GstCaps *
-gst_v4l2src_caps_intersect (GstCaps *caps1,
-                            GstCaps *_caps2)
-{
-       GstCaps *_list = NULL;
-
-       if (!_caps2)
-               return caps1;
-
-       for (;caps1!=NULL;caps1=caps1->next) {
-               GstCaps *caps2 = _caps2;
-
-               for (;caps2!=NULL;caps2=caps2->next) {
-                       if (!strcmp(gst_caps_get_mime(caps1), gst_caps_get_mime(caps2))) {
-                               if (!strcmp(gst_caps_get_mime(caps1), "video/raw")) {
-                                       guint32 fmt1, fmt2;
-                                       gst_caps_get_fourcc_int(caps1, "format", &fmt1);
-                                       gst_caps_get_fourcc_int(caps2, "format", &fmt2);
-                                       if (fmt1 == fmt2)
-                                               goto try_it_out;
-                               } else if (!strncmp(gst_caps_get_mime(caps1), "video/", 6)) {
-                                       goto try_it_out;
+       } else {
+               /* compressed */
+               if (strncmp(format, "video/", 6))
+                       return NULL;
+               format = &format[6];
+               if (strlen(format) != 4)
+                       return NULL;
+               fourcc = GST_MAKE_FOURCC(g_ascii_toupper(format[0]),
+                                        g_ascii_toupper(format[1]),
+                                        g_ascii_toupper(format[2]),
+                                        g_ascii_toupper(format[3]));
+
+               switch (fourcc) {
+               case GST_MAKE_FOURCC('J','P','E','G'): {
+                       struct v4l2_fmtdesc *fmt;
+                       for (i=0;i<g_list_length(v4l2src->formats);i++) {
+                               fmt = g_list_nth_data(v4l2src->formats, i);
+                               if (fmt->pixelformat == V4L2_PIX_FMT_MJPEG ||
+                                   fmt->pixelformat == V4L2_PIX_FMT_JPEG) {
+                                       end_fmt = fmt;
+                                       break;
                                }
-                               continue;
                        }
-                       continue;
-
-               try_it_out:
-                       if (!strcmp(gst_caps_get_mime(caps1), "video/raw")) {
-                               GstCaps *list = _list;
-                               for (;list!=NULL;list=list->next) {
-                                       if (!strcmp(gst_caps_get_mime(list), gst_caps_get_mime(caps1))) {
-                                               guint32 fmt1, fmt2;
-                                               gst_caps_get_fourcc_int(caps1, "format", &fmt1);
-                                               gst_caps_get_fourcc_int(list, "format", &fmt2);
-                                               if (fmt1 == fmt2)
-                                                       break;
-                                       }
-                               }
-                               if (list == NULL)
-                                       goto add_it;
-                       } else {
-                               GstCaps *list = _list;
-                               for (;list!=NULL;list=list->next) {
-                                       if (!strcmp(gst_caps_get_mime(list), gst_caps_get_mime(caps1))) {
-                                                       break;
-                                       }
+                       break;
+               }
+               default: {
+                       /* FIXME: check for fourcc in list */
+                       struct v4l2_fmtdesc *fmt;
+                       for (i=0;i<g_list_length(v4l2src->formats);i++) {
+                               fmt = g_list_nth_data(v4l2src->formats, i);
+                               if (fourcc == fmt->pixelformat) {
+                                       end_fmt = fmt;
+                                       break;
                                }
-                               if (list == NULL)
-                                       goto add_it;
                        }
-                       continue;
-
-               add_it:
-                       _list = gst_caps_append(_list, gst_caps_copy_1(caps1));
                        break;
                }
+               }
        }
 
-       return _list;
+       return end_fmt;
 }
 
+#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_v4l2src_srcconnect (GstPad  *pad,
@@ -644,10 +617,9 @@ gst_v4l2src_srcconnect (GstPad  *pad,
 {
        GstV4l2Src *v4l2src;
        GstV4l2Element *v4l2element;
-       GstCaps *owncapslist;
        GstCaps *caps;
-       GList *fourccs;
-       gint i;
+       struct v4l2_fmtdesc *format;
+       int w, h;
 
        v4l2src = GST_V4L2SRC(gst_pad_get_parent (pad));
        v4l2element = GST_V4L2ELEMENT(v4l2src);
@@ -661,45 +633,50 @@ gst_v4l2src_srcconnect (GstPad  *pad,
                return GST_PAD_LINK_DELAYED;
        }
 
-       /* build our own capslist */
-       owncapslist = gst_v4l2src_getcaps(pad, NULL);
-
-       /* and now, get the caps that we have in common */
-       if (!(caps = gst_v4l2src_caps_intersect(owncapslist, vscapslist)))
-               return GST_PAD_LINK_REFUSED;
-
-       /* and get them back to V4L2-compatible fourcc codes */
-       if (!(fourccs = gst_v4l2_caps_to_v4l2fourcc(v4l2src, caps)))
-               return GST_PAD_LINK_REFUSED;
-
-       /* we now have the fourcc codes. try out each of them */
-       for (i=0;i<g_list_length(fourccs);i++) {
-               guint32 fourcc = (guint32)g_list_nth_data(fourccs, i);
-               gint n;
-               for (n=0;n<g_list_length(v4l2src->formats);n++) {
-                       struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, n);
-                       if (format->pixelformat == fourcc) {
-                               /* we found the pixelformat! - try it out */
-                               if (gst_v4l2src_set_capture(v4l2src, format,
-                                           v4l2src->width, v4l2src->height)) {
-                                       /* it fits! Now, get the proper counterpart and retry
-                                        * it on the other side (again...) - if it works, we're
-                                        * done -> GST_PAD_LINK_OK */
-                                       GstCaps *lastcaps = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
-                                                               v4l2src->format.fmt.pix.width, v4l2src->format.fmt.pix.height,
-                                                               format->flags & V4L2_FMT_FLAG_COMPRESSED);
-                                       GstCaps *onecaps;
-                                       for (;lastcaps != NULL; lastcaps = lastcaps->next) {
-                                               GstPadLinkReturn ret_val;
-                                               onecaps = gst_caps_copy_1(lastcaps);
-                                               if ((ret_val = gst_pad_try_set_caps(v4l2src->srcpad, onecaps)) > 0) {
-                                                       if (gst_v4l2src_capture_init(v4l2src))
-                                                               return GST_PAD_LINK_DONE;
-                                               } else if (ret_val == GST_PAD_LINK_DELAYED) {
-                                                       return GST_PAD_LINK_DELAYED;
-                                               }
-                                       }
+       for (caps = vscapslist; caps != NULL; caps = caps->next) {
+               /* we want our own v4l2 type of fourcc codes */
+               if (!(format = gst_v4l2_caps_to_v4l2fourcc(v4l2src, caps))) {
+                       continue;
+               }
+               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);
+                       }
+               }
+
+               /* we found the pixelformat! - try it out */
+               if (gst_v4l2src_set_capture(v4l2src, format, w, h)) {
+                       /* it fits! Now, get the proper counterpart and retry
+                        * it on the other side (again...) - if it works, we're
+                        * done -> GST_PAD_LINK_OK */
+                       GstCaps *lastcaps;
+                       GstPadLinkReturn ret_val;
+
+                       lastcaps = gst_v4l2src_v4l2fourcc_to_caps_fixed(format->pixelformat,
+                                               v4l2src->format.fmt.pix.width,
+                                               v4l2src->format.fmt.pix.height,
+                                               format->flags & V4L2_FMT_FLAG_COMPRESSED);
+
+                       ret_val = gst_pad_try_set_caps(v4l2src->srcpad,
+                                                      lastcaps);
+
+                       if (ret_val > 0) {
+                               if (gst_v4l2src_capture_init(v4l2src)) {
+                                       return GST_PAD_LINK_DONE;
                                }
+                       } else if (ret_val == GST_PAD_LINK_DELAYED) {
+                               return GST_PAD_LINK_DELAYED;
                        }
                }
        }
@@ -713,32 +690,36 @@ gst_v4l2src_getcaps (GstPad  *pad,
                      GstCaps *caps)
 {
        GstV4l2Src *v4l2src = GST_V4L2SRC(gst_pad_get_parent (pad));
-       GstV4l2Element *v4l2element = GST_V4L2ELEMENT(v4l2src);
-       GstCaps *owncapslist;
+       GstCaps *list = NULL;
+       gint i;
+       struct v4l2_fmtdesc *format;
+       int min_w, max_w, min_h, max_h;
 
-       if (!GST_V4L2_IS_OPEN(v4l2element)) {
+       if (!GST_V4L2_IS_OPEN(GST_V4L2ELEMENT(v4l2src))) {
                return NULL;
        }
 
        /* build our own capslist */
-       if (v4l2src->palette) {
-               struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, v4l2src->palette);
-               owncapslist = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
-                                               v4l2src->width, v4l2src->height,
-                                               format->flags & V4L2_FMT_FLAG_COMPRESSED);
-       } else {
-               gint i;
-               owncapslist = NULL;
-               for (i=0;i<g_list_length(v4l2src->formats);i++) {
-                       struct v4l2_fmtdesc *format = g_list_nth_data(v4l2src->formats, i);
-                       caps = gst_v4l2src_v4l2fourcc_to_caps(format->pixelformat,
-                                                       v4l2src->width, v4l2src->height,
-                                                       format->flags & V4L2_FMT_FLAG_COMPRESSED);
-                       owncapslist = gst_caps_append(owncapslist, caps);
+       for (i=0;i<g_list_length(v4l2src->formats);i++) {
+               format = g_list_nth_data(v4l2src->formats, i);
+
+               /* get size delimiters */
+               if (!gst_v4l2src_get_size_limits(v4l2src, format,
+                                                &min_w, &max_w,
+                                                &min_h, &max_h)) {
+                       continue;
                }
+
+               /* add to list */
+               caps = gst_v4l2src_v4l2fourcc_to_caps_range(format->pixelformat,
+                                                           min_w, max_w,
+                                                           min_h, max_h,
+                                                           format->flags & V4L2_FMT_FLAG_COMPRESSED);
+
+               list = gst_caps_append(list, caps);
        }
 
-       return owncapslist;
+       return list;
 }
 
 
@@ -866,24 +847,6 @@ gst_v4l2src_set_property (GObject      *object,
        v4l2src = GST_V4L2SRC(object);
 
        switch (prop_id) {
-               case ARG_WIDTH:
-                       if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) {
-                               v4l2src->width = g_value_get_int(value);
-                       }
-                       break;
-
-               case ARG_HEIGHT:
-                       if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) {
-                               v4l2src->height = g_value_get_int(value);
-                       }
-                       break;
-
-               case ARG_PALETTE:
-                       if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) {
-                               v4l2src->palette = g_value_get_int(value);
-                       }
-                       break;
-
                case ARG_NUMBUFS:
                        if (!GST_V4L2_IS_ACTIVE(GST_V4L2ELEMENT(v4l2src))) {
                                v4l2src->breq.count = g_value_get_int(value);
@@ -915,22 +878,6 @@ gst_v4l2src_get_property (GObject    *object,
        v4l2src = GST_V4L2SRC(object);
 
        switch (prop_id) {
-               case ARG_WIDTH:
-                       g_value_set_int(value, v4l2src->width);
-                       break;
-
-               case ARG_HEIGHT:
-                       g_value_set_int(value, v4l2src->height);
-                       break;
-
-               case ARG_PALETTE:
-                       g_value_set_int(value, v4l2src->palette);
-                       break;
-
-               case ARG_PALETTE_NAMES:
-                       g_value_set_pointer(value, v4l2src->format_list);
-                       break;
-
                case ARG_NUMBUFS:
                        g_value_set_int(value, v4l2src->breq.count);
                        break;
index ae457e5..76fc5ef 100644 (file)
@@ -72,11 +72,6 @@ struct _GstV4l2Src {
 
        /* bufferpool for the buffers we're gonna use */
        GstBufferPool *bufferpool;
-
-       /* caching values */
-       gint width;
-       gint height;
-       gint palette;
 };
 
 struct _GstV4l2SrcClass {
index 685b37b..1f8be1c 100644 (file)
@@ -413,3 +413,48 @@ gst_v4l2src_capture_deinit (GstV4l2Src *v4l2src)
 
        return TRUE;
 }
+
+
+/*
+
+ */
+
+gboolean
+gst_v4l2src_get_size_limits (GstV4l2Src          *v4l2src,
+                            struct v4l2_fmtdesc *format,
+                            gint *min_w, gint *max_w,
+                            gint *min_h, gint *max_h)
+{
+       struct v4l2_format fmt;
+
+       /* get size delimiters */
+       memset(&fmt, 0, sizeof(fmt));
+       fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       fmt.fmt.pix.width = 0;
+       fmt.fmt.pix.height = 0;
+       fmt.fmt.pix.pixelformat = format->pixelformat;
+       fmt.fmt.pix.field = V4L2_FIELD_ANY;
+       if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd,
+                 VIDIOC_TRY_FMT, &fmt) < 0) {
+               return FALSE;
+       }
+
+       if (min_w)
+               *min_w = fmt.fmt.pix.width;
+       if (min_h)
+               *min_h = fmt.fmt.pix.height;
+
+       fmt.fmt.pix.width = G_MAXINT;
+       fmt.fmt.pix.height = G_MAXINT;
+       if (ioctl(GST_V4L2ELEMENT(v4l2src)->video_fd,
+                 VIDIOC_TRY_FMT, &fmt) < 0) {
+               return FALSE;
+       }
+
+       if (max_w)
+               *max_w = fmt.fmt.pix.width;
+       if (max_h)
+               *max_h = fmt.fmt.pix.height;
+
+       return TRUE;
+}
index 263d89a..fceb575 100644 (file)
@@ -41,5 +41,10 @@ gboolean     gst_v4l2src_capture_deinit      (GstV4l2Src *v4l2src);
 gboolean       gst_v4l2src_fill_format_list    (GstV4l2Src *v4l2src);
 gboolean       gst_v4l2src_empty_format_list   (GstV4l2Src *v4l2src);
 
+/* hacky */
+gboolean       gst_v4l2src_get_size_limits     (GstV4l2Src *v4l2src,
+                                                struct v4l2_fmtdesc *fmt,
+                                                gint *min_w, gint *max_w,
+                                                gint *min_h, gint *max_h);
 
 #endif /* __V4L2_SRC_CALLS_H__ */