aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil-cisco@xs4all.nl>2019-02-08 14:57:04 (GMT)
committerHans Verkuil <hverkuil-cisco@xs4all.nl>2019-02-08 14:57:04 (GMT)
commit98d5622551eb6b9a0397464fb52378949f33c364 (patch)
tree74e25496ad319c1372902e313ba063b7b2c86917
parenta18e32691ed8112e4f5e3d3c1bc37168d711e3bf (diff)
v4l2-compliance: support m2m devices with -f
It is now possible to test m2m devices with the -f option. All combinations of output and capture formats will be tested. In order to speed up this test an optional argument can be given to have to capture only that many frames per streaming test. Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.1.in5
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.cpp28
-rw-r--r--utils/v4l2-compliance/v4l2-compliance.h8
-rw-r--r--utils/v4l2-compliance/v4l2-test-buffers.cpp180
-rw-r--r--utils/v4l2-compliance/v4l2-test-media.cpp6
5 files changed, 192 insertions, 35 deletions
diff --git a/utils/v4l2-compliance/v4l2-compliance.1.in b/utils/v4l2-compliance/v4l2-compliance.1.in
index 94b6e7f..c75a7e7 100644
--- a/utils/v4l2-compliance/v4l2-compliance.1.in
+++ b/utils/v4l2-compliance/v4l2-compliance.1.in
@@ -127,13 +127,14 @@ a valid input (or output) and frequency (when the device has a tuner). For DMABU
The configuration of the driver at the time v4l2-compliance was called
will be used for the streaming tests.
.TP
-\fB\-f\fR, \fB\-\-stream\-all\-formats\fR
+\fB\-f\fR, \fB\-\-stream\-all\-formats\fR \fI[<count>]\fR
Test whether all available formats can be streamed. This attempts to stream using
MMAP mode or read/write (if V4L2_MEMORY_MMAP is not available) for one second for all
formats, at all sizes, at all intervals and with all field values. In addition, if the
driver supports scaling, cropping or composing it will test that as well in various
combinations. If the driver supports a lot of combinations then this test can take
-a long time.
+a long time. If \fI<count>\fR is given, then stream for that many frames instead of
+for one second.
The configuration of the driver at the time v4l2-compliance was called
will be used for the streaming tests.
diff --git a/utils/v4l2-compliance/v4l2-compliance.cpp b/utils/v4l2-compliance/v4l2-compliance.cpp
index d18a443..7ad8d10 100644
--- a/utils/v4l2-compliance/v4l2-compliance.cpp
+++ b/utils/v4l2-compliance/v4l2-compliance.cpp
@@ -143,7 +143,7 @@ static struct option long_options[] = {
{"streaming", optional_argument, 0, OptStreaming},
{"stream-from", required_argument, 0, OptStreamFrom},
{"stream-from-hdr", required_argument, 0, OptStreamFromHdr},
- {"stream-all-formats", no_argument, 0, OptStreamAllFormats},
+ {"stream-all-formats", optional_argument, 0, OptStreamAllFormats},
{"stream-all-io", no_argument, 0, OptStreamAllIO},
{"stream-all-color", required_argument, 0, OptStreamAllColorTest},
{0, 0, 0, 0}
@@ -211,11 +211,12 @@ static void usage(void)
printf(" The --stream-from-hdr variant uses the format written by\n");
printf(" v4l2-ctl --stream-to-hdr where the payload sizes for each\n");
printf(" buffer are stored in a header. Useful for compressed formats.\n");
- printf(" -f, --stream-all-formats\n");
+ printf(" -f, --stream-all-formats [<count>]\n");
printf(" Test streaming all available formats.\n");
printf(" This attempts to stream using MMAP mode or read/write\n");
printf(" for one second for all formats, at all sizes, at all intervals\n");
- printf(" and with all field values.\n");
+ printf(" and with all field values. If <count> is given, then stream\n");
+ printf(" for that many frames instead of one second.\n");
printf(" -a, --stream-all-io\n");
printf(" Do streaming tests for all inputs or outputs instead of just\n");
printf(" the current input or output. This requires that a valid video\n");
@@ -898,7 +899,7 @@ err:
}
void testNode(struct node &node, struct node &expbuf_node, media_type type,
- unsigned frame_count)
+ unsigned frame_count, unsigned all_fmt_frame_count)
{
struct node node2;
struct v4l2_capability vcap; /* list_cap */
@@ -1355,10 +1356,15 @@ void testNode(struct node &node, struct node &expbuf_node, media_type type,
printf("Stream using all formats:\n");
if (node.is_m2m) {
- printf("\tNot supported for M2M devices\n");
+ if (node.codec_mask &
+ (JPEG_DECODER | STATEFUL_DECODER | STATELESS_DECODER)) {
+ printf("\tNot supported for decoder devices\n");
+ } else {
+ streamM2MAllFormats(&node, all_fmt_frame_count);
+ }
} else {
streamingSetup(&node);
- streamAllFormats(&node);
+ streamAllFormats(&node, all_fmt_frame_count);
}
}
@@ -1397,7 +1403,8 @@ show_total:
grand_warnings += warnings;
if (node.is_media() && options[OptSetMediaDevice]) {
- walkTopology(node, expbuf_node, frame_count);
+ walkTopology(node, expbuf_node,
+ frame_count, all_fmt_frame_count);
/* Final test report */
printf("\nGrand Total for %s device %s: %d, Succeeded: %d, Failed: %d, Warnings: %d\n",
driver.c_str(), node.device,
@@ -1424,6 +1431,7 @@ int main(int argc, char **argv)
struct utsname uts;
int v1, v2, v3;
unsigned frame_count = 60;
+ unsigned all_fmt_frame_count = 0;
char short_options[26 * 2 * 3 + 1];
char *value, *subs;
int idx = 0;
@@ -1531,6 +1539,10 @@ int main(int argc, char **argv)
}
break;
}
+ case OptStreamAllFormats:
+ if (optarg)
+ all_fmt_frame_count = strtoul(optarg, NULL, 0);
+ break;
case OptStreamAllColorTest:
subs = optarg;
while (*subs != '\0') {
@@ -1652,7 +1664,7 @@ int main(int argc, char **argv)
}
}
- testNode(node, expbuf_node, type, frame_count);
+ testNode(node, expbuf_node, type, frame_count, all_fmt_frame_count);
if (!expbuf_device.empty())
expbuf_node.close();
diff --git a/utils/v4l2-compliance/v4l2-compliance.h b/utils/v4l2-compliance/v4l2-compliance.h
index f353b6f..d342a44 100644
--- a/utils/v4l2-compliance/v4l2-compliance.h
+++ b/utils/v4l2-compliance/v4l2-compliance.h
@@ -254,7 +254,7 @@ int check_ustring(const __u8 *s, int len);
int check_0(const void *p, int len);
int restoreFormat(struct node *node);
void testNode(struct node &node, struct node &expbuf_node, media_type type,
- unsigned frame_count);
+ unsigned frame_count, unsigned all_fmt_frame_count);
std::string stream_from(std::string pixelformat, bool &use_hdr);
// Media Controller ioctl tests
@@ -262,7 +262,8 @@ int testMediaDeviceInfo(struct node *node);
int testMediaTopology(struct node *node);
int testMediaEnum(struct node *node);
int testMediaSetupLink(struct node *node);
-void walkTopology(struct node &node, struct node &expbuf_node, unsigned frame_count);
+void walkTopology(struct node &node, struct node &expbuf_node,
+ unsigned frame_count, unsigned all_fmt_frame_count);
// Debug ioctl tests
int testRegister(struct node *node);
@@ -330,7 +331,8 @@ int testUserPtr(struct node *node, unsigned frame_count, enum poll_mode pollmode
int testDmaBuf(struct node *expbuf_node, struct node *node, unsigned frame_count,
enum poll_mode pollmode);
int testRequests(struct node *node, bool test_streaming);
-void streamAllFormats(struct node *node);
+void streamAllFormats(struct node *node, unsigned frame_count);
+void streamM2MAllFormats(struct node *node, unsigned frame_count);
// Color tests
int testColorsAllFormats(struct node *node, unsigned component,
diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
index f51a001..5728a87 100644
--- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
+++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
@@ -935,17 +935,19 @@ static int captureBufs(struct node *node, const cv4l_queue &q,
req_idx = (req_idx + 1) % (2 * q.g_buffers());
} while (buf_req_fds[req_idx] < 0);
}
- if (--count == 0)
+ count--;
+ if (!node->is_m2m && !count)
break;
}
if (!node->is_m2m)
continue;
buf.init(m2m_q);
- ret = buf.dqbuf(node);
- if (ret == EAGAIN)
- continue;
+ do {
+ ret = buf.dqbuf(node);
+ } while (ret == EAGAIN);
capture_count++;
+
if (show_info)
printf("\t\t%s Buffer: %d Sequence: %d Field: %s Size: %d Timestamp: %ld.%06lds\n",
v4l_type_is_output(buf.g_type()) ? "Out" : "Cap",
@@ -966,6 +968,8 @@ static int captureBufs(struct node *node, const cv4l_queue &q,
}
fail_on_test(buf.g_flags() & V4L2_BUF_FLAG_DONE);
buf.s_flags(buf.g_flags() & ~V4L2_BUF_FLAG_REQUEST_FD);
+ if (!count)
+ break;
fail_on_test(buf.qbuf(node, m2m_q));
fail_on_test(buf.g_flags() & V4L2_BUF_FLAG_DONE);
}
@@ -2094,7 +2098,7 @@ static int testStreaming(struct node *node, unsigned frame_count)
return 0;
fail_on_test(node->qbuf(buf));
fail_on_test(buf.g_flags() & V4L2_BUF_FLAG_DONE);
- if (frame_count-- == 0)
+ if (--frame_count == 0)
break;
}
q.free(node);
@@ -2211,11 +2215,11 @@ static void streamFmtRun(struct node *node, cv4l_fmt &fmt, unsigned frame_count,
node->reopen();
}
-static void streamFmt(struct node *node, __u32 pixelformat, __u32 w, __u32 h, v4l2_fract *f)
+static void streamFmt(struct node *node, __u32 pixelformat, __u32 w, __u32 h,
+ v4l2_fract *f, unsigned frame_count)
{
const char *op = (node->g_caps() & V4L2_CAP_STREAMING) ? "MMAP" :
(node->can_capture ? "read()" : "write()");
- unsigned frame_count = f ? 1.0 / fract2f(f) : 10;
bool has_compose = node->cur_io_has_compose();
bool has_crop = node->cur_io_has_crop();
__u32 default_field;
@@ -2232,6 +2236,8 @@ static void streamFmt(struct node *node, __u32 pixelformat, __u32 w, __u32 h, v4
cv4l_fmt fmt;
char hz[32] = "";
+ if (!frame_count)
+ frame_count = f ? 1.0 / fract2f(f) : 10;
node->g_fmt(fmt);
fmt.s_pixelformat(pixelformat);
fmt.s_width(w);
@@ -2432,26 +2438,28 @@ static void streamFmt(struct node *node, __u32 pixelformat, __u32 w, __u32 h, v4
restoreCropCompose(node, fmt.g_field(), crop, compose);
}
-static void streamIntervals(struct node *node, __u32 pixelformat, __u32 w, __u32 h)
+static void streamIntervals(struct node *node, __u32 pixelformat, __u32 w, __u32 h,
+ unsigned frame_count)
{
v4l2_frmivalenum frmival = { 0 };
if (node->enum_frameintervals(frmival, pixelformat, w, h)) {
- streamFmt(node, pixelformat, w, h, NULL);
+ streamFmt(node, pixelformat, w, h, NULL, frame_count);
return;
}
if (frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
do {
- streamFmt(node, pixelformat, w, h, &frmival.discrete);
+ streamFmt(node, pixelformat, w, h, &frmival.discrete,
+ frame_count);
} while (!node->enum_frameintervals(frmival));
return;
}
- streamFmt(node, pixelformat, w, h, &frmival.stepwise.min);
- streamFmt(node, pixelformat, w, h, &frmival.stepwise.max);
+ streamFmt(node, pixelformat, w, h, &frmival.stepwise.min, frame_count);
+ streamFmt(node, pixelformat, w, h, &frmival.stepwise.max, frame_count);
}
-void streamAllFormats(struct node *node)
+void streamAllFormats(struct node *node, unsigned frame_count)
{
v4l2_fmtdesc fmtdesc;
@@ -2478,17 +2486,20 @@ void streamAllFormats(struct node *node)
if (min.g_width() != fmt.g_width() ||
min.g_height() != fmt.g_height()) {
streamIntervals(node, fmtdesc.pixelformat,
- min.g_width(), min.g_frame_height());
+ min.g_width(), min.g_frame_height(),
+ frame_count);
restoreFormat(node);
}
if (max.g_width() != fmt.g_width() ||
max.g_height() != fmt.g_height()) {
streamIntervals(node, fmtdesc.pixelformat,
- max.g_width(), max.g_frame_height());
+ max.g_width(), max.g_frame_height(),
+ frame_count);
restoreFormat(node);
}
streamIntervals(node, fmtdesc.pixelformat,
- fmt.g_width(), fmt.g_frame_height());
+ fmt.g_width(), fmt.g_frame_height(),
+ frame_count);
continue;
}
@@ -2499,25 +2510,154 @@ void streamAllFormats(struct node *node)
do {
streamIntervals(node, fmtdesc.pixelformat,
frmsize.discrete.width,
- frmsize.discrete.height);
+ frmsize.discrete.height,
+ frame_count);
} while (!node->enum_framesizes(frmsize));
break;
default:
restoreFormat(node);
streamIntervals(node, fmtdesc.pixelformat,
- ss.min_width, ss.min_height);
+ ss.min_width, ss.min_height,
+ frame_count);
restoreFormat(node);
if (ss.max_width != ss.min_width ||
ss.max_height != ss.min_height) {
streamIntervals(node, fmtdesc.pixelformat,
- ss.max_width, ss.max_height);
+ ss.max_width, ss.max_height,
+ frame_count);
restoreFormat(node);
}
node->g_fmt(fmt);
if (fmt.g_width() != ss.min_width ||
fmt.g_frame_height() != ss.min_height) {
streamIntervals(node, fmtdesc.pixelformat,
- fmt.g_width(), fmt.g_frame_height());
+ fmt.g_width(), fmt.g_frame_height(),
+ frame_count);
+ restoreFormat(node);
+ }
+ break;
+ }
+ } while (!node->enum_fmt(fmtdesc));
+}
+
+static void streamM2MRun(struct node *node, unsigned frame_count)
+{
+ cv4l_fmt cap_fmt, out_fmt;
+ unsigned out_type = v4l_type_invert(node->g_type());
+
+ node->g_fmt(cap_fmt);
+ node->g_fmt(out_fmt, out_type);
+ printf("\r\t\t%s (%s) %dx%d -> %s (%s) %dx%d: %s\n",
+ fcc2s(out_fmt.g_pixelformat()).c_str(),
+ pixfmt2s(out_fmt.g_pixelformat()).c_str(),
+ out_fmt.g_width(), out_fmt.g_height(),
+ fcc2s(cap_fmt.g_pixelformat()).c_str(),
+ pixfmt2s(cap_fmt.g_pixelformat()).c_str(),
+ cap_fmt.g_width(), cap_fmt.g_height(),
+ ok(testMmap(node, frame_count, POLL_MODE_SELECT)));
+}
+
+static int streamM2MOutFormat(struct node *node, __u32 pixelformat, __u32 w, __u32 h,
+ unsigned frame_count)
+{
+ unsigned cap_type = node->g_type();
+ v4l2_fmtdesc fmtdesc;
+ cv4l_fmt out_fmt;
+
+ node->g_fmt(out_fmt, v4l_type_invert(cap_type));
+ out_fmt.s_pixelformat(pixelformat);
+ out_fmt.s_width(w);
+ out_fmt.s_height(h);
+ fail_on_test(node->s_fmt(out_fmt));
+
+ if (node->enum_fmt(fmtdesc, true, 0))
+ return 0;
+ do {
+ cv4l_fmt fmt;
+
+ fail_on_test(node->g_fmt(fmt));
+ fmt.s_pixelformat(fmtdesc.pixelformat);
+ fail_on_test(node->s_fmt(fmt));
+ streamM2MRun(node, frame_count);
+ } while (!node->enum_fmt(fmtdesc));
+ return 0;
+}
+
+void streamM2MAllFormats(struct node *node, unsigned frame_count)
+{
+ v4l2_fmtdesc fmtdesc;
+ unsigned out_type = v4l_type_invert(node->g_type());
+
+ if (node->enum_fmt(fmtdesc, true, 0, out_type))
+ return;
+ selTests.clear();
+ do {
+ v4l2_frmsizeenum frmsize;
+ cv4l_fmt fmt;
+
+ if (node->enum_framesizes(frmsize, fmtdesc.pixelformat)) {
+ cv4l_fmt min, max;
+
+ restoreFormat(node);
+ node->g_fmt(fmt);
+ min = fmt;
+ min.s_width(0);
+ min.s_height(0);
+ node->try_fmt(min);
+ max = fmt;
+ max.s_width(~0);
+ max.s_height(~0);
+ node->try_fmt(max);
+ if (min.g_width() != fmt.g_width() ||
+ min.g_height() != fmt.g_height()) {
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ min.g_width(), min.g_frame_height(),
+ frame_count);
+ restoreFormat(node);
+ }
+ if (max.g_width() != fmt.g_width() ||
+ max.g_height() != fmt.g_height()) {
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ max.g_width(), max.g_frame_height(),
+ frame_count);
+ restoreFormat(node);
+ }
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ fmt.g_width(), fmt.g_frame_height(),
+ frame_count);
+ continue;
+ }
+
+ v4l2_frmsize_stepwise &ss = frmsize.stepwise;
+
+ switch (frmsize.type) {
+ case V4L2_FRMSIZE_TYPE_DISCRETE:
+ do {
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ frmsize.discrete.width,
+ frmsize.discrete.height,
+ frame_count);
+ } while (!node->enum_framesizes(frmsize));
+ break;
+ default:
+ restoreFormat(node);
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ ss.min_width, ss.min_height,
+ frame_count);
+ restoreFormat(node);
+ if (ss.max_width != ss.min_width ||
+ ss.max_height != ss.min_height) {
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ ss.max_width, ss.max_height,
+ frame_count);
+ restoreFormat(node);
+ }
+ node->g_fmt(fmt);
+ if (fmt.g_width() != ss.min_width ||
+ fmt.g_frame_height() != ss.min_height) {
+ streamM2MOutFormat(node, fmtdesc.pixelformat,
+ fmt.g_width(), fmt.g_frame_height(),
+ frame_count);
restoreFormat(node);
}
break;
diff --git a/utils/v4l2-compliance/v4l2-test-media.cpp b/utils/v4l2-compliance/v4l2-test-media.cpp
index b2322e5..ec65ccf 100644
--- a/utils/v4l2-compliance/v4l2-test-media.cpp
+++ b/utils/v4l2-compliance/v4l2-test-media.cpp
@@ -508,7 +508,8 @@ int testMediaSetupLink(struct node *node)
return 0;
}
-void walkTopology(struct node &node, struct node &expbuf_node, unsigned frame_count)
+void walkTopology(struct node &node, struct node &expbuf_node,
+ unsigned frame_count, unsigned all_fmt_frame_count)
{
media_v2_topology topology;
@@ -583,7 +584,8 @@ void walkTopology(struct node &node, struct node &expbuf_node, unsigned frame_co
continue;
}
- testNode(test_node, expbuf_node, type, frame_count);
+ testNode(test_node, expbuf_node, type,
+ frame_count, all_fmt_frame_count);
test_node.close();
}
}

Privacy Policy