sys/v4l2/gstv4l2src.c: Restructure the setcaps function so that we can also compute...
authorWim Taymans <wim.taymans@gmail.com>
Tue, 4 Sep 2007 16:40:05 +0000 (16:40 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 4 Sep 2007 16:40:05 +0000 (16:40 +0000)
Original commit message from CVS:
* sys/v4l2/gstv4l2src.c: (gst_v4l2_get_caps_info),
(gst_v4l2src_set_caps), (gst_v4l2src_get_mmap):
Restructure the setcaps function so that we can also compute the
expected GStreamer output size of the video frames.
Set frame_byte_size correctly so that read-based devices have a chance
of working correctly.
When grabbing a frame, discard frames that are not of the expected size.
Some cameras don't output the right framesize for the first buffer.
Try only a couple of times to get a valid frame, else error out.
* sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
(gst_v4l2_fill_lists), (gst_v4l2_get_input):
Add some more debug info when scanning the device.
* sys/v4l2/v4l2src_calls.c: (gst_v4l2_buffer_new),
(gst_v4l2_buffer_pool_new), (gst_v4l2_buffer_pool_activate),
(gst_v4l2src_fill_format_list), (gst_v4l2src_grab_frame),
(gst_v4l2src_set_capture), (gst_v4l2src_capture_init):
Add some more debug info when dequeing a frame.

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

index 2b9a4ba..9986678 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2007-09-04  Wim Taymans  <wim.taymans@gmail.com>
+
+       * sys/v4l2/gstv4l2src.c: (gst_v4l2_get_caps_info),
+       (gst_v4l2src_set_caps), (gst_v4l2src_get_mmap):
+       Restructure the setcaps function so that we can also compute the
+       expected GStreamer output size of the video frames.
+       Set frame_byte_size correctly so that read-based devices have a chance
+       of working correctly.
+       When grabbing a frame, discard frames that are not of the expected size.
+       Some cameras don't output the right framesize for the first buffer.
+       Try only a couple of times to get a valid frame, else error out.
+
+       * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities),
+       (gst_v4l2_fill_lists), (gst_v4l2_get_input):
+       Add some more debug info when scanning the device.
+
+       * sys/v4l2/v4l2src_calls.c: (gst_v4l2_buffer_new),
+       (gst_v4l2_buffer_pool_new), (gst_v4l2_buffer_pool_activate),
+       (gst_v4l2src_fill_format_list), (gst_v4l2src_grab_frame),
+       (gst_v4l2src_set_capture), (gst_v4l2src_capture_init):
+       Add some more debug info when dequeing a frame.
+
 2007-09-04  Stefan Kost  <ensonic@users.sf.net>
 
        * gst/wavparse/gstwavparse.c:
index 5cc184a..d0c1ddb 100644 (file)
@@ -595,74 +595,6 @@ gst_v4l2src_v4l2fourcc_to_structure (guint32 fourcc)
   return structure;
 }
 
-static guint32
-gst_v4l2_fourcc_from_structure (GstStructure * structure)
-{
-  guint32 fourcc = 0;
-  const gchar *mimetype = gst_structure_get_name (structure);
-
-  if (!strcmp (mimetype, "video/x-raw-yuv")) {
-    gst_structure_get_fourcc (structure, "format", &fourcc);
-
-    switch (fourcc) {
-      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
-      case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
-        fourcc = V4L2_PIX_FMT_YUV420;
-        break;
-      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
-        fourcc = V4L2_PIX_FMT_YUYV;
-        break;
-      case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
-        fourcc = V4L2_PIX_FMT_Y41P;
-        break;
-      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
-        fourcc = V4L2_PIX_FMT_UYVY;
-        break;
-      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
-        fourcc = V4L2_PIX_FMT_YVU420;
-        break;
-      case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
-        fourcc = V4L2_PIX_FMT_YUV411P;
-        break;
-      case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
-        fourcc = V4L2_PIX_FMT_YUV422P;
-        break;
-    }
-  } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
-    gint depth, endianness, r_mask;
-
-    gst_structure_get_int (structure, "depth", &depth);
-    gst_structure_get_int (structure, "endianness", &endianness);
-    gst_structure_get_int (structure, "red_mask", &r_mask);
-
-    switch (depth) {
-      case 8:
-        fourcc = V4L2_PIX_FMT_RGB332;
-        break;
-      case 15:
-        fourcc = (endianness == G_LITTLE_ENDIAN) ?
-            V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
-        break;
-      case 16:
-        fourcc = (endianness == G_LITTLE_ENDIAN) ?
-            V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
-        break;
-      case 24:
-        fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
-        break;
-      case 32:
-        fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
-        break;
-    }
-  } else if (strcmp (mimetype, "video/x-dv") == 0) {
-    fourcc = V4L2_PIX_FMT_DV;
-  } else if (strcmp (mimetype, "image/jpeg") == 0) {
-    fourcc = V4L2_PIX_FMT_JPEG;
-  }
-
-  return fourcc;
-}
-
 static struct v4l2_fmtdesc *
 gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
 {
@@ -689,14 +621,6 @@ gst_v4l2src_get_format_from_fourcc (GstV4l2Src * v4l2src, guint32 fourcc)
   return NULL;
 }
 
