v4l2: Ask the driver about its requirements for min_buffers before initiating buffer...
authorTobias Modschiedler <tobias.modschiedler@cetitec.com>
Mon, 30 Mar 2015 11:12:35 +0000 (13:12 +0200)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>
Thu, 2 Apr 2015 21:29:19 +0000 (17:29 -0400)
If propose_allocation() had not been called yet, it was possible that the driver was not asked at all.
In buffer pool: Consider minimum number of buffers requested by driver when setting config.

https://bugzilla.gnome.org/show_bug.cgi?id=746834

sys/v4l2/gstv4l2bufferpool.c
sys/v4l2/gstv4l2object.c

index 4815336..dec617b 100644 (file)
@@ -549,6 +549,13 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
     GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
   }
 
+  /* respect driver requirements */
+  if (min_buffers < obj->min_buffers) {
+    updated = TRUE;
+    min_buffers = obj->min_buffers;
+    GST_INFO_OBJECT (pool, "increasing minimum buffers to %u", min_buffers);
+  }
+
   if (max_buffers > VIDEO_MAX_FRAME || max_buffers == 0) {
     updated = TRUE;
     max_buffers = VIDEO_MAX_FRAME;
index 9c8dfb2..1f4b84e 100644 (file)
@@ -721,6 +721,28 @@ gst_v4l2_object_get_property_helper (GstV4l2Object * v4l2object,
 }
 
 static void
+gst_v4l2_get_driver_min_buffers (GstV4l2Object * v4l2object)
+{
+  int min;
+  gboolean ret = FALSE;
+
+  /* Certain driver may expose a minimum number of buffers through controls. */
+  /* If the ioctl is not supported by the driver, min_buffers remains zero.  */
+  ret = gst_v4l2_get_attribute (v4l2object,
+      V4L2_TYPE_IS_OUTPUT (v4l2object->type)
+      ? V4L2_CID_MIN_BUFFERS_FOR_OUTPUT : V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+      &min);
+
+  if (ret) {
+    GST_DEBUG_OBJECT (v4l2object->element,
+        "driver requires a minimum of %d buffers", min);
+    v4l2object->min_buffers = min;
+  } else {
+    v4l2object->min_buffers = 0;
+  }
+}
+
+static void
 gst_v4l2_set_defaults (GstV4l2Object * v4l2object)
 {
   GstTunerNorm *norm = NULL;
@@ -2407,6 +2429,11 @@ gst_v4l2_object_setup_pool (GstV4l2Object * v4l2object, GstCaps * caps)
   GST_INFO_OBJECT (v4l2object->element, "accessing buffers via mode %d", mode);
   v4l2object->mode = mode;
 
+  /* If min_buffers is not set, the driver either does not support the control or
+     it has not been asked yet via propose_allocation/decide_allocation. */
+  if (!v4l2object->min_buffers)
+    gst_v4l2_get_driver_min_buffers (v4l2object);
+
   /* Map the buffers */
   GST_LOG_OBJECT (v4l2object->element, "initiating buffer pool");
 
@@ -3315,7 +3342,6 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
   gboolean update;
   gboolean has_video_meta;
   gboolean can_share_own_pool, pushing_from_our_pool = FALSE;
-  struct v4l2_control ctl = { 0, };
   GstAllocator *allocator = NULL;
   GstAllocationParams params = { 0 };
 
@@ -3352,16 +3378,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
 
   can_share_own_pool = (has_video_meta || !obj->need_video_meta);
 
-  /* Certain driver may expose a minimum through controls */
-  ctl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
-  if (v4l2_ioctl (obj->video_fd, VIDIOC_G_CTRL, &ctl) >= 0) {
-    GST_DEBUG_OBJECT (obj->element, "driver require a minimum of %d buffers",
-        ctl.value);
-    obj->min_buffers = ctl.value;
-  } else {
-    obj->min_buffers = 0;
-  }
-
+  gst_v4l2_get_driver_min_buffers (obj);
   /* We can't share our own pool, if it exceed V4L2 capacity */
   if (min + obj->min_buffers + 1 > VIDEO_MAX_FRAME)
     can_share_own_pool = FALSE;
@@ -3597,7 +3614,6 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
   guint size, min, max;
   GstCaps *caps;
   gboolean need_pool;
-  struct v4l2_control ctl = { 0, };
 
   /* Set defaults allocation parameters */
   size = obj->info.size;
@@ -3629,16 +3645,7 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
     }
     gst_structure_free (config);
   }
-
-  /* Some devices may expose a minimum */
-  ctl.id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT;
-  if (v4l2_ioctl (obj->video_fd, VIDIOC_G_CTRL, &ctl) >= 0) {
-    GST_DEBUG_OBJECT (obj->element, "driver require a miminum of %d buffers",
-        ctl.value);
-    obj->min_buffers = ctl.value;
-  } else {
-    obj->min_buffers = 0;
-  }
+  gst_v4l2_get_driver_min_buffers (obj);
 
   min = MAX (obj->min_buffers, GST_V4L2_MIN_BUFFERS);