From c701dcd16c2d4eb4ddc05f62897ea5d55ff6a558 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Wed, 18 Dec 2013 13:37:23 -0500 Subject: [PATCH] v4l2bufferpool: add gst_v4l2_buffer_pool_flush STREAMOFF set all v4l2buffers to DEQUEUE state. Then for CAPTURE we call QBUF on each buffer. For OUTPUT the buffers are just push back in the GstBufferPool base class 's queue. But the loop actually looks like the same. https://bugzilla.gnome.org/show_bug.cgi?id=720568 --- sys/v4l2/gstv4l2bufferpool.c | 123 +++++++++++++++++++++++++++++++++++ sys/v4l2/gstv4l2bufferpool.h | 2 + 2 files changed, 125 insertions(+) diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 430dea0e0d..58fc2f3948 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -663,6 +663,43 @@ gst_v4l2_buffer_pool_free_buffers (GstV4l2BufferPool * pool) } } +static gboolean +stop_streaming (GstV4l2BufferPool * pool) +{ + GstV4l2Object *obj = pool->obj; + + GST_DEBUG_OBJECT (pool, "stopping stream"); + + gst_poll_set_flushing (obj->poll, TRUE); + + switch (obj->mode) { + case GST_V4L2_IO_RW: + break; + case GST_V4L2_IO_MMAP: + case GST_V4L2_IO_USERPTR: + case GST_V4L2_IO_DMABUF: + GST_DEBUG_OBJECT (pool, "STREAMOFF"); + if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0) + goto stop_failed; + break; + default: + g_assert_not_reached (); + break; + } + + pool->streaming = FALSE; + + return TRUE; + + /* ERRORS */ +stop_failed: + { + GST_ERROR_OBJECT (pool, "error with STREAMOFF %d (%s)", errno, + g_strerror (errno)); + return FALSE; + } +} + static gboolean gst_v4l2_buffer_pool_stop (GstBufferPool * bpool) { @@ -1513,3 +1550,89 @@ start_failed: return GST_FLOW_ERROR; } } + + +/** + * gst_v4l2_buffer_pool_flush: + * @bpool: a #GstBufferPool + * + * First, set obj->poll to be flushing + * Call STREAMOFF to clear QUEUED flag on every driver buffers. + * Then release all buffers that are in pool->buffers array. + * Finally call STREAMON if CAPTURE type + * The caller is responsible to unset flushing on obj->pool + * + * Returns: TRUE on success. + */ +gboolean +gst_v4l2_buffer_pool_flush (GstV4l2BufferPool * pool) +{ + GstBufferPool *bpool = GST_BUFFER_POOL_CAST (pool); + GstV4l2Object *obj = pool->obj; + gint i = 0; + + GST_DEBUG_OBJECT (pool, "flush"); + + stop_streaming (pool); + + switch (obj->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + switch (obj->mode) { + case GST_V4L2_IO_RW: + break; + case GST_V4L2_IO_MMAP: + case GST_V4L2_IO_USERPTR: + case GST_V4L2_IO_DMABUF: + { + for (i = 0; i < pool->num_buffers; i++) { + GstBuffer *buf = pool->buffers[i]; + if (buf) { + /* it's necessary to set to NULL before to call + * gst_v4l2_buffer_pool_release_buffer + * otherwise it won't go back to the pool */ + pool->buffers[i] = NULL; + + /* dicrease counter */ + pool->num_queued--; + + /* in CAPTURE mode the pool->num_queued will be re-incremented + * because the buffers are queued when released */ + if (buf->pool) + gst_buffer_unref (buf); + else + gst_v4l2_buffer_pool_release_buffer (bpool, buf); + } + } + + /* do not set pool->num_queued to 0 because + * the buffers are queued when released */ + break; + } + + default: + g_assert_not_reached (); + break; + } + break; + default: + g_assert_not_reached (); + break; + } + /* we can start capturing now, we wait for the playback + * case until we queued the first buffer */ + if (!V4L2_TYPE_IS_OUTPUT (obj->type)) + if (!start_streaming (pool)) + goto start_failed; + + return TRUE; + + /* ERRORS */ +start_failed: + { + GST_ERROR_OBJECT (pool, "failed to start streaming"); + return FALSE; + } +} diff --git a/sys/v4l2/gstv4l2bufferpool.h b/sys/v4l2/gstv4l2bufferpool.h index f3400b931a..7a7f8c733f 100644 --- a/sys/v4l2/gstv4l2bufferpool.h +++ b/sys/v4l2/gstv4l2bufferpool.h @@ -108,6 +108,8 @@ GstBufferPool * gst_v4l2_buffer_pool_new (GstV4l2Object *obj, GstCaps *c GstFlowReturn gst_v4l2_buffer_pool_process (GstV4l2BufferPool * bpool, GstBuffer * buf); +gboolean gst_v4l2_buffer_pool_flush (GstV4l2BufferPool * pool); + G_END_DECLS #endif /*__GST_V4L2_BUFFER_POOL_H__ */