From: Ronald B. <rb...@us...> - 2003-05-10 14:36:47
|
CVS Root: /cvsroot/gstreamer Module: gst-plugins Changes by: rbultje Date: Sat May 10 2003 07:36:46 PDT Log message: This implements filtered-caps negotiation for all the v4l*src elements, and removes the accompanying properties since they're no longer needed Modified files: sys/v4l : gstv4lmjpegsrc.c gstv4lmjpegsrc.h gstv4lsrc.c gstv4lsrc.h sys/v4l2 : gstv4l2src.c gstv4l2src.h v4l2src_calls.c v4l2src_calls.h Links: http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l/gstv4lmjpegsrc.c.diff?r1=1.26&r2=1.27 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l/gstv4lmjpegsrc.h.diff?r1=1.6&r2=1.7 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l/gstv4lsrc.c.diff?r1=1.34&r2=1.35 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l/gstv4lsrc.h.diff?r1=1.12&r2=1.13 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l2/gstv4l2src.c.diff?r1=1.11&r2=1.12 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l2/gstv4l2src.h.diff?r1=1.4&r2=1.5 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l2/v4l2src_calls.c.diff?r1=1.7&r2=1.8 http://cvs.sf.net/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins/sys/v4l2/v4l2src_calls.h.diff?r1=1.3&r2=1.4 ====Begin Diffs==== Index: gstv4lmjpegsrc.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l/gstv4lmjpegsrc.c,v retrieving revision 1.26 retrieving revision 1.27 diff -u -d -r1.26 -r1.27 --- gstv4lmjpegsrc.c 2 May 2003 21:16:54 -0000 1.26 +++ gstv4lmjpegsrc.c 10 May 2003 14:36:34 -0000 1.27 @@ -47,17 +47,16 @@ /* 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 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 @@ 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 @@ 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 @@ 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_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 @@ (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 @@ } +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 @@ * 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 @@ 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 @@ } +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 @@ 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 @@ 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 @@ 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,20 +680,12 @@ 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); Index: gstv4lmjpegsrc.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l/gstv4lmjpegsrc.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- gstv4lmjpegsrc.h 2 May 2003 21:16:54 -0000 1.6 +++ gstv4lmjpegsrc.h 10 May 2003 14:36:34 -0000 1.7 @@ -74,20 +74,19 @@ /* 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: gstv4lsrc.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l/gstv4lsrc.c,v retrieving revision 1.34 retrieving revision 1.35 diff -u -d -r1.34 -r1.35 --- gstv4lsrc.c 2 May 2003 21:16:54 -0000 1.34 +++ gstv4lsrc.c 10 May 2003 14:36:34 -0000 1.35 @@ -48,10 +48,6 @@ /* 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 @@ 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_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 @@ 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_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 @@ (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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } +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 @@ 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 @@ 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 @@ 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: gstv4lsrc.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l/gstv4lsrc.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- gstv4lsrc.h 2 May 2003 21:16:55 -0000 1.12 +++ gstv4lsrc.h 10 May 2003 14:36:34 -0000 1.13 @@ -85,11 +85,6 @@ /* how are we going to push buffers? */ gboolean use_fixed_fps; - - /* caching values */ - gint width; - gint height; - gint palette; }; struct _GstV4lSrcClass { Index: gstv4l2src.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l2/gstv4l2src.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- gstv4l2src.c 2 May 2003 21:16:56 -0000 1.11 +++ gstv4l2src.c 10 May 2003 14:36:34 -0000 1.12 @@ -44,10 +44,6 @@ /* 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 @@ 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_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 @@ 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: - 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); + 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_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); + case V4L2_PIX_FMT_RGB32: + 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; - } + } - /* 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); + 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; - return capslist; -} - - -static GList * -gst_v4l2_caps_to_v4l2fourcc (GstV4l2Src *v4l2src, - GstCaps *capslist) -{ - GList *fourcclist = NULL; - GstCaps *caps; - guint32 fourcc; - gint i; + switch (fourcc) { + case V4L2_PIX_FMT_YUV420: + fcc = GST_MAKE_FOURCC('I','4','2','0'); + break; + case V4L2_PIX_FMT_YUYV: + 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; + } - for (caps = capslist;caps != NULL; caps = caps->next) { - const gchar *format = gst_caps_get_mime(caps); + 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)); - 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; } - } + /* 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<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); + 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 { - /* 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; - } - fourcclist = g_list_append(fourcclist, (gpointer)fourcc); + caps = GST_CAPS_NEW("v4l2src_caps", + "video/raw", + "format",GST_PROPS_FOURCC(fourcc), + NULL); } + break; } - return fourcclist; + 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; } +#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) -static GstCaps * -gst_v4l2src_caps_intersect (GstCaps *caps1, - GstCaps *_caps2) +#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 *caps) { - GstCaps *_list = NULL; + gint i; + guint32 fourcc = 0; + struct v4l2_fmtdesc *end_fmt = NULL; + const gchar *format = gst_caps_get_mime(caps); - if (!_caps2) - return caps1; + if (!strcmp(format, "video/raw")) { + /* non-compressed */ + gst_caps_get_fourcc_int(caps, "format", &fourcc); - for (;caps1!=NULL;caps1=caps1->next) { - GstCaps *caps2 = _caps2; + 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; - 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; - } - continue; + 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; } - continue; + } + 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; + } + } + } 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])); - 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; - } + 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; } - 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 @@ { 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 @@ return GST_PAD_LINK_DELAYED; } - /* build our own capslist */ - owncapslist = gst_v4l2src_getcaps(pad, NULL); + 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); + } + } - /* and now, get the caps that we have in common */ - if (!(caps = gst_v4l2src_caps_intersect(owncapslist, vscapslist))) - return GST_PAD_LINK_REFUSED; + /* 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; - /* and get them back to V4L2-compatible fourcc codes */ - if (!(fourccs = gst_v4l2_caps_to_v4l2fourcc(v4l2src, caps))) - return GST_PAD_LINK_REFUSED; + 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); - /* 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; - } - } + 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 @@ 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 @@ 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 @@ 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: gstv4l2src.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l2/gstv4l2src.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- gstv4l2src.h 2 May 2003 21:16:56 -0000 1.4 +++ gstv4l2src.h 10 May 2003 14:36:34 -0000 1.5 @@ -72,11 +72,6 @@ /* bufferpool for the buffers we're gonna use */ GstBufferPool *bufferpool; - - /* caching values */ - gint width; - gint height; - gint palette; }; struct _GstV4l2SrcClass { Index: v4l2src_calls.c =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l2/v4l2src_calls.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- v4l2src_calls.c 2 May 2003 21:16:56 -0000 1.7 +++ v4l2src_calls.c 10 May 2003 14:36:34 -0000 1.8 @@ -413,3 +413,48 @@ 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: v4l2src_calls.h =================================================================== RCS file: /cvsroot/gstreamer/gst-plugins/sys/v4l2/v4l2src_calls.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- v4l2src_calls.h 2 Mar 2003 21:58:52 -0000 1.3 +++ v4l2src_calls.h 10 May 2003 14:36:34 -0000 1.4 @@ -41,5 +41,10 @@ gbo... [truncated message content] |