Blob Blame History Raw

From: Daniel Drake <dsd@laptop.org>

http://bugzilla.gnome.org/show_bug.cgi?id=541956

Index: gst-plugins-good-0.10.8/sys/v4l2/v4l2src_calls.c
===================================================================
--- gst-plugins-good-0.10.8.orig/sys/v4l2/v4l2src_calls.c
+++ gst-plugins-good-0.10.8/sys/v4l2/v4l2src_calls.c
@@ -1149,11 +1149,23 @@ gst_v4l2src_set_capture (GstV4l2Src * v4
   format.fmt.pix.width = width;
   format.fmt.pix.height = height;
   format.fmt.pix.pixelformat = pixelformat;
-  /* request whole frames; change when gstreamer supports interlaced video */
+  /* request whole frames; change when gstreamer supports interlaced video
+   * (INTERLACED mode returns frames where the fields have already been
+   *  combined, there are other modes for requesting fields individually) */
   format.fmt.pix.field = V4L2_FIELD_INTERLACED;
 
-  if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
-    goto set_fmt_failed;
+  if (ioctl (fd, VIDIOC_S_FMT, &format) < 0) {
+    if (errno != EINVAL)
+      goto set_fmt_failed;
+
+    /* try again with progressive video */
+    format.fmt.pix.width = width;
+    format.fmt.pix.height = height;
+    format.fmt.pix.pixelformat = pixelformat;
+    format.fmt.pix.field = V4L2_FIELD_NONE;
+    if (ioctl (fd, VIDIOC_S_FMT, &format) < 0)
+      goto set_fmt_failed;
+  }
 
   if (format.fmt.pix.width != width || format.fmt.pix.height != height)
     goto invalid_dimensions;
@@ -1473,6 +1485,7 @@ gst_v4l2src_get_nearest_size (GstV4l2Src
 {
   struct v4l2_format fmt;
   int fd;
+  int r;
 
   g_return_val_if_fail (width != NULL, FALSE);
   g_return_val_if_fail (height != NULL, FALSE);
@@ -1491,7 +1504,17 @@ gst_v4l2src_get_nearest_size (GstV4l2Src
   fmt.fmt.pix.pixelformat = pixelformat;
   fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
 
-  if (ioctl (fd, VIDIOC_TRY_FMT, &fmt) < 0) {
+  r = 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 = 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)
@@ -1508,7 +1531,17 @@ gst_v4l2src_get_nearest_size (GstV4l2Src
     fmt.fmt.pix.width = *width;
     fmt.fmt.pix.height = *height;
 
-    if (ioctl (fd, VIDIOC_S_FMT, &fmt) < 0)
+    r = 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 = ioctl (fd, VIDIOC_S_FMT, &fmt);
+    }
+
+    if (r < 0)
       return FALSE;
   }