v4l2-ctl: split off crop/selection options.
authorHans Verkuil <hans.verkuil@cisco.com>
Thu, 26 Jul 2012 11:43:48 +0000 (13:43 +0200)
committerHans Verkuil <hans.verkuil@cisco.com>
Thu, 26 Jul 2012 11:43:48 +0000 (13:43 +0200)
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
utils/v4l2-ctl/Makefile.am
utils/v4l2-ctl/v4l2-ctl-selection.cpp [new file with mode: 0644]
utils/v4l2-ctl/v4l2-ctl.cpp
utils/v4l2-ctl/v4l2-ctl.h

index 1bbbee7..2e29974 100644 (file)
@@ -7,5 +7,5 @@ ivtv_ctl_LDFLAGS = -lm
 
 v4l2_ctl_SOURCES = v4l2-ctl.cpp v4l2-ctl.h v4l2-ctl-common.cpp v4l2-ctl-tuner.cpp \
        v4l2-ctl-io.cpp v4l2-ctl-stds.cpp v4l2-ctl-vidcap.cpp v4l2-ctl-vidout.cpp \
-       v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp
+       v4l2-ctl-overlay.cpp v4l2-ctl-vbi.cpp v4l2-ctl-selection.cpp
 v4l2_ctl_LDADD = ../../lib/libv4l2/libv4l2.la
