v4l2: Probe for CREATE_BUFS in order to correctly set pool min/max

In order to correctly set the pool min/max, we need to probe for CREATE_BUFS
ioctl. This can be done as soon as the format has been negotiated using a
count of 0.
This commit is contained in:
Nicolas Dufresne 2014-03-27 18:41:07 -04:00
parent 8d6e72a299
commit 0028de808b
3 changed files with 28 additions and 16 deletions

View file

@ -165,10 +165,7 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
memset (&create_bufs, 0, sizeof (struct v4l2_create_buffers));
create_bufs.count = 1;
create_bufs.memory = V4L2_MEMORY_MMAP;
create_bufs.format.type = obj->type;
if (v4l2_ioctl (pool->video_fd, VIDIOC_G_FMT, &create_bufs.format) < 0)
goto g_fmt_failed;
create_bufs.format = obj->format;
if (v4l2_ioctl (pool->video_fd, VIDIOC_CREATE_BUFS, &create_bufs) < 0)
goto create_bufs_failed;
@ -365,14 +362,6 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
return GST_FLOW_OK;
/* ERRORS */
g_fmt_failed:
{
gint errnosave = errno;
GST_WARNING ("Failed G_FMT: %s", g_strerror (errnosave));
errno = errnosave;
return GST_FLOW_ERROR;
}
create_bufs_failed:
{
gint errnosave = errno;
@ -1301,6 +1290,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
GstStructure *config;
gboolean res = FALSE;
gint fd;
guint min, max;
fd = v4l2_dup (obj->video_fd);
if (fd < 0)
@ -1309,10 +1299,30 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
pool = (GstV4l2BufferPool *) g_object_new (GST_TYPE_V4L2_BUFFER_POOL, NULL);
pool->video_fd = fd;
pool->obj = obj;
pool->can_alloc = TRUE;
pool->can_alloc = FALSE;
min = max = 2;
/* Check for CREATE_BUFS support */
switch (obj->mode) {
case GST_V4L2_IO_MMAP:
case GST_V4L2_IO_DMABUF:
{
struct v4l2_create_buffers create_bufs = { 0 };
create_bufs.count = 0;
create_bufs.memory = V4L2_MEMORY_MMAP;
create_bufs.format = obj->format;
if (v4l2_ioctl (pool->video_fd, VIDIOC_CREATE_BUFS, &create_bufs) == 0) {
pool->can_alloc = TRUE;
max = 0;
}
break;
}
default:
break;
}
config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
gst_buffer_pool_config_set_params (config, caps, obj->sizeimage, 2, 0);
gst_buffer_pool_config_set_params (config, caps, obj->sizeimage, min, max);
/* Ensure our internal pool has required features */
if (obj->need_video_meta)

View file

@ -2331,6 +2331,7 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
gst_video_info_align (info, align);
v4l2object->info = *info;
v4l2object->align = *align;
v4l2object->format = *format;
v4l2object->fmtdesc = fmtdesc;
/* if we have a framerate pre-calculate duration */
@ -3032,8 +3033,8 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
}
/* Request a bigger max, if one was suggested but it's too small */
if (max != 0 && max < min)
max = min;
if (max != 0)
max = MAX (min, max);
has_video_meta =
gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);

View file

@ -96,6 +96,7 @@ struct _GstV4l2Object {
/* the current format */
struct v4l2_fmtdesc *fmtdesc;
struct v4l2_format format;
GstVideoInfo info;
GstVideoAlignment align;