mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 06:16:36 +00:00
v4l2bufferpool: Request buffers only once
VIDIOC_REQBUFS allocates buffer, it has no place inside set_config. Also, some driver do no allow multiple calls to this ioctl. https://bugzilla.gnome.org/show_bug.cgi?id=720568
This commit is contained in:
parent
b80169a16a
commit
e1be685c34
1 changed files with 102 additions and 80 deletions
|
@ -422,10 +422,9 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
|
||||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||||
GstV4l2Object *obj = pool->obj;
|
GstV4l2Object *obj = pool->obj;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
guint size, min_buffers, max_buffers, num_buffers, copy_threshold;
|
guint size, min_buffers, max_buffers;
|
||||||
GstAllocator *allocator;
|
GstAllocator *allocator;
|
||||||
GstAllocationParams params;
|
GstAllocationParams params;
|
||||||
struct v4l2_requestbuffers breq;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pool, "set config");
|
GST_DEBUG_OBJECT (pool, "set config");
|
||||||
|
|
||||||
|
@ -459,11 +458,90 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
|
||||||
&max_buffers))
|
&max_buffers))
|
||||||
goto wrong_config;
|
goto wrong_config;
|
||||||
|
|
||||||
|
/* FIXME Check alignement, and S_FMT with new size if different */
|
||||||
|
|
||||||
if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
|
if (!gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms))
|
||||||
goto wrong_config;
|
goto wrong_config;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
|
GST_DEBUG_OBJECT (pool, "config %" GST_PTR_FORMAT, config);
|
||||||
|
|
||||||
|
if (obj->mode == GST_V4L2_IO_DMABUF)
|
||||||
|
allocator = gst_dmabuf_allocator_new ();
|
||||||
|
|
||||||
|
if (pool->allocator)
|
||||||
|
gst_object_unref (pool->allocator);
|
||||||
|
if ((pool->allocator = allocator))
|
||||||
|
gst_object_ref (allocator);
|
||||||
|
pool->params = params;
|
||||||
|
|
||||||
|
gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
|
||||||
|
max_buffers);
|
||||||
|
|
||||||
|
return GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
missing_video_api:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (pool, "missing GstMetaVideo API in config, "
|
||||||
|
"default stride: %d, wanted stride %u",
|
||||||
|
GST_VIDEO_INFO_PLANE_STRIDE (&obj->info, 0), obj->bytesperline[0]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
wrong_config:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
start_streaming (GstV4l2BufferPool * pool)
|
||||||
|
{
|
||||||
|
GstV4l2Object *obj = pool->obj;
|
||||||
|
|
||||||
|
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, "STREAMON");
|
||||||
|
if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
|
||||||
|
goto start_failed;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool->streaming = TRUE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
start_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
|
||||||
|
g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
|
||||||
|
{
|
||||||
|
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
||||||
|
GstV4l2Object *obj = pool->obj;
|
||||||
|
GstStructure *config;
|
||||||
|
GstCaps *caps;
|
||||||
|
guint size, num_buffers, min_buffers, max_buffers, copy_threshold;
|
||||||
|
struct v4l2_requestbuffers breq;
|
||||||
|
|
||||||
|
config = gst_buffer_pool_get_config (bpool);
|
||||||
|
if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers,
|
||||||
|
&max_buffers))
|
||||||
|
goto wrong_config;
|
||||||
|
|
||||||
switch (obj->mode) {
|
switch (obj->mode) {
|
||||||
case GST_V4L2_IO_RW:
|
case GST_V4L2_IO_RW:
|
||||||
/* we preallocate 1 buffer, this value also instructs the latency
|
/* we preallocate 1 buffer, this value also instructs the latency
|
||||||
|
@ -518,6 +596,9 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
|
||||||
* copy */
|
* copy */
|
||||||
copy_threshold = 0;
|
copy_threshold = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME try to call CREATEBUFS with count 0 to check if max shall
|
||||||
|
* remain 0 */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GST_V4L2_IO_USERPTR:
|
case GST_V4L2_IO_USERPTR:
|
||||||
|
@ -532,86 +613,9 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
|
||||||
pool->num_buffers = num_buffers;
|
pool->num_buffers = num_buffers;
|
||||||
pool->copy_threshold = copy_threshold;
|
pool->copy_threshold = copy_threshold;
|
||||||
|
|
||||||
if (obj->mode == GST_V4L2_IO_DMABUF)
|
|
||||||
allocator = gst_dmabuf_allocator_new ();
|
|
||||||
|
|
||||||
if (pool->allocator)
|
|
||||||
gst_object_unref (pool->allocator);
|
|
||||||
if ((pool->allocator = allocator))
|
|
||||||
gst_object_ref (allocator);
|
|
||||||
pool->params = params;
|
|
||||||
|
|
||||||
gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
|
gst_buffer_pool_config_set_params (config, caps, size, min_buffers,
|
||||||
max_buffers);
|
max_buffers);
|
||||||
|
GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
|
||||||
return GST_BUFFER_POOL_CLASS (parent_class)->set_config (bpool, config);
|
|
||||||
|
|
||||||
/* ERRORS */
|
|
||||||
missing_video_api:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (pool, "missing GstMetaVideo API in config, "
|
|
||||||
"default stride: %d, wanted stride %u",
|
|
||||||
GST_VIDEO_INFO_PLANE_STRIDE (&obj->info, 0), obj->bytesperline[0]);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
wrong_config:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
reqbufs_failed:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (pool,
|
|
||||||
"error requesting %d buffers: %s", num_buffers, g_strerror (errno));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
no_buffers:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (pool,
|
|
||||||
"we received %d from device '%s', we want at least %d",
|
|
||||||
breq.count, obj->videodev, GST_V4L2_MIN_BUFFERS);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
start_streaming (GstV4l2BufferPool * pool)
|
|
||||||
{
|
|
||||||
GstV4l2Object *obj = pool->obj;
|
|
||||||
|
|
||||||
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, "STREAMON");
|
|
||||||
if (v4l2_ioctl (pool->video_fd, VIDIOC_STREAMON, &obj->type) < 0)
|
|
||||||
goto start_failed;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pool->streaming = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/* ERRORS */
|
|
||||||
start_failed:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (pool, "error with STREAMON %d (%s)", errno,
|
|
||||||
g_strerror (errno));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
|
|
||||||
{
|
|
||||||
GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool);
|
|
||||||
GstV4l2Object *obj = pool->obj;
|
|
||||||
|
|
||||||
pool->obj = obj;
|
pool->obj = obj;
|
||||||
pool->buffers = g_new0 (GstBuffer *, pool->num_buffers);
|
pool->buffers = g_new0 (GstBuffer *, pool->num_buffers);
|
||||||
|
@ -632,6 +636,24 @@ gst_v4l2_buffer_pool_start (GstBufferPool * bpool)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
wrong_config:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (pool, "invalid config %" GST_PTR_FORMAT, config);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
reqbufs_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (pool,
|
||||||
|
"error requesting %d buffers: %s", num_buffers, g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
no_buffers:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (pool,
|
||||||
|
"we received %d from device '%s', we want at least %d",
|
||||||
|
breq.count, obj->videodev, GST_V4L2_MIN_BUFFERS);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
start_failed:
|
start_failed:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (pool, "failed to start streaming");
|
GST_ERROR_OBJECT (pool, "failed to start streaming");
|
||||||
|
|
Loading…
Reference in a new issue