sys/v4l2/v4l2_calls.c: Treat ENOTTY (driver does not implement ioctl) the same as
authorJan Schmidt <thaytan@mad.scientist.com>
Thu, 31 Jan 2008 16:12:28 +0000 (16:12 +0000)
committerJan Schmidt <thaytan@mad.scientist.com>
Thu, 31 Jan 2008 16:12:28 +0000 (16:12 +0000)
Original commit message from CVS:
* sys/v4l2/v4l2_calls.c: (gst_v4l2_fill_lists):
Treat ENOTTY (driver does not implement ioctl) the same as
EINVAL since it implies there are no available standards.
* sys/v4l2/v4l2src_calls.c: (gst_v4l2src_probe_caps_for_format),
(gst_v4l2src_get_nearest_size):
Replace gst_v4l2src_get_size_limits with 2 calls to new function
gst_v4l2src_get_nearest_size, and get it to use VIDIOC_S_FMT to
probe if the driver does not support VIDIOC_TRY_FMT for whatever
reason, and if we aren't yet actively capturing.
* sys/v4l2/v4l2src_calls.h:
Remove replaced function declaration.

ChangeLog
sys/v4l2/v4l2_calls.c
sys/v4l2/v4l2src_calls.c
sys/v4l2/v4l2src_calls.h

index a166e53..b2e5a28 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2008-01-31  Jan Schmidt  <Jan.Schmidt@sun.com>
 
+       * sys/v4l2/v4l2_calls.c: (gst_v4l2_fill_lists):
+       Treat ENOTTY (driver does not implement ioctl) the same as
+       EINVAL since it implies there are no available standards.
+
+       * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_probe_caps_for_format),
+       (gst_v4l2src_get_nearest_size):
+       Replace gst_v4l2src_get_size_limits with 2 calls to new function
+       gst_v4l2src_get_nearest_size, and get it to use VIDIOC_S_FMT to
+       probe if the driver does not support VIDIOC_TRY_FMT for whatever
+       reason, and if we aren't yet actively capturing.
+
+       * sys/v4l2/v4l2src_calls.h:
+       Remove replaced function declaration.
+
+2008-01-31  Jan Schmidt  <Jan.Schmidt@sun.com>
+
        * configure.ac:
        Bump plugins-base requirement to 0.10.16 for the gst_video_format_*
        API.
index 616f659..e22678c 100644 (file)
@@ -185,7 +185,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
     standard.index = n;
 
     if (ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
-      if (errno == EINVAL)
+      if (errno == EINVAL || errno == ENOTTY)
         break;                  /* end of enumeration */
       else {
         GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
index 4ecedf3..5d9d66a 100644 (file)
@@ -66,6 +66,12 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2src_debug);
 #define GST_IS_V4L2_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L2_BUFFER))
 #define GST_V4L2_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER, GstV4l2Buffer))
 
+
+/* Local functions */
+static gboolean
+gst_v4l2src_get_nearest_size (GstV4l2Src * v4l2src, guint32 pixelformat,
+    gint * width, gint * height);
+
 static void
 gst_v4l2_buffer_finalize (GstV4l2Buffer * buffer)
 {
@@ -853,11 +859,19 @@ default_frame_sizes:
     gint min_w, max_w, min_h, max_h;
 
     /* This code is for Linux < 2.6.19 */
-    if (!gst_v4l2src_get_size_limits (v4l2src, pixelformat, &min_w, &max_w,
-            &min_h, &max_h)) {
-      min_w = min_h = 1;
-      max_w = max_h = GST_V4L2_MAX_SIZE;
+    min_w = min_h = 1;
+    max_w = max_h = GST_V4L2_MAX_SIZE;
+    if (!gst_v4l2src_get_nearest_size (v4l2src, pixelformat, &min_w, &min_h)) {
+      GST_WARNING_OBJECT (v4l2src,
+          "Could not probe minimum capture size for pixelformat %"
+          GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
     }
+    if (!gst_v4l2src_get_nearest_size (v4l2src, pixelformat, &max_w, &max_h)) {
+      GST_WARNING_OBJECT (v4l2src,
+          "Could not probe maximum capture size for pixelformat %"
+          GST_FOURCC_FORMAT, GST_FOURCC_ARGS (pixelformat));
+    }
+
     ret = gst_caps_new_empty ();
     tmp = gst_structure_copy (template);
     gst_structure_set (tmp,
@@ -1418,53 +1432,56 @@ gst_v4l2src_capture_deinit (GstV4l2Src * v4l2src)
 
 /*
  */
-gboolean
-gst_v4l2src_get_size_limits (GstV4l2Src * v4l2src,
-    guint32 pixelformat, gint * min_w, gint * max_w, gint * min_h, gint * max_h)
+static gboolean
+gst_v4l2src_get_nearest_size (GstV4l2Src * v4l2src, guint32 pixelformat,
+    gint * width, gint * height)
 {
-
   struct v4l2_format fmt;
+  int fd;
+
+  g_return_val_if_fail (width != NULL, FALSE);
+  g_return_val_if_fail (height != NULL, FALSE);
 
   GST_LOG_OBJECT (v4l2src,
-      "getting size limits with format %" GST_FOURCC_FORMAT,
-      GST_FOURCC_ARGS (pixelformat));
+      "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 = 0;
-  fmt.fmt.pix.height = 0;
+  fmt.fmt.pix.width = *width;
+  fmt.fmt.pix.height = *height;
   fmt.fmt.pix.pixelformat = pixelformat;
   fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
-  if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_TRY_FMT, &fmt) < 0) {
-    GST_DEBUG_OBJECT (v4l2src, "failed to get min size: %s",
-        g_strerror (errno));
-    return FALSE;
-  }
 
-  if (min_w)
-    *min_w = fmt.fmt.pix.width;
-  if (min_h)
-    *min_h = fmt.fmt.pix.height;
+  if (ioctl (fd, VIDIOC_TRY_FMT, &fmt) < 0) {
+    /* The driver might not implement TRY_FMT, in which case we will try
+       S_FMT to probe */
+    if (errno != ENOTTY)
+      return FALSE;
 
-  GST_LOG_OBJECT (v4l2src,
-      "got min size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
+    /* 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;
 
-  fmt.fmt.pix.width = GST_V4L2_MAX_SIZE;
-  fmt.fmt.pix.height = GST_V4L2_MAX_SIZE;
-  if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_TRY_FMT, &fmt) < 0) {
-    GST_DEBUG_OBJECT (v4l2src, "failed to get max size: %s",
-        g_strerror (errno));
-    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;
 
-  if (max_w)
-    *max_w = fmt.fmt.pix.width;
-  if (max_h)
-    *max_h = fmt.fmt.pix.height;
+    if (ioctl (fd, VIDIOC_S_FMT, &fmt) < 0)
+      return FALSE;
+  }
 
   GST_LOG_OBJECT (v4l2src,
-      "got max size %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height);
+      "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;
 }
index 139d1f0..038aad0 100644 (file)
@@ -47,9 +47,4 @@ gboolean   gst_v4l2src_clear_format_list (GstV4l2Src * v4l2src);
 GstCaps*   gst_v4l2src_probe_caps_for_format (GstV4l2Src * v4l2src, guint32 pixelformat,
                                           const GstStructure *template);
 
-gboolean   gst_v4l2src_get_size_limits   (GstV4l2Src * v4l2src,
-                                          guint32 pixelformat,
-                                          gint * min_w, gint * max_w,
-                                          gint * min_h, gint * max_h);
-
 #endif /* __V4L2SRC_CALLS_H__ */