linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ricardo Ribalda <ribalda@chromium.org>
To: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	Tomasz Figa <tfiga@chromium.org>,
	Mauro Carvalho Chehab <mchehab@kernel.org>,
	Hans Verkuil <hverkuil-cisco@xs4all.nl>,
	Linux Media Mailing List <linux-media@vger.kernel.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: [PATCHv3 5/6] media: uvcvideo: add UVC 1.5 ROI control
Date: Tue, 23 Mar 2021 17:16:38 +0100	[thread overview]
Message-ID: <CANiDSCt72o_E=gRBRhMWWmta-H2WGmDqg5_PBGHBrVCG4iepZw@mail.gmail.com> (raw)
In-Reply-To: <20210319055342.127308-6-senozhatsky@chromium.org>

Hi Sergey

On Fri, Mar 19, 2021 at 6:54 AM Sergey Senozhatsky
<senozhatsky@chromium.org> wrote:
>
> This patch implements UVC 1.5 Region of Interest (ROI) control.
>
> Note that, UVC 1.5 defines CT_DIGITAL_WINDOW_CONTROL controls
> and mentions that ROI rectangle coordinates "must be within
> the current Digital Window as specified by the CT_WINDOW control."
> (4.2.2.1.20 Digital Region of Interest (ROI) Control).
>
> It's is not entirely clear if we need to implement WINDOW_CONTROL.
> ROI is naturally limited by GET_MIN and GET_MAX rectangles.
>
> Another thing to note is that ROI support is implemented as
> V4L2 selection target: selection rectangle represents ROI
> rectangle and selection flags represent ROI auto-controls.
> User-space is required to set valid values for both rectangle
> and auto-controls every time SET_CUR is issued.
>
> Usage example:
>
>        struct v4l2_selection roi = {0, };
>
>        roi.target     = V4L2_SEL_TGT_ROI;
>        roi.r.left     = 0;
>        roi.r.top      = 0;
>        roi.r.width    = 42;
>        roi.r.height   = 42;
>        roi.flags      = V4L2_SEL_FLAG_ROI_AUTO_EXPOSURE;
>
>        ioctl(fd, VIDIOC_S_SELECTION, &roi);
>
> Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
> ---
>  drivers/media/usb/uvc/uvc_v4l2.c | 147 ++++++++++++++++++++++++++++++-
>  include/uapi/linux/usb/video.h   |   1 +
>  2 files changed, 145 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
> index 252136cc885c..d0fe6c33fab6 100644
> --- a/drivers/media/usb/uvc/uvc_v4l2.c
> +++ b/drivers/media/usb/uvc/uvc_v4l2.c
> @@ -1139,14 +1139,66 @@ static int uvc_ioctl_querymenu(struct file *file, void *fh,
>         return uvc_query_v4l2_menu(chain, qm);
>  }
>
> -static int uvc_ioctl_g_selection(struct file *file, void *fh,
> -                                struct v4l2_selection *sel)
> +/* UVC 1.5 ROI rectangle is half the size of v4l2_rect */
> +struct uvc_roi_rect {
> +       __u16                   top;
> +       __u16                   left;
> +       __u16                   bottom;
> +       __u16                   right;
> +       __u16                   auto_controls;
> +} __packed;
> +
> +static int uvc_ioctl_g_roi_target(struct file *file, void *fh,
> +                                 struct v4l2_selection *sel)
>  {
>         struct uvc_fh *handle = fh;
>         struct uvc_streaming *stream = handle->stream;
> +       struct uvc_roi_rect *roi;
> +       u8 query;
> +       int ret;
>
> -       if (sel->type != stream->type)
> +       switch (sel->target) {
> +       case V4L2_SEL_TGT_ROI:
> +               query = UVC_GET_CUR;
> +               break;
> +       case V4L2_SEL_TGT_ROI_DEFAULT:
> +               query = UVC_GET_DEF;
> +               break;
> +       case V4L2_SEL_TGT_ROI_BOUNDS_MIN:
> +               query = UVC_GET_MAX;
> +               break;
> +       case V4L2_SEL_TGT_ROI_BOUNDS_MAX:
> +               query = UVC_GET_MAX;
> +               break;
> +       default:
>                 return -EINVAL;
> +       }
> +
> +       roi = kzalloc(sizeof(struct uvc_roi_rect), GFP_KERNEL);
> +       if (!roi)
> +               return -ENOMEM;
> +
> +       ret = uvc_query_ctrl(stream->dev, query, 1, stream->dev->intfnum,
> +                            UVC_CT_REGION_OF_INTEREST_CONTROL, roi,
> +                            sizeof(struct uvc_roi_rect));
> +       if (!ret) {
> +               /* ROI left, top, right, bottom are global coordinates. */
> +               sel->r.left     = roi->left;
> +               sel->r.top      = roi->top;
> +               sel->r.width    = roi->right - roi->left + 1;
> +               sel->r.height   = roi->bottom - roi->top + 1;
> +               sel->flags      = roi->auto_controls;
> +       }
> +
> +       kfree(roi);
> +       return ret;
> +}
> +
> +static int uvc_ioctl_g_sel_target(struct file *file, void *fh,
> +                                 struct v4l2_selection *sel)
> +{
> +       struct uvc_fh *handle = fh;
> +       struct uvc_streaming *stream = handle->stream;
>
>         switch (sel->target) {
>         case V4L2_SEL_TGT_CROP_DEFAULT:
> @@ -1173,6 +1225,94 @@ static int uvc_ioctl_g_selection(struct file *file, void *fh,
>         return 0;
>  }
>
> +static int uvc_ioctl_g_selection(struct file *file, void *fh,
> +                                struct v4l2_selection *sel)
> +{
> +       struct uvc_fh *handle = fh;
> +       struct uvc_streaming *stream = handle->stream;
> +
> +       if (sel->type != stream->type)
> +               return -EINVAL;
> +
> +       switch (sel->target) {
> +       case V4L2_SEL_TGT_CROP_DEFAULT:
> +       case V4L2_SEL_TGT_CROP_BOUNDS:
> +       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
> +       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
> +               return uvc_ioctl_g_sel_target(file, fh, sel);
> +       case V4L2_SEL_TGT_ROI:
> +       case V4L2_SEL_TGT_ROI_DEFAULT:
> +       case V4L2_SEL_TGT_ROI_BOUNDS_MIN:
> +       case V4L2_SEL_TGT_ROI_BOUNDS_MAX:
> +               return uvc_ioctl_g_roi_target(file, fh, sel);
> +       }
> +
> +       return -EINVAL;
> +}
> +
> +static bool validate_roi_bounds(struct uvc_streaming *stream,
> +                               struct v4l2_selection *sel)
> +{
> +       if (sel->r.left > USHRT_MAX ||
> +           sel->r.top > USHRT_MAX ||
> +           (sel->r.width + sel->r.left) > USHRT_MAX ||
> +           (sel->r.height + sel->r.top) > USHRT_MAX ||
> +           !sel->r.width || !sel->r.height)
> +               return false;
> +
> +       if (sel->flags > V4L2_SEL_FLAG_ROI_AUTO_HIGHER_QUALITY)
> +               return false;

Is it not allowed V4L2_SEL_FLAG_ROI_AUTO_IRIS |
V4L2_SEL_FLAG_ROI_AUTO_HIGHER_QUALITY   ?

> +
> +       return true;
> +}
> +
> +static int uvc_ioctl_s_roi(struct file *file, void *fh,
> +                          struct v4l2_selection *sel)
> +{
> +       struct uvc_fh *handle = fh;
> +       struct uvc_streaming *stream = handle->stream;
> +       struct uvc_roi_rect *roi;
> +       int ret;
> +
> +       if (!validate_roi_bounds(stream, sel))
> +               return -E2BIG;

Not sure if this is the correct approach or if we should convert the
value to the closest valid...


> +
> +       roi = kzalloc(sizeof(struct uvc_roi_rect), GFP_KERNEL);
> +       if (!roi)
> +               return -ENOMEM;
> +
> +       /* ROI left, top, right, bottom are global coordinates. */
> +       roi->left               = sel->r.left;
> +       roi->top                = sel->r.top;
> +       roi->right              = sel->r.width + sel->r.left - 1;
> +       roi->bottom             = sel->r.height + sel->r.top - 1;
> +       roi->auto_controls      = sel->flags;
> +
> +       ret = uvc_query_ctrl(stream->dev, UVC_SET_CUR, 1, stream->dev->intfnum,
> +                            UVC_CT_REGION_OF_INTEREST_CONTROL, roi,
> +                            sizeof(struct uvc_roi_rect));
> +
> +       kfree(roi);
> +       return ret;
> +}
> +
> +static int uvc_ioctl_s_selection(struct file *file, void *fh,
> +                                struct v4l2_selection *sel)
> +{
> +       struct uvc_fh *handle = fh;
> +       struct uvc_streaming *stream = handle->stream;
> +
> +       if (sel->type != stream->type)
> +               return -EINVAL;
> +
> +       switch (sel->target) {
> +       case V4L2_SEL_TGT_ROI:
> +               return uvc_ioctl_s_roi(file, fh, sel);
> +       }
> +
> +       return -EINVAL;
> +}
> +
>  static int uvc_ioctl_g_parm(struct file *file, void *fh,
>                             struct v4l2_streamparm *parm)
>  {
> @@ -1533,6 +1673,7 @@ const struct v4l2_ioctl_ops uvc_ioctl_ops = {
>         .vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
>         .vidioc_querymenu = uvc_ioctl_querymenu,
>         .vidioc_g_selection = uvc_ioctl_g_selection,
> +       .vidioc_s_selection = uvc_ioctl_s_selection,
>         .vidioc_g_parm = uvc_ioctl_g_parm,
>         .vidioc_s_parm = uvc_ioctl_s_parm,
>         .vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
> diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
> index d854cb19c42c..c87624962896 100644
> --- a/include/uapi/linux/usb/video.h
> +++ b/include/uapi/linux/usb/video.h
> @@ -104,6 +104,7 @@
>  #define UVC_CT_ROLL_ABSOLUTE_CONTROL                   0x0f
>  #define UVC_CT_ROLL_RELATIVE_CONTROL                   0x10
>  #define UVC_CT_PRIVACY_CONTROL                         0x11
> +#define UVC_CT_REGION_OF_INTEREST_CONTROL              0x14
>
>  /* A.9.5. Processing Unit Control Selectors */
>  #define UVC_PU_CONTROL_UNDEFINED                       0x00
> --
> 2.31.0.rc2.261.g7f71774620-goog
>


-- 
Ricardo Ribalda

  reply	other threads:[~2021-03-23 16:17 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-19  5:53 [PATCHv3 0/6] media: uvcvideo: implement UVC 1.5 ROI Sergey Senozhatsky
2021-03-19  5:53 ` [PATCHv3 1/6] media: v4l UAPI: add ROI selection targets Sergey Senozhatsky
2021-03-19  5:53 ` [PATCHv3 2/6] media: v4l UAPI: document " Sergey Senozhatsky
2021-03-23 16:05   ` Ricardo Ribalda
2021-03-19  5:53 ` [PATCHv3 3/6] media: v4l UAPI: add ROI auto-controls flags Sergey Senozhatsky
2021-03-23 16:04   ` Ricardo Ribalda
2021-03-24  2:22     ` Sergey Senozhatsky
2021-03-24  7:28       ` Ricardo Ribalda
2021-03-24  7:35         ` Sergey Senozhatsky
2021-03-19  5:53 ` [PATCHv3 4/6] media: v4l UAPI: document " Sergey Senozhatsky
2021-03-19  5:53 ` [PATCHv3 5/6] media: uvcvideo: add UVC 1.5 ROI control Sergey Senozhatsky
2021-03-23 16:16   ` Ricardo Ribalda [this message]
2021-03-24  2:01     ` Sergey Senozhatsky
2021-03-24  2:14       ` Tomasz Figa
2021-03-24  2:31         ` Sergey Senozhatsky
2021-03-24  2:34           ` Tomasz Figa
2021-03-24  2:52             ` Sergey Senozhatsky
2021-03-24  3:00               ` Tomasz Figa
2021-03-24  3:05                 ` Sergey Senozhatsky
2021-03-24  3:08                   ` Sergey Senozhatsky
2021-03-19  5:53 ` [PATCHv3 6/6] MAINTAINERS: update Senozhatsky email address Sergey Senozhatsky
2021-03-19  5:56   ` Sergey Senozhatsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CANiDSCt72o_E=gRBRhMWWmta-H2WGmDqg5_PBGHBrVCG4iepZw@mail.gmail.com' \
    --to=ribalda@chromium.org \
    --cc=hverkuil-cisco@xs4all.nl \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=mchehab@kernel.org \
    --cc=senozhatsky@chromium.org \
    --cc=tfiga@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).