diff --git a/utils/v4l2-ctl/v4l2-ctl-selection.cpp b/utils/v4l2-ctl/v4l2-ctl-selection.cpp
new file mode 100644 (file)
index 0000000..c8b0db9
--- /dev/null
@@ -0,0 +1,460 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <math.h>
+#include <config.h>
+
+#include <linux/videodev2.h>
+#include <libv4l2.h>
+#include <string>
+
+#include "v4l2-ctl.h"
+
+/* crop specified */
+#define CropWidth              (1L<<0)
+#define CropHeight             (1L<<1)
+#define CropLeft               (1L<<2)
+#define CropTop                (1L<<3)
+
+/* selection specified */
+#define SelectionWidth         (1L<<0)
+#define SelectionHeight                (1L<<1)
+#define SelectionLeft          (1L<<2)
+#define SelectionTop           (1L<<3)
+#define SelectionFlags                 (1L<<4)
+
+/* bitfield for fmts */
+static unsigned int set_crop;
+static unsigned int set_crop_out;
+static unsigned int set_crop_overlay;
+static unsigned int set_crop_out_overlay;
+static unsigned int set_selection;
+static unsigned int set_selection_out;
+static int get_sel_target;
+static struct v4l2_rect vcrop;         /* crop rect */
+static struct v4l2_rect vcrop_out;     /* crop rect */
+static struct v4l2_rect vcrop_overlay;         /* crop rect */
+static struct v4l2_rect vcrop_out_overlay;     /* crop rect */
+static struct v4l2_selection vselection;       /* capture selection */
+static struct v4l2_selection vselection_out;   /* output selection */
+
+void selection_usage(void)
+{
+       printf("\nSelection/Cropping options:\n"
+              "  --get-cropcap      query the crop capabilities [VIDIOC_CROPCAP]\n"
+              "  --get-crop         query the video capture crop window [VIDIOC_G_CROP]\n"
+              "  --set-crop=top=<x>,left=<y>,width=<w>,height=<h>\n"
+              "                     set the video capture crop window [VIDIOC_S_CROP]\n"
+              "  --get-cropcap-output\n"
+              "                     query crop capabilities for video output [VIDIOC_CROPCAP]\n"
+              "  --get-crop-output  query the video output crop window [VIDIOC_G_CROP]\n"
+              "  --set-crop-output=top=<x>,left=<y>,width=<w>,height=<h>\n"
+              "                     set the video output crop window [VIDIOC_S_CROP]\n"
+              "  --get-cropcap-overlay\n"
+              "                     query crop capabilities for video overlay [VIDIOC_CROPCAP]\n"
+              "  --get-crop-overlay query the video overlay crop window [VIDIOC_G_CROP]\n"
+              "  --set-crop-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"
+              "                     set the video overlay crop window [VIDIOC_S_CROP]\n"
+              "  --get-cropcap-output-overlay\n"
+              "                     query the crop capabilities for video output overlays\n"
+              "                     [VIDIOC_CROPCAP]\n"
+              "  --get-crop-output-overlay\n"
+              "                     query the video output overlay crop window [VIDIOC_G_CROP]\n"
+              "  --set-crop-output-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"
+              "                     set the video output overlay crop window [VIDIOC_S_CROP]\n"
+              "  --get-selection=target=<target>\n"
+              "                     query the video capture selection rectangle [VIDIOC_G_SELECTION]\n"
+              "                     See --set-selection command for the valid <target> values.\n"
+              "  --set-selection=target=<target>,flags=<flags>,top=<x>,left=<y>,width=<w>,height=<h>\n"
+              "                     set the video capture selection rectangle [VIDIOC_S_SELECTION]\n"
+              "                     target=crop|crop_bounds|crop_default|compose|compose_bounds|\n"
+              "                            compose_default|compose_padded\n"
+              "                     flags=le|ge\n"
+              "  --get-selection-output=target=<target>\n"
+              "                     query the video output selection rectangle [VIDIOC_G_SELECTION]\n"
+              "                     See --set-selection command for the valid <target> values.\n"
+              "  --set-selection-output=target=<target>,flags=<flags>,top=<x>,left=<y>,width=<w>,height=<h>\n"
+              "                     set the video output selection rectangle [VIDIOC_S_SELECTION]\n"
+              "                     See --set-selection command for the arguments.\n"
+              );
+}
+
+static void do_crop(int fd, unsigned int set_crop, struct v4l2_rect &vcrop, v4l2_buf_type type)
+{
+       struct v4l2_crop in_crop;
+
+       in_crop.type = type;
+       if (doioctl(fd, VIDIOC_G_CROP, &in_crop) == 0) {
+               if (set_crop & CropWidth)
+                       in_crop.c.width = vcrop.width;
+               if (set_crop & CropHeight)
+                       in_crop.c.height = vcrop.height;
+               if (set_crop & CropLeft)
+                       in_crop.c.left = vcrop.left;
+               if (set_crop & CropTop)
+                       in_crop.c.top = vcrop.top;
+               doioctl(fd, VIDIOC_S_CROP, &in_crop);
+       }
+}
+
+static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop)
+{
+       char *value;
+       char *subs = optarg;
+
+       while (*subs != '\0') {
+               static const char *const subopts[] = {
+                       "left",
+                       "top",
+                       "width",
+                       "height",
+                       NULL
+               };
+
+               switch (parse_subopt(&subs, subopts, &value)) {
+               case 0:
+                       vcrop.left = strtol(value, 0L, 0);
+                       set_crop |= CropLeft;
+                       break;
+               case 1:
+                       vcrop.top = strtol(value, 0L, 0);
+                       set_crop |= CropTop;
+                       break;
+               case 2:
+                       vcrop.width = strtol(value, 0L, 0);
+                       set_crop |= CropWidth;
+                       break;
+               case 3:
+                       vcrop.height = strtol(value, 0L, 0);
+                       set_crop |= CropHeight;
+                       break;
+               default:
+                       selection_usage();
+                       exit(1);
+               }
+       }
+}
+
+static void do_selection(int fd, unsigned int set_selection, struct v4l2_selection &vsel,
+                        v4l2_buf_type type)
+{
+       struct v4l2_selection in_selection;
+
+       in_selection.type = type;
+       in_selection.target = vsel.target;
+
+       if (doioctl(fd, VIDIOC_G_SELECTION, &in_selection) == 0) {
+               if (set_selection & SelectionWidth)
+                       in_selection.r.width = vsel.r.width;
+               if (set_selection & SelectionHeight)
+                       in_selection.r.height = vsel.r.height;
+               if (set_selection & SelectionLeft)
+                       in_selection.r.left = vsel.r.left;
+               if (set_selection & SelectionTop)
+                       in_selection.r.top = vsel.r.top;
+               in_selection.flags = (set_selection & SelectionFlags) ? vsel.flags : 0;
+               doioctl(fd, VIDIOC_S_SELECTION, &in_selection);
+       }
+}
+
+static int parse_selection_target(const char *s, unsigned int &target)
+{
+       if (!strcmp(s, "crop")) target = V4L2_SEL_TGT_CROP_ACTIVE;
+       else if (!strcmp(s, "crop_default")) target = V4L2_SEL_TGT_CROP_DEFAULT;
+       else if (!strcmp(s, "crop_bounds")) target = V4L2_SEL_TGT_CROP_BOUNDS;
+       else if (!strcmp(s, "compose")) target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
+       else if (!strcmp(s, "compose_default")) target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+       else if (!strcmp(s, "compose_bounds")) target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+       else if (!strcmp(s, "compose_padded")) target = V4L2_SEL_TGT_COMPOSE_PADDED;
+       else return -EINVAL;
+
+       return 0;
+}
+
+static int parse_selection_flags(const char *s)
+{
+       if (!strcmp(s, "le")) return V4L2_SEL_FLAG_LE;
+       if (!strcmp(s, "ge")) return V4L2_SEL_FLAG_GE;
+       return 0;
+}
+
+static int parse_selection(char *optarg, unsigned int &set_sel, v4l2_selection &vsel)
+{
+       char *value;
+       char *subs = optarg;
+
+       while (*subs != '\0') {
+               static const char *const subopts[] = {
+                       "target",
+                       "flags",
+                       "left",
+                       "top",
+                       "width",
+                       "height",
+                       NULL
+               };
+
+               switch (parse_subopt(&subs, subopts, &value)) {
+               case 0:
+                       if (parse_selection_target(value, vsel.target)) {
+                               fprintf(stderr, "Unknown selection target\n");
+                               selection_usage();
+                               exit(1);
+                       }
+                       break;
+               case 1:
+                       vsel.flags = parse_selection_flags(value);
+                       set_sel |= SelectionFlags;
+                       break;
+               case 2:
+                       vsel.r.left = strtol(value, 0L, 0);
+                       set_sel |= SelectionLeft;
+                       break;
+               case 3:
+                       vsel.r.top = strtol(value, 0L, 0);
+                       set_sel |= SelectionTop;
+                       break;
+               case 4:
+                       vsel.r.width = strtol(value, 0L, 0);
+                       set_sel |= SelectionWidth;
+                       break;
+               case 5:
+                       vsel.r.height = strtol(value, 0L, 0);
+                       set_sel |= SelectionHeight;
+                       break;
+               default:
+                       fprintf(stderr, "Unknown option\n");
+                       selection_usage();
+                       exit(1);
+               }
+       }
+
+       return 0;
+}
+
+static void printcrop(const struct v4l2_crop &crop)
+{
+       printf("Crop: Left %d, Top %d, Width %d, Height %d\n",
+                       crop.c.left, crop.c.top, crop.c.width, crop.c.height);
+}
+
+static void printcropcap(const struct v4l2_cropcap &cropcap)
+{
+       printf("Crop Capability %s:\n", buftype2s(cropcap.type).c_str());
+       printf("\tBounds      : Left %d, Top %d, Width %d, Height %d\n",
+                       cropcap.bounds.left, cropcap.bounds.top, cropcap.bounds.width, cropcap.bounds.height);
+       printf("\tDefault     : Left %d, Top %d, Width %d, Height %d\n",
+                       cropcap.defrect.left, cropcap.defrect.top, cropcap.defrect.width, cropcap.defrect.height);
+       printf("\tPixel Aspect: %u/%u\n", cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
+}
+
+static const flag_def selection_targets_def[] = {
+       { V4L2_SEL_TGT_CROP_ACTIVE, "crop" },
+       { V4L2_SEL_TGT_CROP_DEFAULT, "crop_default" },
+       { V4L2_SEL_TGT_CROP_BOUNDS, "crop_bounds" },
+       { V4L2_SEL_TGT_COMPOSE_ACTIVE, "compose" },
+       { V4L2_SEL_TGT_COMPOSE_DEFAULT, "compose_default" },
+       { V4L2_SEL_TGT_COMPOSE_BOUNDS, "compose_bounds" },
+       { V4L2_SEL_TGT_COMPOSE_PADDED, "compose_padded" },
+       { 0, NULL }
+};
+
+static std::string seltarget2s(__u32 target)
+{
+       int i = 0;
+
+       while (selection_targets_def[i++].str != NULL) {
+               if (selection_targets_def[i].flag == target)
+                       return selection_targets_def[i].str;
+       }
+       return "Unknown";
+}
+
+static void print_selection(const struct v4l2_selection &sel)
+{
+       printf("Selection: %s, Left %d, Top %d, Width %d, Height %d\n",
+                       seltarget2s(sel.target).c_str(),
+                       sel.r.left, sel.r.top, sel.r.width, sel.r.height);
+}
+
+void selection_cmd(int ch, char *optarg)
+{
+       switch (ch) {
+               case OptSetCrop:
+                       parse_crop(optarg, set_crop, vcrop);
+                       break;
+               case OptSetOutputCrop:
+                       parse_crop(optarg, set_crop_out, vcrop_out);
+                       break;
+               case OptSetOverlayCrop:
+                       parse_crop(optarg, set_crop_overlay, vcrop_overlay);
+                       break;
+               case OptSetOutputOverlayCrop:
+                       parse_crop(optarg, set_crop_out_overlay, vcrop_out_overlay);
+                       break;
+               case OptSetSelection:
+                       parse_selection(optarg, set_selection, vselection);
+                       break;
+               case OptSetOutputSelection:
+                       parse_selection(optarg, set_selection_out, vselection_out);
+                       break;
+               case OptGetOutputSelection:
+               case OptGetSelection: {
+                       struct v4l2_selection gsel;
+                       unsigned int get_sel;
+
+                       if (parse_selection(optarg, get_sel, gsel)) {
+                               fprintf(stderr, "Unknown selection target\n");
+                               selection_usage();
+                               exit(1);
+                       }
+                       get_sel_target = gsel.target;
+                       break;
+               }
+       }
+}
+
+void selection_set(int fd)
+{
+       if (options[OptSetCrop]) {
+               do_crop(fd, set_crop, vcrop, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       }
+
+       if (options[OptSetOutputCrop]) {
+               do_crop(fd, set_crop_out, vcrop_out, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       }
+
+       if (options[OptSetOverlayCrop]) {
+               do_crop(fd, set_crop_overlay, vcrop_overlay, V4L2_BUF_TYPE_VIDEO_OVERLAY);
+       }
+
+       if (options[OptSetOutputOverlayCrop]) {
+               do_crop(fd, set_crop_out_overlay, vcrop_out_overlay, V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY);
+       }
+
+       if (options[OptSetSelection]) {
+               do_selection(fd, set_selection, vselection, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       }
+
+       if (options[OptSetOutputSelection]) {
+               do_selection(fd, set_selection_out, vselection_out, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       }
+}
+
+void selection_get(int fd)
+{
+       if (options[OptGetCropCap]) {
+               struct v4l2_cropcap cropcap;
+
+               cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
+                       printcropcap(cropcap);
+       }
+
+       if (options[OptGetOutputCropCap]) {
+               struct v4l2_cropcap cropcap;
+
+               cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
+                       printcropcap(cropcap);
+       }
+
+       if (options[OptGetOverlayCropCap]) {
+               struct v4l2_cropcap cropcap;
+
+               cropcap.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
+                       printcropcap(cropcap);
+       }
+
+       if (options[OptGetOutputOverlayCropCap]) {
+               struct v4l2_cropcap cropcap;
+
+               cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
+               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
+                       printcropcap(cropcap);
+       }
+
+       if (options[OptGetCrop]) {
+               struct v4l2_crop crop;
+
+               crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
+                       printcrop(crop);
+       }
+
+       if (options[OptGetOutputCrop]) {
+               struct v4l2_crop crop;
+
+               crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
+                       printcrop(crop);
+       }
+
+       if (options[OptGetOverlayCrop]) {
+               struct v4l2_crop crop;
+
+               crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
+                       printcrop(crop);
+       }
+
+       if (options[OptGetOutputOverlayCrop]) {
+               struct v4l2_crop crop;
+
+               crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
+               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
+                       printcrop(crop);
+       }
+
+       if (options[OptGetSelection]) {
+               struct v4l2_selection sel;
+               int t = 0;
+
+               memset(&sel, 0, sizeof(sel));
+               sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+               if (options[OptAll] || get_sel_target == -1) {
+                       while (selection_targets_def[t++].str != NULL) {
+                               sel.target = selection_targets_def[t].flag;
+                               if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
+                                       print_selection(sel);
+                       }
+               } else {
+                       sel.target = get_sel_target;
+                       if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
+                               print_selection(sel);
+               }
+       }
+
+       if (options[OptGetOutputSelection]) {
+               struct v4l2_selection sel;
+               int t = 0;
+
+               memset(&sel, 0, sizeof(sel));
+               sel.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+
+               if (options[OptAll] || get_sel_target == -1) {
+                       while (selection_targets_def[t++].str != NULL) {
+                               sel.target = selection_targets_def[t].flag;
+                               if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
+                                       print_selection(sel);
+                       }
+               } else {
+                       sel.target = get_sel_target;
+                       if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
+                               print_selection(sel);
+               }
+       }
+}
index f4fb74b..accf271 100644 (file)
@@ -60,19 +60,6 @@ int verbose;
 
 unsigned capabilities;
 
-/* crop specified */
-#define CropWidth              (1L<<0)
-#define CropHeight             (1L<<1)
-#define CropLeft               (1L<<2)
-#define CropTop                (1L<<3)
-
-/* selection specified */
-#define SelectionWidth         (1L<<0)
-#define SelectionHeight                (1L<<1)
-#define SelectionLeft          (1L<<2)
-#define SelectionTop           (1L<<3)
-#define SelectionFlags                 (1L<<4)
-
 static struct option long_options[] = {
        {"list-audio-inputs", no_argument, 0, OptListAudioInputs},
        {"list-audio-outputs", no_argument, 0, OptListAudioOutputs},
@@ -205,47 +192,6 @@ static struct option long_options[] = {
        {0, 0, 0, 0}
 };
 
-static void usage_selection(void)
-{
-       printf("\nSelection/Cropping options:\n"
-              "  --get-cropcap      query the crop capabilities [VIDIOC_CROPCAP]\n"
-              "  --get-crop         query the video capture crop window [VIDIOC_G_CROP]\n"
-              "  --set-crop=top=<x>,left=<y>,width=<w>,height=<h>\n"
-              "                     set the video capture crop window [VIDIOC_S_CROP]\n"
-              "  --get-cropcap-output\n"
-              "                     query crop capabilities for video output [VIDIOC_CROPCAP]\n"
-              "  --get-crop-output  query the video output crop window [VIDIOC_G_CROP]\n"
-              "  --set-crop-output=top=<x>,left=<y>,width=<w>,height=<h>\n"
-              "                     set the video output crop window [VIDIOC_S_CROP]\n"
-              "  --get-cropcap-overlay\n"
-              "                     query crop capabilities for video overlay [VIDIOC_CROPCAP]\n"
-              "  --get-crop-overlay query the video overlay crop window [VIDIOC_G_CROP]\n"
-              "  --set-crop-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"
-              "                     set the video overlay crop window [VIDIOC_S_CROP]\n"
-              "  --get-cropcap-output-overlay\n"
-              "                     query the crop capabilities for video output overlays\n"
-              "                     [VIDIOC_CROPCAP]\n"
-              "  --get-crop-output-overlay\n"
-              "                     query the video output overlay crop window [VIDIOC_G_CROP]\n"
-              "  --set-crop-output-overlay=top=<x>,left=<y>,width=<w>,height=<h>\n"
-              "                     set the video output overlay crop window [VIDIOC_S_CROP]\n"
-              "  --get-selection=target=<target>\n"
-              "                     query the video capture selection rectangle [VIDIOC_G_SELECTION]\n"
-              "                     See --set-selection command for the valid <target> values.\n"
-              "  --set-selection=target=<target>,flags=<flags>,top=<x>,left=<y>,width=<w>,height=<h>\n"
-              "                     set the video capture selection rectangle [VIDIOC_S_SELECTION]\n"
-              "                     target=crop|crop_bounds|crop_default|compose|compose_bounds|\n"
-              "                            compose_default|compose_padded\n"
-              "                     flags=le|ge\n"
-              "  --get-selection-output=target=<target>\n"
-              "                     query the video output selection rectangle [VIDIOC_G_SELECTION]\n"
-              "                     See --set-selection command for the valid <target> values.\n"
-              "  --set-selection-output=target=<target>,flags=<flags>,top=<x>,left=<y>,width=<w>,height=<h>\n"
-              "                     set the video output selection rectangle [VIDIOC_S_SELECTION]\n"
-              "                     See --set-selection command for the arguments.\n"
-              );
-}
-
 static void usage_misc(void)
 {
        printf("\nMiscellaneous options:\n"
@@ -302,7 +248,7 @@ static void usage_all(void)
        vidout_usage();
        overlay_usage();
        vbi_usage();
-       usage_selection();
+       selection_usage();
        usage_misc();
 }
 
@@ -489,51 +435,6 @@ static void printjpegcomp(const struct v4l2_jpegcompression &jc)
        printf("%s", markers2s(jc.jpeg_markers).c_str());
 }
 
-static void printcrop(const struct v4l2_crop &crop)
-{
-       printf("Crop: Left %d, Top %d, Width %d, Height %d\n",
-                       crop.c.left, crop.c.top, crop.c.width, crop.c.height);
-}
-
-static void printcropcap(const struct v4l2_cropcap &cropcap)
-{
-       printf("Crop Capability %s:\n", buftype2s(cropcap.type).c_str());
-       printf("\tBounds      : Left %d, Top %d, Width %d, Height %d\n",
-                       cropcap.bounds.left, cropcap.bounds.top, cropcap.bounds.width, cropcap.bounds.height);
-       printf("\tDefault     : Left %d, Top %d, Width %d, Height %d\n",
-                       cropcap.defrect.left, cropcap.defrect.top, cropcap.defrect.width, cropcap.defrect.height);
-       printf("\tPixel Aspect: %u/%u\n", cropcap.pixelaspect.numerator, cropcap.pixelaspect.denominator);
-}
-
-static const flag_def selection_targets_def[] = {
-       { V4L2_SEL_TGT_CROP_ACTIVE, "crop" },
-       { V4L2_SEL_TGT_CROP_DEFAULT, "crop_default" },
-       { V4L2_SEL_TGT_CROP_BOUNDS, "crop_bounds" },
-       { V4L2_SEL_TGT_COMPOSE_ACTIVE, "compose" },
-       { V4L2_SEL_TGT_COMPOSE_DEFAULT, "compose_default" },
-       { V4L2_SEL_TGT_COMPOSE_BOUNDS, "compose_bounds" },
-       { V4L2_SEL_TGT_COMPOSE_PADDED, "compose_padded" },
-       { 0, NULL }
-};
-
-static std::string seltarget2s(__u32 target)
-{
-       int i = 0;
-
-       while (selection_targets_def[i++].str != NULL) {
-               if (selection_targets_def[i].flag == target)
-                       return selection_targets_def[i].str;
-       }
-       return "Unknown";
-}
-
-static void print_selection(const struct v4l2_selection &sel)
-{
-       printf("Selection: %s, Left %d, Top %d, Width %d, Height %d\n",
-                       seltarget2s(sel.target).c_str(),
-                       sel.r.left, sel.r.top, sel.r.width, sel.r.height);
-}
-
 static const flag_def service_def[] = {
        { V4L2_SLICED_TELETEXT_B,  "teletext" },
        { V4L2_SLICED_VPS,         "vps" },
@@ -885,159 +786,6 @@ static void print_deccmd(const struct v4l2_decoder_cmd &cmd)
        }
 }
 
-static void do_crop(int fd, unsigned int set_crop, struct v4l2_rect &vcrop, v4l2_buf_type type)
-{
-       struct v4l2_crop in_crop;
-
-       in_crop.type = type;
-       if (doioctl(fd, VIDIOC_G_CROP, &in_crop) == 0) {
-               if (set_crop & CropWidth)
-                       in_crop.c.width = vcrop.width;
-               if (set_crop & CropHeight)
-                       in_crop.c.height = vcrop.height;
-               if (set_crop & CropLeft)
-                       in_crop.c.left = vcrop.left;
-               if (set_crop & CropTop)
-                       in_crop.c.top = vcrop.top;
-               doioctl(fd, VIDIOC_S_CROP, &in_crop);
-       }
-}
-
-static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop)
-{
-       char *value;
-       char *subs = optarg;
-
-       while (*subs != '\0') {
-               static const char *const subopts[] = {
-                       "left",
-                       "top",
-                       "width",
-                       "height",
-                       NULL
-               };
-
-               switch (parse_subopt(&subs, subopts, &value)) {
-               case 0:
-                       vcrop.left = strtol(value, 0L, 0);
-                       set_crop |= CropLeft;
-                       break;
-               case 1:
-                       vcrop.top = strtol(value, 0L, 0);
-                       set_crop |= CropTop;
-                       break;
-               case 2:
-                       vcrop.width = strtol(value, 0L, 0);
-                       set_crop |= CropWidth;
-                       break;
-               case 3:
-                       vcrop.height = strtol(value, 0L, 0);
-                       set_crop |= CropHeight;
-                       break;
-               default:
-                       usage_selection();
-                       exit(1);
-               }
-       }
-}
-
-static void do_selection(int fd, unsigned int set_selection, struct v4l2_selection &vsel,
-                        v4l2_buf_type type)
-{
-       struct v4l2_selection in_selection;
-
-       in_selection.type = type;
-       in_selection.target = vsel.target;
-
-       if (doioctl(fd, VIDIOC_G_SELECTION, &in_selection) == 0) {
-               if (set_selection & SelectionWidth)
-                       in_selection.r.width = vsel.r.width;
-               if (set_selection & SelectionHeight)
-                       in_selection.r.height = vsel.r.height;
-               if (set_selection & SelectionLeft)
-                       in_selection.r.left = vsel.r.left;
-               if (set_selection & SelectionTop)
-                       in_selection.r.top = vsel.r.top;
-               in_selection.flags = (set_selection & SelectionFlags) ? vsel.flags : 0;
-               doioctl(fd, VIDIOC_S_SELECTION, &in_selection);
-       }
-}
-
-static int parse_selection_target(const char *s, unsigned int &target)
-{
-       if (!strcmp(s, "crop")) target = V4L2_SEL_TGT_CROP_ACTIVE;
-       else if (!strcmp(s, "crop_default")) target = V4L2_SEL_TGT_CROP_DEFAULT;
-       else if (!strcmp(s, "crop_bounds")) target = V4L2_SEL_TGT_CROP_BOUNDS;
-       else if (!strcmp(s, "compose")) target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
-       else if (!strcmp(s, "compose_default")) target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
-       else if (!strcmp(s, "compose_bounds")) target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
-       else if (!strcmp(s, "compose_padded")) target = V4L2_SEL_TGT_COMPOSE_PADDED;
-       else return -EINVAL;
-
-       return 0;
-}
-
-static int parse_selection_flags(const char *s)
-{
-       if (!strcmp(s, "le")) return V4L2_SEL_FLAG_LE;
-       if (!strcmp(s, "ge")) return V4L2_SEL_FLAG_GE;
-       return 0;
-}
-
-static int parse_selection(char *optarg, unsigned int &set_sel, v4l2_selection &vsel)
-{
-       char *value;
-       char *subs = optarg;
-
-       while (*subs != '\0') {
-               static const char *const subopts[] = {
-                       "target",
-                       "flags",
-                       "left",
-                       "top",
-                       "width",
-                       "height",
-                       NULL
-               };
-
-               switch (parse_subopt(&subs, subopts, &value)) {
-               case 0:
-                       if (parse_selection_target(value, vsel.target)) {
-                               fprintf(stderr, "Unknown selection target\n");
-                               usage_selection();
-                               exit(1);
-                       }
-                       break;
-               case 1:
-                       vsel.flags = parse_selection_flags(value);
-                       set_sel |= SelectionFlags;
-                       break;
-               case 2:
-                       vsel.r.left = strtol(value, 0L, 0);
-                       set_sel |= SelectionLeft;
-                       break;
-               case 3:
-                       vsel.r.top = strtol(value, 0L, 0);
-                       set_sel |= SelectionTop;
-                       break;
-               case 4:
-                       vsel.r.width = strtol(value, 0L, 0);
-                       set_sel |= SelectionWidth;
-                       break;
-               case 5:
-                       vsel.r.height = strtol(value, 0L, 0);
-                       set_sel |= SelectionHeight;
-                       break;
-               default:
-                       fprintf(stderr, "Unknown option\n");
-                       usage_selection();
-                       exit(1);
-               }
-       }
-
-       return 0;
-}
-
 /* Used for both encoder and decoder commands since they are the same
    at the moment. */
 static int parse_cmd(const char *s)
@@ -1137,25 +885,10 @@ int main(int argc, char **argv)
 
        int fd = -1;
 
-       /* bitfield for fmts */
-       unsigned int set_crop = 0;
-       unsigned int set_crop_out = 0;
-       unsigned int set_crop_overlay = 0;
-       unsigned int set_crop_out_overlay = 0;
-       unsigned int set_selection = 0;
-       unsigned int set_selection_out = 0;
-       int get_sel_target = 0;
-
        /* command args */
        int ch;
        const char *device = "/dev/video0";     /* -d device */
        struct v4l2_capability vcap;    /* list_cap */
-       struct v4l2_rect vcrop;         /* crop rect */
-       struct v4l2_rect vcrop_out;     /* crop rect */
-       struct v4l2_rect vcrop_overlay;         /* crop rect */
-       struct v4l2_rect vcrop_out_overlay;     /* crop rect */
-       struct v4l2_selection vselection;       /* capture selection */
-       struct v4l2_selection vselection_out;   /* output selection */
        struct v4l2_jpegcompression jpegcomp; /* jpeg compression */
        struct v4l2_streamparm parm;    /* get/set parm */
        struct v4l2_encoder_cmd enc_cmd; /* (try_)encoder_cmd */
@@ -1171,12 +904,6 @@ int main(int argc, char **argv)
        int idx = 0;
 
        memset(&vcap, 0, sizeof(vcap));
-       memset(&vcrop, 0, sizeof(vcrop));
-       memset(&vcrop_out, 0, sizeof(vcrop_out));
-       memset(&vcrop_overlay, 0, sizeof(vcrop_overlay));
-       memset(&vcrop_out_overlay, 0, sizeof(vcrop_out_overlay));
-       memset(&vselection, 0, sizeof(vselection));
-       memset(&vselection_out, 0, sizeof(vselection_out));
        memset(&jpegcomp, 0, sizeof(jpegcomp));
        memset(&enc_cmd, 0, sizeof(enc_cmd));
        memset(&dec_cmd, 0, sizeof(dec_cmd));
@@ -1228,7 +955,7 @@ int main(int argc, char **argv)
                        vbi_usage();
                        return 0;
                case OptHelpSelection:
-                       usage_selection();
+                       selection_usage();
                        return 0;
                case OptHelpMisc:
                        usage_misc();
@@ -1249,37 +976,6 @@ int main(int argc, char **argv)
                case OptSleep:
                        secs = strtoul(optarg, 0L, 0);
                        break;
-               case OptSetCrop:
-                       parse_crop(optarg, set_crop, vcrop);
-                       break;
-               case OptSetOutputCrop:
-                       parse_crop(optarg, set_crop_out, vcrop_out);
-                       break;
-               case OptSetOverlayCrop:
-                       parse_crop(optarg, set_crop_overlay, vcrop_overlay);
-                       break;
-               case OptSetOutputOverlayCrop:
-                       parse_crop(optarg, set_crop_out_overlay, vcrop_out_overlay);
-                       break;
-               case OptSetSelection:
-                       parse_selection(optarg, set_selection, vselection);
-                       break;
-               case OptSetOutputSelection:
-                       parse_selection(optarg, set_selection_out, vselection_out);
-                       break;
-               case OptGetOutputSelection:
-               case OptGetSelection: {
-                       struct v4l2_selection gsel;
-                       unsigned int get_sel;
-
-                       if (parse_selection(optarg, get_sel, gsel)) {
-                               fprintf(stderr, "Unknown selection target\n");
-                               usage_selection();
-                               exit(1);
-                       }
-                       get_sel_target = gsel.target;
-                       break;
-               }
                case OptSetParm:
                        fps = strtod(optarg, NULL);
                        break;
@@ -1434,6 +1130,7 @@ int main(int argc, char **argv)
                        vidout_cmd(ch, optarg);
                        overlay_cmd(ch, optarg);
                        vbi_cmd(ch, optarg);
+                       selection_cmd(ch, optarg);
                        break;
                }
        }
@@ -1501,7 +1198,6 @@ int main(int argc, char **argv)
                options[OptGetSelection] = 1;
                options[OptGetOutputSelection] = 1;
                options[OptListCtrls] = 1;
-               get_sel_target = -1;
                options[OptSilent] = 1;
        }
 
@@ -1541,6 +1237,7 @@ int main(int argc, char **argv)
        vidout_set(fd);
        overlay_set(fd);
        vbi_set(fd);
+       selection_set(fd);
 
        if (options[OptSetParm]) {
                memset(&parm, 0, sizeof(parm));
@@ -1581,30 +1278,6 @@ int main(int argc, char **argv)
        if (options[OptSetJpegComp]) {
                doioctl(fd, VIDIOC_S_JPEGCOMP, &jpegcomp);
        }
-
-       if (options[OptSetCrop]) {
-               do_crop(fd, set_crop, vcrop, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       }
-
-       if (options[OptSetOutputCrop]) {
-               do_crop(fd, set_crop_out, vcrop_out, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-       }
-
-       if (options[OptSetOverlayCrop]) {
-               do_crop(fd, set_crop_overlay, vcrop_overlay, V4L2_BUF_TYPE_VIDEO_OVERLAY);
-       }
-
-       if (options[OptSetOutputOverlayCrop]) {
-               do_crop(fd, set_crop_out_overlay, vcrop_out_overlay, V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY);
-       }
-
-       if (options[OptSetSelection]) {
-               do_selection(fd, set_selection, vselection, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       }
-
-       if (options[OptSetOutputSelection]) {
-               do_selection(fd, set_selection_out, vselection_out, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-       }
        
        if (options[OptEncoderCmd])
                doioctl(fd, VIDIOC_ENCODER_CMD, &enc_cmd);
@@ -1627,6 +1300,7 @@ int main(int argc, char **argv)
        vidout_get(fd);
        overlay_get(fd);
        vbi_get(fd);
+       selection_get(fd);
 
        if (options[OptGetJpegComp]) {
                struct v4l2_jpegcompression jc;
@@ -1634,110 +1308,6 @@ int main(int argc, char **argv)
                        printjpegcomp(jc);
        }
 
-       if (options[OptGetCropCap]) {
-               struct v4l2_cropcap cropcap;
-
-               cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
-                       printcropcap(cropcap);
-       }
-
-       if (options[OptGetOutputCropCap]) {
-               struct v4l2_cropcap cropcap;
-
-               cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
-                       printcropcap(cropcap);
-       }
-
-       if (options[OptGetOverlayCropCap]) {
-               struct v4l2_cropcap cropcap;
-
-               cropcap.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
-                       printcropcap(cropcap);
-       }
-
-       if (options[OptGetOutputOverlayCropCap]) {
-               struct v4l2_cropcap cropcap;
-
-               cropcap.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
-               if (doioctl(fd, VIDIOC_CROPCAP, &cropcap) == 0)
-                       printcropcap(cropcap);
-       }
-
-       if (options[OptGetCrop]) {
-               struct v4l2_crop crop;
-
-               crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
-                       printcrop(crop);
-       }
-
-       if (options[OptGetOutputCrop]) {
-               struct v4l2_crop crop;
-
-               crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
-                       printcrop(crop);
-       }
-
-       if (options[OptGetOverlayCrop]) {
-               struct v4l2_crop crop;
-
-               crop.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
-               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
-                       printcrop(crop);
-       }
-
-       if (options[OptGetOutputOverlayCrop]) {
-               struct v4l2_crop crop;
-
-               crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY;
-               if (doioctl(fd, VIDIOC_G_CROP, &crop) == 0)
-                       printcrop(crop);
-       }
-
-       if (options[OptGetSelection]) {
-               struct v4l2_selection sel;
-               int t = 0;
-
-               memset(&sel, 0, sizeof(sel));
-               sel.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-               if (get_sel_target == -1) {
-                       while (selection_targets_def[t++].str != NULL) {
-                               sel.target = selection_targets_def[t].flag;
-                               if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
-                                       print_selection(sel);
-                       }
-               } else {
-                       sel.target = get_sel_target;
-                       if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
-                               print_selection(sel);
-               }
-       }
-
-       if (options[OptGetOutputSelection]) {
-               struct v4l2_selection sel;
-               int t = 0;
-
-               memset(&sel, 0, sizeof(sel));
-               sel.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-
-               if (get_sel_target == -1) {
-                       while (selection_targets_def[t++].str != NULL) {
-                               sel.target = selection_targets_def[t].flag;
-                               if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
-                                       print_selection(sel);
-                       }
-               } else {
-                       sel.target = get_sel_target;
-                       if (doioctl(fd, VIDIOC_G_SELECTION, &sel) == 0)
-                               print_selection(sel);
-               }
-       }
-
         if (options[OptGetParm]) {
                memset(&parm, 0, sizeof(parm));
                parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
index afb0d65..66fddad 100644 (file)
@@ -242,5 +242,11 @@ void vbi_set(int fd);
 void vbi_get(int fd);
 void vbi_list(int fd);
 
+// v4l2-ctl-selection.cpp
+void selection_usage(void);
+void selection_cmd(int ch, char *optarg);
+void selection_set(int fd);
+void selection_get(int fd);
+
 
 #endif