Report the minimum and recommended number of buffers in struct v4l2_create_buffers. This is useful for those applications that want to have more precise control over how many buffers they want to allocate. Signed-off-by: Hans Verkuil <hverkuil@xxxxxxxxx> --- This is a follow up to my RFC here: https://lore.kernel.org/linux-media/126cd76a-6224-483b-a18d-a3cc89e5ff2d@xxxxxxxxx/T/#u This patch adds a new buffer capability and new fields for struct v4l2_create_buffers to report the absolute minimum number of buffers that you have to allocate to stream, and the recommended number of buffers. min_num_buffers equals q->min_queued_buffers + 1 and rec_num_buffers equals q->min_reqbufs_allocation. I have one question how this relates to V4L2_CID_MIN_BUFFERS_FOR_CAPTURE/OUTPUT as used by codecs: I think drivers that set those controls should also update q->min_reqbufs_allocation to the same value. I think that would make sense. This is an RFC, once we are in agreement on this I will make a proper patch which also includes updating the documentation. Regards, Hans --- .../media/common/videobuf2/videobuf2-v4l2.c | 19 +++++++++++++----- include/uapi/linux/videodev2.h | 20 +++++++++++++++---- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 9201d854dbcc..15394bb4168c 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -672,7 +672,8 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b) EXPORT_SYMBOL(vb2_querybuf); static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 memory, - u32 *flags, u32 *caps, u32 *max_num_bufs) + u32 *flags, u32 *caps, u32 *max_num_bufs, + u16 *min_num_bufs, u16 *rec_num_bufs) { if (!q->allow_cache_hints || memory != V4L2_MEMORY_MMAP) { /* @@ -702,6 +703,11 @@ static void vb2_set_flags_and_caps(struct vb2_queue *q, u32 memory, *max_num_bufs = q->max_num_buffers; *caps |= V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS; } + if (min_num_bufs && rec_num_bufs) { + *min_num_bufs = q->min_queued_buffers + 1; + *rec_num_bufs = q->min_reqbufs_allocation; + *caps |= V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS; + } } int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) @@ -710,7 +716,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req) u32 flags = req->flags; vb2_set_flags_and_caps(q, req->memory, &flags, - &req->capabilities, NULL); + &req->capabilities, NULL, NULL, NULL); req->flags = flags; return ret ? ret : vb2_core_reqbufs(q, req->memory, req->flags, &req->count); @@ -753,7 +759,9 @@ int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create) create->index = vb2_get_num_buffers(q); vb2_set_flags_and_caps(q, create->memory, &create->flags, - &create->capabilities, &create->max_num_buffers); + &create->capabilities, &create->max_num_buffers, + &create->min_num_buffers, + &create->rec_num_buffers); if (create->count == 0) return ret != -EBUSY ? ret : 0; @@ -1027,7 +1035,7 @@ int vb2_ioctl_reqbufs(struct file *file, void *priv, u32 flags = p->flags; vb2_set_flags_and_caps(vdev->queue, p->memory, &flags, - &p->capabilities, NULL); + &p->capabilities, NULL, NULL, NULL); p->flags = flags; if (res) return res; @@ -1050,7 +1058,8 @@ int vb2_ioctl_create_bufs(struct file *file, void *priv, p->index = vb2_get_num_buffers(vdev->queue); vb2_set_flags_and_caps(vdev->queue, p->memory, &p->flags, - &p->capabilities, &p->max_num_buffers); + &p->capabilities, &p->max_num_buffers, + &p->min_num_buffers, &p->rec_num_buffers); /* * If count == 0, then just check if memory and type are valid. * Any -EBUSY result from vb2_verify_memory_type can be mapped to 0. diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index e7c4dce39007..e738b7956e58 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -1079,6 +1079,7 @@ struct v4l2_requestbuffers { #define V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS (1 << 6) #define V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS (1 << 7) #define V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS (1 << 8) +#define V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS (1 << 9) /** * struct v4l2_plane - plane info for multi-planar buffers @@ -2660,9 +2661,18 @@ struct v4l2_dbg_chip_info { * @flags: additional buffer management attributes (ignored unless the * queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability * and configured for MMAP streaming I/O). - * @max_num_buffers: if V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability flag is set - * this field indicate the maximum possible number of buffers - * for this queue. + * @max_num_buffers: if the V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability + * flag is set, then this field indicate the maximum possible + * number of buffers for this queue. + * @min_num_buffers: if the V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS capability + * flag is set, then this field indicate the minimum possible + * number of buffers for this queue. Using this value might cause + * dropped frames, but it will be able to stream video. Useful for + * capturing only a single frame. + * @rec_num_buffers: if the V4L2_BUF_CAP_SUPPORTS_MIN_REC_NUM_BUFFERS capability + * flag is set, then this field indicates the recommended number + * of buffers for this queue. This is also used when calling + * VIDIOC_REQBUFS with count = 1. * @reserved: future extensions */ struct v4l2_create_buffers { @@ -2673,7 +2683,9 @@ struct v4l2_create_buffers { __u32 capabilities; __u32 flags; __u32 max_num_buffers; - __u32 reserved[5]; + __u16 min_num_buffers; + __u16 rec_num_buffers; + __u32 reserved[4]; }; /** -- 2.45.2