-static struct v4l2_fmtdesc *
-gst_v4l2_structure_to_v4l2fourcc (GstV4l2Src * v4l2src,
-    GstStructure * structure)
-{
-  return gst_v4l2src_get_format_from_fourcc (v4l2src,
-      gst_v4l2_fourcc_from_structure (structure));
-}
-
 static GstCaps *
 gst_v4l2src_get_all_caps (void)
 {
@@ -771,15 +695,132 @@ gst_v4l2src_get_caps (GstBaseSrc * src)
   return ret;
 }
 
+/* collect data for the given caps
+ * @caps: given input caps
+ * @format: location for the v4l format
+ * @w/@h: location for width and height
+ * @fps_n/@fps_d: location for framerate
+ * @size: location for expected size of the frame or 0 if unknown
+ */
+static gboolean
+gst_v4l2_get_caps_info (GstV4l2Src * v4l2src, GstCaps * caps,
+    struct v4l2_fmtdesc **format, gint * w, gint * h, guint * fps_n,
+    guint * fps_d, guint * size)
+{
+  GstStructure *structure;
+  const GValue *framerate;
+  guint32 fourcc;
+  const gchar *mimetype;
+  guint outsize;
+
+  /* default unknown values */
+  fourcc = 0;
+  outsize = 0;
+
+  structure = gst_caps_get_structure (caps, 0);
+
+  if (!gst_structure_get_int (structure, "width", w))
+    return FALSE;
+
+  if (!gst_structure_get_int (structure, "height", h))
+    return FALSE;
+
+  framerate = gst_structure_get_value (structure, "framerate");
+  if (!framerate)
+    return FALSE;
+
+  *fps_n = gst_value_get_fraction_numerator (framerate);
+  *fps_d = gst_value_get_fraction_denominator (framerate);
+
+  mimetype = gst_structure_get_name (structure);
+
+  if (!strcmp (mimetype, "video/x-raw-yuv")) {
+    gst_structure_get_fourcc (structure, "format", &fourcc);
+
+    switch (fourcc) {
+      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+      case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
+        fourcc = V4L2_PIX_FMT_YUV420;
+        outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+        outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
+        break;
+      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+        fourcc = V4L2_PIX_FMT_YUYV;
+        outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+        break;
+      case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
+        fourcc = V4L2_PIX_FMT_Y41P;
+        outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+        break;
+      case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+        fourcc = V4L2_PIX_FMT_UYVY;
+        outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
+        break;
+      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+        fourcc = V4L2_PIX_FMT_YVU420;
+        outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
+        outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
+        break;
+      case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
+        fourcc = V4L2_PIX_FMT_YUV411P;
+        outsize = GST_ROUND_UP_4 (*w) * *h;
+        outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
+        break;
+      case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
+        fourcc = V4L2_PIX_FMT_YUV422P;
+        outsize = GST_ROUND_UP_4 (*w) * *h;
+        outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
+        break;
+    }
+  } else if (!strcmp (mimetype, "video/x-raw-rgb")) {
+    gint depth, endianness, r_mask;
+
+    gst_structure_get_int (structure, "depth", &depth);
+    gst_structure_get_int (structure, "endianness", &endianness);
+    gst_structure_get_int (structure, "red_mask", &r_mask);
+
+    switch (depth) {
+      case 8:
+        fourcc = V4L2_PIX_FMT_RGB332;
+        break;
+      case 15:
+        fourcc = (endianness == G_LITTLE_ENDIAN) ?
+            V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
+        break;
+      case 16:
+        fourcc = (endianness == G_LITTLE_ENDIAN) ?
+            V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
+        break;
+      case 24:
+        fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
+        break;
+      case 32:
+        fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
+        break;
+    }
+  } else if (strcmp (mimetype, "video/x-dv") == 0) {
+    fourcc = V4L2_PIX_FMT_DV;
+  } else if (strcmp (mimetype, "image/jpeg") == 0) {
+    fourcc = V4L2_PIX_FMT_JPEG;
+  }
+
+  if (fourcc == 0)
+    return FALSE;
+
+  *format = gst_v4l2src_get_format_from_fourcc (v4l2src, fourcc);
+  *size = outsize;
+
+  return TRUE;
+}
+
 static gboolean
 gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
 {
   GstV4l2Src *v4l2src;
   gint w = 0, h = 0;
-  GstStructure *structure;
   struct v4l2_fmtdesc *format;
-  const GValue *framerate;
   guint fps_n, fps_d;
+  guint size;
 
   v4l2src = GST_V4L2SRC (src);
 
@@ -796,28 +837,14 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
       return FALSE;
   }
 
