diff mbox series

[RFC] media: vb2: add support for min/rec_num_buffers

Message ID 6b303108-6ab6-43c9-9c7b-7776ef64fb06@xs4all.nl
State Superseded
Headers show
Series [RFC] media: vb2: add support for min/rec_num_buffers | expand

Commit Message

Hans Verkuil Oct. 31, 2024, 7:59 a.m. UTC
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@xs4all.nl>
---
This is a follow up to my RFC here:

https://lore.kernel.org/linux-media/126cd76a-6224-483b-a18d-a3cc89e5ff2d@xs4all.nl/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 mbox series

Patch

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

 /**