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
This commit is contained in:
Julien Isorce 2013-12-18 13:37:23 -05:00 committed by Nicolas Dufresne
parent 062f4f8710
commit c701dcd16c
2 changed files with 125 additions and 0 deletions

View file

@ -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;
}
}

View file

@ -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__ */