[libcamera-devel] [PATCH v2 2/4] ipa: raspberrypi: Limit the calculated vblank based on the sensor mode

Naushir Patuck naush at raspberrypi.com
Tue Jan 26 15:26:59 CET 2021


Hi Jacopo,

On Tue, 26 Jan 2021 at 14:21, Jacopo Mondi <jacopo at jmondi.org> wrote:

> Hi Naush,
>
> On Tue, Jan 26, 2021 at 02:12:50PM +0000, Naushir Patuck wrote:
> > Hi Jacopo,
> >
> > On Tue, 26 Jan 2021 at 13:44, Jacopo Mondi <jacopo at jmondi.org> wrote:
> >
>
> [snip]
>
> > > > > > +      */
> > > > > > +     const auto itVblank = sensorCtrls_.find(V4L2_CID_VBLANK);
> > > > > > +     mode_.vblank_min = itVblank->second.min().get<int32_t>();
> > > > > > +     mode_.vblank_max = itVblank->second.max().get<int32_t>();
> > > > >
> > > > > The trouble here is that sensorCtrls_ will not be updated after the
> > > > > sensor configuration has changed. It comes from the
> > > > > V4L2Device::controls() call in RPiCameraData::configureIPA(), and
> that
> > > > > function returns a cached copy.
> > > > >
> > > >
> > > > I don't exactly know all of this in very much detail, so apologies
> if the
> > > > following statements sound basic, or don't make much sense :-)
> > > >
> > > > In  RPiCameraData::configureIPA(), would it be possible to "update"
> the
> > > > cached values of V4L2Device::controls_ by
> > > > calling V4L2Device::listControls(), or maybe a new method such
> > > > as V4L2Device::updateControls().  This only needs to be called once
> > > > in PipelineHandlerRPi::configure(), after the sensor mode has been
> set.
> > > > This way, the VBLANK control will have up-to-date numbers for the
> IPA to
> > > > use.
> > > >
> > > > Alternatively, CameraSensorInfo gets populated in
> > > > RPiCameraData::configureIPA() with a  call
> > > > to CameraSensor::sensorInfo(). Looks like this directly queries the
> > > device
> > > > for controls via V4L2Device::getControls().  Perhaps we should
> re-visit
> > > > Jacopo's suggestion and add the min/max vblank values to the mode?
> > > >
> > > >
> > > > >
> > > > > I really dislike the fact that V4L2 provides us with a control
> whose
> > > > > limits change when the analog crop rectangle height changes, while
> the
> > > > > sensors usually have a fixed vertical total size limit. Wouldn't
> it be
> > > > > better to base the code on the vertical total size limit in
> libcamera,
> > > > > instead of vertical blanking ?
> > > >
> > > >
> > > > By vertical total size limit, I assume you mean what sensors
> generally
> > > call
> > > > vts or frame length?  If so, then yes, it does make sense.  In fact,
> you
> > > > can see from my patch, the first thing I do is convert from vblank to
> > > frame
> > > > length for all of my calculations.
> > > >
> > > >
> > >
> > > Let me summarize your understandings:
> > > - You need the VBLANK limits to clamp frame durations in the sensor
> > >   limits
> > > - VBLANK min and max are combined with the current mode height and
> > >   line length to get the min and max frame sizes, from where the min
> > >   and max frame duration limits are calculated
> > > - min frame size = (mode_.height + frameIntegrationDiff) *
> > > mode_.line_length
> > > - max frame size = (mode_.height + max vblank) * mode_.line_length
> > >
> > > From the CameraSensorInfo you already know the visibile height and the
> > > line_length. Wouldn't be enough to add to that structure
> > >         - maxFrameHeight = (mode_.height + max vblank)
> > >         - frameIntegrationDiff
> > >           This is sensor property and will be made available in the
> > >           sensor database. You can keep it in the IPA as long as no
> > >           sensor database is available
> > >
> > > To sum it up: is it enough for you to pass to the IPA the maximum
> > > frame length (mode_.height + max vblank) in the CameraSensorClass ?
> > >
> >
> > This is *mostly* correct.  max frame size as calculated above is fine.
> > However, I do also need min frame size.  Your calculation above assumes
> > min_vblank = 0.  This may not be the case always, so min frame size must
> be
> > computed and presented in CameraSensorInfo.
>
> Correct, I had assumed min_vblank = frameIntegrationDiff, which might
> not always be the case.
>
> Considering the requirement for 'updates' and the fact the
> CameraSensorInfo is guaranteed to be fresh at IPA::Configure() time,
> I would be happy to see minFrameSize (or Height) and maxFrameSize (or
> Height) added there an computed once for all IPAs in the CameraSensor
> class.
>

