diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index f18a40d406e2f7a2a2488950efdb2ffc85d3112d..c166bb3540881c0e255e02fc37be81325bf28b02 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -864,6 +864,9 @@ struct v4l2_fmtdesc { #define V4L2_FMT_FLAG_CSC_QUANTIZATION 0x0100 #define V4L2_FMT_FLAG_META_LINE_BASED 0x0200 +/* Format description flag, to be ORed with the index */ +#define V4L2_FMTDESC_FLAG_ENUM_ALL 0x80000000 + /* Frame Size and frame rate enumeration */ /* * F R A M E S I Z E E N U M E R A T I O N diff --git a/utils/common/v4l2-info.cpp b/utils/common/v4l2-info.cpp index aaf7b0b5297c503db3f54fe069aa7bdb1f43918e..248ab9c3863be4fe663bf5d93c04a88f9c082ead 100644 --- a/utils/common/v4l2-info.cpp +++ b/utils/common/v4l2-info.cpp @@ -383,6 +383,7 @@ static constexpr flag_def fmtdesc_ ## enc_type ## _def[] = { \ { V4L2_FMT_FLAG_CSC_QUANTIZATION, "csc-quantization" }, \ { V4L2_FMT_FLAG_CSC_XFER_FUNC, "csc-xfer-func" }, \ { V4L2_FMT_FLAG_META_LINE_BASED, "meta-line-based" }, \ + { V4L2_FMTDESC_FLAG_ENUM_ALL, "enum-all-format" }, \ { 0, NULL } \ }; diff --git a/utils/v4l2-compliance/v4l2-test-formats.cpp b/utils/v4l2-compliance/v4l2-test-formats.cpp index fc16ad3968f1db90e479ddd44cdbd5a9015201bb..2b743da548288b6c6e0a62cd7238e181f7f8d0d9 100644 --- a/utils/v4l2-compliance/v4l2-test-formats.cpp +++ b/utils/v4l2-compliance/v4l2-test-formats.cpp @@ -224,6 +224,7 @@ static int testEnumFrameSizes(struct node *node, __u32 pixfmt) static int testEnumFormatsType(struct node *node, unsigned type) { pixfmt_map &map = node->buftype_pixfmts[type]; + pixfmt_map enum_all; struct v4l2_fmtdesc fmtdesc; unsigned f = 0; int ret; @@ -317,6 +318,41 @@ static int testEnumFormatsType(struct node *node, unsigned type) fmtdesc.pixelformat, fcc2s(fmtdesc.pixelformat).c_str()); map[fmtdesc.pixelformat] = fmtdesc.flags; } + + /* Test V4L2_FMTDESC_FLAG_ENUM_ALL if supported */ + f = 0; + for (;;) { + memset(&fmtdesc, 0xff, sizeof(fmtdesc)); + fmtdesc.type = type; + fmtdesc.index = f | V4L2_FMTDESC_FLAG_ENUM_ALL; + fmtdesc.mbus_code = 0; + + ret = doioctl(node, VIDIOC_ENUM_FMT, &fmtdesc); + if (ret == ENOTTY) + return ret; + if (f == 0 && ret == EINVAL) + return 0; + if (ret == EINVAL) + break; + if (ret) + return fail("expected EINVAL, but got %d when enumerating buftype %d\n", ret, type); + if (fmtdesc.index != f) + return fail("V4L2_FMTDESC_FLAG_ENUM_ALL hasn't been cleared from fmtdesc.index 0x%x f 0x%x\n", fmtdesc.index, f); + f++; + if (type == V4L2_BUF_TYPE_PRIVATE) + continue; + assert(type <= V4L2_BUF_TYPE_LAST); + if (enum_all.find(fmtdesc.pixelformat) != enum_all.end()) + return fail("duplicate format %08x (%s)\n", + fmtdesc.pixelformat, fcc2s(fmtdesc.pixelformat).c_str()); + enum_all[fmtdesc.pixelformat] = fmtdesc.flags; + } + /* if V4L2_FMTDESC_FLAG_ENUM_ALL is supported, verify that the list is a subset of VIDIOC_ENUM_FMT list */ + if (!enum_all.empty()) { + for (auto it = map.begin(); it != map.end(); it++) + if (enum_all.find(it->first) == enum_all.end()) + return fail("V4L2_FMTDESC_FLAG_ENUM_ALL failed to enumerate format %08x (%s)\n", it->first, fcc2s(it->first).c_str()); + } info("found %d formats for buftype %d\n", f, type); return 0; }