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-ctl: share capture/output format updates Author: Hans Verkuil <[email protected]> Date: Tue Oct 6 09:30:20 2026 +0200 Add a video_format_request, shared capture/output updater using cv4l_fmt, and consolidated FOURCC parsing. Capture-only CSC flags and streaming reconfiguration behavior are preserved. Also fixed numeric frame-interval parsing, bounded repeated plane values, and updated the man page. Signed-off-by: Hans Verkuil <[email protected]> Assisted-by: GPT-6.1 Sol utils/v4l2-ctl/meson.build | 1 + utils/v4l2-ctl/v4l2-ctl-format.cpp | 85 +++++++++++++++++++ utils/v4l2-ctl/v4l2-ctl-meta.cpp | 3 +- utils/v4l2-ctl/v4l2-ctl-sdr.cpp | 3 +- utils/v4l2-ctl/v4l2-ctl-vidcap.cpp | 164 ++----------------------------------- utils/v4l2-ctl/v4l2-ctl-vidout.cpp | 109 ++---------------------- utils/v4l2-ctl/v4l2-ctl.1.in | 6 ++ utils/v4l2-ctl/v4l2-ctl.cpp | 94 ++++++++++----------- utils/v4l2-ctl/v4l2-ctl.h | 25 +++++- 9 files changed, 173 insertions(+), 317 deletions(-) --- http://git.linuxtv.org/cgit.cgi/v4l-utils.git/commit/?id=1616bf9e3c8111d3c8f3995d26bc6d0402cc77c3 diff --git a/utils/v4l2-ctl/meson.build b/utils/v4l2-ctl/meson.build index 8bcf8785878e..28af5a2804b4 100644 --- a/utils/v4l2-ctl/meson.build +++ b/utils/v4l2-ctl/meson.build @@ -5,6 +5,7 @@ v4l2_ctl_sources = files( 'v4l-stream.c', 'v4l2-ctl-common.cpp', 'v4l2-ctl-edid.cpp', + 'v4l2-ctl-format.cpp', 'v4l2-ctl-io.cpp', 'v4l2-ctl-meta.cpp', 'v4l2-ctl-misc.cpp', diff --git a/utils/v4l2-ctl/v4l2-ctl-format.cpp b/utils/v4l2-ctl/v4l2-ctl-format.cpp new file mode 100644 index 000000000000..0df65cc37abe --- /dev/null +++ b/utils/v4l2-ctl/v4l2-ctl-format.cpp @@ -0,0 +1,85 @@ +#include <cctype> + +#include "v4l2-ctl.h" + +__u32 parse_pixelformat(const char *value) +{ + bool be = strlen(value) == 7 && !memcmp(value + 4, "-BE", 3); + + if (be || strlen(value) == 4) { + __u32 pixelformat = v4l2_fourcc(value[0], value[1], value[2], value[3]); + + return be ? pixelformat | (1U << 31) : pixelformat; + } + if (isdigit(value[0])) + return strtoul(value, nullptr, 0); + + fprintf(stderr, "The pixelformat '%s' is invalid\n", value); + std::exit(EXIT_FAILURE); +} + +int video_get_and_update_fmt(cv4l_fd &fd, struct v4l2_format &vfmt, + __u32 type, __u32 magic, video_format_request &request) +{ + cv4l_fmt fmt(type); + bool output = type == V4L2_BUF_TYPE_VIDEO_OUTPUT || + type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + bool mplane = V4L2_TYPE_IS_MULTIPLANAR(type); + unsigned fields = request.fields; + + fmt.fmt.pix.priv = magic; + int ret = doioctl(fd.g_fd(), VIDIOC_G_FMT, &fmt); + + if (ret) + return ret; + + if (fields & FmtWidth) + fmt.s_width(request.width); + if (fields & FmtHeight) + fmt.s_height(request.height); + if (fields & FmtPixelFormat) { + if (request.pixelformat < 256) + request.pixelformat = find_pixel_format(fd.g_fd(), + request.pixelformat, output, mplane); + fmt.s_pixelformat(request.pixelformat); + } + if (fields & FmtField) + fmt.s_field(request.field); + if (fields & FmtFlags) + fmt.s_flags(request.flags); + if (fields & FmtBytesPerLine) { + for (unsigned i = 0; i < (mplane ? VIDEO_MAX_PLANES : 1); i++) + fmt.s_bytesperline(request.bytesperline[i], i); + } else { + // Let the driver recalculate the stride for the new width. + for (unsigned i = 0; i < fmt.g_num_planes(); i++) + fmt.s_bytesperline(0, i); + } + if (fields & FmtSizeImage) { + for (unsigned i = 0; i < (mplane ? VIDEO_MAX_PLANES : 1); i++) + fmt.s_sizeimage(request.sizeimage[i], i); + } + if (fields & FmtColorspace) + fmt.s_colorspace(request.colorspace); + if (fields & FmtYCbCr) + fmt.s_ycbcr_enc(request.ycbcr); + if (fields & FmtQuantization) + fmt.s_quantization(request.quantization); + if (fields & FmtXferFunc) + fmt.s_xfer_func(request.xfer_func); + if (!output && (fields & (FmtColorspace | FmtYCbCr | + FmtQuantization | FmtXferFunc))) + fmt.s_flags(fmt.g_flags() | V4L2_PIX_FMT_FLAG_SET_CSC); + + vfmt = fmt; + if ((fields & FmtPixelFormat) && + !valid_pixel_format(fd.g_fd(), request.pixelformat, output, mplane)) { + if (request.pixelformat) + fprintf(stderr, "The pixelformat '%s' is invalid\n", + fcc2s(request.pixelformat).c_str()); + else + fprintf(stderr, "The pixelformat index was invalid\n"); + return -EINVAL; + } + return 0; +} diff --git a/utils/v4l2-ctl/v4l2-ctl-meta.cpp b/utils/v4l2-ctl/v4l2-ctl-meta.cpp index 634aba8ce0ca..7c173d76d7fc 100644 --- a/utils/v4l2-ctl/v4l2-ctl-meta.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-meta.cpp @@ -53,8 +53,7 @@ void meta_cmd(int ch, char *optarg) meta_usage(); std::exit(EXIT_FAILURE); } else if (strlen(optarg) == 4) { - vfmt.fmt.meta.dataformat = v4l2_fourcc(optarg[0], - optarg[1], optarg[2], optarg[3]); + vfmt.fmt.meta.dataformat = parse_pixelformat(optarg); } else { vfmt.fmt.meta.dataformat = strtoul(optarg, nullptr, 0); } diff --git a/utils/v4l2-ctl/v4l2-ctl-sdr.cpp b/utils/v4l2-ctl/v4l2-ctl-sdr.cpp index 35e7885e188e..5dce72937afe 100644 --- a/utils/v4l2-ctl/v4l2-ctl-sdr.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-sdr.cpp @@ -38,8 +38,7 @@ void sdr_cmd(int ch, char *optarg) sdr_usage(); std::exit(EXIT_FAILURE); } else if (strlen(optarg) == 4) { - vfmt.fmt.sdr.pixelformat = v4l2_fourcc(optarg[0], - optarg[1], optarg[2], optarg[3]); + vfmt.fmt.sdr.pixelformat = parse_pixelformat(optarg); } else { vfmt.fmt.sdr.pixelformat = strtoul(optarg, nullptr, 0); } diff --git a/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp b/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp index a16443f4d682..11402202dcbe 100644 --- a/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp @@ -1,16 +1,10 @@ -#include <cctype> - #include <endian.h> #include "v4l2-ctl.h" static struct v4l2_frmsizeenum frmsize; /* list frame sizes */ static struct v4l2_frmivalenum frmival; /* list frame intervals */ -static unsigned set_fmts; -static __u32 width, height, pixfmt, field, flags; -static __u32 ycbcr, quantization, xfer_func, colorspace; -static __u32 bytesperline[VIDEO_MAX_PLANES]; -static __u32 sizeimage[VIDEO_MAX_PLANES]; +static video_format_request format_request; static unsigned mbus_code; static bool enum_all; @@ -104,15 +98,11 @@ static void print_video_fields(int fd) void vidcap_cmd(int ch, char *optarg) { char *value, *subs; - bool be_pixfmt; switch (ch) { case OptSetVideoFormat: case OptTryVideoFormat: - set_fmts = parse_fmt(optarg, width, height, pixfmt, field, colorspace, - xfer_func, ycbcr, quantization, flags, bytesperline, - sizeimage); - if (!set_fmts) { + if (!parse_fmt(optarg, format_request)) { vidcap_usage(); std::exit(EXIT_FAILURE); } @@ -127,18 +117,7 @@ void vidcap_cmd(int ch, char *optarg) } break; case OptListFrameSizes: - be_pixfmt = strlen(optarg) == 7 && !memcmp(optarg + 4, "-BE", 3); - if (be_pixfmt || strlen(optarg) == 4) { - frmsize.pixel_format = v4l2_fourcc(optarg[0], optarg[1], - optarg[2], optarg[3]); - if (be_pixfmt) - frmsize.pixel_format |= 1U << 31; - } else if (isdigit(optarg[0])) { - frmsize.pixel_format = strtoul(optarg, nullptr, 0); - } else { - fprintf(stderr, "The pixelformat '%s' is invalid\n", optarg); - std::exit(EXIT_FAILURE); - } + frmsize.pixel_format = parse_pixelformat(optarg); break; case OptListFrameIntervals: subs = optarg; @@ -158,19 +137,7 @@ void vidcap_cmd(int ch, char *optarg) frmival.height = strtoul(value, nullptr, 0); break; case 2: - be_pixfmt = strlen(value) == 7 && !memcmp(value + 4, "-BE", 3); - if (be_pixfmt || strlen(value) == 4) { - frmival.pixel_format = - v4l2_fourcc(value[0], value[1], - value[2], value[3]); - if (be_pixfmt) - frmival.pixel_format |= 1U << 31; - } else if (isdigit(optarg[0])) { - frmival.pixel_format = strtoul(value, nullptr, 0); - } else { - fprintf(stderr, "The pixelformat '%s' is invalid\n", optarg); - std::exit(EXIT_FAILURE); - } + frmival.pixel_format = parse_pixelformat(value); break; default: vidcap_usage(); @@ -183,127 +150,8 @@ void vidcap_cmd(int ch, char *optarg) int vidcap_get_and_update_fmt(cv4l_fd &_fd, struct v4l2_format &vfmt) { - int fd = _fd.g_fd(); - int ret; - - memset(&vfmt, 0, sizeof(vfmt)); - vfmt.fmt.pix.priv = priv_magic; - vfmt.type = vidcap_buftype; - - ret = doioctl(fd, VIDIOC_G_FMT, &vfmt); - if (ret) - return ret; - - if (is_multiplanar) { - if (set_fmts & FmtWidth) - vfmt.fmt.pix_mp.width = width; - if (set_fmts & FmtHeight) - vfmt.fmt.pix_mp.height = height; - if (set_fmts & FmtPixelFormat) { - vfmt.fmt.pix_mp.pixelformat = pixfmt; - if (vfmt.fmt.pix_mp.pixelformat < 256) { - vfmt.fmt.pix_mp.pixelformat = pixfmt = - find_pixel_format(fd, vfmt.fmt.pix_mp.pixelformat, - false, true); - } - } - if (set_fmts & FmtField) - vfmt.fmt.pix_mp.field = field; - if (set_fmts & FmtFlags) - vfmt.fmt.pix_mp.flags = flags; - if (set_fmts & FmtBytesPerLine) { - for (unsigned i = 0; i < VIDEO_MAX_PLANES; i++) - vfmt.fmt.pix_mp.plane_fmt[i].bytesperline = - bytesperline[i]; - } else { - /* - * G_FMT might return bytesperline values > width, - * reset them to 0 to force the driver to update them - * to the closest value for the new width. - */ - for (unsigned i = 0; i < vfmt.fmt.pix_mp.num_planes; i++) - vfmt.fmt.pix_mp.plane_fmt[i].bytesperline = 0; - } - if (set_fmts & FmtSizeImage) { - for (unsigned i = 0; i < VIDEO_MAX_PLANES; i++) - vfmt.fmt.pix_mp.plane_fmt[i].sizeimage = - sizeimage[i]; - } - - if (set_fmts & FmtColorspace) { - vfmt.fmt.pix_mp.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix_mp.colorspace = colorspace; - } - if (set_fmts & FmtYCbCr) { - vfmt.fmt.pix_mp.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix_mp.ycbcr_enc = ycbcr; - } - if (set_fmts & FmtQuantization) { - vfmt.fmt.pix_mp.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix_mp.quantization = quantization; - } - if (set_fmts & FmtXferFunc) { - vfmt.fmt.pix_mp.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix_mp.xfer_func = xfer_func; - } - } else { - if (set_fmts & FmtWidth) - vfmt.fmt.pix.width = width; - if (set_fmts & FmtHeight) - vfmt.fmt.pix.height = height; - if (set_fmts & FmtPixelFormat) { - vfmt.fmt.pix.pixelformat = pixfmt; - if (vfmt.fmt.pix.pixelformat < 256) { - vfmt.fmt.pix.pixelformat = pixfmt = - find_pixel_format(fd, vfmt.fmt.pix.pixelformat, - false, false); - } - } - if (set_fmts & FmtField) - vfmt.fmt.pix.field = field; - if (set_fmts & FmtFlags) - vfmt.fmt.pix.flags = flags; - if (set_fmts & FmtBytesPerLine) { - vfmt.fmt.pix.bytesperline = bytesperline[0]; - } else { - /* - * G_FMT might return a bytesperline value > width, - * reset this to 0 to force the driver to update it - * to the closest value for the new width. - */ - vfmt.fmt.pix.bytesperline = 0; - } - if (set_fmts & FmtSizeImage) - vfmt.fmt.pix.sizeimage = sizeimage[0]; - if (set_fmts & FmtColorspace) { - vfmt.fmt.pix.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix.colorspace = colorspace; - } - if (set_fmts & FmtYCbCr) { - vfmt.fmt.pix.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix.ycbcr_enc = ycbcr; - } - if (set_fmts & FmtQuantization) { - vfmt.fmt.pix.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix.quantization = quantization; - } - if (set_fmts & FmtXferFunc) { - vfmt.fmt.pix.flags |= V4L2_PIX_FMT_FLAG_SET_CSC; - vfmt.fmt.pix.xfer_func = xfer_func; - } - - } - - if ((set_fmts & FmtPixelFormat) && - !valid_pixel_format(fd, pixfmt, false, is_multiplanar)) { - if (pixfmt) - fprintf(stderr, "The pixelformat '%s' is invalid\n", - fcc2s(pixfmt).c_str()); - else - fprintf(stderr, "The pixelformat index was invalid\n"); - return -EINVAL; - } - return 0; + return video_get_and_update_fmt(_fd, vfmt, vidcap_buftype, + priv_magic, format_request); } void vidcap_set(cv4l_fd &_fd) diff --git a/utils/v4l2-ctl/v4l2-ctl-vidout.cpp b/utils/v4l2-ctl/v4l2-ctl-vidout.cpp index bbdbfc451614..20b0b958d22e 100644 --- a/utils/v4l2-ctl/v4l2-ctl-vidout.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-vidout.cpp @@ -1,9 +1,6 @@ #include "v4l2-ctl.h" -static unsigned set_fmts_out; -static __u32 width, height, pixfmt, field, colorspace, xfer_func, ycbcr, quantization, flags; -static __u32 bytesperline[VIDEO_MAX_PLANES]; -static __u32 sizeimage[VIDEO_MAX_PLANES]; +static video_format_request format_request; static unsigned mbus_code_out; static bool enum_all; @@ -90,11 +87,8 @@ void vidout_cmd(int ch, char *optarg) switch (ch) { case OptSetVideoOutFormat: case OptTryVideoOutFormat: - set_fmts_out = parse_fmt(optarg, width, height, pixfmt, field, - colorspace, xfer_func, ycbcr, quantization, flags, bytesperline, - sizeimage); - if (!set_fmts_out) { - vidcap_usage(); + if (!parse_fmt(optarg, format_request)) { + vidout_usage(); std::exit(EXIT_FAILURE); } break; @@ -118,98 +112,11 @@ void vidout_set(cv4l_fd &_fd) if (options[OptSetVideoOutFormat] || options[OptTryVideoOutFormat]) { struct v4l2_format vfmt; - memset(&vfmt, 0, sizeof(vfmt)); - vfmt.fmt.pix.priv = priv_magic; - vfmt.type = vidout_buftype; - if (doioctl(fd, VIDIOC_G_FMT, &vfmt) == 0) { - if (is_multiplanar) { - if (set_fmts_out & FmtWidth) - vfmt.fmt.pix_mp.width = width; - if (set_fmts_out & FmtHeight) - vfmt.fmt.pix_mp.height = height; - if (set_fmts_out & FmtPixelFormat) { - vfmt.fmt.pix_mp.pixelformat = pixfmt; - if (vfmt.fmt.pix_mp.pixelformat < 256) { - vfmt.fmt.pix_mp.pixelformat = pixfmt = - find_pixel_format(fd, vfmt.fmt.pix_mp.pixelformat, - true, true); - } - } - if (set_fmts_out & FmtField) - vfmt.fmt.pix_mp.field = field; - if (set_fmts_out & FmtColorspace) - vfmt.fmt.pix_mp.colorspace = colorspace; - if (set_fmts_out & FmtXferFunc) - vfmt.fmt.pix_mp.xfer_func = xfer_func; - if (set_fmts_out & FmtYCbCr) - vfmt.fmt.pix_mp.ycbcr_enc = ycbcr; - if (set_fmts_out & FmtQuantization) - vfmt.fmt.pix_mp.quantization = quantization; - if (set_fmts_out & FmtFlags) - vfmt.fmt.pix_mp.flags = flags; - if (set_fmts_out & FmtBytesPerLine) { - for (unsigned i = 0; i < VIDEO_MAX_PLANES; i++) - vfmt.fmt.pix_mp.plane_fmt[i].bytesperline = - bytesperline[i]; - } else { - /* G_FMT might return bytesperline values > width, - * reset them to 0 to force the driver to update them - * to the closest value for the new width. */ - for (unsigned i = 0; i < vfmt.fmt.pix_mp.num_planes; i++) - vfmt.fmt.pix_mp.plane_fmt[i].bytesperline = 0; - } - if (set_fmts_out & FmtSizeImage) { - for (unsigned i = 0; i < VIDEO_MAX_PLANES; i++) - vfmt.fmt.pix_mp.plane_fmt[i].sizeimage = - sizeimage[i]; - } - } else { - if (set_fmts_out & FmtWidth) - vfmt.fmt.pix.width = width; - if (set_fmts_out & FmtHeight) - vfmt.fmt.pix.height = height; - if (set_fmts_out & FmtPixelFormat) { - vfmt.fmt.pix.pixelformat = pixfmt; - if (vfmt.fmt.pix.pixelformat < 256) { - vfmt.fmt.pix.pixelformat = pixfmt = - find_pixel_format(fd, vfmt.fmt.pix.pixelformat, - true, false); - } - } - if (set_fmts_out & FmtField) - vfmt.fmt.pix.field = field; - if (set_fmts_out & FmtColorspace) - vfmt.fmt.pix.colorspace = colorspace; - if (set_fmts_out & FmtXferFunc) - vfmt.fmt.pix.xfer_func = xfer_func; - if (set_fmts_out & FmtYCbCr) - vfmt.fmt.pix.ycbcr_enc = ycbcr; - if (set_fmts_out & FmtQuantization) - vfmt.fmt.pix.quantization = quantization; - if (set_fmts_out & FmtFlags) - vfmt.fmt.pix.flags = flags; - if (set_fmts_out & FmtBytesPerLine) { - vfmt.fmt.pix.bytesperline = bytesperline[0]; - } else { - /* G_FMT might return a bytesperline value > width, - * reset this to 0 to force the driver to update it - * to the closest value for the new width. */ - vfmt.fmt.pix.bytesperline = 0; - } - if (set_fmts_out & FmtSizeImage) - vfmt.fmt.pix.sizeimage = sizeimage[0]; - } - - if ((set_fmts_out & FmtPixelFormat) && - !valid_pixel_format(fd, pixfmt, true, is_multiplanar)) { - if (pixfmt) - fprintf(stderr, "The pixelformat '%s' is invalid\n", - fcc2s(pixfmt).c_str()); - else - fprintf(stderr, "The pixelformat index was invalid\n"); - std::exit(EXIT_FAILURE); - } - + ret = video_get_and_update_fmt(_fd, vfmt, vidout_buftype, + priv_magic, format_request); + if (ret == -EINVAL) + std::exit(EXIT_FAILURE); + if (ret == 0) { if (options[OptSetVideoOutFormat]) ret = doioctl(fd, VIDIOC_S_FMT, &vfmt); else diff --git a/utils/v4l2-ctl/v4l2-ctl.1.in b/utils/v4l2-ctl/v4l2-ctl.1.in index cbb10064684c..3f44d0c84c94 100644 --- a/utils/v4l2-ctl/v4l2-ctl.1.in +++ b/utils/v4l2-ctl/v4l2-ctl.1.in @@ -155,6 +155,12 @@ Only set the result code, do not print any messages. .TP \fB--sleep\fR \fI<secs>\fR Sleep \fI<secs>\fR, call QUERYCAP and close the file handle. +.SH VIDEO FORMATS +Video pixel formats accept a four-character FOURCC, a FOURCC followed by +\fB-BE\fR for a big-endian format, or a numeric value. For set/try video +formats, numeric values below 256 select an index from the enumerated formats. +The \fBbytesperline\fR and \fBsizeimage\fR suboptions may each be repeated once +per plane, up to eight values (VIDEO_MAX_PLANES). .SH EXIT STATUS On success, it returns 0. Otherwise, it will return the error code. .SH EXAMPLES diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp index 6afb572c9d7c..c52c08fff176 100644 --- a/utils/v4l2-ctl/v4l2-ctl.cpp +++ b/utils/v4l2-ctl/v4l2-ctl.cpp @@ -767,19 +767,15 @@ __u32 parse_quantization(const char *s) return V4L2_QUANTIZATION_DEFAULT; } -int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat, - __u32 &field, __u32 &colorspace, __u32 &xfer_func, __u32 &ycbcr, - __u32 &quantization, __u32 &flags, __u32 *bytesperline, - __u32 *sizeimage) +bool parse_fmt(char *optarg, video_format_request &request) { char *value, *subs; - int fmts = 0; unsigned bpl_index = 0; unsigned sizeimage_index = 0; - bool be_pixfmt; - field = V4L2_FIELD_ANY; - flags = 0; + request.fields = 0; + request.field = V4L2_FIELD_ANY; + request.flags = 0; subs = optarg; while (*subs != '\0') { static constexpr const char *subopts[] = { @@ -800,82 +796,80 @@ int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat, switch (parse_subopt(&subs, subopts, &value)) { case 0: - width = strtoul(value, nullptr, 0); - fmts |= FmtWidth; + request.width = strtoul(value, nullptr, 0); + request.fields |= FmtWidth; break; case 1: - height = strtoul(value, nullptr, 0); - fmts |= FmtHeight; + request.height = strtoul(value, nullptr, 0); + request.fields |= FmtHeight; break; case 2: - be_pixfmt = strlen(value) == 7 && !memcmp(value + 4, "-BE", 3); - if (be_pixfmt || strlen(value) == 4) { - pixelformat = - v4l2_fourcc(value[0], value[1], - value[2], value[3]); - if (be_pixfmt) - pixelformat |= 1U << 31; - } else if (isdigit(value[0])) { - pixelformat = strtoul(value, nullptr, 0); - } else { - fprintf(stderr, "The pixelformat '%s' is invalid\n", value); - std::exit(EXIT_FAILURE); - } - fmts |= FmtPixelFormat; + request.pixelformat = parse_pixelformat(value); + request.fields |= FmtPixelFormat; break; case 3: - field = parse_field(value); - fmts |= FmtField; + request.field = parse_field(value); + request.fields |= FmtField; break; case 4: - colorspace = parse_colorspace(value); - if (colorspace) - fmts |= FmtColorspace; + request.colorspace = parse_colorspace(value); + if (request.colorspace) + request.fields |= FmtColorspace; else fprintf(stderr, "unknown colorspace %s\n", value); break; case 5: - ycbcr = parse_ycbcr(value); - fmts |= FmtYCbCr; + request.ycbcr = parse_ycbcr(value); + request.fields |= FmtYCbCr; break; case 6: - ycbcr = parse_hsv(value); - fmts |= FmtYCbCr; + request.ycbcr = parse_hsv(value); + request.fields |= FmtYCbCr; break; case 7: - bytesperline[bpl_index] = strtoul(value, nullptr, 0); - if (bytesperline[bpl_index] > 0xffff) { + if (bpl_index == VIDEO_MAX_PLANES) { + fprintf(stderr, "Too many bytesperline values (maximum %u)\n", + VIDEO_MAX_PLANES); + return false; + } + request.bytesperline[bpl_index] = strtoul(value, nullptr, 0); + if (request.bytesperline[bpl_index] > 0xffff) { fprintf(stderr, "bytesperline can't be more than 65535\n"); - bytesperline[bpl_index] = 0; + request.bytesperline[bpl_index] = 0; } bpl_index++; - fmts |= FmtBytesPerLine; + request.fields |= FmtBytesPerLine; break; case 8: if (strtoul(value, nullptr, 0)) - flags |= V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; + request.flags |= V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; else - flags &= ~V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; - fmts |= FmtFlags; + request.flags &= ~V4L2_PIX_FMT_FLAG_PREMUL_ALPHA; + request.fields |= FmtFlags; break; case 9: - quantization = parse_quantization(value); - fmts |= FmtQuantization; + request.quantization = parse_quantization(value); + request.fields |= FmtQuantization; break; case 10: - xfer_func = parse_xfer_func(value); - fmts |= FmtXferFunc; + request.xfer_func = parse_xfer_func(value); + request.fields |= FmtXferFunc; break; case 11: - sizeimage[sizeimage_index] = strtoul(value, nullptr, 0); + if (sizeimage_index == VIDEO_MAX_PLANES) { + fprintf(stderr, "Too many sizeimage values (maximum %u)\n", + VIDEO_MAX_PLANES); + return false; + } + request.sizeimage[sizeimage_index] = strtoul(value, nullptr, 0); sizeimage_index++; - fmts |= FmtSizeImage; + request.fields |= FmtSizeImage; break; default: - return 0; + return false; } } - return fmts; + return request.fields != 0; } int parse_selection_flags(const char *s) diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h index c4d955deb710..9aacf9274eda 100644 --- a/utils/v4l2-ctl/v4l2-ctl.h +++ b/utils/v4l2-ctl/v4l2-ctl.h @@ -297,6 +297,26 @@ extern int verbose; #define FmtXferFunc (1L<<13) #define FmtSizeImage (1L<<14) +struct video_format_request { + unsigned fields = 0; + __u32 width = 0; + __u32 height = 0; + __u32 pixelformat = 0; + __u32 field = V4L2_FIELD_ANY; + __u32 colorspace = 0; + __u32 xfer_func = 0; + __u32 ycbcr = 0; + __u32 quantization = 0; + __u32 flags = 0; + __u32 bytesperline[VIDEO_MAX_PLANES] = {}; + __u32 sizeimage[VIDEO_MAX_PLANES] = {}; +}; + +// v4l2-ctl-format.cpp +__u32 parse_pixelformat(const char *value); +int video_get_and_update_fmt(cv4l_fd &fd, struct v4l2_format &vfmt, + __u32 type, __u32 magic, video_format_request &request); + // v4l2-ctl.cpp int doioctl_name(int fd, unsigned long int request, void *parm, const char *name); int test_ioctl(int fd, unsigned long cmd, void *arg); @@ -307,10 +327,7 @@ __u32 parse_xfer_func(const char *s); __u32 parse_ycbcr(const char *s); __u32 parse_hsv(const char *s); __u32 parse_quantization(const char *s); -int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat, - __u32 &field, __u32 &colorspace, __u32 &xfer, __u32 &ycbcr, - __u32 &quantization, __u32 &flags, __u32 *bytesperline, - __u32 *sizeimage); +bool parse_fmt(char *optarg, video_format_request &request); int parse_selection_target(const char *s, unsigned int &target); int parse_selection_flags(const char *s); void print_selection(const struct v4l2_selection &sel); _______________________________________________ linuxtv-commits mailing list -- [email protected] To unsubscribe send an email to [email protected]
