v4l2-ctl: add support for fields
authorHans Verkuil <hans.verkuil@cisco.com>
Wed, 12 Feb 2014 08:30:05 +0000 (09:30 +0100)
committerHans Verkuil <hans.verkuil@cisco.com>
Wed, 12 Feb 2014 08:30:05 +0000 (09:30 +0100)
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 <hans.verkuil@cisco.com>
utils/v4l2-ctl/v4l2-ctl-overlay.cpp
utils/v4l2-ctl/v4l2-ctl-vidcap.cpp
utils/v4l2-ctl/v4l2-ctl-vidout.cpp
utils/v4l2-ctl/v4l2-ctl.cpp
utils/v4l2-ctl/v4l2-ctl.h

index 91bddac..6b39df1 100644 (file)
@@ -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;
index f25ccd3..8ba25dc 100644 (file)
@@ -46,25 +46,35 @@ void vidcap_usage(void)
               "                     list supported frame intervals for pixelformat <f> 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=<w>,height=<h>,pixelformat=<f>\n"
+              "  -v, --set-fmt-video=width=<w>,height=<h>,pixelformat=<pf>,field=<f>\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=<w>,height=<h>,pixelformat=<f>\n"
+              "                     --list-formats, or the fourcc value as a string.\n"
+              "                     <f> 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=<w>,height=<h>,pixelformat=<pf>,field=<f>\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"
+              "                     <f> 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=<w>,height=<h>,pixelformat=<f>\n"
+              "  --try-fmt-video-mplane=width=<w>,height=<h>,pixelformat=<pf>,field=<f>\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"
+              "                     <f> 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;
index 27d8e1a..3e4fcb5 100644 (file)
@@ -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=<w>,height=<h>,pixelformat=<f>\n"
+              "  --try-fmt-video-out=width=<w>,height=<h>,pixelformat=<pf>,field=<f>\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"
+              "                     <f> 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=<w>,height=<h>,pixelformat=<f>\n"
+              "  --try-fmt-video-out-mplane=width=<w>,height=<h>,pixelformat=<pf>,field=<f>\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"
+              "                     <f> 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);
+       }
 }
index de92936..5cfafa7 100644 (file)
@@ -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],
index 03c45b7..5161808 100644 (file)
@@ -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);