From 351ac548228ec91fe3d73ee07c5a4e1618559e9d Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 4 Nov 2010 18:36:09 +0100 Subject: [PATCH] v4l2src: check field information and set interlaced caps accordingly Reject the format if the field type is not supported. https://bugzilla.gnome.org/show_bug.cgi?id=634391 --- sys/v4l2/gstv4l2object.c | 44 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c index 96b6e59139..8653573f20 100644 --- a/sys/v4l2/gstv4l2object.c +++ b/sys/v4l2/gstv4l2object.c @@ -1454,6 +1454,10 @@ done: } +static gboolean +gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, + guint32 pixelformat, gint * width, gint * height, gboolean * interlaced); + /* The frame interval enumeration code first appeared in Linux 2.6.19. */ #ifdef VIDIOC_ENUM_FRAMEINTERVALS @@ -1467,6 +1471,14 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object, guint32 num, denom; GstStructure *s; GValue rates = { 0, }; + gboolean interlaced; + gint int_width = width; + gint int_height = height; + + /* interlaced detection using VIDIOC_TRY/S_FMT */ + if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, + &int_width, &int_height, &interlaced)) + return NULL; memset (&ival, 0, sizeof (struct v4l2_frmivalenum)); ival.index = 0; @@ -1624,7 +1636,8 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object, return_data: s = gst_structure_copy (template); gst_structure_set (s, "width", G_TYPE_INT, (gint) width, - "height", G_TYPE_INT, (gint) height, NULL); + "height", G_TYPE_INT, (gint) height, + "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); if (G_IS_VALUE (&rates)) { /* only change the framerate on the template when we have a valid probed new @@ -1672,10 +1685,6 @@ sort_by_frame_size (GstStructure * s1, GstStructure * s2) } #endif -static gboolean -gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, - guint32 pixelformat, gint * width, gint * height); - GstCaps * gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object, guint32 pixelformat, const GstStructure * template) @@ -1831,18 +1840,19 @@ default_frame_sizes: #endif /* defined VIDIOC_ENUM_FRAMESIZES */ { gint min_w, max_w, min_h, max_h, fix_num = 0, fix_denom = 0; + gboolean interlaced; /* This code is for Linux < 2.6.19 */ min_w = min_h = 1; max_w = max_h = GST_V4L2_MAX_SIZE; if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &min_w, - &min_h)) { + &min_h, &interlaced)) { GST_WARNING_OBJECT (v4l2object->element, "Could not probe minimum capture size for pixelformat %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat)); } if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &max_w, - &max_h)) { + &max_h, &interlaced)) { GST_WARNING_OBJECT (v4l2object->element, "Could not probe maximum capture size for pixelformat %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat)); @@ -1885,6 +1895,8 @@ default_frame_sizes: else gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL); + gst_structure_set (tmp, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); + gst_caps_append_structure (ret, tmp); return ret; @@ -1893,7 +1905,7 @@ default_frame_sizes: static gboolean gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, - guint32 pixelformat, gint * width, gint * height) + guint32 pixelformat, gint * width, gint * height, gboolean * interlaced) { struct v4l2_format fmt; int fd; @@ -1963,6 +1975,22 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, *width = fmt.fmt.pix.width; *height = fmt.fmt.pix.height; + switch (fmt.fmt.pix.field) { + case V4L2_FIELD_NONE: + *interlaced = FALSE; + break; + case V4L2_FIELD_INTERLACED: + case V4L2_FIELD_INTERLACED_TB: + case V4L2_FIELD_INTERLACED_BT: + *interlaced = TRUE; + break; + default: + GST_WARNING_OBJECT (v4l2object->element, + "Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u", + GST_FOURCC_ARGS (pixelformat), width, height); + return FALSE; + } + return TRUE; }