This is an automatic generated email to let you know that the following patch were queued at the http://git.linuxtv.org/cgit.cgi/v4l-utils.git tree:
Subject: v4l2-compliance: add new CREATE_BUFS tests Author: Hans Verkuil <hverkuil-ci...@xs4all.nl> Date: Wed Jun 26 13:08:03 2024 +0200 The tests to verify correct VIDIOC_CREATE_BUFS behavior were insufficient, causing drivers with bugs in their implementation to pass. Add new tests and improve existing tests so such corner cases are now caught. Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl> utils/v4l2-compliance/v4l2-test-buffers.cpp | 90 +++++++++++++++++++++++++---- 1 file changed, 79 insertions(+), 11 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=47113938a0f5aef23aad7d9cfcbbefb0e547b93f diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp index fbd68d8dbb4e..941355bc1dfe 100644 --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp @@ -671,6 +671,8 @@ int testReqBufs(struct node *node) fail_on_test_val(ret != EINVAL, ret); fail_on_test(node->node2 == nullptr); for (i = 1; i <= V4L2_BUF_TYPE_LAST; i++) { + bool is_vbi_raw = (i == V4L2_BUF_TYPE_VBI_CAPTURE || + i == V4L2_BUF_TYPE_VBI_OUTPUT); bool is_overlay = v4l_type_is_overlay(i); __u32 caps = 0; @@ -854,25 +856,91 @@ int testReqBufs(struct node *node) fail_on_test(q2.create_bufs(node->node2, 1) != EBUSY); q.reqbufs(node); - if (node->is_video) { - cv4l_fmt fmt; + cv4l_fmt fmt; + node->g_fmt(fmt, q.g_type()); + if (V4L2_TYPE_IS_MULTIPLANAR(q.g_type())) { + // num_planes == 0 is not allowed + fmt.s_num_planes(0); + fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); node->g_fmt(fmt, q.g_type()); - if (V4L2_TYPE_IS_MULTIPLANAR(q.g_type())) { + + if (fmt.g_num_planes() > 1) { + // fewer planes than required by the format + // is not allowed + fmt.s_num_planes(fmt.g_num_planes() - 1); + fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); + node->g_fmt(fmt, q.g_type()); + + // A last plane with a 0 sizeimage is not allowed + fmt.s_sizeimage(0, fmt.g_num_planes() - 1); + fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); + node->g_fmt(fmt, q.g_type()); + } + + if (fmt.g_num_planes() < VIDEO_MAX_PLANES) { + // Add an extra plane, but with size 0 fmt.s_num_planes(fmt.g_num_planes() + 1); + fmt.s_sizeimage(0, fmt.g_num_planes() - 1); + fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); + + // This test is debatable: should we allow CREATE_BUFS + // to create buffers with more planes than required + // by the format? + // + // For now disallow this. If there is a really good + // reason for allowing this, then that should be + // documented and carefully tested. + fmt.s_sizeimage(65536, fmt.g_num_planes() - 1); fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); node->g_fmt(fmt, q.g_type()); } - fmt.s_height(fmt.g_height() / 2); - for (unsigned p = 0; p < fmt.g_num_planes(); p++) + } + if (is_vbi_raw) { + fmt.fmt.vbi.count[0] = 0; + fmt.fmt.vbi.count[1] = 0; + } else { + fmt.s_sizeimage(0, 0); + } + // zero size for the first plane is not allowed + fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); + node->g_fmt(fmt, q.g_type()); + + // plane sizes that are too small are not allowed + for (unsigned p = 0; p < fmt.g_num_planes(); p++) { + if (is_vbi_raw) { + fmt.fmt.vbi.count[0] /= 2; + fmt.fmt.vbi.count[1] /= 2; + } else { fmt.s_sizeimage(fmt.g_sizeimage(p) / 2, p); - fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); - fail_on_test(testQueryBuf(node, fmt.type, q.g_buffers())); - node->g_fmt(fmt, q.g_type()); - for (unsigned p = 0; p < fmt.g_num_planes(); p++) - fmt.s_sizeimage(fmt.g_sizeimage(p) * 2, p); - fail_on_test(q.create_bufs(node, 1, &fmt)); + } } + fail_on_test(q.create_bufs(node, 1, &fmt) != EINVAL); + fail_on_test(testQueryBuf(node, fmt.type, q.g_buffers())); + node->g_fmt(fmt, q.g_type()); + + // Add 1 MB to each plane or double the vbi counts. + // This is allowed. + for (unsigned p = 0; p < fmt.g_num_planes(); p++) { + if (is_vbi_raw) { + fmt.fmt.vbi.count[0] *= 2; + fmt.fmt.vbi.count[1] *= 2; + } else { + fmt.s_sizeimage(fmt.g_sizeimage(p) + (1 << 20), p); + } + } + fail_on_test(q.create_bufs(node, 1, &fmt)); + buffer buf(q); + + // Check that the new buffer lengths are at least those of + // the large sizes as specified by CREATE_BUFS + fail_on_test(buf.querybuf(node, 0)); + fail_on_test(buf.g_num_planes() != fmt.g_num_planes()); + // Verify that the new buffers actually have the requested + // buffer size + for (unsigned p = 0; p < buf.g_num_planes(); p++) + fail_on_test(buf.g_length(p) < fmt.g_sizeimage(p)); + node->g_fmt(fmt, q.g_type()); } fail_on_test(q.reqbufs(node)); }