v4l2bufferpool: Validate that capture buffers were queued
[platform/upstream/gst-plugins-good.git] / sys / v4l2 / gstv4l2bufferpool.c
index c3a243b..7dd862f 100644 (file)
@@ -870,6 +870,9 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
     goto start_failed;
 
   if (!V4L2_TYPE_IS_OUTPUT (obj->type)) {
+    if (g_atomic_int_get (&pool->num_queued) < min_buffers)
+      goto queue_failed;
+
     pool->group_released_handler =
         g_signal_connect_swapped (pool->vallocator, "group-released",
         G_CALLBACK (gst_v4l2_buffer_pool_resurect_buffer), pool);
@@ -904,6 +907,11 @@ other_pool_failed:
         GST_PTR_FORMAT, pool->other_pool);
     return FALSE;
   }
+queue_failed:
+  {
+    GST_ERROR_OBJECT (pool, "failed to queue buffers into the capture queue");
+    return FALSE;
+  }
 }
 
 static gboolean
@@ -1057,18 +1065,13 @@ no_buffers:
 }
 
 static GstFlowReturn
-gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf)
+gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf,
+    GstV4l2MemoryGroup * group)
 {
-  GstV4l2MemoryGroup *group = NULL;
   const GstV4l2Object *obj = pool->obj;
   GstClockTime timestamp;
   gint index;
 
-  if (!gst_v4l2_is_buffer_valid (buf, &group)) {
-    GST_ERROR_OBJECT (pool, "invalid buffer %p", buf);
-    return GST_FLOW_ERROR;
-  }
-
   index = group->buffer.index;
 
   if (pool->buffers[index] != NULL)
@@ -1415,7 +1418,7 @@ gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
             /* queue back in the device */
             if (pool->other_pool)
               gst_v4l2_buffer_pool_prepare_buffer (pool, buffer, NULL);
-            if (gst_v4l2_buffer_pool_qbuf (pool, buffer) != GST_FLOW_OK)
+            if (gst_v4l2_buffer_pool_qbuf (pool, buffer, group) != GST_FLOW_OK)
               pclass->release_buffer (bpool, buffer);
           } else {
             /* Simply release invalide/modified buffer, the allocator will
@@ -1740,12 +1743,13 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
             guint num_queued;
             gsize size = gst_buffer_get_size (*buf);
 
-            if (size == 0) {
-              if (GST_BUFFER_FLAG_IS_SET (*buf, GST_BUFFER_FLAG_CORRUPTED))
-                goto buffer_corrupted;
-              else
-                goto eos;
-            }
+            /* Legacy M2M devices return empty buffer when drained */
+            if (size == 0 && GST_V4L2_IS_M2M (obj->device_caps))
+              goto eos;
+
+            if (GST_VIDEO_INFO_FORMAT (&pool->caps_info) !=
+                GST_VIDEO_FORMAT_ENCODED && size < pool->size)
+              goto buffer_truncated;
 
             num_queued = g_atomic_int_get (&pool->num_queued);
             GST_TRACE_OBJECT (pool, "Only %i buffer left in the capture queue.",
@@ -1792,14 +1796,10 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
 
           /* An empty buffer on capture indicates the end of stream */
           if (gst_buffer_get_size (tmp) == 0) {
-            gboolean corrupted = GST_BUFFER_FLAG_IS_SET (tmp,
-                GST_BUFFER_FLAG_CORRUPTED);
-
             gst_v4l2_buffer_pool_release_buffer (bpool, tmp);
 
-            if (corrupted)
-              goto buffer_corrupted;
-            else
+            /* Legacy M2M devices return empty buffer when drained */
+            if (GST_V4L2_IS_M2M (obj->device_caps))
               goto eos;
           }
 
@@ -1911,9 +1911,13 @@ gst_v4l2_buffer_pool_process (GstV4l2BufferPool * pool, GstBuffer ** buf)
               gst_buffer_unref (to_queue);
               goto prepare_failed;
             }
+
+            /* retreive the group */
+            gst_v4l2_is_buffer_valid (to_queue, &group);
           }
 
-          if ((ret = gst_v4l2_buffer_pool_qbuf (pool, to_queue)) != GST_FLOW_OK)
+          if ((ret = gst_v4l2_buffer_pool_qbuf (pool, to_queue, group))
+              != GST_FLOW_OK)
             goto queue_failed;
 
           /* if we are not streaming yet (this is the first buffer, start
@@ -1977,9 +1981,10 @@ copy_failed:
     GST_ERROR_OBJECT (pool, "failed to copy buffer");
     return ret;
   }
-buffer_corrupted:
+buffer_truncated:
   {
-    GST_WARNING_OBJECT (pool, "Dropping corrupted buffer without payload");
+    GST_WARNING_OBJECT (pool,
+        "Dropping truncated buffer, this is likely a driver bug.");
     gst_buffer_unref (*buf);
     *buf = NULL;
     return GST_V4L2_FLOW_CORRUPTED_BUFFER;