| Message ID | 20260827104108.1432632-7-barnabas.pocze@ideasonboard.com |
|---|---|
| State | New |
| Headers | show |
| Series |
|
| Related | show |
Hi Jacopo, hi Barnabás, Quoting Barnabás Pőcze (2026-08-27 12:41:06) > From: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > > There is a margin between the maximum achievable shutter time and the frame > length. The value is sensor-dependent and should be used to adjust the > maximum achievable exposure time whenever the frame length changes. > > Introduce in the CameraSensorHelper the notion of exposureMargin_ as the > minimum difference in number of lines between the current frame length and > the maximum exposure time. > > This feature is already implemented in the RPi CamHelper class hierarchy > with the name of frameIntegrationDiff. > > Populate the CameraSensorHelper instances with an exposureMargin_. The > value of the exposure margin comes from the mainline driver version of each > sensor, and it has been compared with the frameIntegrationDiff_ value in > the rpi camera helpers. > > Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> > Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> > --- > src/ipa/libipa/camera_sensor_helper.cpp | 59 +++++++++++++++++++++++++ > src/ipa/libipa/camera_sensor_helper.h | 2 + > 2 files changed, 61 insertions(+) > > diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp > index 1a90343c00..3da69bf17b 100644 > --- a/src/ipa/libipa/camera_sensor_helper.cpp > +++ b/src/ipa/libipa/camera_sensor_helper.cpp > @@ -76,6 +76,16 @@ namespace ipa { > * \return The black level of the sensor, or std::nullopt if not known > */ > > +/** > + * \fn CameraSensorHelper::exposureMargin() > + * \brief Fetch the exposure margin of the sensor > + * > + * This function returns the exposure margin of the sensor, in lines, which > + * is the minimum difference between the integration time and frame length. > + * > + * \return The exposure margin of the sensor, or std::nullopt if not know s/know/known/ I'm not a big fan of hardcoding these inside libcamera. But I guess querying the sensor for that is difficult/impossible? If the answer is "Yes, difficult/impossible": Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com> Best regards, Stefan > + */ > + > /** > * \brief Compute gain code from the analogue gain absolute value > * \param[in] gain The real gain to pass > @@ -229,6 +239,12 @@ double CameraSensorHelper::quantizeGain(double _gain, double *quantizationGain) > * sensor specific. Use this variable to store the values at init time. > */ > > +/** > + * \var CameraSensorHelper::exposureMargin_ > + * \brief The smallest margin between the integration time and the frame length > + * in lines > + */ > + > /** > * \class CameraSensorHelperFactoryBase > * \brief Base class for camera sensor helper factories > @@ -385,6 +401,7 @@ public: > { > /* Power-on default value: 168 at 12bits. */ > blackLevel_ = 2688; > + exposureMargin_ = 4; > } > > uint32_t gainCode(double gain) const override > @@ -474,6 +491,11 @@ REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) > class CameraSensorHelperAr0521 : public CameraSensorHelper > { > public: > + CameraSensorHelperAr0521() > + { > + exposureMargin_ = 4; > + } > + > uint32_t gainCode(double gain) const override > { > gain = std::clamp(gain, 1.0, 15.5); > @@ -504,6 +526,7 @@ public: > /* From datasheet: 64 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("gc05a2", CameraSensorHelperGc05a2) > @@ -516,6 +539,7 @@ public: > /* From datasheet: 64 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 }; > + exposureMargin_ = 16; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("gc08a3", CameraSensorHelperGc08a3) > @@ -526,6 +550,7 @@ public: > CameraSensorHelperHm1246() > { > gain_ = AnalogueGainLinear{ 1, 16, 0, 16 }; > + exposureMargin_ = 2; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("hm1246", CameraSensorHelperHm1246) > @@ -538,6 +563,7 @@ public: > /* From datasheet: 64 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 0, 512, -1, 512 }; > + exposureMargin_ = 10; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx214", CameraSensorHelperImx214) > @@ -550,6 +576,7 @@ public: > /* From datasheet: 64 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 0, 256, -1, 256 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219) > @@ -562,6 +589,7 @@ public: > /* From datasheet: 0x40 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 0, 512, -1, 512 }; > + exposureMargin_ = 10; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258) > @@ -574,6 +602,7 @@ public: > /* From datasheet: 0x32 at 10bits. */ > blackLevel_ = 3200; > gain_ = AnalogueGainLinear{ 0, 2048, -1, 2048 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx283", CameraSensorHelperImx283) > @@ -586,6 +615,7 @@ public: > /* From datasheet: 0xf0 at 12bits. */ > blackLevel_ = 3840; > gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; > + exposureMargin_ = 2; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx290", CameraSensorHelperImx290) > @@ -596,6 +626,11 @@ public: > CameraSensorHelperImx296() > { > gain_ = AnalogueGainExp{ 1.0, expGainDb(0.1) }; > + /* > + * The driver doesn't apply any margin. Use the value > + * in RPi's CamHelper. > + */ > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx296", CameraSensorHelperImx296) > @@ -613,6 +648,7 @@ public: > /* From datasheet: 0x32 at 10bits. */ > blackLevel_ = 3200; > gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; > + exposureMargin_ = 9; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx335", CameraSensorHelperImx335) > @@ -635,6 +671,7 @@ public: > CameraSensorHelperImx415() > { > gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; > + exposureMargin_ = 8; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx415", CameraSensorHelperImx415) > @@ -663,6 +700,7 @@ public: > CameraSensorHelperImx477() > { > gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 }; > + exposureMargin_ = 22; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477) > @@ -762,6 +800,7 @@ public: > * This has been validated with some empirical testing only. > */ > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov2685", CameraSensorHelperOv2685) > @@ -774,6 +813,7 @@ public: > /* From Linux kernel driver: 0x40 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 8; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740) > @@ -786,6 +826,7 @@ public: > /* From datasheet: 0x40 at 12bits. */ > blackLevel_ = 1024; > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov4689", CameraSensorHelperOv4689) > @@ -798,6 +839,14 @@ public: > /* From datasheet: 0x10 at 10bits. */ > blackLevel_ = 1024; > gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; > + /* > + * Very convoluted in the driver that however applies a margin > + * of 4 lines when setting vts. > + * > + * cap_vts = cap_shutter + 4; > + * ret = ov5640_set_vts(sensor, cap_vts); > + */ > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov5640", CameraSensorHelperOv5640) > @@ -808,6 +857,7 @@ public: > CameraSensorHelperOv5647() > { > gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov5647", CameraSensorHelperOv5647) > @@ -818,6 +868,7 @@ public: > CameraSensorHelperOv5670() > { > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 8; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670) > @@ -830,6 +881,7 @@ public: > /* From Linux kernel driver: 0x40 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov5675", CameraSensorHelperOv5675) > @@ -841,6 +893,7 @@ public: > { > blackLevel_ = 1024; > gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; > + exposureMargin_ = 8; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693) > @@ -851,6 +904,7 @@ public: > CameraSensorHelperOv64a40() > { > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 32; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov64a40", CameraSensorHelperOv64a40) > @@ -867,6 +921,7 @@ public: > * See: https://patchwork.linuxtv.org/project/linux-media/patch/20221106171129.166892-2-nicholas@rothemail.net/#142267 > */ > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 4; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov8858", CameraSensorHelperOv8858) > @@ -877,6 +932,7 @@ public: > CameraSensorHelperOv8865() > { > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 8; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865) > @@ -887,6 +943,7 @@ public: > CameraSensorHelperOv13858() > { > gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; > + exposureMargin_ = 8; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858) > @@ -899,6 +956,7 @@ public: > /* From datasheet: 0x40 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 0, 32, -1, 32 }; > + exposureMargin_ = 64; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("vd55g1", CameraSensorHelperVd55g1) > @@ -911,6 +969,7 @@ public: > /* From datasheet: 0x40 at 10bits. */ > blackLevel_ = 4096; > gain_ = AnalogueGainLinear{ 0, 32, -1, 32 }; > + exposureMargin_ = 75; > } > }; > REGISTER_CAMERA_SENSOR_HELPER("vd56g3", CameraSensorHelperVd56g3) > diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h > index bd3d0beec7..a9e55c832d 100644 > --- a/src/ipa/libipa/camera_sensor_helper.h > +++ b/src/ipa/libipa/camera_sensor_helper.h > @@ -27,6 +27,7 @@ public: > virtual ~CameraSensorHelper() = default; > > std::optional<int16_t> blackLevel() const { return blackLevel_; } > + std::optional<uint32_t> exposureMargin() const { return exposureMargin_; } > virtual uint32_t gainCode(double gain) const; > virtual double gain(uint32_t gainCode) const; > double quantizeGain(double gain, double *quantizationGain) const; > @@ -46,6 +47,7 @@ protected: > > std::optional<int16_t> blackLevel_; > std::variant<std::monostate, AnalogueGainLinear, AnalogueGainExp> gain_; > + std::optional<uint32_t> exposureMargin_; > > private: > LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelper) > -- > 2.55.0 >
2026. 08. 27. 15:52 keltezéssel, Stefan Klug írta: > Hi Jacopo, hi Barnabás, > > Quoting Barnabás Pőcze (2026-08-27 12:41:06) >> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com> >> >> There is a margin between the maximum achievable shutter time and the frame >> length. The value is sensor-dependent and should be used to adjust the >> maximum achievable exposure time whenever the frame length changes. >> >> Introduce in the CameraSensorHelper the notion of exposureMargin_ as the >> minimum difference in number of lines between the current frame length and >> the maximum exposure time. >> >> This feature is already implemented in the RPi CamHelper class hierarchy >> with the name of frameIntegrationDiff. >> >> Populate the CameraSensorHelper instances with an exposureMargin_. The >> value of the exposure margin comes from the mainline driver version of each >> sensor, and it has been compared with the frameIntegrationDiff_ value in >> the rpi camera helpers. >> >> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> >> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com> >> --- >> src/ipa/libipa/camera_sensor_helper.cpp | 59 +++++++++++++++++++++++++ >> src/ipa/libipa/camera_sensor_helper.h | 2 + >> 2 files changed, 61 insertions(+) >> >> diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp >> index 1a90343c00..3da69bf17b 100644 >> --- a/src/ipa/libipa/camera_sensor_helper.cpp >> +++ b/src/ipa/libipa/camera_sensor_helper.cpp >> @@ -76,6 +76,16 @@ namespace ipa { >> * \return The black level of the sensor, or std::nullopt if not known >> */ >> >> +/** >> + * \fn CameraSensorHelper::exposureMargin() >> + * \brief Fetch the exposure margin of the sensor >> + * >> + * This function returns the exposure margin of the sensor, in lines, which >> + * is the minimum difference between the integration time and frame length. >> + * >> + * \return The exposure margin of the sensor, or std::nullopt if not know > > s/know/known/ > > I'm not a big fan of hardcoding these inside libcamera. But I guess > querying the sensor for that is difficult/impossible? Well, a new v4l2 control is possible, I think. Other than that, maybe libcamera could check the max exposure for the min and max vblank values. I think that should be enough to derive a safe margin for any sensor where it is a monotonic function of the vblank. Then that could maybe be provided in `IPACameraSensorInfo`. Thoughts? > > If the answer is "Yes, difficult/impossible": > > Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com> > > Best regards, > Stefan > >> + */ >> + >> /** >> * \brief Compute gain code from the analogue gain absolute value >> * \param[in] gain The real gain to pass >> @@ -229,6 +239,12 @@ double CameraSensorHelper::quantizeGain(double _gain, double *quantizationGain) >> * sensor specific. Use this variable to store the values at init time. >> */ >> >> +/** >> + * \var CameraSensorHelper::exposureMargin_ >> + * \brief The smallest margin between the integration time and the frame length >> + * in lines >> + */ >> + >> /** >> * \class CameraSensorHelperFactoryBase >> * \brief Base class for camera sensor helper factories >> @@ -385,6 +401,7 @@ public: >> { >> /* Power-on default value: 168 at 12bits. */ >> blackLevel_ = 2688; >> + exposureMargin_ = 4; >> } >> >> uint32_t gainCode(double gain) const override >> @@ -474,6 +491,11 @@ REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) >> class CameraSensorHelperAr0521 : public CameraSensorHelper >> { >> public: >> + CameraSensorHelperAr0521() >> + { >> + exposureMargin_ = 4; >> + } >> + >> uint32_t gainCode(double gain) const override >> { >> gain = std::clamp(gain, 1.0, 15.5); >> @@ -504,6 +526,7 @@ public: >> /* From datasheet: 64 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("gc05a2", CameraSensorHelperGc05a2) >> @@ -516,6 +539,7 @@ public: >> /* From datasheet: 64 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 }; >> + exposureMargin_ = 16; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("gc08a3", CameraSensorHelperGc08a3) >> @@ -526,6 +550,7 @@ public: >> CameraSensorHelperHm1246() >> { >> gain_ = AnalogueGainLinear{ 1, 16, 0, 16 }; >> + exposureMargin_ = 2; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("hm1246", CameraSensorHelperHm1246) >> @@ -538,6 +563,7 @@ public: >> /* From datasheet: 64 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 0, 512, -1, 512 }; >> + exposureMargin_ = 10; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx214", CameraSensorHelperImx214) >> @@ -550,6 +576,7 @@ public: >> /* From datasheet: 64 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 0, 256, -1, 256 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219) >> @@ -562,6 +589,7 @@ public: >> /* From datasheet: 0x40 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 0, 512, -1, 512 }; >> + exposureMargin_ = 10; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258) >> @@ -574,6 +602,7 @@ public: >> /* From datasheet: 0x32 at 10bits. */ >> blackLevel_ = 3200; >> gain_ = AnalogueGainLinear{ 0, 2048, -1, 2048 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx283", CameraSensorHelperImx283) >> @@ -586,6 +615,7 @@ public: >> /* From datasheet: 0xf0 at 12bits. */ >> blackLevel_ = 3840; >> gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; >> + exposureMargin_ = 2; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx290", CameraSensorHelperImx290) >> @@ -596,6 +626,11 @@ public: >> CameraSensorHelperImx296() >> { >> gain_ = AnalogueGainExp{ 1.0, expGainDb(0.1) }; >> + /* >> + * The driver doesn't apply any margin. Use the value >> + * in RPi's CamHelper. >> + */ >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx296", CameraSensorHelperImx296) >> @@ -613,6 +648,7 @@ public: >> /* From datasheet: 0x32 at 10bits. */ >> blackLevel_ = 3200; >> gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; >> + exposureMargin_ = 9; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx335", CameraSensorHelperImx335) >> @@ -635,6 +671,7 @@ public: >> CameraSensorHelperImx415() >> { >> gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; >> + exposureMargin_ = 8; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx415", CameraSensorHelperImx415) >> @@ -663,6 +700,7 @@ public: >> CameraSensorHelperImx477() >> { >> gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 }; >> + exposureMargin_ = 22; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477) >> @@ -762,6 +800,7 @@ public: >> * This has been validated with some empirical testing only. >> */ >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov2685", CameraSensorHelperOv2685) >> @@ -774,6 +813,7 @@ public: >> /* From Linux kernel driver: 0x40 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 8; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740) >> @@ -786,6 +826,7 @@ public: >> /* From datasheet: 0x40 at 12bits. */ >> blackLevel_ = 1024; >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov4689", CameraSensorHelperOv4689) >> @@ -798,6 +839,14 @@ public: >> /* From datasheet: 0x10 at 10bits. */ >> blackLevel_ = 1024; >> gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; >> + /* >> + * Very convoluted in the driver that however applies a margin >> + * of 4 lines when setting vts. >> + * >> + * cap_vts = cap_shutter + 4; >> + * ret = ov5640_set_vts(sensor, cap_vts); >> + */ >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov5640", CameraSensorHelperOv5640) >> @@ -808,6 +857,7 @@ public: >> CameraSensorHelperOv5647() >> { >> gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov5647", CameraSensorHelperOv5647) >> @@ -818,6 +868,7 @@ public: >> CameraSensorHelperOv5670() >> { >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 8; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670) >> @@ -830,6 +881,7 @@ public: >> /* From Linux kernel driver: 0x40 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov5675", CameraSensorHelperOv5675) >> @@ -841,6 +893,7 @@ public: >> { >> blackLevel_ = 1024; >> gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; >> + exposureMargin_ = 8; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693) >> @@ -851,6 +904,7 @@ public: >> CameraSensorHelperOv64a40() >> { >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 32; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov64a40", CameraSensorHelperOv64a40) >> @@ -867,6 +921,7 @@ public: >> * See: https://patchwork.linuxtv.org/project/linux-media/patch/20221106171129.166892-2-nicholas@rothemail.net/#142267 >> */ >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 4; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov8858", CameraSensorHelperOv8858) >> @@ -877,6 +932,7 @@ public: >> CameraSensorHelperOv8865() >> { >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 8; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865) >> @@ -887,6 +943,7 @@ public: >> CameraSensorHelperOv13858() >> { >> gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; >> + exposureMargin_ = 8; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858) >> @@ -899,6 +956,7 @@ public: >> /* From datasheet: 0x40 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 0, 32, -1, 32 }; >> + exposureMargin_ = 64; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("vd55g1", CameraSensorHelperVd55g1) >> @@ -911,6 +969,7 @@ public: >> /* From datasheet: 0x40 at 10bits. */ >> blackLevel_ = 4096; >> gain_ = AnalogueGainLinear{ 0, 32, -1, 32 }; >> + exposureMargin_ = 75; >> } >> }; >> REGISTER_CAMERA_SENSOR_HELPER("vd56g3", CameraSensorHelperVd56g3) >> diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h >> index bd3d0beec7..a9e55c832d 100644 >> --- a/src/ipa/libipa/camera_sensor_helper.h >> +++ b/src/ipa/libipa/camera_sensor_helper.h >> @@ -27,6 +27,7 @@ public: >> virtual ~CameraSensorHelper() = default; >> >> std::optional<int16_t> blackLevel() const { return blackLevel_; } >> + std::optional<uint32_t> exposureMargin() const { return exposureMargin_; } >> virtual uint32_t gainCode(double gain) const; >> virtual double gain(uint32_t gainCode) const; >> double quantizeGain(double gain, double *quantizationGain) const; >> @@ -46,6 +47,7 @@ protected: >> >> std::optional<int16_t> blackLevel_; >> std::variant<std::monostate, AnalogueGainLinear, AnalogueGainExp> gain_; >> + std::optional<uint32_t> exposureMargin_; >> >> private: >> LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelper) >> -- >> 2.55.0 >>
diff --git a/src/ipa/libipa/camera_sensor_helper.cpp b/src/ipa/libipa/camera_sensor_helper.cpp index 1a90343c00..3da69bf17b 100644 --- a/src/ipa/libipa/camera_sensor_helper.cpp +++ b/src/ipa/libipa/camera_sensor_helper.cpp @@ -76,6 +76,16 @@ namespace ipa { * \return The black level of the sensor, or std::nullopt if not known */ +/** + * \fn CameraSensorHelper::exposureMargin() + * \brief Fetch the exposure margin of the sensor + * + * This function returns the exposure margin of the sensor, in lines, which + * is the minimum difference between the integration time and frame length. + * + * \return The exposure margin of the sensor, or std::nullopt if not know + */ + /** * \brief Compute gain code from the analogue gain absolute value * \param[in] gain The real gain to pass @@ -229,6 +239,12 @@ double CameraSensorHelper::quantizeGain(double _gain, double *quantizationGain) * sensor specific. Use this variable to store the values at init time. */ +/** + * \var CameraSensorHelper::exposureMargin_ + * \brief The smallest margin between the integration time and the frame length + * in lines + */ + /** * \class CameraSensorHelperFactoryBase * \brief Base class for camera sensor helper factories @@ -385,6 +401,7 @@ public: { /* Power-on default value: 168 at 12bits. */ blackLevel_ = 2688; + exposureMargin_ = 4; } uint32_t gainCode(double gain) const override @@ -474,6 +491,11 @@ REGISTER_CAMERA_SENSOR_HELPER("ar0144", CameraSensorHelperAr0144) class CameraSensorHelperAr0521 : public CameraSensorHelper { public: + CameraSensorHelperAr0521() + { + exposureMargin_ = 4; + } + uint32_t gainCode(double gain) const override { gain = std::clamp(gain, 1.0, 15.5); @@ -504,6 +526,7 @@ public: /* From datasheet: 64 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("gc05a2", CameraSensorHelperGc05a2) @@ -516,6 +539,7 @@ public: /* From datasheet: 64 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 100, 0, 0, 1024 }; + exposureMargin_ = 16; } }; REGISTER_CAMERA_SENSOR_HELPER("gc08a3", CameraSensorHelperGc08a3) @@ -526,6 +550,7 @@ public: CameraSensorHelperHm1246() { gain_ = AnalogueGainLinear{ 1, 16, 0, 16 }; + exposureMargin_ = 2; } }; REGISTER_CAMERA_SENSOR_HELPER("hm1246", CameraSensorHelperHm1246) @@ -538,6 +563,7 @@ public: /* From datasheet: 64 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 0, 512, -1, 512 }; + exposureMargin_ = 10; } }; REGISTER_CAMERA_SENSOR_HELPER("imx214", CameraSensorHelperImx214) @@ -550,6 +576,7 @@ public: /* From datasheet: 64 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 0, 256, -1, 256 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("imx219", CameraSensorHelperImx219) @@ -562,6 +589,7 @@ public: /* From datasheet: 0x40 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 0, 512, -1, 512 }; + exposureMargin_ = 10; } }; REGISTER_CAMERA_SENSOR_HELPER("imx258", CameraSensorHelperImx258) @@ -574,6 +602,7 @@ public: /* From datasheet: 0x32 at 10bits. */ blackLevel_ = 3200; gain_ = AnalogueGainLinear{ 0, 2048, -1, 2048 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("imx283", CameraSensorHelperImx283) @@ -586,6 +615,7 @@ public: /* From datasheet: 0xf0 at 12bits. */ blackLevel_ = 3840; gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; + exposureMargin_ = 2; } }; REGISTER_CAMERA_SENSOR_HELPER("imx290", CameraSensorHelperImx290) @@ -596,6 +626,11 @@ public: CameraSensorHelperImx296() { gain_ = AnalogueGainExp{ 1.0, expGainDb(0.1) }; + /* + * The driver doesn't apply any margin. Use the value + * in RPi's CamHelper. + */ + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("imx296", CameraSensorHelperImx296) @@ -613,6 +648,7 @@ public: /* From datasheet: 0x32 at 10bits. */ blackLevel_ = 3200; gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; + exposureMargin_ = 9; } }; REGISTER_CAMERA_SENSOR_HELPER("imx335", CameraSensorHelperImx335) @@ -635,6 +671,7 @@ public: CameraSensorHelperImx415() { gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) }; + exposureMargin_ = 8; } }; REGISTER_CAMERA_SENSOR_HELPER("imx415", CameraSensorHelperImx415) @@ -663,6 +700,7 @@ public: CameraSensorHelperImx477() { gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 }; + exposureMargin_ = 22; } }; REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477) @@ -762,6 +800,7 @@ public: * This has been validated with some empirical testing only. */ gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("ov2685", CameraSensorHelperOv2685) @@ -774,6 +813,7 @@ public: /* From Linux kernel driver: 0x40 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 8; } }; REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740) @@ -786,6 +826,7 @@ public: /* From datasheet: 0x40 at 12bits. */ blackLevel_ = 1024; gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("ov4689", CameraSensorHelperOv4689) @@ -798,6 +839,14 @@ public: /* From datasheet: 0x10 at 10bits. */ blackLevel_ = 1024; gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; + /* + * Very convoluted in the driver that however applies a margin + * of 4 lines when setting vts. + * + * cap_vts = cap_shutter + 4; + * ret = ov5640_set_vts(sensor, cap_vts); + */ + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("ov5640", CameraSensorHelperOv5640) @@ -808,6 +857,7 @@ public: CameraSensorHelperOv5647() { gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("ov5647", CameraSensorHelperOv5647) @@ -818,6 +868,7 @@ public: CameraSensorHelperOv5670() { gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 8; } }; REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670) @@ -830,6 +881,7 @@ public: /* From Linux kernel driver: 0x40 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("ov5675", CameraSensorHelperOv5675) @@ -841,6 +893,7 @@ public: { blackLevel_ = 1024; gain_ = AnalogueGainLinear{ 1, 0, 0, 16 }; + exposureMargin_ = 8; } }; REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693) @@ -851,6 +904,7 @@ public: CameraSensorHelperOv64a40() { gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 32; } }; REGISTER_CAMERA_SENSOR_HELPER("ov64a40", CameraSensorHelperOv64a40) @@ -867,6 +921,7 @@ public: * See: https://patchwork.linuxtv.org/project/linux-media/patch/20221106171129.166892-2-nicholas@rothemail.net/#142267 */ gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 4; } }; REGISTER_CAMERA_SENSOR_HELPER("ov8858", CameraSensorHelperOv8858) @@ -877,6 +932,7 @@ public: CameraSensorHelperOv8865() { gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 8; } }; REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865) @@ -887,6 +943,7 @@ public: CameraSensorHelperOv13858() { gain_ = AnalogueGainLinear{ 1, 0, 0, 128 }; + exposureMargin_ = 8; } }; REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858) @@ -899,6 +956,7 @@ public: /* From datasheet: 0x40 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 0, 32, -1, 32 }; + exposureMargin_ = 64; } }; REGISTER_CAMERA_SENSOR_HELPER("vd55g1", CameraSensorHelperVd55g1) @@ -911,6 +969,7 @@ public: /* From datasheet: 0x40 at 10bits. */ blackLevel_ = 4096; gain_ = AnalogueGainLinear{ 0, 32, -1, 32 }; + exposureMargin_ = 75; } }; REGISTER_CAMERA_SENSOR_HELPER("vd56g3", CameraSensorHelperVd56g3) diff --git a/src/ipa/libipa/camera_sensor_helper.h b/src/ipa/libipa/camera_sensor_helper.h index bd3d0beec7..a9e55c832d 100644 --- a/src/ipa/libipa/camera_sensor_helper.h +++ b/src/ipa/libipa/camera_sensor_helper.h @@ -27,6 +27,7 @@ public: virtual ~CameraSensorHelper() = default; std::optional<int16_t> blackLevel() const { return blackLevel_; } + std::optional<uint32_t> exposureMargin() const { return exposureMargin_; } virtual uint32_t gainCode(double gain) const; virtual double gain(uint32_t gainCode) const; double quantizeGain(double gain, double *quantizationGain) const; @@ -46,6 +47,7 @@ protected: std::optional<int16_t> blackLevel_; std::variant<std::monostate, AnalogueGainLinear, AnalogueGainExp> gain_; + std::optional<uint32_t> exposureMargin_; private: LIBCAMERA_DISABLE_COPY_AND_MOVE(CameraSensorHelper)