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
This commit is contained in:
Janne Grunau 2010-11-04 18:36:09 +01:00 committed by Tim-Philipp Müller
parent b68ae7ac83
commit 351ac54822

View file

@ -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. */ /* The frame interval enumeration code first appeared in Linux 2.6.19. */
#ifdef VIDIOC_ENUM_FRAMEINTERVALS #ifdef VIDIOC_ENUM_FRAMEINTERVALS
@ -1467,6 +1471,14 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
guint32 num, denom; guint32 num, denom;
GstStructure *s; GstStructure *s;
GValue rates = { 0, }; 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)); memset (&ival, 0, sizeof (struct v4l2_frmivalenum));
ival.index = 0; ival.index = 0;
@ -1624,7 +1636,8 @@ gst_v4l2_object_probe_caps_for_format_and_size (GstV4l2Object * v4l2object,
return_data: return_data:
s = gst_structure_copy (template); s = gst_structure_copy (template);
gst_structure_set (s, "width", G_TYPE_INT, (gint) width, 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)) { if (G_IS_VALUE (&rates)) {
/* only change the framerate on the template when we have a valid probed new /* 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 #endif
static gboolean
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
guint32 pixelformat, gint * width, gint * height);
GstCaps * GstCaps *
gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object, gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
guint32 pixelformat, const GstStructure * template) guint32 pixelformat, const GstStructure * template)
@ -1831,18 +1840,19 @@ default_frame_sizes:
#endif /* defined VIDIOC_ENUM_FRAMESIZES */ #endif /* defined VIDIOC_ENUM_FRAMESIZES */
{ {
gint min_w, max_w, min_h, max_h, fix_num = 0, fix_denom = 0; 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 */ /* This code is for Linux < 2.6.19 */
min_w = min_h = 1; min_w = min_h = 1;
max_w = max_h = GST_V4L2_MAX_SIZE; max_w = max_h = GST_V4L2_MAX_SIZE;
if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &min_w, if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &min_w,
&min_h)) { &min_h, &interlaced)) {
GST_WARNING_OBJECT (v4l2object->element, GST_WARNING_OBJECT (v4l2object->element,
"Could not probe minimum capture size for pixelformat %" "Could not probe minimum capture size for pixelformat %"
GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat)); GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
} }
if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &max_w, if (!gst_v4l2_object_get_nearest_size (v4l2object, pixelformat, &max_w,
&max_h)) { &max_h, &interlaced)) {
GST_WARNING_OBJECT (v4l2object->element, GST_WARNING_OBJECT (v4l2object->element,
"Could not probe maximum capture size for pixelformat %" "Could not probe maximum capture size for pixelformat %"
GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat)); GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
@ -1885,6 +1895,8 @@ default_frame_sizes:
else else
gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL); 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); gst_caps_append_structure (ret, tmp);
return ret; return ret;
@ -1893,7 +1905,7 @@ default_frame_sizes:
static gboolean static gboolean
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, 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; struct v4l2_format fmt;
int fd; int fd;
@ -1963,6 +1975,22 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
*width = fmt.fmt.pix.width; *width = fmt.fmt.pix.width;
*height = fmt.fmt.pix.height; *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; return TRUE;
} }