}
static gboolean
-start_streaming (GstV4l2BufferPool * pool)
+gst_v4l2_buffer_pool_streamon (GstV4l2BufferPool * pool)
{
GstV4l2Object *obj = pool->obj;
- GST_DEBUG_OBJECT (pool, "start streaming");
-
- if (pool->streaming)
- return 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:
case GST_V4L2_IO_DMABUF_IMPORT:
- {
- /* For capture device, we need to re-enqueue buffers before be can let
- * the driver stream again */
- if (!V4L2_TYPE_IS_OUTPUT (obj->type) && pool->vallocator) {
- GstBufferPool *bpool = GST_BUFFER_POOL (pool);
- GstBufferPoolAcquireParams params = { 0 };
- gsize num_allocated, num_to_queue;
- GstFlowReturn ret;
-
- num_allocated = gst_v4l2_allocator_num_allocated (pool->vallocator);
- num_to_queue = num_allocated - pool->num_queued;
+ if (!pool->streaming) {
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
+ goto streamon_failed;
- while (num_to_queue > 0) {
- GstBuffer *buf;
+ pool->streaming = TRUE;
- params.flags = GST_BUFFER_POOL_ACQUIRE_FLAG_DONTWAIT;
- ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
- &buf, ¶ms);
+ GST_DEBUG_OBJECT (pool, "Started streaming");
+ }
+ break;
+ default:
+ break;
+ }
- if (ret != GST_FLOW_OK)
- goto requeue_failed;
+ return TRUE;
- gst_v4l2_buffer_pool_release_buffer (bpool, buf);
- num_to_queue--;
- }
+streamon_failed:
+ {
+ GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
+ g_strerror (errno));
+ return FALSE;
+ }
+}
- if (num_allocated != pool->num_queued)
- goto requeue_failed;
- }
+static gboolean
+gst_v4l2_buffer_pool_streamoff (GstV4l2BufferPool * pool)
+{
+ GstV4l2Object *obj = pool->obj;
- if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
- goto start_failed;
+ switch (obj->mode) {
+ case GST_V4L2_IO_MMAP:
+ case GST_V4L2_IO_USERPTR:
+ case GST_V4L2_IO_DMABUF:
+ case GST_V4L2_IO_DMABUF_IMPORT:
+ if (pool->streaming) {
+ if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
+ goto streamoff_failed;
- GST_DEBUG_OBJECT (pool, "STREAMON");
+ pool->streaming = FALSE;
+ GST_DEBUG_OBJECT (pool, "Stopped streaming");
+ }
break;
- }
default:
- g_assert_not_reached ();
break;
}
- pool->streaming = TRUE;
-
return TRUE;
- /* ERRORS */
-start_failed:
+streamoff_failed:
{
- GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
+ GST_ERROR_OBJECT (pool, "error with STREAMOFF %d (%s)", errno,
g_strerror (errno));
return FALSE;
}
-requeue_failed:
- {
- GST_ERROR_OBJECT (pool, "failed to re-enqueue buffers");
- return FALSE;
- }
}
static void
gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
{
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
GstV4l2Object *obj = pool->obj;
GstStructure *config;
GstCaps *caps;
gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
max_buffers);
- GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
+ pclass->set_config (bpool, config);
gst_structure_free (config);
if (pool->other_pool)
goto other_pool_failed;
/* now, allocate the buffers: */
- if (!GST_BUFFER_POOL_CLASS (parent_class)->start (bpool))
+ if (!pclass->start (bpool))
goto start_failed;
- /* 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;
-
if (!V4L2_TYPE_IS_OUTPUT (obj->type))
pool->group_released_handler =
g_signal_connect_swapped (pool->vallocator, "group-released",
G_CALLBACK (gst_v4l2_buffer_pool_group_released), pool);
- gst_poll_set_flushing (obj->poll, FALSE);
-
return TRUE;
/* ERRORS */
}
}
-
static gboolean
-stop_streaming (GstV4l2BufferPool * pool)
+gst_v4l2_buffer_pool_stop (GstBufferPool * bpool)
{
- GstV4l2Object *obj = pool->obj;
+ GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
+ gboolean ret;
gint i;
- GST_DEBUG_OBJECT (pool, "stopping stream");
+ GST_DEBUG_OBJECT (pool, "stopping pool");
- gst_poll_set_flushing (obj->poll, TRUE);
+ if (pool->group_released_handler > 0) {
+ g_signal_handler_disconnect (pool->vallocator,
+ pool->group_released_handler);
+ pool->group_released_handler = 0;
+ }
+
+ if (pool->other_pool) {
+ gst_object_unref (pool->other_pool);
+ pool->other_pool = NULL;
+ }
+
+ if (!gst_v4l2_buffer_pool_streamoff (pool))
+ goto streamoff_failed;
+
+ gst_v4l2_allocator_flush (pool->vallocator);
+
+ for (i = 0; i < VIDEO_MAX_FRAME; i++) {
+ if (pool->buffers[i]) {
+ GstBuffer *buffer = pool->buffers[i];
+
+ pool->buffers[i] = NULL;
+
+ if (V4L2_TYPE_IS_OUTPUT (pool->obj->type))
+ gst_buffer_unref (buffer);
+ else
+ pclass->release_buffer (bpool, buffer);
+
+ g_atomic_int_add (&pool->num_queued, -1);
+ }
+ }
+
+ ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
+
+ if (ret) {
+ GstV4l2Return vret;
+
+ vret = gst_v4l2_allocator_stop (pool->vallocator);
- if (!pool->streaming) {
- /* it avoid error: STREAMOFF 22 (Invalid argument) when
- * attempting to stop a stream not previously started */
- GST_DEBUG_OBJECT (pool, "no need to stop, was not previously started");
- return TRUE;
+ if (vret == GST_V4L2_BUSY)
+ GST_WARNING_OBJECT (pool, "some buffers are still outstanding");
+
+ ret = (vret == GST_V4L2_OK);
}
- pool->flushing = TRUE;
+ return ret;
+
+ /* ERRORS */
+streamoff_failed:
+ GST_ERROR_OBJECT (pool, "device refused to stop streaming");
+ return FALSE;
+}
+
+static void
+gst_v4l2_buffer_pool_flush_start (GstBufferPool * bpool)
+{
+ GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+
+ GST_DEBUG_OBJECT (pool, "start flushing");
+
+ gst_poll_set_flushing (pool->poll, TRUE);
+
+ if (pool->other_pool)
+ gst_buffer_pool_set_flushing (pool->other_pool, TRUE);
+}
+
+static void
+gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool)
+{
+ GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstV4l2Object *obj = pool->obj;
+ gint i;
+
+ GST_DEBUG_OBJECT (pool, "stop flushing");
+
+ /* If we haven't started streaming yet, simply call streamon */
+ if (!pool->streaming)
+ goto streamon;
+
+ if (pool->other_pool)
+ gst_buffer_pool_set_flushing (pool->other_pool, FALSE);
+ if (!gst_v4l2_buffer_pool_streamoff (pool))
+ goto stop_failed;
+
+ gst_v4l2_allocator_flush (pool->vallocator);
+
+ /* Reset our state */
switch (obj->mode) {
case GST_V4L2_IO_RW:
break;
{
gsize num_allocated;
- if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMOFF, &obj->type) < 0)
- goto stop_failed;
-
- GST_DEBUG_OBJECT (pool, "STREAMOFF");
-
- gst_v4l2_allocator_flush (pool->vallocator);
-
num_allocated = gst_v4l2_allocator_num_allocated (pool->vallocator);
for (i = 0; i < num_allocated; i++) {
+ /* Re-enqueue buffers */
if (pool->buffers[i]) {
GstBufferPool *bpool = (GstBufferPool *) pool;
GstBuffer *buffer = pool->buffers[i];
pool->buffers[i] = NULL;
- pool->num_queued--;
- /* Remove qdata, this will unmap any map data in userptr */
+ /* Remove qdata, this will unmap any map data in
+ * userptr/dmabuf-import */
gst_mini_object_set_qdata (GST_MINI_OBJECT (buffer),
GST_V4L2_IMPORT_QUARK, NULL, NULL);
if (V4L2_TYPE_IS_OUTPUT (obj->type))
gst_buffer_unref (buffer);
else
- /* Give back the outstanding buffer to the pool */
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool,
- buffer);
+ gst_v4l2_buffer_pool_release_buffer (bpool, buffer);
+
+ g_atomic_int_add (&pool->num_queued, -1);
}
}
- g_return_val_if_fail (pool->num_queued == 0, FALSE);
break;
}
default:
- g_return_val_if_reached (FALSE);
+ g_assert_not_reached ();
break;
}
- pool->flushing = FALSE;
- 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)
-{
- gboolean ret;
- GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
- GstV4l2Object *obj = pool->obj;
-
- GST_DEBUG_OBJECT (pool, "stopping pool");
-
- if (pool->group_released_handler > 0) {
- g_signal_handler_disconnect (pool->vallocator,
- pool->group_released_handler);
- pool->group_released_handler = 0;
- }
-
- gst_poll_set_flushing (obj->poll, TRUE);
- if (!stop_streaming (pool))
- goto stop_failed;
-
- ret = GST_BUFFER_POOL_CLASS (parent_class)->stop (bpool);
-
- if (ret) {
- GstV4l2Return vret;
-
- vret = gst_v4l2_allocator_stop (pool->vallocator);
+streamon:
+ /* Start streaming on capture device only */
+ if (!V4L2_TYPE_IS_OUTPUT (obj->type))
+ gst_v4l2_buffer_pool_streamon (pool);
- if (vret == GST_V4L2_BUSY) {
- GST_WARNING_OBJECT (pool, "allocated buffer need to be reclaimed");
- /* FIXME deal with reclaiming */
- } else if (vret == GST_V4L2_ERROR) {
- ret = FALSE;
- }
- }
+ gst_poll_set_flushing (pool->poll, FALSE);
- return ret;
+ return;
/* ERRORS */
stop_failed:
{
- GST_ERROR_OBJECT (pool, "error with STREAMOFF %d (%s)", errno,
- g_strerror (errno));
- return FALSE;
+ GST_ERROR_OBJECT (pool, "device refused to flush");
}
}
static GstFlowReturn
-gst_v4l2_object_poll (GstV4l2Object * v4l2object)
+gst_v4l2_buffer_pool_poll (GstV4l2BufferPool * pool)
{
gint ret;
- if (v4l2object->can_poll_device) {
- GST_LOG_OBJECT (v4l2object->element, "polling device");
- ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE);
+ if (pool->can_poll_device) {
+ GST_LOG_OBJECT (pool, "polling device");
+ ret = gst_poll_wait (pool->poll, GST_CLOCK_TIME_NONE);
+ GST_LOG_OBJECT (pool, "device polled %i %s", ret, g_strerror (errno));
if (G_UNLIKELY (ret < 0)) {
if (errno == EBUSY)
goto stopped;
if (errno == ENXIO) {
- GST_WARNING_OBJECT (v4l2object->element,
+ GST_WARNING_OBJECT (pool,
"v4l2 device doesn't support polling. Disabling");
- v4l2object->can_poll_device = FALSE;
+ pool->can_poll_device = FALSE;
} else {
if (errno != EAGAIN && errno != EINTR)
goto select_error;
/* ERRORS */
stopped:
{
- GST_DEBUG ("stop called");
+ GST_DEBUG_OBJECT (pool, "stop called");
return GST_FLOW_FLUSHING;
}
select_error:
{
- GST_ELEMENT_ERROR (v4l2object->element, RESOURCE, READ, (NULL),
+ GST_ELEMENT_ERROR (pool->obj->element, RESOURCE, READ, (NULL),
("poll error %d: %s (%d)", ret, g_strerror (errno), errno));
return GST_FLOW_ERROR;
}
goto queue_failed;
pool->buffers[index] = buf;
- pool->num_queued++;
+ g_atomic_int_inc (&pool->num_queued);
return GST_FLOW_OK;
GstV4l2MemoryGroup *group;
gint i;
- if ((res = gst_v4l2_object_poll (obj)) != GST_FLOW_OK)
+ if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK)
goto poll_failed;
GST_LOG_OBJECT (pool, "dequeueing a buffer");
/* mark the buffer outstanding */
pool->buffers[group->buffer.index] = NULL;
- pool->num_queued--;
+ g_atomic_int_add (&pool->num_queued, -1);
timestamp = GST_TIMEVAL_TO_TIME (group->buffer.timestamp);
{
GstFlowReturn ret;
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
GstV4l2Object *obj = pool->obj;
GST_DEBUG_OBJECT (pool, "acquire");
- if (GST_BUFFER_POOL_IS_FLUSHING (bpool))
- goto flushing;
-
/* If this is being called to resurect a lost buffer */
if (params && params->flags & GST_V4L2_POOL_ACQUIRE_FLAG_RESURECT) {
- ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool, buffer,
- params);
+ ret = pclass->acquire_buffer (bpool, buffer, params);
goto done;
}
case GST_V4L2_IO_RW:
{
/* take empty buffer from the pool */
- ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
- buffer, params);
+ ret = pclass->acquire_buffer (bpool, buffer, params);
break;
}
case GST_V4L2_IO_DMABUF:
goto done;
/* start copying buffers when we are running low on buffers */
- if (pool->num_queued < pool->copy_threshold) {
+ if (g_atomic_int_get (&pool->num_queued) < pool->copy_threshold) {
GstBuffer *copy;
if (GST_V4L2_ALLOCATOR_CAN_ALLOCATE (pool->vallocator, MMAP)) {
- if (GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
- ©, params) == GST_FLOW_OK) {
+ if (pclass->acquire_buffer (bpool, ©, params) == GST_FLOW_OK) {
gst_v4l2_buffer_pool_release_buffer (bpool, copy);
break;
}
switch (obj->mode) {
case GST_V4L2_IO_RW:
/* get an empty buffer */
- ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
- buffer, params);
+ ret = pclass->acquire_buffer (bpool, buffer, params);
break;
case GST_V4L2_IO_MMAP:
case GST_V4L2_IO_USERPTR:
case GST_V4L2_IO_DMABUF_IMPORT:
/* get a free unqueued buffer */
- ret = GST_BUFFER_POOL_CLASS (parent_class)->acquire_buffer (bpool,
- buffer, params);
+ ret = pclass->acquire_buffer (bpool, buffer, params);
break;
default:
}
done:
return ret;
-
- /* ERRORS */
-flushing:
- {
- GST_DEBUG_OBJECT (pool, "We are flushing");
- return GST_FLOW_FLUSHING;
- }
}
static void
gst_v4l2_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer)
{
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
+ GstBufferPoolClass *pclass = GST_BUFFER_POOL_CLASS (parent_class);
GstV4l2Object *obj = pool->obj;
GST_DEBUG_OBJECT (pool, "release buffer %p", buffer);
switch (obj->mode) {
case GST_V4L2_IO_RW:
/* release back in the pool */
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool, buffer);
+ pclass->release_buffer (bpool, buffer);
break;
case GST_V4L2_IO_DMABUF:
case GST_V4L2_IO_USERPTR:
case GST_V4L2_IO_DMABUF_IMPORT:
{
- if (pool->flushing) {
- /* put back on outstanding list */
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool,
- buffer);
- } else if (gst_v4l2_is_buffer_valid (buffer, NULL)) {
+ if (gst_v4l2_is_buffer_valid (buffer, NULL)) {
/* 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)
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool,
- buffer);
+ pclass->release_buffer (bpool, buffer);
} else {
/* Simply release invalide/modified buffer, the allocator will
* give it back later */
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool,
- buffer);
+ pclass->release_buffer (bpool, buffer);
}
break;
}
switch (obj->mode) {
case GST_V4L2_IO_RW:
/* release back in the pool */
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool, buffer);
+ pclass->release_buffer (bpool, buffer);
break;
case GST_V4L2_IO_MMAP:
/* Simply release invalide/modified buffer, the allocator will
* give it back later */
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_TAG_MEMORY);
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool,
- buffer);
+ pclass->release_buffer (bpool, buffer);
break;
}
gst_v4l2_allocator_reset_group (pool->vallocator, group);
/* playback, put the buffer back in the queue to refill later. */
- GST_BUFFER_POOL_CLASS (parent_class)->release_buffer (bpool,
- buffer);
+ pclass->release_buffer (bpool, buffer);
} else {
/* We keep a ref on queued buffer, so this should never happen */
g_assert_not_reached ();
if (pool->video_fd >= 0)
v4l2_close (pool->video_fd);
+ gst_poll_free (pool->poll);
+
if (pool->vallocator)
gst_object_unref (pool->vallocator);
static void
gst_v4l2_buffer_pool_init (GstV4l2BufferPool * pool)
{
+ pool->poll = gst_poll_new (TRUE);
+ pool->can_poll_device = TRUE;
}
static void
bufferpool_class->alloc_buffer = gst_v4l2_buffer_pool_alloc_buffer;
bufferpool_class->acquire_buffer = gst_v4l2_buffer_pool_acquire_buffer;
bufferpool_class->release_buffer = gst_v4l2_buffer_pool_release_buffer;
+ bufferpool_class->flush_start = gst_v4l2_buffer_pool_flush_start;
+ bufferpool_class->flush_stop = gst_v4l2_buffer_pool_flush_stop;
}
/**
GstStructure *config;
gchar *name, *parent_name;
gint fd;
+ GstPollFD pollfd = GST_POLL_FD_INIT;
fd = v4l2_dup (obj->video_fd);
if (fd < 0)
"name", name, NULL);
g_free (name);
+ pollfd.fd = fd;
+ gst_poll_add_fd (pool->poll, &pollfd);
+ if (V4L2_TYPE_IS_OUTPUT (obj->type))
+ gst_poll_fd_ctl_write (pool->poll, &pollfd, TRUE);
+ else
+ gst_poll_fd_ctl_read (pool->poll, &pollfd, TRUE);
+
pool->video_fd = fd;
pool->obj = obj;
+ pool->can_poll_device = TRUE;
pool->vallocator =
gst_v4l2_allocator_new (GST_OBJECT (pool), obj->video_fd, &obj->format);
gst_buffer_map (buf, &map, GST_MAP_WRITE);
do {
- if ((res = gst_v4l2_object_poll (obj)) != GST_FLOW_OK)
+ if ((res = gst_v4l2_buffer_pool_poll (pool)) != GST_FLOW_OK)
goto poll_error;
amount = v4l2_read (obj->video_fd, map.data, toread);
g_return_val_if_fail (gst_buffer_pool_is_active (bpool), GST_FLOW_ERROR);
+ if (GST_BUFFER_POOL_IS_FLUSHING (pool))
+ return GST_FLOW_FLUSHING;
+
switch (obj->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
/* if we are not streaming yet (this is the first buffer, start
* streaming now */
- if (!pool->streaming) {
- if (!start_streaming (pool)) {
- gst_buffer_unref (to_queue);
- goto start_failed;
- }
+ if (!gst_v4l2_buffer_pool_streamon (pool)) {
+ gst_buffer_unref (to_queue);
+ goto start_failed;
}
- if (pool->num_queued ==
+ if (g_atomic_int_get (&pool->num_queued) ==
gst_v4l2_allocator_num_allocated (pool->vallocator)) {
GstBuffer *out;
/* all buffers are queued, try to dequeue one and release it back
}
}
-
-/**
- * gst_v4l2_buffer_pool_stop_streaming:
- * @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.
- *
- * Returns: TRUE on success.
- */
-gboolean
-gst_v4l2_buffer_pool_stop_streaming (GstV4l2BufferPool * pool)
-{
- GST_DEBUG_OBJECT (pool, "stop streaming");
-
- if (!stop_streaming (pool))
- goto stop_failed;
-
- return TRUE;
-
- /* ERRORS */
-stop_failed:
- {
- GST_ERROR_OBJECT (pool, "failed to stop streaming");
- return FALSE;
- }
-}
-
-gboolean
-gst_v4l2_buffer_pool_start_streaming (GstV4l2BufferPool * pool)
-{
- GST_DEBUG_OBJECT (pool, "start straming");
-
- if (!start_streaming (pool))
- goto start_failed;
-
- return TRUE;
-
- /* ERRORS */
-start_failed:
- {
- GST_ERROR_OBJECT (pool, "failed to start streaming");
- return FALSE;
- }
-}
-
void
gst_v4l2_buffer_pool_set_other_pool (GstV4l2BufferPool * pool,
GstBufferPool * other_pool)
{
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
- GST_DEBUG_OBJECT (self, "Flushing");
+ GST_DEBUG_OBJECT (self, "Flushed");
- /* Wait for capture thread to stop */
- GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- gst_v4l2_object_unlock (self->v4l2capture);
- gst_pad_stop_task (decoder->srcpad);
- GST_VIDEO_DECODER_STREAM_LOCK (decoder);
+ /* Ensure the processing thread has stopped for the reverse playback
+ * discount case */
+ if (g_atomic_int_get (&self->processing)) {
+ GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- self->output_flow = GST_FLOW_OK;
+ gst_v4l2_object_unlock (self->v4l2output);
+ gst_v4l2_object_unlock (self->v4l2capture);
+ gst_pad_stop_task (decoder->srcpad);
+ GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
+ }
- if (self->v4l2output->pool)
- gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
- (self->v4l2output->pool));
+ self->output_flow = GST_FLOW_OK;
- if (self->v4l2capture->pool)
- gst_v4l2_buffer_pool_stop_streaming (GST_V4L2_BUFFER_POOL
- (self->v4l2capture->pool));
+ gst_v4l2_object_unlock_stop (self->v4l2output);
+ gst_v4l2_object_unlock_stop (self->v4l2capture);
return TRUE;
}
v4l2output->pool), &buffer);
gst_buffer_unref (buffer);
}
- GST_VIDEO_DECODER_STREAM_LOCK (decoder);
- /* Ensure the processing thread has stopped */
- if (g_atomic_int_get (&self->processing)) {
- gst_v4l2_object_unlock (self->v4l2capture);
- gst_pad_stop_task (decoder->srcpad);
- g_assert (g_atomic_int_get (&self->processing) == FALSE);
- }
+ /* and ensure the processing thread has stopped in case another error
+ * occured. */
+ gst_v4l2_object_unlock (self->v4l2capture);
+ gst_pad_stop_task (decoder->srcpad);
+ GST_VIDEO_DECODER_STREAM_LOCK (decoder);
if (ret == GST_FLOW_FLUSHING)
ret = self->output_flow;
}
GST_VIDEO_DECODER_STREAM_UNLOCK (decoder);
- gst_v4l2_object_unlock_stop (self->v4l2output);
ret =
gst_v4l2_buffer_pool_process (GST_V4L2_BUFFER_POOL (self->
v4l2output->pool), &codec_data);
- gst_v4l2_object_unlock (self->v4l2output);
GST_VIDEO_DECODER_STREAM_LOCK (decoder);
gst_buffer_unref (codec_data);
GST_DEBUG_OBJECT (self, "Starting decoding thread");
- /* Enable processing input */
- if (!gst_v4l2_buffer_pool_start_streaming (GST_V4L2_BUFFER_POOL
- (self->v4l2capture->pool)))
- goto start_streaming_failed;
-
- gst_v4l2_object_unlock_stop (self->v4l2output);
- gst_v4l2_object_unlock_stop (self->v4l2capture);
-
/* Start the processing task, when it quits, the task will disable input
* processing to unlock input if draining, or prevent potential block */
g_atomic_int_set (&self->processing, TRUE);
ret = GST_FLOW_NOT_NEGOTIATED;
goto drop;
}
-start_streaming_failed:
- {
- GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
- (_("Failed to re-enabled decoder.")),
- ("Could not re-enqueue and start streaming on decide."));
- return GST_FLOW_ERROR;
- }
activate_failed:
{
GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS,
gst_v4l2_video_dec_sink_event (GstVideoDecoder * decoder, GstEvent * event)
{
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
+ gboolean ret;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
gst_v4l2_object_unlock (self->v4l2output);
gst_v4l2_object_unlock (self->v4l2capture);
+ break;
default:
break;
}
- return GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
+ ret = GST_VIDEO_DECODER_CLASS (parent_class)->sink_event (decoder, event);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_START:
+ /* The processing thread should stop now, wait for it */
+ gst_pad_stop_task (decoder->srcpad);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
}
static GstStateChangeReturn
GstStateChange transition)
{
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (element);
+ GstVideoDecoder *decoder = GST_VIDEO_DECODER (element);
if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) {
g_atomic_int_set (&self->active, FALSE);
gst_v4l2_object_unlock (self->v4l2output);
gst_v4l2_object_unlock (self->v4l2capture);
+ gst_pad_stop_task (decoder->srcpad);
}
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);