-  structure = gst_caps_get_structure (caps, 0);
-
   /* we want our own v4l2 type of fourcc codes */
-  if (!(format = gst_v4l2_structure_to_v4l2fourcc (v4l2src, structure))) {
-    GST_DEBUG_OBJECT (v4l2src, "can't get capture format from caps %"
-        GST_PTR_FORMAT, caps);
+  if (!gst_v4l2_get_caps_info (v4l2src, caps, &format, &w, &h, &fps_n, &fps_d,
+          &size)) {
+    GST_DEBUG_OBJECT (v4l2src,
+        "can't get capture format from caps %" GST_PTR_FORMAT, caps);
     return FALSE;
   }
 
-  if (!gst_structure_get_int (structure, "width", &w))
-    return FALSE;
-
-  if (!gst_structure_get_int (structure, "height", &h))
-    return FALSE;
-
-  framerate = gst_structure_get_value (structure, "framerate");
-  if (!framerate)
-    return FALSE;
-
-  fps_n = gst_value_get_fraction_numerator (framerate);
-  fps_d = gst_value_get_fraction_denominator (framerate);
-
   GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, "
       "format %s", w, h, fps_n, fps_d, format->description);
 
@@ -832,6 +859,9 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps)
   if (!gst_v4l2src_capture_start (v4l2src))
     return FALSE;
 
+  /* now store the expected output size */
+  v4l2src->frame_byte_size = size;
+
   return TRUE;
 }
 
@@ -945,7 +975,46 @@ read_error:
 static GstFlowReturn
 gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf)
 {
-  return gst_v4l2src_grab_frame (v4l2src, buf);
+  GstBuffer *temp;
+  GstFlowReturn ret;
+  guint size;
+  guint count;
+
+  count = 0;
+
+again:
+  ret = gst_v4l2src_grab_frame (v4l2src, &temp);
+  if (ret != GST_FLOW_OK)
+    goto done;
+
+  if (v4l2src->frame_byte_size > 0) {
+    size = GST_BUFFER_SIZE (temp);
+
+    /* if size does not match what we expected, try again */
+    if (size != v4l2src->frame_byte_size) {
+      GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ,
+          (_("Got unexpected frame size of %u instead of %u."),
+              size, v4l2src->frame_byte_size), (NULL));
+      gst_buffer_unref (temp);
+      if (count++ > 50)
+        goto size_error;
+
+      goto again;
+    }
+  }
+
+  *buf = temp;
+done:
+  return ret;
+
+  /* ERRORS */
+size_error:
+  {
+    GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
+        (_("Error read()ing %d bytes on device '%s'."),
+            v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL));
+    return GST_FLOW_ERROR;
+  }
 }
 
 static GstFlowReturn
