ipa: rkisp1: add FrameDurationLimits control

Currently, the Android HAL does not work on rkisp1-based devices because
required FrameDurationLimits metadata is missing from the IPA
implementation.

This change sets FrameDurationLimits for rkisp1 based on the existing
ipu3 implementation, using the sensor's reported range of vertical
blanking intervals with the minimum reported horizontal blanking
interval.

Signed-off-by: Nicholas Roth <nicholas@rothemail.net>
Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Nicholas Roth 2022-10-30 18:04:57 -05:00 committed by Jacopo Mondi
parent 13d85e632a
commit 1d8fb31759
3 changed files with 67 additions and 13 deletions

View file

@ -15,14 +15,16 @@ struct IPAConfigInfo {
interface IPARkISP1Interface { interface IPARkISP1Interface {
init(libcamera.IPASettings settings, init(libcamera.IPASettings settings,
uint32 hwRevision) uint32 hwRevision,
libcamera.IPACameraSensorInfo sensorInfo,
libcamera.ControlInfoMap sensorControls)
=> (int32 ret, libcamera.ControlInfoMap ipaControls); => (int32 ret, libcamera.ControlInfoMap ipaControls);
start() => (int32 ret); start() => (int32 ret);
stop(); stop();
configure(IPAConfigInfo configInfo, configure(IPAConfigInfo configInfo,
map<uint32, libcamera.IPAStream> streamConfig) map<uint32, libcamera.IPAStream> streamConfig)
=> (int32 ret); => (int32 ret, libcamera.ControlInfoMap ipaControls);
mapBuffers(array<libcamera.IPABuffer> buffers); mapBuffers(array<libcamera.IPABuffer> buffers);
unmapBuffers(array<uint32> ids); unmapBuffers(array<uint32> ids);

View file

@ -49,12 +49,15 @@ public:
IPARkISP1(); IPARkISP1();
int init(const IPASettings &settings, unsigned int hwRevision, int init(const IPASettings &settings, unsigned int hwRevision,
const IPACameraSensorInfo &sensorInfo,
const ControlInfoMap &sensorControls,
ControlInfoMap *ipaControls) override; ControlInfoMap *ipaControls) override;
int start() override; int start() override;
void stop() override; void stop() override;
int configure(const IPAConfigInfo &ipaConfig, int configure(const IPAConfigInfo &ipaConfig,
const std::map<uint32_t, IPAStream> &streamConfig) override; const std::map<uint32_t, IPAStream> &streamConfig,
ControlInfoMap *ipaControls) override;
void mapBuffers(const std::vector<IPABuffer> &buffers) override; void mapBuffers(const std::vector<IPABuffer> &buffers) override;
void unmapBuffers(const std::vector<unsigned int> &ids) override; void unmapBuffers(const std::vector<unsigned int> &ids) override;
@ -67,6 +70,9 @@ protected:
std::string logPrefix() const override; std::string logPrefix() const override;
private: private:
void updateControls(const IPACameraSensorInfo &sensorInfo,
const ControlInfoMap &sensorControls,
ControlInfoMap *ipaControls);
void setControls(unsigned int frame); void setControls(unsigned int frame);
std::map<unsigned int, FrameBuffer> buffers_; std::map<unsigned int, FrameBuffer> buffers_;
@ -114,6 +120,8 @@ std::string IPARkISP1::logPrefix() const
} }
int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision, int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
const IPACameraSensorInfo &sensorInfo,
const ControlInfoMap &sensorControls,
ControlInfoMap *ipaControls) ControlInfoMap *ipaControls)
{ {
/* \todo Add support for other revisions */ /* \todo Add support for other revisions */
@ -179,9 +187,8 @@ int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
if (ret) if (ret)
return ret; return ret;
/* Return the controls handled by the IPA. */ /* Initialize controls. */
ControlInfoMap::Map ctrlMap = rkisp1Controls; updateControls(sensorInfo, sensorControls, ipaControls);
*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
return 0; return 0;
} }
@ -199,7 +206,8 @@ void IPARkISP1::stop()
} }
int IPARkISP1::configure(const IPAConfigInfo &ipaConfig, int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
[[maybe_unused]] const std::map<uint32_t, IPAStream> &streamConfig) [[maybe_unused]] const std::map<uint32_t, IPAStream> &streamConfig,
ControlInfoMap *ipaControls)
{ {
sensorControls_ = ipaConfig.sensorControls; sensorControls_ = ipaConfig.sensorControls;
@ -229,6 +237,9 @@ int IPARkISP1::configure(const IPAConfigInfo &ipaConfig,
context_.configuration.sensor.size = info.outputSize; context_.configuration.sensor.size = info.outputSize;
context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate; context_.configuration.sensor.lineDuration = info.minLineLength * 1.0s / info.pixelRate;
/* Update the camera controls using the new sensor settings. */
updateControls(info, sensorControls_, ipaControls);
/* /*
* When the AGC computes the new exposure values for a frame, it needs * When the AGC computes the new exposure values for a frame, it needs
* to know the limits for shutter speed and analogue gain. * to know the limits for shutter speed and analogue gain.
@ -331,6 +342,42 @@ void IPARkISP1::processStatsBuffer(const uint32_t frame, const uint32_t bufferId
metadataReady.emit(frame, metadata); metadataReady.emit(frame, metadata);
} }
void IPARkISP1::updateControls(const IPACameraSensorInfo &sensorInfo,
const ControlInfoMap &sensorControls,
ControlInfoMap *ipaControls)
{
ControlInfoMap::Map ctrlMap = rkisp1Controls;
/*
* Compute the frame duration limits.
*
* The frame length is computed assuming a fixed line length combined
* with the vertical frame sizes.
*/
const ControlInfo &v4l2HBlank = sensorControls.find(V4L2_CID_HBLANK)->second;
uint32_t hblank = v4l2HBlank.def().get<int32_t>();
uint32_t lineLength = sensorInfo.outputSize.width + hblank;
const ControlInfo &v4l2VBlank = sensorControls.find(V4L2_CID_VBLANK)->second;
std::array<uint32_t, 3> frameHeights{
v4l2VBlank.min().get<int32_t>() + sensorInfo.outputSize.height,
v4l2VBlank.max().get<int32_t>() + sensorInfo.outputSize.height,
v4l2VBlank.def().get<int32_t>() + sensorInfo.outputSize.height,
};
std::array<int64_t, 3> frameDurations;
for (unsigned int i = 0; i < frameHeights.size(); ++i) {
uint64_t frameSize = lineLength * frameHeights[i];
frameDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);
}
ctrlMap[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],
frameDurations[1],
frameDurations[2]);
*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
}
void IPARkISP1::setControls(unsigned int frame) void IPARkISP1::setControls(unsigned int frame)
{ {
/* /*

View file

@ -347,8 +347,15 @@ int RkISP1CameraData::loadIPA(unsigned int hwRevision)
ipaTuningFile = std::string(configFromEnv); ipaTuningFile = std::string(configFromEnv);
} }
int ret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision, IPACameraSensorInfo sensorInfo{};
&controlInfo_); int ret = sensor_->sensorInfo(&sensorInfo);
if (ret) {
LOG(RkISP1, Error) << "Camera sensor information not available";
return ret;
}
ret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision,
sensorInfo, sensor_->controls(), &controlInfo_);
if (ret < 0) { if (ret < 0) {
LOG(RkISP1, Error) << "IPA initialization failure"; LOG(RkISP1, Error) << "IPA initialization failure";
return ret; return ret;
@ -718,14 +725,12 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
ipa::rkisp1::IPAConfigInfo ipaConfig{}; ipa::rkisp1::IPAConfigInfo ipaConfig{};
ret = data->sensor_->sensorInfo(&ipaConfig.sensorInfo); ret = data->sensor_->sensorInfo(&ipaConfig.sensorInfo);
if (ret) { if (ret)
LOG(RkISP1, Error) << "Camera sensor information not available";
return ret; return ret;
}
ipaConfig.sensorControls = data->sensor_->controls(); ipaConfig.sensorControls = data->sensor_->controls();
ret = data->ipa_->configure(ipaConfig, streamConfig); ret = data->ipa_->configure(ipaConfig, streamConfig, &data->controlInfo_);
if (ret) { if (ret) {
LOG(RkISP1, Error) << "failed configuring IPA (" << ret << ")"; LOG(RkISP1, Error) << "failed configuring IPA (" << ret << ")";
return ret; return ret;