linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Hans Verkuil <hverkuil@xs4all.nl>
Cc: Jacopo Mondi <jacopo@jmondi.org>,
	Linux Media Mailing List <linux-media@vger.kernel.org>,
	Sowjanya Komatineni <skomatineni@nvidia.com>,
	Sakari Ailus <sakari.ailus@linux.intel.com>,
	Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>,
	libcamera-devel@lists.libcamera.org
Subject: Re: [PATCH] imx219: selection compliance fixes
Date: Fri, 17 Jul 2020 02:20:31 +0300	[thread overview]
Message-ID: <20200716232031.GI5960@pendragon.ideasonboard.com> (raw)
In-Reply-To: <a6c1896c-583d-3b74-dd18-30c735218b98@xs4all.nl>

Hi Hans,

On Thu, Jul 16, 2020 at 03:53:41PM +0200, Hans Verkuil wrote:
> On 16/07/2020 14:59, Laurent Pinchart wrote:
> > On Thu, Jul 16, 2020 at 11:48:19AM +0200, Hans Verkuil wrote:
> >> On 15/07/2020 09:19, Jacopo Mondi wrote:
> >>> On Wed, Jul 15, 2020 at 02:49:38AM +0300, Laurent Pinchart wrote:
> >>>> On Tue, Jul 14, 2020 at 02:31:46PM +0200, Jacopo Mondi wrote:
> >>>>> On Thu, Jul 02, 2020 at 03:50:04PM +0200, Hans Verkuil wrote:
> >>>>>> The top/left crop coordinates were 0, 0 instead of 8, 8 in the
> >>>>>> supported_modes array. This was a mismatch with the default values,
> >>>>>> so this is corrected. Found with v4l2-compliance.
> >>>>>>
> >>>>>> Also add V4L2_SEL_TGT_CROP_BOUNDS support: CROP_DEFAULT and CROP_BOUNDS
> >>>>>> always go together. Found with v4l2-compliance.
> >>>>>
> >>>>> I actually introduced this with
> >>>>> e6d4ef7d58aa ("media: i2c: imx219: Implement get_selection")
> >>>>>
> >>>>>>
> >>>>>> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
> >>>>>> ---
> >>>>>>  drivers/media/i2c/imx219.c | 17 +++++++++--------
> >>>>>>  1 file changed, 9 insertions(+), 8 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/media/i2c/imx219.c b/drivers/media/i2c/imx219.c
> >>>>>> index 0a546b8e466c..935e2a258ce5 100644
> >>>>>> --- a/drivers/media/i2c/imx219.c
> >>>>>> +++ b/drivers/media/i2c/imx219.c
> >>>>>> @@ -473,8 +473,8 @@ static const struct imx219_mode supported_modes[] = {
> >>>>>>  		.width = 3280,
> >>>>>>  		.height = 2464,
> >>>>>>  		.crop = {
> >>>>>> -			.left = 0,
> >>>>>> -			.top = 0,
> >>>>>> +			.left = 8,
> >>>>>> +			.top = 8,
> >>>>>
> >>>>> Mmmm, why this change ?
> >>>>> This values are used to report V4L2_SEL_TGT_CROP rectangle, which
> >>>>> according to the documentation is defined as
> >>>>> "Crop rectangle. Defines the cropped area."
> >>>>> (not a much extensive description :)
> >>
> >> Unless changed by calling S_SELECTION(TGT_CROP) the initial crop is equal
> >> to TGT_CROP_DEFAULT, and but TGT_CROP and TGT_CROP_DEFAULT shall be inside
> >> TGT_CROP_BOUNDS. CROP_BOUNDS may be larger than CROP_DEFAULT and describes
> >> the whole area from which you can crop. I.e. in the case of sensors you can
> >> set the crop rectangle to include optical blanks active pixels.
> >>
> >> In this driver the initial TGT_CROP rectangle as specified in supported_modes
> >> (aligned with the top-left pixel) was outside CROP_BOUNDS (centered) and also
> >> a mismatch with CROP_DEFAULT (also centered).
> >>
> >>>>> Clearly this is a faulty definition, and I know from experience how
> >>>>> hard is proving to define pixel array properties and in which extent
> >>>>> the documentation has to go:
> >>>>> https://lists.libcamera.org/pipermail/libcamera-devel/2020-June/009115.html
> >>>>>
> >>>>> My understanding is that target should report the current crop
> >>>>> rectangle, defined from the rectangle retrieved with the
> >>>>> V4L2_SEL_TGT_CROP_DEFAULT target, which, according documentation
> >>>>> reports the:
> >>>>> "Suggested cropping rectangle that covers the “whole picture”.
> >>>>> This includes only active pixels and excludes other non-active pixels such
> >>>>> as black pixels"
> >>>>>
> >>>>> The TGT_CROP_DEFAULT then reports the active pixel array portion, and
> >>>>> needs to be defined in respect to the TGT_NATIVE_SIZE, which reports
> >>>>> the dimensions of the whole pixel matrix, including non-active pixels,
> >>>>> optical blanks active and non-active pixels.
> >>
> >> The relationship between NATIVE_SIZE and CROP_BOUNDS is not properly defined,
> >> but I would expect that CROP_BOUNDS is inside the NATIVE_SIZE target rectangle.
> >>
> >> If NATIVE_SIZE is larger than BOUNDS, then I would expect that the additional
> >> margins are pixels that are invalid or otherwise useless.
> >>
> >> The hard rule though is that you can crop anywhere within the CROP_BOUNDS area.
> >>
> >> Historically CROP_BOUNDS originated with analog SDTV video capture where it was
> >> possible to capture more data than just the typical 720x576/480 PAL/NTSC active
> >> video area. Analog video was often overscanned, i.e. there was more video data
> >> outside the 'active' video area. That was how CRTs worked. So you could move the
> >> crop window around within the CROP_BOUNDS area, or just capture the full CROP_BOUNDS
> >> are. Although this was often poorly tested/implemented. The bttv driver is one of
> >> the few that could do this.
> >>
> >> This is actually simplified since you could do weird things with the horizontal
> >> sample rate as well, effectively changing the pixel aspect ratio, making things
> >> really complicated. It's analog video so while the video lines were discrete,
> >> horizontally you are just sampling a waveform, so you could sample at different
> >> rates if you wanted to. I doubt anyone ever used it since doing that would give
> >> you a huge headache :-)
> >>
> >> With digital video interfaces (HDMI, DVI, SDI, DP, etc.) that no longer applies and
> >> for those receivers the initial CROP/CROP_DEFAULT/CROP_BOUNDS rectangles are all
> >> the same, e.g. 1920x1080 for 1080p HDMI video.
> >>
> >>>>>
> >>>>> The TGT_CROP rectangle is hence defined from the CROP_DEFAULT one, and
> >>>>> if the 'whole active area' is selected, its top-left corner is placed
> >>>>> in position (0, 0) (what's the point of defining it in respect to an
> >>>>> area which cannot be read anyway ?)
> >>>>>
> >>>>> Unless TGT_CROP should be defined in respect to the NATIVE_SIZE
> >>>>> rectangle too, but that's not specified anywhere.
> >>>>>
> >>>>> Anyway, those selection targets badly apply to image sensors, are
> >>>>> ill-defined as the definition of active pixels, optical blank (active
> >>>>> and non-active) pixels is not provided anywhere, and it's not specified
> >>>>> anywhere what is the reference area for each of those rectangles, so I
> >>>>> might very well got them wrongly.
> >>>>
> >>>> My understanding is that both TGT_CROP_DEFAULT and TGT_CROP_BOUNDS are
> >>>> relative to TGT_NATIVE_SIZE. BOUNDS defines all the pixels that can be
> >>>
> >>> And what is TGT_CROP reference in your understanding ?
> >>
> >> That's the rectangle you are actually cropping. Initially CROP == CROP_DEFAULT
> >> and CROP shall always be inside CROP_BOUNDS. And CROP_BOUNDS shall be equal
> >> or larger than CROP_DEFAULT.
> > 
> > I think you've missed the point of Jacopo's question. He wasn't asking
> > if CROP needed to be inside CROP_BOUNDS, but what the reference was for
> > the left and top coordinates. That is, for all the crop rectangles, what
> > is the location of the (0,0) point ? Do they all refer to the same
> > location, or are they relative to each other ? This is not defined.
> 
> Ah, I misunderstood.
> 
> For analog video it was actually undefined. It could be anything, although typically
> the initial crop rectangle was at (0, 0). That meant that the larger BOUNDS area
> could be at (-8, -8).
> 
> For sensors nothing is defined at the moment, but IMHO the largest rectangle
> (i.e. TGT_NATIVE_SIZE) should be at (0, 0). I think negative top-left coordinates
> are just weird and can potentially cause signedness issues.
> 
> In any case, all target rectangles are relative to the same point since you need
> to know where the BOUNDS rectangle is within the larger NATIVE_SIZE rectangle
> (ugly name BTW), and ditto for CROP/CROP_DEFAULT within the larger CROP_BOUNDS.

That makes sense to me, having the same reference for all targets should
make it simpler. Jacopo, do you think that's good ?

> >>>> captured, including optical black and invalid pixels, while DEFAULT
> >>>> defines the active area, excluding optical black and invalida pixels. To
> >>>> put it another way, DEFAULT is what the kernel recommends applications
> >>>> to use if they have no specific requirement and/or no specific knowledge
> >>>> about the sensor.
> >>>>
> >>>> I fully agree this is very under-documented, which also means that my
> >>>> understanding may be wrong :-)
> >>>
> >>> With some consensus on this interpretation I would be happy to update
> >>> the documentation. I already considered that, but the selection API
> >>> does not apply to image sensors only, and giving a description which
> >>> is about the pixel array properties might be not totally opportune as
> >>> it would rule out other devices like bridges or muxers.
> >>
> >> And m2m devices like codecs.
> >>
> >>>>>>  			.width = 3280,
> >>>>>>  			.height = 2464
> >>>>>>  		},
> >>>>>> @@ -489,8 +489,8 @@ static const struct imx219_mode supported_modes[] = {
> >>>>>>  		.width = 1920,
> >>>>>>  		.height = 1080,
> >>>>>>  		.crop = {
> >>>>>> -			.left = 680,
> >>>>>> -			.top = 692,
> >>>>>> +			.left = 8 + 680,
> >>>>>> +			.top = 8 + 692,
> >>>>>>  			.width = 1920,
> >>>>>>  			.height = 1080
> >>>>>>  		},
> >>>>>> @@ -505,8 +505,8 @@ static const struct imx219_mode supported_modes[] = {
> >>>>>>  		.width = 1640,
> >>>>>>  		.height = 1232,
> >>>>>>  		.crop = {
> >>>>>> -			.left = 0,
> >>>>>> -			.top = 0,
> >>>>>> +			.left = 8,
> >>>>>> +			.top = 8,
> >>>>>>  			.width = 3280,
> >>>>>>  			.height = 2464
> >>>>>>  		},
> >>>>>> @@ -521,8 +521,8 @@ static const struct imx219_mode supported_modes[] = {
> >>>>>>  		.width = 640,
> >>>>>>  		.height = 480,
> >>>>>>  		.crop = {
> >>>>>> -			.left = 1000,
> >>>>>> -			.top = 752,
> >>>>>> +			.left = 8 + 1000,
> >>>>>> +			.top = 8 + 752,
> >>>>>>  			.width = 1280,
> >>>>>>  			.height = 960
> >>>>>>  		},
> >>>>>> @@ -1014,6 +1014,7 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
> >>>>>>  		return 0;
> >>>>>>
> >>>>>>  	case V4L2_SEL_TGT_CROP_DEFAULT:
> >>>>>> +	case V4L2_SEL_TGT_CROP_BOUNDS:
> >>>>>
> >>>>> Still not getting what is the purpose of two targets if the "always
> >>>>> have to go together" :)
> >>>>>
> >>>>>>  		sel->r.top = IMX219_PIXEL_ARRAY_TOP;
> >>>>>>  		sel->r.left = IMX219_PIXEL_ARRAY_LEFT;
> >>>>>>  		sel->r.width = IMX219_PIXEL_ARRAY_WIDTH;

-- 
Regards,

Laurent Pinchart

  reply	other threads:[~2020-07-16 23:20 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-02 13:50 [PATCH] imx219: selection compliance fixes Hans Verkuil
2020-07-14 12:31 ` Jacopo Mondi
2020-07-14 23:49   ` Laurent Pinchart
2020-07-15  7:19     ` Jacopo Mondi
2020-07-16  9:48       ` Hans Verkuil
2020-07-16 12:59         ` Laurent Pinchart
2020-07-16 13:53           ` Hans Verkuil
2020-07-16 23:20             ` Laurent Pinchart [this message]
2020-07-17  6:34               ` Jacopo Mondi
2020-08-01 11:19 ` Jacopo Mondi
2020-08-01 15:13   ` Laurent Pinchart
2020-08-03  8:33     ` Jacopo Mondi
2020-08-03  9:07     ` Hans Verkuil
2020-08-03  8:37   ` Hans Verkuil
2020-08-03  9:58   ` [libcamera-devel] " Dave Stevenson

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=20200716232031.GI5960@pendragon.ideasonboard.com \
    --to=laurent.pinchart@ideasonboard.com \
    --cc=hverkuil@xs4all.nl \
    --cc=jacopo@jmondi.org \
    --cc=libcamera-devel@lists.libcamera.org \
    --cc=linux-media@vger.kernel.org \
    --cc=ricardo.ribalda@gmail.com \
    --cc=sakari.ailus@linux.intel.com \
    --cc=skomatineni@nvidia.com \
    /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).