<div dir="ltr"><div dir="ltr">Hi Laurent,<div><br></div><div>Thank you for your feedback.</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 9 Jun 2022 at 17:08, Laurent Pinchart <<a href="mailto:laurent.pinchart@ideasonboard.com" target="_blank">laurent.pinchart@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Naush,<br>
<br>
Thank you for the patch.<br>
<br>
On Thu, Jun 09, 2022 at 01:58:30PM +0100, Naushir Patuck via libcamera-devel wrote:<br>
> The pipeline handler currently advertises a static ControlInfoMap to specify the<br>
> available controls and their limits. Fix this limitation by having the IPA<br>
> populate a ControlInfoMap during Camera::Configure() that is then returned from<br>
> the pipeline handle. This will allow the ExposureTime, AnalogueGain, and<br>
> FrameDurationLimits controls to advertise the correct limits for the programmed<br>
> mode.<br>
> <br>
> Note that with this change, the ControlInfoMap provided by Camera::Controls()<br>
> is only valid after a successful Camera::Configure() call.<br>
<br>
That's an issue, we need to initialize it earlier. You can update it at<br>
configure() time, but it has to bet set at init() time.<br></blockquote><div><br></div><div>Sure I can do that. What do you suggest we do about the AnalogueGain, ExposureTime</div><div>and FrameDurationLimits controls during the init() phase? Should I exclude them from</div><div>the list, or include time, with min/max values set to 0 or something else? I'm leaning towards</div><div>simply excluding them from the list until the limits are actually known.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> Signed-off-by: Naushir Patuck <<a href="mailto:naush@raspberrypi.com" target="_blank">naush@raspberrypi.com</a>><br>
> ---<br>
> include/libcamera/ipa/raspberrypi.h | 55 -------------------<br>
> include/libcamera/ipa/raspberrypi.mojom | 1 +<br>
> src/ipa/raspberrypi/raspberrypi.cpp | 42 +++++++++++++-<br>
> .../pipeline/raspberrypi/raspberrypi.cpp | 6 +-<br>
> .../pipeline/raspberrypi/rpi_stream.h | 1 -<br>
> 5 files changed, 45 insertions(+), 60 deletions(-)<br>
> delete mode 100644 include/libcamera/ipa/raspberrypi.h<br>
> <br>
> diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h<br>
> deleted file mode 100644<br>
> index 6a56b0083b85..000000000000<br>
> --- a/include/libcamera/ipa/raspberrypi.h<br>
> +++ /dev/null<br>
> @@ -1,55 +0,0 @@<br>
> -/* SPDX-License-Identifier: LGPL-2.1-or-later */<br>
> -/*<br>
> - * Copyright (C) 2019-2020, Raspberry Pi Ltd.<br>
> - *<br>
> - * raspberrypi.h - Image Processing Algorithm interface for Raspberry Pi<br>
> - */<br>
> -<br>
> -#pragma once<br>
> -<br>
> -#include <stdint.h><br>
> -<br>
> -#include <libcamera/control_ids.h><br>
> -#include <libcamera/controls.h><br>
> -<br>
> -#ifndef __DOXYGEN__<br>
> -<br>
> -namespace libcamera {<br>
> -<br>
> -namespace RPi {<br>
> -<br>
> -/*<br>
> - * List of controls handled by the Raspberry Pi IPA<br>
> - *<br>
> - * \todo This list will need to be built dynamically from the control<br>
> - * algorithms loaded by the json file, once this is supported. At that<br>
> - * point applications should check first whether a control is supported,<br>
> - * and the pipeline handler may be reverted so that it aborts when an<br>
> - * unsupported control is encountered.<br>
> - */<br>
> -static const ControlInfoMap Controls({<br>
> - { &controls::AeEnable, ControlInfo(false, true) },<br>
> - { &controls::ExposureTime, ControlInfo(0, 999999) },<br>
> - { &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },<br>
> - { &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },<br>
> - { &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },<br>
> - { &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) },<br>
> - { &controls::ExposureValue, ControlInfo(-8.0f, 8.0f, 0.0f) },<br>
> - { &controls::AwbEnable, ControlInfo(false, true) },<br>
> - { &controls::ColourGains, ControlInfo(0.0f, 32.0f) },<br>
> - { &controls::AwbMode, ControlInfo(controls::AwbModeValues) },<br>
> - { &controls::Brightness, ControlInfo(-1.0f, 1.0f, 0.0f) },<br>
> - { &controls::Contrast, ControlInfo(0.0f, 32.0f, 1.0f) },<br>
> - { &controls::Saturation, ControlInfo(0.0f, 32.0f, 1.0f) },<br>
> - { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },<br>
> - { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },<br>
> - { &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },<br>
> - { &controls::FrameDurationLimits, ControlInfo(INT64_C(1000), INT64_C(1000000000)) },<br>
> - { &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) }<br>
> - }, controls::controls);<br>
> -<br>
> -} /* namespace RPi */<br>
> -<br>
> -} /* namespace libcamera */<br>
> -<br>
> -#endif /* __DOXYGEN__ */<br>
> diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom<br>
> index a60c3bb43d3c..ed7adebce1b8 100644<br>
> --- a/include/libcamera/ipa/raspberrypi.mojom<br>
> +++ b/include/libcamera/ipa/raspberrypi.mojom<br>
> @@ -40,6 +40,7 @@ struct IPAConfig {<br>
> <br>
> struct IPAConfigResult {<br>
> float modeSensitivity;<br>
> + libcamera.ControlInfoMap controlInfo;<br>
> };<br>
> <br>
> struct StartConfig {<br>
> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp<br>
> index 3b126bb5175e..7eb04a24c41e 100644<br>
> --- a/src/ipa/raspberrypi/raspberrypi.cpp<br>
> +++ b/src/ipa/raspberrypi/raspberrypi.cpp<br>
> @@ -24,7 +24,6 @@<br>
> #include <libcamera/framebuffer.h><br>
> #include <libcamera/ipa/ipa_interface.h><br>
> #include <libcamera/ipa/ipa_module_info.h><br>
> -#include <libcamera/ipa/raspberrypi.h><br>
> #include <libcamera/ipa/raspberrypi_ipa_interface.h><br>
> #include <libcamera/request.h><br>
> <br>
> @@ -72,6 +71,28 @@ constexpr Duration defaultMaxFrameDuration = 250.0s;<br>
> */<br>
> constexpr Duration controllerMinFrameDuration = 1.0s / 30.0;<br>
> <br>
> +/* List of controls handled by the Raspberry Pi IPA */<br>
> +static const ControlInfoMap Controls({<br>
<br>
While at it, could you rename the variable to start with a lowercase<br>
letter ? "controls" is a bit too generic, so you could call it<br>
"rpiControls" or anything similar.<br></blockquote><div><br></div><div>Ack.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
> + { &controls::AeEnable, ControlInfo(false, true) },<br>
> + { &controls::ExposureTime, ControlInfo(0, 999999) },<br>
> + { &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },<br>
> + { &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },<br>
> + { &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },<br>
> + { &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) },<br>
> + { &controls::ExposureValue, ControlInfo(-8.0f, 8.0f, 0.0f) },<br>
> + { &controls::AwbEnable, ControlInfo(false, true) },<br>
> + { &controls::ColourGains, ControlInfo(0.0f, 32.0f) },<br>
> + { &controls::AwbMode, ControlInfo(controls::AwbModeValues) },<br>
> + { &controls::Brightness, ControlInfo(-1.0f, 1.0f, 0.0f) },<br>
> + { &controls::Contrast, ControlInfo(0.0f, 32.0f, 1.0f) },<br>
> + { &controls::Saturation, ControlInfo(0.0f, 32.0f, 1.0f) },<br>
> + { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },<br>
> + { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },<br>
> + { &controls::ScalerCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },<br>
<br>
As you've said yourself in<br>
<a href="https://lists.libcamera.org/pipermail/libcamera-devel/2022-January/028735.html" rel="noreferrer" target="_blank">https://lists.libcamera.org/pipermail/libcamera-devel/2022-January/028735.html</a>,<br>
this one doesn't belong to the IPA side :-) It can be fixed on top<br>
though.<br></blockquote><div><br></div><div>I can add a patch on top to move ScalerCrop to the pipeline handler. It's a bit awkward to code because<br></div><div>I cannot add elements to a ControlInfoMap after initialisation since it derives from a private unordered_map.</div><div>Instead, I will have to construct a new ControlInfoMap::Map with the contents of the ControlInfoMap provided</div><div>by the IPA, add ScalerCrop to the ControlInfoMap::Map, and then convert back to a ControlInfoMap.</div><div>Can you suggest a more elegant way to do this?</div><div><br></div><div>Regards,</div><div>Naush</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
If it helps moving forward, I can resubmit the patch from<br>
<a href="https://lists.libcamera.org/pipermail/libcamera-devel/2022-January/028731.html" rel="noreferrer" target="_blank">https://lists.libcamera.org/pipermail/libcamera-devel/2022-January/028731.html</a><br>
as a proper patch, and then you can update the frame duration limits and<br>
exposure time controls at configure time on top ?<br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
> + { &controls::FrameDurationLimits, ControlInfo(INT64_C(1000), INT64_C(1000000000)) },<br>
> + { &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) }<br>
> +}, controls::controls);<br>
> +<br>
> LOG_DEFINE_CATEGORY(IPARPI)<br>
> <br>
> namespace ipa::RPi {<br>
> @@ -421,6 +442,25 @@ int IPARPi::configure(const IPACameraSensorInfo &sensorInfo,<br>
> ASSERT(controls);<br>
> *controls = std::move(ctrls);<br>
> <br>
> + /*<br>
> + * Apply the correct limits to the exposure, gain and frame duration controls<br>
> + * based on the current sensor mode.<br>
> + */<br>
> + result->controlInfo = Controls;<br>
> + const Duration minSensorFrameDuration = mode_.min_frame_length * mode_.line_length;<br>
> + const Duration maxSensorFrameDuration = mode_.max_frame_length * mode_.line_length;<br>
> + result->controlInfo.at(controls::FrameDurationLimits.id()) =<br>
> + ControlInfo(static_cast<int64_t>(minSensorFrameDuration.get<std::micro>()),<br>
> + static_cast<int64_t>(maxSensorFrameDuration.get<std::micro>()));<br>
> +<br>
> + result->controlInfo.at(controls::AnalogueGain.id()) =<br>
> + ControlInfo(1.0f, static_cast<float>(helper_->Gain(maxSensorGainCode_)));<br>
> +<br>
> + const uint32_t exposureMin = sensorCtrls_.at(V4L2_CID_EXPOSURE).min().get<int32_t>();<br>
> + const uint32_t exposureMax = sensorCtrls_.at(V4L2_CID_EXPOSURE).max().get<int32_t>();<br>
> + result->controlInfo.at(controls::ExposureTime.id()) =<br>
> + ControlInfo(static_cast<int32_t>(helper_->Exposure(exposureMin).get<std::micro>()),<br>
> + static_cast<int32_t>(helper_->Exposure(exposureMax).get<std::micro>()));<br>
> return 0;<br>
> }<br>
> <br>
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> index adc397e8aabd..abb29a8d24b9 100644<br>
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
> @@ -20,7 +20,6 @@<br>
> #include <libcamera/camera.h><br>
> #include <libcamera/control_ids.h><br>
> #include <libcamera/formats.h><br>
> -#include <libcamera/ipa/raspberrypi.h><br>
> #include <libcamera/ipa/raspberrypi_ipa_interface.h><br>
> #include <libcamera/ipa/raspberrypi_ipa_proxy.h><br>
> #include <libcamera/logging.h><br>
> @@ -941,6 +940,9 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)<br>
> /* Store the mode sensitivity for the application. */<br>
> data->properties_.set(properties::SensorSensitivity, result.modeSensitivity);<br>
> <br>
> + /* Register the controls that the Raspberry Pi IPA can handle. */<br>
> + data->controlInfo_ = result.controlInfo;<br>
> +<br>
> /* Setup the Video Mux/Bridge entities. */<br>
> for (auto &[device, link] : data->bridgeDevices_) {<br>
> /*<br>
> @@ -1282,8 +1284,6 @@ int PipelineHandlerRPi::registerCamera(MediaDevice *unicam, MediaDevice *isp, Me<br>
> data->delayedCtrls_ = std::make_unique<DelayedControls>(data->sensor_->device(), params);<br>
> data->sensorMetadata_ = sensorConfig.sensorMetadata;<br>
> <br>
> - /* Register the controls that the Raspberry Pi IPA can handle. */<br>
> - data->controlInfo_ = RPi::Controls;<br>
> /* Initialize the camera properties. */<br>
> data->properties_ = data->sensor_->properties();<br>
> <br>
> diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h<br>
> index c37f7e82eef6..fe01110019b7 100644<br>
> --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h<br>
> +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h<br>
> @@ -12,7 +12,6 @@<br>
> #include <unordered_map><br>
> #include <vector><br>
> <br>
> -#include <libcamera/ipa/raspberrypi.h><br>
> #include <libcamera/ipa/raspberrypi_ipa_interface.h><br>
> #include <libcamera/stream.h><br>
> <br>
<br>
-- <br>
Regards,<br>
<br>
Laurent Pinchart<br>
</blockquote></div></div>