[v1] v4l2-ctl: Add support for VIDIOC_G/S_SELECTION ioctls
Commit Message
This patch adds following commands for the selection API ioctls:
--get-selection, --set-selection,
--get-selection-output, --set-selection-output.
All supported selection rectangles at a video node are now also
displayed in case of --all command.
Signed-off-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
---
utils/v4l2-ctl/v4l2-ctl.cpp | 239 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 239 insertions(+), 0 deletions(-)
--
1.7.4.1
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Comments
On Sun July 22 2012 22:42:02 Sylwester Nawrocki wrote:
> This patch adds following commands for the selection API ioctls:
>
> --get-selection, --set-selection,
> --get-selection-output, --set-selection-output.
>
> All supported selection rectangles at a video node are now also
> displayed in case of --all command.
I've committed both patches. Thanks!
Regards,
Hans
>
> Signed-off-by: Sylwester Nawrocki <sylvester.nawrocki@gmail.com>
> ---
> utils/v4l2-ctl/v4l2-ctl.cpp | 239 +++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 239 insertions(+), 0 deletions(-)
>
> diff --git a/utils/v4l2-ctl/v4l2-ctl.cpp b/utils/v4l2-ctl/v4l2-ctl.cpp
> index 1a6c4ae..c70e88c 100644
> --- a/utils/v4l2-ctl/v4l2-ctl.cpp
> +++ b/utils/v4l2-ctl/v4l2-ctl.cpp
> @@ -139,6 +139,10 @@ enum Option {
> OptSetOverlayCrop,
> OptGetOutputOverlayCrop,
> OptSetOutputOverlayCrop,
> + OptGetSelection,
> + OptSetSelection,
> + OptGetOutputSelection,
> + OptSetOutputSelection,
> OptGetAudioInput,
> OptSetAudioInput,
> OptGetAudioOutput,
> @@ -233,6 +237,13 @@ static const flag_def service_def[] = {
> #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},
> @@ -322,6 +333,10 @@ static struct option long_options[] = {
> {"get-cropcap-output-overlay", no_argument, 0, OptGetOutputOverlayCropCap},
> {"get-crop-output-overlay", no_argument, 0, OptGetOutputOverlayCrop},
> {"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop},
> + {"get-selection", required_argument, 0, OptGetSelection},
> + {"set-selection", required_argument, 0, OptSetSelection},
> + {"get-selection-output", required_argument, 0, OptGetOutputSelection},
> + {"set-selection-output", required_argument, 0, OptSetOutputSelection},
> {"get-jpeg-comp", no_argument, 0, OptGetJpegComp},
> {"set-jpeg-comp", required_argument, 0, OptSetJpegComp},
> {"get-modulator", no_argument, 0, OptGetModulator},
> @@ -631,6 +646,26 @@ static void usage_crop(void)
> );
> }
>
> +static void usage_selection(void)
> +{
> + printf("\nSelection options:\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"
> @@ -688,6 +723,7 @@ static void usage(void)
> usage_vidout();
> usage_overlay();
> usage_vbi();
> + usage_selection();
> usage_crop();
> usage_misc();
> }
> @@ -1267,6 +1303,35 @@ static void printcropcap(const struct v4l2_cropcap &cropcap)
> 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 void printfmt(const struct v4l2_format &vfmt)
> {
> const flag_def vbi_def[] = {
> @@ -2008,6 +2073,103 @@ static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop)
> }
> }
>
> +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;
> +}
> +
> static void parse_freq_seek(char *optarg, struct v4l2_hw_freq_seek &seek)
> {
> char *value;
> @@ -2323,6 +2485,9 @@ int main(int argc, char **argv)
> 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;
> unsigned int set_fbuf = 0;
> unsigned int set_overlay_fmt = 0;
> unsigned int set_overlay_fmt_out = 0;
> @@ -2353,6 +2518,8 @@ int main(int argc, char **argv)
> 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_framebuffer fbuf; /* fbuf */
> struct v4l2_jpegcompression jpegcomp; /* jpeg compression */
> struct v4l2_streamparm parm; /* get/set parm */
> @@ -2409,6 +2576,8 @@ int main(int argc, char **argv)
> 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(&vf, 0, sizeof(vf));
> memset(&vs, 0, sizeof(vs));
> memset(&fbuf, 0, sizeof(fbuf));
> @@ -2694,6 +2863,25 @@ int main(int argc, char **argv)
> 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 OptSetInput:
> input = strtol(optarg, 0L, 0);
> break;
> @@ -3097,6 +3285,9 @@ int main(int argc, char **argv)
> options[OptGetDvTimings] = 1;
> options[OptGetDvTimingsCap] = 1;
> options[OptGetPriority] = 1;
> + options[OptGetSelection] = 1;
> + options[OptGetOutputSelection] = 1;
> + get_sel_target = -1;
> options[OptSilent] = 1;
> }
>
> @@ -3489,6 +3680,14 @@ int main(int argc, char **argv)
> 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[OptSetCtrl] && !set_ctrls.empty()) {
> struct v4l2_ext_controls ctrls;
> class2ctrls_map class2ctrls;
> @@ -3720,6 +3919,46 @@ int main(int argc, char **argv)
> 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[OptGetInput]) {
> if (doioctl(fd, VIDIOC_G_INPUT, &input) == 0) {
> printf("Video input : %d", input);
> --
> 1.7.4.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
@@ -139,6 +139,10 @@ enum Option {
OptSetOverlayCrop,
OptGetOutputOverlayCrop,
OptSetOutputOverlayCrop,
+ OptGetSelection,
+ OptSetSelection,
+ OptGetOutputSelection,
+ OptSetOutputSelection,
OptGetAudioInput,
OptSetAudioInput,
OptGetAudioOutput,
@@ -233,6 +237,13 @@ static const flag_def service_def[] = {
#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},
@@ -322,6 +333,10 @@ static struct option long_options[] = {
{"get-cropcap-output-overlay", no_argument, 0, OptGetOutputOverlayCropCap},
{"get-crop-output-overlay", no_argument, 0, OptGetOutputOverlayCrop},
{"set-crop-output-overlay", required_argument, 0, OptSetOutputOverlayCrop},
+ {"get-selection", required_argument, 0, OptGetSelection},
+ {"set-selection", required_argument, 0, OptSetSelection},
+ {"get-selection-output", required_argument, 0, OptGetOutputSelection},
+ {"set-selection-output", required_argument, 0, OptSetOutputSelection},
{"get-jpeg-comp", no_argument, 0, OptGetJpegComp},
{"set-jpeg-comp", required_argument, 0, OptSetJpegComp},
{"get-modulator", no_argument, 0, OptGetModulator},
@@ -631,6 +646,26 @@ static void usage_crop(void)
);
}
+static void usage_selection(void)
+{
+ printf("\nSelection options:\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"
@@ -688,6 +723,7 @@ static void usage(void)
usage_vidout();
usage_overlay();
usage_vbi();
+ usage_selection();
usage_crop();
usage_misc();
}
@@ -1267,6 +1303,35 @@ static void printcropcap(const struct v4l2_cropcap &cropcap)
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 void printfmt(const struct v4l2_format &vfmt)
{
const flag_def vbi_def[] = {
@@ -2008,6 +2073,103 @@ static void parse_crop(char *optarg, unsigned int &set_crop, v4l2_rect &vcrop)
}
}
+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;
+}
+
static void parse_freq_seek(char *optarg, struct v4l2_hw_freq_seek &seek)
{
char *value;
@@ -2323,6 +2485,9 @@ int main(int argc, char **argv)
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;
unsigned int set_fbuf = 0;
unsigned int set_overlay_fmt = 0;
unsigned int set_overlay_fmt_out = 0;
@@ -2353,6 +2518,8 @@ int main(int argc, char **argv)
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_framebuffer fbuf; /* fbuf */
struct v4l2_jpegcompression jpegcomp; /* jpeg compression */
struct v4l2_streamparm parm; /* get/set parm */
@@ -2409,6 +2576,8 @@ int main(int argc, char **argv)
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(&vf, 0, sizeof(vf));
memset(&vs, 0, sizeof(vs));
memset(&fbuf, 0, sizeof(fbuf));
@@ -2694,6 +2863,25 @@ int main(int argc, char **argv)
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 OptSetInput:
input = strtol(optarg, 0L, 0);
break;
@@ -3097,6 +3285,9 @@ int main(int argc, char **argv)
options[OptGetDvTimings] = 1;
options[OptGetDvTimingsCap] = 1;
options[OptGetPriority] = 1;
+ options[OptGetSelection] = 1;
+ options[OptGetOutputSelection] = 1;
+ get_sel_target = -1;
options[OptSilent] = 1;
}
@@ -3489,6 +3680,14 @@ int main(int argc, char **argv)
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[OptSetCtrl] && !set_ctrls.empty()) {
struct v4l2_ext_controls ctrls;
class2ctrls_map class2ctrls;
@@ -3720,6 +3919,46 @@ int main(int argc, char **argv)
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[OptGetInput]) {
if (doioctl(fd, VIDIOC_G_INPUT, &input) == 0) {
printf("Video input : %d", input);