v4l2: take care not to change the current format where appropriate

Some drivers are buggy are will change the current format when
processing VIDIOC_TRY_FMT. Save and restore the current format
to ensure the format is kept unchanged.

https://bugzilla.gnome.org/show_bug.cgi?id=649067
This commit is contained in:
Vincent Penquerc'h 2011-08-08 10:54:26 +01:00 committed by Sebastian Dröge
parent 8edb15d12f
commit 639abf01f9

View file

@ -1991,9 +1991,10 @@ static gboolean
gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
guint32 pixelformat, gint * width, gint * height, gboolean * interlaced)
{
struct v4l2_format fmt;
struct v4l2_format fmt, prevfmt;
int fd;
int r;
int prevfmt_valid;
g_return_val_if_fail (width != NULL, FALSE);
g_return_val_if_fail (height != NULL, FALSE);
@ -2004,6 +2005,11 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
fd = v4l2object->video_fd;
/* Some drivers are buggy and will modify the currently set format
when processing VIDIOC_TRY_FMT, so we remember what is set at the
minute, and will reset it when done. */
prevfmt_valid = (v4l2_ioctl (fd, VIDIOC_G_FMT, &prevfmt) >= 0);
/* get size delimiters */
memset (&fmt, 0, sizeof (fmt));
fmt.type = v4l2object->type;
@ -2026,12 +2032,12 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
/* The driver might not implement TRY_FMT, in which case we will try
S_FMT to probe */
if (errno != ENOTTY)
return FALSE;
goto error;
/* Only try S_FMT if we're not actively capturing yet, which we shouldn't
be, because we're still probing */
if (GST_V4L2_IS_ACTIVE (v4l2object))
return FALSE;
goto error;
GST_LOG_OBJECT (v4l2object->element,
"Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
@ -2050,7 +2056,7 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
}
if (r < 0)
return FALSE;
goto error;
}
GST_LOG_OBJECT (v4l2object->element,
@ -2073,10 +2079,17 @@ gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object,
GST_WARNING_OBJECT (v4l2object->element,
"Unsupported field type for %" GST_FOURCC_FORMAT "@%ux%u",
GST_FOURCC_ARGS (pixelformat), *width, *height);
return FALSE;
goto error;
}
if (prevfmt_valid)
v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
return TRUE;
error:
if (prevfmt_valid)
v4l2_ioctl (fd, VIDIOC_S_FMT, &prevfmt);
return FALSE;
}