summaryrefslogtreecommitdiff
path: root/sys/v4l2/v4l2src_calls.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/v4l2/v4l2src_calls.c')
-rw-r--r--sys/v4l2/v4l2src_calls.c508
1 files changed, 500 insertions, 8 deletions
diff --git a/sys/v4l2/v4l2src_calls.c b/sys/v4l2/v4l2src_calls.c
index d8e365f9a..d87bdf4f1 100644
--- a/sys/v4l2/v4l2src_calls.c
+++ b/sys/v4l2/v4l2src_calls.c
@@ -44,12 +44,38 @@
#include "gstv4l2tuner.h"
#include "gstv4l2bufferpool.h"
+#include "gsticbvideo.h"
#include "gst/gst-i18n-plugin.h"
GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
#define GST_CAT_DEFAULT v4l2src_debug
+enum
+{
+ PROP_0,
+ V4L2_STD_OBJECT_PROPS,
+ PROP_QUEUE_SIZE,
+ PROP_ALWAYS_COPY,
+
+ /* additionnal properties for PNX sensors */
+ PROP_EFFECT,
+ PROP_HFLIP,
+ PROP_VFLIP,
+ PROP_BRIGHTNESS,
+ PROP_CONTRAST,
+ PROP_SATURATION,
+ PROP_ZOOM,
+ PROP_WB_MODE,
+ PROP_SCENE,
+ PROP_SENSITIVITY,
+ PROP_MET_EXP,
+ PROP_FOCUS_CTRL,
+ PROP_FOCUS_STATE,
+ PROP_FLICKER_MOD,
+};
+
+
/* lalala... */
#define GST_V4L2_SET_ACTIVE(element) (element)->buffer = GINT_TO_POINTER (-1)
#define GST_V4L2_SET_INACTIVE(element) (element)->buffer = NULL
@@ -125,6 +151,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
}
pool_buffer = GST_BUFFER (gst_v4l2_buffer_pool_dqbuf (pool));
+
if (pool_buffer)
break;
@@ -156,6 +183,8 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
need_copy = v4l2src->always_copy
|| !gst_v4l2_buffer_pool_available_buffers (pool);
+ need_copy = FALSE;
+
if (G_UNLIKELY (need_copy)) {
*buf = gst_buffer_copy (pool_buffer);
GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY);
@@ -226,14 +255,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
goto done;
}
- /* Note: V4L2 provides the frame interval, we have the frame rate */
- if (fractions_are_equal (stream.parm.capture.timeperframe.numerator,
- stream.parm.capture.timeperframe.denominator, fps_d, fps_n)) {
- GST_LOG_OBJECT (v4l2src, "Desired framerate already set");
- v4l2src->fps_n = fps_n;
- v4l2src->fps_d = fps_d;
- goto done;
- }
+ /* initialize default values */
+ v4l2src->fps_n = stream.parm.capture.timeperframe.numerator;
+ v4l2src->fps_d = stream.parm.capture.timeperframe.denominator;
/* We want to change the frame rate, so check whether we can. Some cheap USB
* cameras don't have the capability */
@@ -416,3 +440,471 @@ gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
return TRUE;
}
+
+/******************************************************
+ * gst_v4l2src_capture_set_all_controls():
+ * set control on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_all_controls (GstV4l2Src * v4l2src)
+{
+ struct v4l2_control control;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set controls on capture device");
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_HFLIP;
+ control.value = v4l2src->hflip;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_HFLIP");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_VFLIP;
+ control.value = v4l2src->vflip;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_VFLIP");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_SCENE;
+ control.value = v4l2src->scene;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SCENE");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_SENSITIVITY;
+ control.value = v4l2src->sensitivity;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SENSITIVITY");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_MET_EXP;
+ control.value = v4l2src->metering_exposure;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_MET_EXP");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_BRIGHTNESS;
+ control.value = v4l2src->brightness;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_BRIGHTNESS");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_CONTRAST;
+ control.value = v4l2src->contrast;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_CONTRAST");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_SATURATION;
+ control.value = v4l2src->saturation;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SATURATION");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_FOCUS_AUTO;
+ control.value = v4l2src->focus_ctrl;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_FOCUS_AUTO");
+ }
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+ control.id = V4L2_CID_POWER_LINE_FREQUENCY;
+ control.value = v4l2src->flicker_mod;
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_POWER_LINE_FREQUENCY");
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_set_control():
+ * set a specific control on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_control (GstV4l2Src * v4l2src, guint prop_id)
+{
+ struct v4l2_control control;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set control on capture device");
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+
+ switch (prop_id) {
+ case PROP_HFLIP:
+ control.id = V4L2_CID_HFLIP;
+ control.value = v4l2src->hflip;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_HFLIP");
+ }
+ break;
+ case PROP_VFLIP:
+ control.id = V4L2_CID_VFLIP;
+ control.value = v4l2src->vflip;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_VFLIP");
+ }
+ break;
+ case PROP_BRIGHTNESS:
+ control.id = V4L2_CID_BRIGHTNESS;
+ control.value = v4l2src->brightness;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_BRIGHTNESS");
+ }
+ break;
+ case PROP_CONTRAST:
+ control.id = V4L2_CID_CONTRAST;
+ control.value = v4l2src->contrast;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_CONTRAST");
+ }
+ break;
+ case PROP_SATURATION:
+ control.id = V4L2_CID_SATURATION;
+ control.value = v4l2src->saturation;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SATURATION");
+ }
+ break;
+ case PROP_SCENE:
+ control.id = V4L2_CID_SCENE;
+ control.value = v4l2src->scene;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SCENE");
+ }
+ break;
+ case PROP_SENSITIVITY:
+ control.id = V4L2_CID_SENSITIVITY;
+ control.value = v4l2src->sensitivity;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SENSITIVITY");
+ }
+ break;
+ case PROP_MET_EXP:
+ control.id = V4L2_CID_MET_EXP;
+ control.value = v4l2src->metering_exposure;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_MET_EXP");
+ }
+ break;
+ case PROP_FOCUS_CTRL:
+ control.id = V4L2_CID_FOCUS_AUTO;
+ control.value = v4l2src->focus_ctrl;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_FOCUS_AUTO");
+ }
+ break;
+ case PROP_FLICKER_MOD:
+ control.id = V4L2_CID_POWER_LINE_FREQUENCY;
+ control.value = v4l2src->flicker_mod;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src,
+ "failed to set V4L2_CID_POWER_LINE_FREQUENCY");
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_get_control():
+ * get a specific control on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_get_control (GstV4l2Src * v4l2src, guint prop_id)
+{
+ struct v4l2_control control;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set control on capture device");
+
+ memset (&control, 0, sizeof (struct v4l2_control));
+
+ switch (prop_id) {
+ case PROP_HFLIP:
+ control.id = V4L2_CID_HFLIP;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_HFLIP");
+ }
+ v4l2src->hflip = control.value;
+ break;
+ case PROP_VFLIP:
+ control.id = V4L2_CID_VFLIP;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_VFLIP");
+ }
+ v4l2src->vflip = control.value;
+ break;
+ case PROP_BRIGHTNESS:
+ control.id = V4L2_CID_BRIGHTNESS;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_BRIGHTNESS");
+ }
+ v4l2src->brightness = control.value;
+ break;
+ case PROP_CONTRAST:
+ control.id = V4L2_CID_CONTRAST;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_CONTRAST");
+ }
+ v4l2src->contrast = control.value;
+ break;
+ case PROP_SATURATION:
+ control.id = V4L2_CID_SATURATION;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SATURATION");
+ }
+ v4l2src->saturation = control.value;
+ break;
+ case PROP_SCENE:
+ control.id = V4L2_CID_SCENE;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SCENE");
+ }
+ v4l2src->scene = control.value;
+ break;
+ case PROP_SENSITIVITY:
+ control.id = V4L2_CID_SENSITIVITY;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_SENSITIVITY");
+ }
+ v4l2src->sensitivity = control.value;
+ break;
+ case PROP_MET_EXP:
+ control.id = V4L2_CID_MET_EXP;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_MET_EXP");
+ }
+ v4l2src->metering_exposure = control.value;
+ break;
+ case PROP_FOCUS_STATE:
+ control.id = V4L2_CID_FOCUS_AUTO;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set V4L2_CID_FOCUS_AUTO");
+ }
+ v4l2src->focus_ctrl = control.value;
+ break;
+ case PROP_FLICKER_MOD:
+ control.id = V4L2_CID_POWER_LINE_FREQUENCY;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_G_CTRL, &control) < 0) {
+ GST_WARNING_OBJECT (v4l2src,
+ "failed to set V4L2_CID_POWER_LINE_FREQUENCY");
+ }
+ v4l2src->flicker_mod = control.value;
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/******************************************************
+ * gst_v4l2src_capture_set_effect():
+ * set effect on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_effect (GstV4l2Src * v4l2src, gchar * effect_name)
+{
+ struct v4l2_efx v4l2_effect;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set effect on capture device");
+
+ memset (&v4l2_effect, 0, sizeof (struct v4l2_efx));
+ sprintf (v4l2_effect.efx_name, "%s", effect_name);
+ GST_DEBUG_OBJECT (v4l2src, "set effect: %s", effect_name);
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_EFX, &v4l2_effect) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set effect");
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_set_white_balance_mode():
+ * set white_balance mode on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_white_balance_mode (GstV4l2Src * v4l2src,
+ gchar * wb_mode_name)
+{
+ struct v4l2_wb_mode wb_mode;
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set white balance on capture device");
+
+ memset (&wb_mode, 0, sizeof (struct v4l2_efx));
+ sprintf (wb_mode.wb_mode_name, "%s", wb_mode_name);
+ GST_DEBUG_OBJECT (v4l2src, "set white balance mode: %s", wb_mode_name);
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_WBMODE, &wb_mode) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "failed to set white balance");
+ }
+
+ return TRUE;
+}
+
+/******************************************************
+ * gst_v4l2src_capture_set_zoom():
+ * set zoom value mode on capture device
+ * return value: TRUE on success, FALSE on error
+ ******************************************************/
+gboolean
+gst_v4l2src_capture_set_zoom (GstV4l2Src * v4l2src)
+{
+ double zoom_max = 1.0;
+ struct v4l2_crop crop;
+ struct v4l2_cropcap cropcap;
+
+#define min(a,b) ((a) > (b) ? (b) : (a))
+
+ GST_V4L2_CHECK_OPEN (v4l2src->v4l2object);
+ GST_DEBUG_OBJECT (v4l2src, "set ZOOM on capture device");
+
+
+ /* get crop cap */
+ memset (&cropcap, 0, sizeof (struct v4l2_cropcap));
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_CROPCAP, &cropcap) < 0) {
+ GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, (NULL),
+ ("failed to get crop caps"));
+ return FALSE;
+ }
+ GST_DEBUG_OBJECT (v4l2src, "defrect: w:%d h:%d l:%d t:%d",
+ cropcap.defrect.width, cropcap.defrect.height,
+ cropcap.defrect.left, cropcap.defrect.top);
+ GST_DEBUG_OBJECT (v4l2src, "bounds: w:%d h:%d l:%d t:%d",
+ cropcap.bounds.width, cropcap.bounds.height,
+ cropcap.bounds.left, cropcap.bounds.top);
+
+ /* limit zoom to zoomax */
+ zoom_max = cropcap.defrect.width / cropcap.bounds.width;
+ v4l2src->zoom = min (v4l2src->zoom, zoom_max);
+ GST_DEBUG_OBJECT (v4l2src, "set zoom: %f (zoom max:%f)", v4l2src->zoom,
+ zoom_max);
+
+ /* set croppping zone */
+ memset (&crop, 0, sizeof (struct v4l2_crop));
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c.width = cropcap.defrect.width / v4l2src->zoom;
+ crop.c.height = cropcap.defrect.height / v4l2src->zoom;
+ /* center crop */
+ crop.c.left =
+ (cropcap.defrect.width + cropcap.defrect.left * 2 - crop.c.width) / 2;
+ crop.c.top =
+ (cropcap.defrect.height + cropcap.defrect.top * 2 - crop.c.height) / 2;
+ GST_DEBUG_OBJECT (v4l2src, "=> CROP: w:%d h:%d l:%d t:%d", crop.c.width,
+ crop.c.height, crop.c.left, crop.c.top);
+
+ if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_S_CROP, &crop) < 0) {
+ GST_WARNING_OBJECT (v4l2src, "Crop setting failed");
+ }
+
+ return TRUE;
+}
+
+/*
+ */
+static gboolean
+gst_v4l2src_get_nearest_size (GstV4l2Src * v4l2src, guint32 pixelformat,
+ gint * width, gint * height)
+{
+ struct v4l2_format fmt;
+ int fd;
+ int r;
+
+ g_return_val_if_fail (width != NULL, FALSE);
+ g_return_val_if_fail (height != NULL, FALSE);
+
+ GST_LOG_OBJECT (v4l2src,
+ "getting nearest size to %dx%d with format %" GST_FOURCC_FORMAT,
+ *width, *height, GST_FOURCC_ARGS (pixelformat));
+
+ fd = v4l2src->v4l2object->video_fd;
+
+ /* get size delimiters */
+ memset (&fmt, 0, sizeof (fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with progressive video */
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt);
+ }
+
+ if (r < 0) {
+ /* The driver might not implement TRY_FMT, in which case we will try
+ S_FMT to probe */
+ if (errno != ENOTTY)
+ return FALSE;
+
+ /* 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 (v4l2src->v4l2object))
+ return FALSE;
+
+ GST_LOG_OBJECT (v4l2src,
+ "Failed to probe size limit with VIDIOC_TRY_FMT, trying VIDIOC_S_FMT");
+
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ if (r < 0 && errno == EINVAL) {
+ /* try again with progressive video */
+ fmt.fmt.pix.width = *width;
+ fmt.fmt.pix.height = *height;
+ fmt.fmt.pix.pixelformat = pixelformat;
+ fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ r = v4l2_ioctl (fd, VIDIOC_S_FMT, &fmt);
+ }
+
+ if (r < 0)
+ return FALSE;
+ }
+
+ GST_LOG_OBJECT (v4l2src,
+ "got nearest size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
+
+ *width = fmt.fmt.pix.width;
+ *height = fmt.fmt.pix.height;
+
+ return TRUE;
+}