@@ -154,6 +154,18 @@ double CameraSensorHelper::quantizeGain(double _gain, double *quantizationGain)
return g;
}
+/**
+ * \fn CameraSensorHelper::exposureMargin()
+ * \brief Fetch the integration time margin
+ *
+ * This function returns the number of lines that represent the minimum
+ * difference between the frame length and the maximum achievable integration
+ * time. If it is unknown an empty optional is returned.
+ *
+ * \return The minimum difference between the exposure time and the frame
+ * length in lines, or an empty optional
+ */
+
/**
* \struct CameraSensorHelper::AnalogueGainLinear
* \brief Analogue gain constants for the linear gain model
@@ -229,6 +241,13 @@ 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 lenght
+ * in lines
+ * \sa CameraSensorHelper::exposureMargin()
+ */
+
/**
* \class CameraSensorHelperFactoryBase
* \brief Base class for camera sensor helper factories
@@ -385,6 +404,7 @@ public:
{
/* Power-on default value: 168 at 12bits. */
blackLevel_ = 2688;
+ exposureMargin_ = 4;
}
uint32_t gainCode(double gain) const override
@@ -474,6 +494,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 +529,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 +542,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 +553,7 @@ public:
CameraSensorHelperHm1246()
{
gain_ = AnalogueGainLinear{ 1, 16, 0, 16 };
+ exposureMargin_ = 2;
}
};
REGISTER_CAMERA_SENSOR_HELPER("hm1246", CameraSensorHelperHm1246)
@@ -538,6 +566,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 +579,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 +592,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 +605,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 +618,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 +629,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 +651,7 @@ public:
/* From datasheet: 0x32 at 10bits. */
blackLevel_ = 3200;
gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+ exposureMargin_ = 9;
}
};
REGISTER_CAMERA_SENSOR_HELPER("imx335", CameraSensorHelperImx335)
@@ -623,6 +662,7 @@ public:
CameraSensorHelperImx415()
{
gain_ = AnalogueGainExp{ 1.0, expGainDb(0.3) };
+ exposureMargin_ = 8;
}
};
REGISTER_CAMERA_SENSOR_HELPER("imx415", CameraSensorHelperImx415)
@@ -638,6 +678,7 @@ public:
CameraSensorHelperImx477()
{
gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 };
+ exposureMargin_ = 22;
}
};
REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477)
@@ -652,6 +693,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)
@@ -662,6 +704,7 @@ public:
CameraSensorHelperOv2740()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+ exposureMargin_ = 8;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov2740", CameraSensorHelperOv2740)
@@ -674,6 +717,7 @@ public:
/* From datasheet: 0x40 at 12bits. */
blackLevel_ = 1024;
gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+ exposureMargin_ = 4;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov4689", CameraSensorHelperOv4689)
@@ -686,6 +730,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)
@@ -696,6 +748,7 @@ public:
CameraSensorHelperOv5647()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 16 };
+ exposureMargin_ = 4;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov5647", CameraSensorHelperOv5647)
@@ -706,6 +759,7 @@ public:
CameraSensorHelperOv5670()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+ exposureMargin_ = 8;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov5670", CameraSensorHelperOv5670)
@@ -718,6 +772,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)
@@ -728,6 +783,7 @@ public:
CameraSensorHelperOv5693()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 16 };
+ exposureMargin_ = 8;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov5693", CameraSensorHelperOv5693)
@@ -738,6 +794,7 @@ public:
CameraSensorHelperOv64a40()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+ exposureMargin_ = 32;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov64a40", CameraSensorHelperOv64a40)
@@ -754,6 +811,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)
@@ -764,6 +822,7 @@ public:
CameraSensorHelperOv8865()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+ exposureMargin_ = 8;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov8865", CameraSensorHelperOv8865)
@@ -774,6 +833,7 @@ public:
CameraSensorHelperOv13858()
{
gain_ = AnalogueGainLinear{ 1, 0, 0, 128 };
+ exposureMargin_ = 8;
}
};
REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858)
@@ -786,6 +846,7 @@ public:
/* From datasheet: 0x40 at 10bits. */
blackLevel_ = 4096;
gain_ = AnalogueGainLinear{ 0, 32, -1, 32 };
+ exposureMargin_ = 64;
}
};
REGISTER_CAMERA_SENSOR_HELPER("vd55g1", CameraSensorHelperVd55g1)
@@ -798,6 +859,17 @@ public:
/* From datasheet: 0x40 at 10bits. */
blackLevel_ = 4096;
gain_ = AnalogueGainLinear{ 0, 32, -1, 32 };
+ /*
+ * The mainline driver version has
+ * #define VD56G3_EXPOSURE_MARGIN 75
+ * while the frameIntegrationDiff value in the RPi cam
+ * helper for this sensor has
+ * static constexpr int frameIntegrationDiff = 61;
+ *
+ * Trust the driver and report 75 which is also larger and
+ * hence "safer"
+ */
+ exposureMargin_ = 75;
}
};
REGISTER_CAMERA_SENSOR_HELPER("vd56g3", CameraSensorHelperVd56g3)
@@ -30,6 +30,7 @@ public:
virtual uint32_t gainCode(double gain) const;
virtual double gain(uint32_t gainCode) const;
double quantizeGain(double gain, double *quantizationGain) const;
+ std::optional<uint32_t> exposureMargin() const { return exposureMargin_; }
protected:
struct AnalogueGainLinear {
@@ -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)
There is a margin between the maximum achievable exposure 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 an exposureMargin() function that returns a std::optional<> with the sensor-specific margin. Use a std::optional<> to easily identify CameraSensorHelper implementations that do not populate exposureMargin_ and warn about possibly sub-optimal results in exposure time calculations. 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. The only outliner is the Vd56g3 sensor, whose exposure margin from the driver differs from the RPi camera helper. Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> --- src/ipa/libipa/camera_sensor_helper.cpp | 72 +++++++++++++++++++++++++++++++++ src/ipa/libipa/camera_sensor_helper.h | 2 + 2 files changed, 74 insertions(+)