@@ -743,6 +743,7 @@ public:
unsigned g_type() const { return v4l_queue_g_type(this); }
unsigned g_memory() const { return v4l_queue_g_memory(this); }
unsigned g_buffers() const { return v4l_queue_g_buffers(this); }
+ unsigned g_max_num_buffers() const { return v4l_queue_g_max_num_buffers(this); }
unsigned g_num_planes() const { return v4l_queue_g_num_planes(this); }
unsigned g_capabilities() const { return v4l_queue_g_capabilities(this); }
unsigned g_length(unsigned plane) const { return v4l_queue_g_length(this, plane); }
@@ -1429,6 +1429,7 @@ struct v4l_queue {
unsigned mappings;
unsigned num_planes;
unsigned capabilities;
+ unsigned max_num_buffers;
__u32 lengths[VIDEO_MAX_PLANES];
__u32 mem_offsets[VIDEO_MAX_FRAME][VIDEO_MAX_PLANES];
@@ -1453,6 +1454,7 @@ static inline void v4l_queue_init(struct v4l_queue *q,
static inline unsigned v4l_queue_g_type(const struct v4l_queue *q) { return q->type; }
static inline unsigned v4l_queue_g_memory(const struct v4l_queue *q) { return q->memory; }
static inline unsigned v4l_queue_g_buffers(const struct v4l_queue *q) { return q->buffers; }
+static inline unsigned v4l_queue_g_max_num_buffers(const struct v4l_queue *q) { return q->max_num_buffers; }
static inline unsigned v4l_queue_g_mappings(const struct v4l_queue *q) { return q->mappings; }
static inline unsigned v4l_queue_g_num_planes(const struct v4l_queue *q) { return q->num_planes; }
static inline unsigned v4l_queue_g_capabilities(const struct v4l_queue *q) { return q->capabilities; }
@@ -1587,6 +1589,9 @@ static inline int v4l_queue_create_bufs(struct v4l_fd *f,
if (ret)
return ret;
q->capabilities = createbufs.capabilities;
+ q->max_num_buffers = 32;
+ if (q->capabilities & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)
+ q->max_num_buffers = createbufs.max_num_buffers;
q->buffers += createbufs.count;
return v4l_queue_querybufs(f, q, q->buffers - createbufs.count);
}
@@ -206,6 +206,7 @@ static constexpr flag_def bufcap_def[] = {
{ V4L2_BUF_CAP_SUPPORTS_ORPHANED_BUFS, "orphaned-bufs" },
{ V4L2_BUF_CAP_SUPPORTS_M2M_HOLD_CAPTURE_BUF, "m2m-hold-capture-buf" },
{ V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS, "mmap-cache-hints" },
+ { V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS, "set-max-num-buffers" },
{ 0, nullptr }
};
@@ -1453,6 +1453,7 @@ void testNode(struct node &node, struct node &node_m2m_cap, struct node &expbuf_
printf("Buffer ioctls%s:\n", suffix);
printf("\ttest VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: %s\n", ok(testReqBufs(&node)));
+ printf("\ttest CREATE_BUFS maximum buffers: %s\n", ok(testCreateBufsMax(&node)));
// Reopen after each streaming test to reset the streaming state
// in case of any errors in the preceeding test.
node.reopen();
@@ -383,6 +383,7 @@ int testReqBufs(struct node *node);
int testReadWrite(struct node *node);
int testExpBuf(struct node *node);
int testBlockingWait(struct node *node);
+int testCreateBufsMax(struct node *node);
// 32-bit architecture, 32/64-bit time_t tests
int testTime32_64(struct node *node);
@@ -761,6 +761,37 @@ int testReqBufs(struct node *node)
return 0;
}
+int testCreateBufsMax(struct node *node)
+{
+ unsigned int i;
+ int ret;
+
+ node->reopen();
+
+ cv4l_queue q(0, 0);
+
+ for (i = 1; i <= V4L2_BUF_TYPE_LAST; i++) {
+ if (!(node->valid_buftypes & (1 << i)))
+ continue;
+
+ q.init(i, V4L2_MEMORY_MMAP);
+ ret = q.create_bufs(node, 0);
+ if (!ret && (q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS)) {
+ fail_on_test(q.create_bufs(node, q.g_max_num_buffers()));
+ /* Some drivers may not have allocated all the requested buffers
+ * because of memory limitation, that is OK but make the next test
+ * failed so skip it
+ */
+ if (q.g_max_num_buffers() != q.g_buffers())
+ continue;
+ ret = q.create_bufs(node, 1);
+ fail_on_test(ret != ENOBUFS);
+ }
+ }
+
+ return 0;
+}
+
int testExpBuf(struct node *node)
{
bool have_expbuf = false;
If V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS is set v4l2_create_buffers 'max_num_buffers' field reports the maximum number of buffers supported by the queue. Add a test to allocate this maximum value and make sure that one more allocation is failing. Display the flag in v4l2-ctl. Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com> --- version 6: - fix compilation issue utils/common/cv4l-helpers.h | 1 + utils/common/v4l-helpers.h | 5 ++++ utils/common/v4l2-info.cpp | 1 + utils/v4l2-compliance/v4l2-compliance.cpp | 1 + utils/v4l2-compliance/v4l2-compliance.h | 1 + utils/v4l2-compliance/v4l2-test-buffers.cpp | 31 +++++++++++++++++++++ 6 files changed, 40 insertions(+)