Great, I can put together a change for this and submit for review as part
of this series.  One question, what name would you and Laurent prefer for
this field - maxFrameSize or maxFrameLength (and equivalent for min)?
Generally, I think sensors prefer using frame length in their terminology,
but v4l2 probably prefers frame size.  I am ok with either.

Regards,
Naush



> >
> >
> >
> > >
> > >
> > > > > We would still have the issue of
> > > > > retrieving this value, and I can see multiple options:
> > > > >
> > > > > - Compute it once at initialization from vblank limits + analog
> crop
> > > > >
> > > >
> > > > This is assuming that vblank + crop height is always going to be
> equal to
> > > > frame length?  We need to think if that is strictly true for all
> sensors,
> > > > I'm not sure.
> > > >
> > > >
> > > >
> > > > > - Extend V4L2 with a new vertical total size control and use it
> (that
> > > > >   will be more work as we need to synchronize with the kernel
> changes)
> > > > >
> > > >
> > > > I expect this would have the longest lead time :-)
> > > >
> > > >
> > > > > - Hardcode the value in a sensor database in libcamera, bypassing
> the
> > > > >   kernel completly
> > > > >
> > > >
> > > > This is possible, but...
> > > >
> > > >
> > > > >
> > > > > One question that I'm not sure I can answer by myself is whether
> we can
> > > > > rely on the vertical total size limits being constant.
> > > > >
> > > >
> > > > ... I don't think you can assume total vertical size (frame length)
> is
> > > > going to be the same for all modes a sensor advertises.  In this
> case,
> > > the
> > > > sensor database would have to know about every mode available in the
> > > kernel
> > > > driver.  This is something we moved away from with the Raspberry Pi
> > > > CamHelper, so I doubt you want to re-introduce that link.
> > > >
> > > > My feeling is that we could work something out by forcing a
> "refresh" of
> > > > the cached controls on every configure, and I think that should
> cover our
> > > > (or at least Raspberry Pi's in this particular instance) usage.
> > > >
> > > > Let me know your thoughts.
> > > >
> > > > Regards,
> > > > Naush
> > > >
> > > >
> > > >
> > > > > >  }
> > > > > >
>
> [snip]
>
> > > > > >  void IPARPi::configure(const CameraSensorInfo &sensorInfo,
> > > > > > @@ -384,8 +393,8 @@ void IPARPi::configure(const CameraSensorInfo
> > > > > &sensorInfo,
> > > > > >               controller_.Initialise();
> > > > > >               controllerInit_ = true;
> > > > > >
> > > > > > -             minFrameDuration_ = defaultMinFrameDuration;
> > > > > > -             maxFrameDuration_ = defaultMaxFrameDuration;
> > > > > > +             /* Supply initial values for frame durations. */
> > > > > > +             applyFrameDurations(defaultMinFrameDuration,
> > > > > defaultMaxFrameDuration);
> > > > > >
> > > > > >               /* Supply initial values for gain and exposure. */
> > > > > >               ControlList ctrls(sensorCtrls_);
> > > > > > @@ -819,20 +828,7 @@ void IPARPi::queueRequest(const ControlList
> > > > > &controls)
> > > > > >
> > > > > >               case controls::FRAME_DURATIONS: {
> > > > > >                       auto frameDurations =
> > > ctrl.second.get<Span<const
> > > > > int64_t>>();
> > > > > > -
> > > > > > -                     /* This will be applied once AGC
> recalculations
> > > > > occur. */
> > > > > > -                     minFrameDuration_ = frameDurations[0] ?
> > > > > frameDurations[0] : defaultMinFrameDuration;
> > > > > > -                     maxFrameDuration_ = frameDurations[1] ?
> > > > > frameDurations[1] : defaultMaxFrameDuration;
> > > > > > -                     maxFrameDuration_ =
> std::max(maxFrameDuration_,
> > > > > minFrameDuration_);
> > > > > > -
> > > > > > -                     /*
> > > > > > -                      * \todo The values returned in the
> metadata
> > > below
> > > > > must be
> > > > > > -                      * correctly clipped by what the sensor
> mode
> > > > > supports and
> > > > > > -                      * what the AGC exposure mode or manual
> shutter
> > > > > speed limits
> > > > > > -                      */
> > > > > > -
> > >  libcameraMetadata_.set(controls::FrameDurations,
> > > > > > -                                            {
> > > > > static_cast<int64_t>(minFrameDuration_),
> > > > > > -
> > > > > static_cast<int64_t>(maxFrameDuration_) });
> > > > > > +                     applyFrameDurations(frameDurations[0],
> > > > > frameDurations[1]);
> > > > > >                       break;
> > > > > >               }
> > > > > >
> > > > > > @@ -991,6 +987,29 @@ void IPARPi::applyAWB(const struct AwbStatus
> > > > > *awbStatus, ControlList &ctrls)
> > > > > >                 static_cast<int32_t>(awbStatus->gain_b * 1000));
> > > > > >  }
> > > > > >
> > > > > > +void IPARPi::applyFrameDurations(double minFrameDuration, double
> > > > > maxFrameDuration)
> > > > > > +{
> > > > > > +     const double minSensorFrameDuration = 1e-3 *
> (mode_.vblank_min
> > > +
> > > > > mode_.height) *
> > > > > > +                                           mode_.line_length;
> > > > > > +     const double maxSensorFrameDuration = 1e-3 *
> (mode_.vblank_max
> > > +
> > > > > mode_.height) *
> > > > > > +                                           mode_.line_length;
> > >
> > > To transform the frame size expressed in pixels:
> > >         (mode_.vblank + mode_.height) * mode_.line_length
> > >
> > > in a duration expressed in seconds sub-units, don't you need to use
> > > the pixel clock (which is available in CameraSensorInfo afair)
> > >         frameDuration (usec) = frame size (pixels)
> > >                              / pixel rate (pixels/usec)
> > >
> >
> > Yes we do.  However, mode_.line_length already factors the pixel rate:
> > mode_.line_length = 1e9 * sensorInfo.lineLength / sensorInfo.pixelRate
> >
> > So mode_.line_length is already converted into units of time.
>
> Oh sorry, I assumed CameraMode.line_lenght == CameraSensorInfo.lineLength
>
> I should have checked.
>
> Thanks
>   j
>
> >
> > Regards,
> > Naush
> >
> >
> >
> > >
> > > Thanks
> > >    j
> > >
> > > > > > +     /*
> > > > > > +      * This will only be applied once AGC recalculations occur.
> > > > > > +      * The values may be clamped based on the sensor mode
> > > capabilities
> > > > > as well.
> > > > > > +      */
> > > > > > +     minFrameDuration_ = minFrameDuration ? minFrameDuration :
> > > > > defaultMaxFrameDuration;
> > > > > > +     maxFrameDuration_ = maxFrameDuration ? maxFrameDuration :
> > > > > defaultMinFrameDuration;
> > > > > > +     minFrameDuration_ = std::clamp(minFrameDuration_,
> > > > > > +                                    minSensorFrameDuration,
> > > > > maxSensorFrameDuration);
> > > > > > +     maxFrameDuration_ = std::clamp(maxFrameDuration_,
> > > > > > +                                    minSensorFrameDuration,
> > > > > maxSensorFrameDuration);
> > > > > > +
> > > > > > +     /* Return the validated limits out though metadata. */
> > > > > > +     libcameraMetadata_.set(controls::FrameDurations,
> > > > > > +                            {
> > > static_cast<int64_t>(minFrameDuration_),
> > > > > > +
> > > static_cast<int64_t>(maxFrameDuration_)
> > > > > });
> > > > > > +}
> > > > > > +
> > > > > >  void IPARPi::applyAGC(const struct AgcStatus *agcStatus,
> ControlList
> > > > > &ctrls)
> > > > > >  {
> > > > > --
> > > > > Regards,
> > > > >
> > > > > Laurent Pinchart
> > > > >
> > >
> > >
> > > > _______________________________________________
> > > > libcamera-devel mailing list
> > > > libcamera-devel at lists.libcamera.org
> > > > https://lists.libcamera.org/listinfo/libcamera-devel
> > >
> > >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.libcamera.org/pipermail/libcamera-devel/attachments/20210126/9ad9ef20/attachment-0001.htm>


More information about the libcamera-devel mailing list