From 34f39d8ab8dc65cfe6b9a1aa01dd7fd5d5d08006 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Wed, 12 Feb 2014 09:30:05 +0100 Subject: [PATCH] v4l2-ctl: add support for fields It is now possible to specify the field to use when setting a format, and new options --list-fields and --list-fields-out are added to list the available fields for the current format. Signed-off-by: Hans Verkuil --- utils/v4l2-ctl/v4l2-ctl-overlay.cpp | 15 --------- utils/v4l2-ctl/v4l2-ctl-vidcap.cpp | 67 ++++++++++++++++++++++++++++++++----- utils/v4l2-ctl/v4l2-ctl-vidout.cpp | 60 +++++++++++++++++++++++++++++---- utils/v4l2-ctl/v4l2-ctl.cpp | 25 +++++++++++++- utils/v4l2-ctl/v4l2-ctl.h | 5 ++- 5 files changed, 139 insertions(+), 33 deletions(-) diff --git a/utils/v4l2-ctl/v4l2-ctl-overlay.cpp b/utils/v4l2-ctl/v4l2-ctl-overlay.cpp index 91bddac..6b39df1 100644 --- a/utils/v4l2-ctl/v4l2-ctl-overlay.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-overlay.cpp @@ -117,21 +117,6 @@ static void printfbuf(const struct v4l2_framebuffer &fb) } } -static enum v4l2_field parse_field(const char *s) -{ - if (!strcmp(s, "any")) return V4L2_FIELD_ANY; - if (!strcmp(s, "none")) return V4L2_FIELD_NONE; - if (!strcmp(s, "top")) return V4L2_FIELD_TOP; - if (!strcmp(s, "bottom")) return V4L2_FIELD_BOTTOM; - if (!strcmp(s, "interlaced")) return V4L2_FIELD_INTERLACED; - if (!strcmp(s, "seq_tb")) return V4L2_FIELD_SEQ_TB; - if (!strcmp(s, "seq_bt")) return V4L2_FIELD_SEQ_BT; - if (!strcmp(s, "alternate")) return V4L2_FIELD_ALTERNATE; - if (!strcmp(s, "interlaced_tb")) return V4L2_FIELD_INTERLACED_TB; - if (!strcmp(s, "interlaced_bt")) return V4L2_FIELD_INTERLACED_BT; - return V4L2_FIELD_ANY; -} - void overlay_cmd(int ch, char *optarg) { unsigned int *set_overlay_fmt_ptr = NULL; diff --git a/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp b/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp index f25ccd3..8ba25dc 100644 --- a/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-vidcap.cpp @@ -46,25 +46,35 @@ void vidcap_usage(void) " list supported frame intervals for pixelformat and\n" " the given width and height [VIDIOC_ENUM_FRAMEINTERVALS]\n" " pixelformat is the fourcc value as a string\n" + " --list-fields list supported fields for the current format\n" " -V, --get-fmt-video\n" " query the video capture format [VIDIOC_G_FMT]\n" - " -v, --set-fmt-video=width=,height=,pixelformat=\n" + " -v, --set-fmt-video=width=,height=,pixelformat=,field=\n" " set the video capture format [VIDIOC_S_FMT]\n" " pixelformat is either the format index as reported by\n" - " --list-formats, or the fourcc value as a string\n" - " --try-fmt-video=width=,height=,pixelformat=\n" + " --list-formats, or the fourcc value as a string.\n" + " can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt,\n" + " alternate, interlaced_tb, interlaced_bt\n" + " --try-fmt-video=width=,height=,pixelformat=,field=\n" " try the video capture format [VIDIOC_TRY_FMT]\n" " pixelformat is either the format index as reported by\n" - " --list-formats, or the fourcc value as a string\n" + " --list-formats, or the fourcc value as a string.\n" + " can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt,\n" + " alternate, interlaced_tb, interlaced_bt\n" " --get-fmt-video-mplane\n" " query the video capture format through the multi-planar API\n" " [VIDIOC_G_FMT]\n" " --set-fmt-video-mplane\n" - " --try-fmt-video-mplane=width=,height=,pixelformat=\n" + " --try-fmt-video-mplane=width=,height=,pixelformat=,field=\n" " set/try the video capture format using the multi-planar API\n" " [VIDIOC_S/TRY_FMT]\n" " pixelformat is either the format index as reported by\n" - " --list-formats-mplane, or the fourcc value as a string\n" + " --list-formats-mplane, or the fourcc value as a string.\n" + " can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt,\n" + " alternate, interlaced_tb, interlaced_bt\n" ); } @@ -168,33 +178,68 @@ static void print_video_formats_ext(int fd, enum v4l2_buf_type type) } } +static void print_video_fields(int fd) +{ + struct v4l2_format fmt; + struct v4l2_format tmp; + bool is_mplane = capabilities & + (V4L2_CAP_VIDEO_CAPTURE_MPLANE | + V4L2_CAP_VIDEO_M2M_MPLANE); + + fmt.type = is_mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : + V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (test_ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) + return; + + printf("Supported Video Fields:\n"); + for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) { + bool ok; + + tmp = fmt; + if (is_mplane) + tmp.fmt.pix_mp.field = f; + else + tmp.fmt.pix.field = f; + if (test_ioctl(fd, VIDIOC_TRY_FMT, &tmp) < 0) + continue; + if (is_mplane) + ok = tmp.fmt.pix_mp.field == f; + else + ok = tmp.fmt.pix.field == f; + if (ok) + printf("\t%s\n", field2s(f).c_str()); + } +} + void vidcap_cmd(int ch, char *optarg) { - __u32 width, height, pixfmt; + __u32 width, height, field, pixfmt; char *value, *subs; switch (ch) { case OptSetVideoMplaneFormat: case OptTryVideoMplaneFormat: - set_fmts = parse_fmt(optarg, width, height, pixfmt); + set_fmts = parse_fmt(optarg, width, height, field, pixfmt); if (!set_fmts) { vidcap_usage(); exit(1); } vfmt.fmt.pix_mp.width = width; vfmt.fmt.pix_mp.height = height; + vfmt.fmt.pix_mp.field = field; vfmt.fmt.pix_mp.pixelformat = pixfmt; break; case OptSetVideoFormat: case OptTryVideoFormat: - set_fmts = parse_fmt(optarg, width, height, pixfmt); + set_fmts = parse_fmt(optarg, width, height, field, pixfmt); if (!set_fmts) { vidcap_usage(); exit(1); } vfmt.fmt.pix.width = width; vfmt.fmt.pix.height = height; + vfmt.fmt.pix.field = field; vfmt.fmt.pix.pixelformat = pixfmt; break; case OptListFrameSizes: @@ -341,6 +386,10 @@ void vidcap_list(int fd) print_video_formats_ext(fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); } + if (options[OptListFields]) { + print_video_fields(fd); + } + if (options[OptListFrameSizes]) { printf("ioctl: VIDIOC_ENUM_FRAMESIZES\n"); frmsize.index = 0; diff --git a/utils/v4l2-ctl/v4l2-ctl-vidout.cpp b/utils/v4l2-ctl/v4l2-ctl-vidout.cpp index 27d8e1a..3e4fcb5 100644 --- a/utils/v4l2-ctl/v4l2-ctl-vidout.cpp +++ b/utils/v4l2-ctl/v4l2-ctl-vidout.cpp @@ -28,13 +28,17 @@ void vidout_usage(void) { printf("\nVideo Output Formats options:\n" " --list-formats-out display supported video output formats [VIDIOC_ENUM_FMT]\n" + " --list-fields-out list supported fields for the current output format\n" " --get-fmt-video-out\n" " query the video output format [VIDIOC_G_FMT]\n" " --set-fmt-video-out\n" - " --try-fmt-video-out=width=,height=,pixelformat=\n" + " --try-fmt-video-out=width=,height=,pixelformat=,field=\n" " set/try the video output format [VIDIOC_TRY_FMT]\n" " pixelformat is either the format index as reported by\n" - " --list-formats-out, or the fourcc value as a string\n" + " --list-formats-out, or the fourcc value as a string.\n" + " can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt,\n" + " alternate, interlaced_tb, interlaced_bt\n" " --list-formats-out-mplane\n" " display supported video output multi-planar formats\n" " [VIDIOC_ENUM_FMT]\n" @@ -42,40 +46,78 @@ void vidout_usage(void) " query the video output format using the multi-planar API\n" " [VIDIOC_G_FMT]\n" " --set-fmt-video-out-mplane\n" - " --try-fmt-video-out-mplane=width=,height=,pixelformat=\n" + " --try-fmt-video-out-mplane=width=,height=,pixelformat=,field=\n" " set/try the video output format with the multi-planar API\n" " [VIDIOC_S/TRY_FMT]\n" " pixelformat is either the format index as reported by\n" - " --list-formats-out-mplane, or the fourcc value as a string\n" + " --list-formats-out-mplane, or the fourcc value as a string.\n" + " can be one of:\n" + " any, none, top, bottom, interlaced, seq_tb, seq_bt,\n" + " alternate, interlaced_tb, interlaced_bt\n" ); } +static void print_video_out_fields(int fd) +{ + struct v4l2_format fmt; + struct v4l2_format tmp; + bool is_mplane = capabilities & + (V4L2_CAP_VIDEO_OUTPUT_MPLANE | + V4L2_CAP_VIDEO_M2M_MPLANE); + + fmt.type = is_mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : + V4L2_BUF_TYPE_VIDEO_OUTPUT; + if (test_ioctl(fd, VIDIOC_G_FMT, &fmt) < 0) + return; + + printf("Supported Video Output Fields:\n"); + for (__u32 f = V4L2_FIELD_NONE; f <= V4L2_FIELD_INTERLACED_BT; f++) { + bool ok; + + tmp = fmt; + if (is_mplane) + tmp.fmt.pix_mp.field = f; + else + tmp.fmt.pix.field = f; + if (test_ioctl(fd, VIDIOC_TRY_FMT, &tmp) < 0) + continue; + if (is_mplane) + ok = tmp.fmt.pix_mp.field == f; + else + ok = tmp.fmt.pix.field == f; + if (ok) + printf("\t%s\n", field2s(f).c_str()); + } +} + void vidout_cmd(int ch, char *optarg) { - __u32 width, height, pixfmt; + __u32 width, height, field, pixfmt; switch (ch) { case OptSetVideoOutMplaneFormat: case OptTryVideoOutMplaneFormat: - set_fmts_out = parse_fmt(optarg, width, height, pixfmt); + set_fmts_out = parse_fmt(optarg, width, height, field, pixfmt); if (!set_fmts_out) { vidcap_usage(); exit(1); } vfmt_out.fmt.pix_mp.width = width; vfmt_out.fmt.pix_mp.height = height; + vfmt_out.fmt.pix_mp.field = field; vfmt_out.fmt.pix_mp.pixelformat = pixfmt; break; case OptSetVideoOutFormat: case OptTryVideoOutFormat: - set_fmts_out = parse_fmt(optarg, width, height, pixfmt); + set_fmts_out = parse_fmt(optarg, width, height, field, pixfmt); if (!set_fmts_out) { vidcap_usage(); exit(1); } vfmt_out.fmt.pix.width = width; vfmt_out.fmt.pix.height = height; + vfmt_out.fmt.pix.field = field; vfmt_out.fmt.pix.pixelformat = pixfmt; break; } @@ -175,4 +217,8 @@ void vidout_list(int fd) printf("ioctl: VIDIOC_ENUM_FMT\n"); print_video_formats(fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); } + + if (options[OptListOutFields]) { + print_video_out_fields(fd); + } } diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp index de92936..5cfafa7 100644 --- a/utils/v4l2-ctl/v4l2-ctl.cpp +++ b/utils/v4l2-ctl/v4l2-ctl.cpp @@ -108,11 +108,13 @@ static struct option long_options[] = { {"list-formats-mplane", no_argument, 0, OptListMplaneFormats}, {"list-formats-ext", no_argument, 0, OptListFormatsExt}, {"list-formats-ext-mplane", no_argument, 0, OptListMplaneFormatsExt}, + {"list-fields", no_argument, 0, OptListFields}, {"list-framesizes", required_argument, 0, OptListFrameSizes}, {"list-frameintervals", required_argument, 0, OptListFrameIntervals}, {"list-formats-overlay", no_argument, 0, OptListOverlayFormats}, {"list-formats-out", no_argument, 0, OptListOutFormats}, {"list-formats-out-mplane", no_argument, 0, OptListOutMplaneFormats}, + {"list-fields-out", no_argument, 0, OptListOutFields}, {"get-standard", no_argument, 0, OptGetStandard}, {"set-standard", required_argument, 0, OptSetStandard}, {"get-detected-standard", no_argument, 0, OptQueryStandard}, @@ -632,16 +634,33 @@ void print_v4lstd(v4l2_std_id std) } } -int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat) +__u32 parse_field(const char *s) +{ + if (!strcmp(s, "any")) return V4L2_FIELD_ANY; + if (!strcmp(s, "none")) return V4L2_FIELD_NONE; + if (!strcmp(s, "top")) return V4L2_FIELD_TOP; + if (!strcmp(s, "bottom")) return V4L2_FIELD_BOTTOM; + if (!strcmp(s, "interlaced")) return V4L2_FIELD_INTERLACED; + if (!strcmp(s, "seq_tb")) return V4L2_FIELD_SEQ_TB; + if (!strcmp(s, "seq_bt")) return V4L2_FIELD_SEQ_BT; + if (!strcmp(s, "alternate")) return V4L2_FIELD_ALTERNATE; + if (!strcmp(s, "interlaced_tb")) return V4L2_FIELD_INTERLACED_TB; + if (!strcmp(s, "interlaced_bt")) return V4L2_FIELD_INTERLACED_BT; + return V4L2_FIELD_ANY; +} + +int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &field, __u32 &pixelformat) { char *value, *subs; int fmts = 0; + field = V4L2_FIELD_ANY; subs = optarg; while (*subs != '\0') { static const char *const subopts[] = { "width", "height", + "field", "pixelformat", NULL }; @@ -656,6 +675,10 @@ int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat) fmts |= FmtHeight; break; case 2: + field = parse_field(value); + fmts |= FmtField; + break; + case 3: if (strlen(value) == 4) pixelformat = v4l2_fourcc(value[0], value[1], diff --git a/utils/v4l2-ctl/v4l2-ctl.h b/utils/v4l2-ctl/v4l2-ctl.h index 03c45b7..5161808 100644 --- a/utils/v4l2-ctl/v4l2-ctl.h +++ b/utils/v4l2-ctl/v4l2-ctl.h @@ -69,11 +69,13 @@ enum Option { OptListMplaneFormats, OptListFormatsExt, OptListMplaneFormatsExt, + OptListFields, OptListFrameSizes, OptListFrameIntervals, OptListOverlayFormats, OptListOutFormats, OptListOutMplaneFormats, + OptListOutFields, OptLogStatus, OptVerbose, OptSilent, @@ -192,7 +194,8 @@ std::string colorspace2s(int val); std::string service2s(unsigned service); std::string field2s(int val); void print_v4lstd(v4l2_std_id std); -int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &pixelformat); +__u32 parse_field(const char *s); +int parse_fmt(char *optarg, __u32 &width, __u32 &height, __u32 &field, __u32 &pixelformat); __u32 find_pixel_format(int fd, unsigned index, bool output, bool mplane); void printfmt(const struct v4l2_format &vfmt); void print_video_formats(int fd, enum v4l2_buf_type type); -- 2.7.4