index 0721a2e..6233d01 100644 (file)
@@ -51,7 +51,11 @@ GST_DEBUG_CATEGORY_EXTERN (v4l2_debug);
 gboolean
 gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
 {
-  GST_DEBUG_OBJECT (v4l2object->element, "getting capabilities");
+  GstElement *e;
+
+  e = v4l2object->element;
+
+  GST_DEBUG_OBJECT (e, "getting capabilities");
 
   if (!GST_V4L2_IS_OPEN (v4l2object))
     return FALSE;
@@ -59,6 +63,12 @@ gst_v4l2_get_capabilities (GstV4l2Object * v4l2object)
   if (ioctl (v4l2object->video_fd, VIDIOC_QUERYCAP, &v4l2object->vcap) < 0)
     goto cap_failed;
 
+  GST_LOG_OBJECT (e, "driver:      '%s'", v4l2object->vcap.driver);
+  GST_LOG_OBJECT (e, "card:        '%s'", v4l2object->vcap.card);
+  GST_LOG_OBJECT (e, "bus_info:    '%s'", v4l2object->vcap.bus_info);
+  GST_LOG_OBJECT (e, "version:     %08x", v4l2object->vcap.version);
+  GST_LOG_OBJECT (e, "capabilites: %08x", v4l2object->vcap.capabilities);
+
   return TRUE;
 
   /* ERRORS */
@@ -82,11 +92,14 @@ static gboolean
 gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
 {
   gint n;
+  GstElement *e;
+
+  e = v4l2object->element;
 
-  GST_DEBUG_OBJECT (v4l2object->element, "getting enumerations");
+  GST_DEBUG_OBJECT (e, "getting enumerations");
   GST_V4L2_CHECK_OPEN (v4l2object);
 
-  GST_DEBUG_OBJECT (v4l2object->element, "  channels");
+  GST_DEBUG_OBJECT (e, "  channels");
   /* and now, the channels */
   for (n = 0;; n++) {
     struct v4l2_input input;
@@ -98,7 +111,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
       if (errno == EINVAL)
         break;                  /* end of enumeration */
       else {
-        GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+        GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
             (_("Failed to query attributes of input %d in device %s"),
                 n, v4l2object->videodev),
             ("Failed to get %d in input enumeration for %s. (%d - %s)",
@@ -107,13 +120,19 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
       }
     }
 
-    GST_DEBUG_OBJECT (v4l2object->element, "    '%s'", input.name);
+    GST_LOG_OBJECT (e, "   index:     %d", input.index);
+    GST_LOG_OBJECT (e, "   name:      '%s'", input.name);
+    GST_LOG_OBJECT (e, "   type:      %08x", input.type);
+    GST_LOG_OBJECT (e, "   audioset:  %08x", input.audioset);
+    GST_LOG_OBJECT (e, "   std:       %016x", input.std);
+    GST_LOG_OBJECT (e, "   status:    %08x", input.status);
 
     v4l2channel = g_object_new (GST_TYPE_V4L2_TUNER_CHANNEL, NULL);
     channel = GST_TUNER_CHANNEL (v4l2channel);
     channel->label = g_strdup ((const gchar *) input.name);
     channel->flags = GST_TUNER_CHANNEL_INPUT;
     v4l2channel->index = n;
+
     if (input.type == V4L2_INPUT_TYPE_TUNER) {
       struct v4l2_tuner vtun;
 
@@ -122,12 +141,13 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
 
       vtun.index = input.tuner;
       if (ioctl (v4l2object->video_fd, VIDIOC_G_TUNER, &vtun) < 0) {
-        GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+        GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
             (_("Failed to get setting of tuner %d on device '%s'."),
                 input.tuner, v4l2object->videodev), GST_ERROR_SYSTEM);
         g_object_unref (G_OBJECT (channel));
         return FALSE;
       }
+
       channel->freq_multiplicator =
           62.5 * ((vtun.capability & V4L2_TUNER_CAP_LOW) ? 1 : 1000);
       channel->min_frequency = vtun.rangelow * channel->freq_multiplicator;
@@ -147,7 +167,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
         g_list_append (v4l2object->channels, (gpointer) channel);
   }
 
-  GST_DEBUG_OBJECT (v4l2object->element, "  norms");
+  GST_DEBUG_OBJECT (e, "  norms");
   /* norms... */
   for (n = 0;; n++) {
     struct v4l2_standard standard;
@@ -158,11 +178,12 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
     standard.frameperiod.numerator = 1;
     standard.frameperiod.denominator = 0;
     standard.index = n;
+
     if (ioctl (v4l2object->video_fd, VIDIOC_ENUMSTD, &standard) < 0) {
       if (errno == EINVAL)
         break;                  /* end of enumeration */
       else {
-        GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+        GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
             (_("Failed to query norm on device '%s'."),
                 v4l2object->videodev),
             ("Failed to get attributes for norm %d on devide '%s'. (%d - %s)",
@@ -171,7 +192,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
       }
     }
 
-    GST_DEBUG_OBJECT (v4l2object->element, "    '%s', fps: %d / %d",
+    GST_DEBUG_OBJECT (e, "    '%s', fps: %d / %d",
         standard.name, standard.frameperiod.denominator,
         standard.frameperiod.numerator);
 
@@ -185,7 +206,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
     v4l2object->norms = g_list_append (v4l2object->norms, (gpointer) norm);
   }
 
-  GST_DEBUG_OBJECT (v4l2object->element, "  controls+menus");
+  GST_DEBUG_OBJECT (e, "  controls+menus");
   /* and lastly, controls+menus (if appropriate) */
   for (n = V4L2_CID_BASE;; n++) {
     struct v4l2_queryctrl control;
@@ -194,7 +215,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
 
     /* when we reached the last official CID, continue with private CIDs */
     if (n == V4L2_CID_LASTP1) {
-      GST_DEBUG_OBJECT (v4l2object->element, "checking private CIDs");
+      GST_DEBUG_OBJECT (e, "checking private CIDs");
       n = V4L2_CID_PRIVATE_BASE;
       /* FIXME: We are still not handling private controls. We need a new GstInterface
          to export those controls */
@@ -210,7 +231,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
         else
           break;
       } else {
-        GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+        GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
             (_("Failed getting controls attributes on device '%s.'"),
                 v4l2object->videodev),
             ("Failed querying control %d on device '%s'. (%d - %s)",
@@ -253,7 +274,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
         /* FIXME: We should implement GstMixer interface */
         /* fall through */
       default:
-        GST_DEBUG_OBJECT (v4l2object->element,
+        GST_DEBUG_OBJECT (e,
             "ControlID %s (%x) unhandled, FIXME", control.name, n);
         control.id++;
         break;
@@ -261,8 +282,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
     if (n != control.id)
       continue;
 
-    GST_DEBUG_OBJECT (v4l2object->element,
-        "Adding ControlID %s (%x)", control.name, n);
+    GST_DEBUG_OBJECT (e, "Adding ControlID %s (%x)", control.name, n);
     v4l2channel = g_object_new (GST_TYPE_V4L2_COLOR_BALANCE_CHANNEL, NULL);
     channel = GST_COLOR_BALANCE_CHANNEL (v4l2channel);
     channel->label = g_strdup ((const gchar *) control.name);
@@ -281,7 +301,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
           if (errno == EINVAL)
             break;              /* end of enumeration */
           else {
-            GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, SETTINGS,
+            GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
                 (_("Failed getting controls attributes on device '%s'."),
                     v4l2object->videodev),
                 ("Failed to get %d in menu enumeration for %s. (%d - %s)",
@@ -310,7 +330,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
         /* FIXME we should find out how to handle V4L2_CTRL_TYPE_BUTTON.
            BUTTON controls like V4L2_CID_DO_WHITE_BALANCE can just be set (1) or
            unset (0), but can't be queried */
-        GST_DEBUG_OBJECT (v4l2object->element,
+        GST_DEBUG_OBJECT (e,
             "Control with non supported type %s (%x), type=%d",
             control.name, n, control.type);
         channel->min_value = channel->max_value = 0;
@@ -320,7 +340,7 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
     v4l2object->colors = g_list_append (v4l2object->colors, (gpointer) channel);
   }
 
-  GST_DEBUG_OBJECT (v4l2object->element, "done");
+  GST_DEBUG_OBJECT (e, "done");
   return TRUE;
 }
 
@@ -720,6 +740,8 @@ gst_v4l2_get_input (GstV4l2Object * v4l2object, gint * input)
 
   *input = n;
 
+  GST_DEBUG_OBJECT (v4l2object->element, "input: %d", n);
+
   return TRUE;
 
   /* ERRORS */
index 0006f0e..5483e6d 100644 (file)
@@ -138,12 +138,16 @@ static GstV4l2Buffer *
 gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
 {
   GstV4l2Buffer *ret;
+  guint8 *data;
 
   ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER);
 
+  GST_LOG ("creating buffer %u, %p in pool %p", index, ret, pool);
+
   ret->pool = pool;
   gst_mini_object_ref (GST_MINI_OBJECT (pool));
   memset (&ret->vbuffer, 0x00, sizeof (ret->vbuffer));
+
   ret->vbuffer.index = index;
   ret->vbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
   ret->vbuffer.memory = V4L2_MEMORY_MMAP;
@@ -151,18 +155,34 @@ gst_v4l2_buffer_new (GstV4l2BufferPool * pool, guint index, GstCaps * caps)
   if (ioctl (pool->video_fd, VIDIOC_QUERYBUF, &ret->vbuffer) < 0)
     goto querybuf_failed;
 
-  GST_BUFFER_DATA (ret) = mmap (0, ret->vbuffer.length,
+  GST_LOG ("  index:     %u", ret->vbuffer.index);
+  GST_LOG ("  type:      %d", ret->vbuffer.type);
+  GST_LOG ("  bytesused: %u", ret->vbuffer.bytesused);
+  GST_LOG ("  flags:     %08x", ret->vbuffer.flags);
+  GST_LOG ("  field:     %d", ret->vbuffer.field);
+  GST_LOG ("  memory:    %d", ret->vbuffer.memory);
+  if (ret->vbuffer.memory == V4L2_MEMORY_MMAP)
+    GST_LOG ("  MMAP offset:  %u", ret->vbuffer.m.offset);
+  GST_LOG ("  length:    %u", ret->vbuffer.length);
+  GST_LOG ("  input:     %u", ret->vbuffer.input);
+
+  data = mmap (0, ret->vbuffer.length,
       PROT_READ | PROT_WRITE, MAP_SHARED, pool->video_fd,
       ret->vbuffer.m.offset);
 
-  if (GST_BUFFER_DATA (ret) == MAP_FAILED)
+  if (data == MAP_FAILED)
     goto mmap_failed;
 
+  GST_BUFFER_DATA (ret) = data;
+  GST_BUFFER_SIZE (ret) = ret->vbuffer.length;
+
   GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY);
+
   gst_buffer_set_caps (GST_BUFFER (ret), caps);
 
   return ret;
 
+  /* ERRORS */
 querybuf_failed:
   {
     gint errnosave = errno;
@@ -266,6 +286,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Src * v4l2src, gint fd, gint num_buffers,
 
   return pool;
 
+  /* ERRORS */
 dup_failed:
   {
     gint errnosave = errno;
@@ -296,18 +317,22 @@ gst_v4l2_buffer_pool_activate (GstV4l2BufferPool * pool, GstV4l2Src * v4l2src)
   g_mutex_lock (pool->lock);
 
   for (n = 0; n < pool->buffer_count; n++) {
-    struct v4l2_buffer *buf = &pool->buffers[n]->vbuffer;
+    struct v4l2_buffer *buf;
+
+    buf = &pool->buffers[n]->vbuffer;
+
+    GST_LOG ("enqueue pool buffer %d", n);
 
     if (ioctl (pool->video_fd, VIDIOC_QBUF, buf) < 0)
       goto queue_failed;
   }
-
   pool->running = TRUE;
 
   g_mutex_unlock (pool->lock);
 
   return TRUE;
 
+  /* ERRORS */
 queue_failed:
   {
     GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ,
@@ -367,19 +392,27 @@ gst_v4l2src_fill_format_list (GstV4l2Src * v4l2src)
 
     format->index = n;
     format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
     if (ioctl (v4l2src->v4l2object->video_fd, VIDIOC_ENUM_FMT, format) < 0) {
-      if (errno == EINVAL) {
+      if (errno == EINVAL)
         break;                  /* end of enumeration */
-      else
+      else
         goto failed;
     }
-    GST_DEBUG_OBJECT (v4l2src, "got format %" GST_FOURCC_FORMAT,
+
+    GST_LOG_OBJECT (v4l2src, "index:       %u", format->index);
+    GST_LOG_OBJECT (v4l2src, "type:        %d", format->type);
+    GST_LOG_OBJECT (v4l2src, "flags:       %08x", format->flags);
+    GST_LOG_OBJECT (v4l2src, "description: '%s'", format->description);
+    GST_LOG_OBJECT (v4l2src, "pixelformat: %" GST_FOURCC_FORMAT,
         GST_FOURCC_ARGS (format->pixelformat));
 
     v4l2src->formats = g_slist_prepend (v4l2src->formats, format);
   }
   v4l2src->formats = g_slist_reverse (v4l2src->formats);
+
   GST_DEBUG_OBJECT (v4l2src, "got %d format(s)", n);
+
   return TRUE;
 
   /* ERRORS */
@@ -803,8 +836,9 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l2src, GstBuffer ** buf)
     *buf = pool_buffer;
   }
 
-  GST_LOG_OBJECT (v4l2src, "grabbed frame %d (ix=%d), pool-ct=%d",
-      buffer.sequence, buffer.index, v4l2src->pool->num_live_buffers);
+  GST_LOG_OBJECT (v4l2src, "grabbed frame %d (ix=%d), flags %08x, pool-ct=%d",
+      buffer.sequence, buffer.index, buffer.flags,
+      v4l2src->pool->num_live_buffers);
 
   return GST_FLOW_OK;
 
@@ -910,11 +944,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
       if (stream.parm.capture.timeperframe.numerator != fps_d
           || stream.parm.capture.timeperframe.denominator != fps_n)
         goto invalid_framerate;
-
     }
   }
 
-
   return TRUE;
 
   /* ERRORS */
@@ -986,24 +1018,30 @@ gst_v4l2src_capture_init (GstV4l2Src * v4l2src, GstCaps * caps)
   GST_V4L2_CHECK_NOT_ACTIVE (v4l2src->v4l2object);
 
   if (v4l2src->v4l2object->vcap.capabilities & V4L2_CAP_STREAMING) {
-    breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    breq.count = v4l2src->num_buffers;
 
+    GST_DEBUG_OBJECT (v4l2src, "STREAMING, requesting %d MMAP CAPTURE buffers",
+        v4l2src->num_buffers);
+
+    breq.count = v4l2src->num_buffers;
+    breq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     breq.memory = V4L2_MEMORY_MMAP;
+
     if (ioctl (fd, VIDIOC_REQBUFS, &breq) < 0)
       goto reqbufs_failed;
 
+    GST_LOG_OBJECT (v4l2src, " count:  %u", breq.count);
+    GST_LOG_OBJECT (v4l2src, " type:   %d", breq.type);
+    GST_LOG_OBJECT (v4l2src, " memory: %d", breq.memory);
+
     if (breq.count < GST_V4L2_MIN_BUFFERS)
       goto no_buffers;
 
     if (v4l2src->num_buffers != breq.count) {
+      GST_WARNING_OBJECT (v4l2src, "using %u buffers instead", breq.count);
       v4l2src->num_buffers = breq.count;
       g_object_notify (G_OBJECT (v4l2src), "queue-size");
     }
 
-    GST_INFO_OBJECT (v4l2src, "Got %d buffers of size %d kB",
-        breq.count, v4l2src->frame_byte_size / 1024);
-
     /* Map the buffers */
     GST_LOG_OBJECT (v4l2src, "initiating buffer pool");