diff --git a/include/libcamera/ipa/raspberrypi.mojom b/include/libcamera/ipa/raspberrypi.mojom index 12b083e9..1b7e0358 100644 --- a/include/libcamera/ipa/raspberrypi.mojom +++ b/include/libcamera/ipa/raspberrypi.mojom @@ -18,6 +18,7 @@ struct SensorConfig { struct InitParams { bool lensPresent; libcamera.IPACameraSensorInfo sensorInfo; + float controllerMinFrameDurationUs; /* PISP specific */ libcamera.SharedFD fe; libcamera.SharedFD be; diff --git a/src/ipa/rpi/common/ipa_base.cpp b/src/ipa/rpi/common/ipa_base.cpp index 17f6850f..faa77719 100644 --- a/src/ipa/rpi/common/ipa_base.cpp +++ b/src/ipa/rpi/common/ipa_base.cpp @@ -46,14 +46,6 @@ constexpr Duration defaultExposureTime = 20.0ms; constexpr Duration defaultMinFrameDuration = 1.0s / 30.0; constexpr Duration defaultMaxFrameDuration = 250.0s; -/* - * Determine the minimum allowable inter-frame duration to run the controller - * algorithms. If the pipeline handler provider frames at a rate higher than this, - * we rate-limit the controller Prepare() and Process() calls to lower than or - * equal to this rate. - */ -constexpr Duration controllerMinFrameDuration = 1.0s / 30.0; - /* List of controls handled by the Raspberry Pi IPA */ const ControlInfoMap::Map ipaControls{ /* \todo Move this to the Camera class */ @@ -186,6 +178,14 @@ int32_t IpaBase::init(const IPASettings &settings, const InitParams ¶ms, Ini result->controlInfo = ControlInfoMap(std::move(ctrlMap), controls::controls); + /* + * This determines the minimum allowable inter-frame duration to run the + * controller algorithms. If the pipeline handler provider frames at a + * rate higher than this, we rate-limit the controller Prepare() and + * Process() calls to lower than or equal to this rate. + */ + controllerMinFrameDuration_ = params.controllerMinFrameDurationUs * 1us; + return platformInit(params, result); } @@ -467,7 +467,7 @@ void IpaBase::prepareIsp(const PrepareParams ¶ms) /* Allow a 10% margin on the comparison below. */ Duration delta = (frameTimestamp - lastRunTimestamp_) * 1.0ns; if (lastRunTimestamp_ && frameCount_ > invalidCount_ && - delta < controllerMinFrameDuration * 0.9 && !hdrChange) { + delta < controllerMinFrameDuration_ * 0.9 && !hdrChange) { /* * Ensure we merge the previous frame's metadata with the current * frame. This will not overwrite exposure/gain values for the diff --git a/src/ipa/rpi/common/ipa_base.h b/src/ipa/rpi/common/ipa_base.h index 5348f2ea..90f018b2 100644 --- a/src/ipa/rpi/common/ipa_base.h +++ b/src/ipa/rpi/common/ipa_base.h @@ -142,6 +142,8 @@ private: } flickerState_; bool awbEnabled_; + + utils::Duration controllerMinFrameDuration_; }; } /* namespace ipa::RPi */ diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp index c507b44b..867ecf1b 100644 --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp @@ -33,6 +33,12 @@ LOG_DEFINE_CATEGORY(RPI) using StreamFlag = RPi::Stream::StreamFlag; +/* + * The IPA's algorithms will not be called more often than this many + * microseconds. The default corresponds to 30fps. + */ +constexpr float defaultControllerMinimumFrameDurationUs = 1000000.0 / 30.0; + namespace { constexpr unsigned int defaultRawBitDepth = 12; @@ -800,6 +806,12 @@ int PipelineHandlerBase::registerCamera(std::unique_ptr &camera if (!data->sensor_) return -EINVAL; + ret = data->loadPipelineConfiguration(); + if (ret) { + LOG(RPI, Error) << "Unable to load pipeline configuration"; + return ret; + } + /* Populate the map of sensor supported formats and sizes. */ for (const auto mbusCode : data->sensor_->mbusCodes()) data->sensorFormats_.emplace(mbusCode, @@ -859,12 +871,6 @@ int PipelineHandlerBase::registerCamera(std::unique_ptr &camera if (ret) return ret; - ret = data->loadPipelineConfiguration(); - if (ret) { - LOG(RPI, Error) << "Unable to load pipeline configuration"; - return ret; - } - /* Setup the general IPA signal handlers. */ data->frontendDevice()->dequeueTimeout.connect(data, &RPi::CameraData::cameraTimeout); data->frontendDevice()->frameStart.connect(data, &RPi::CameraData::frameStarted); @@ -1095,6 +1101,7 @@ int CameraData::loadPipelineConfiguration() { config_ = { .cameraTimeoutValue = 0, + .controllerMinFrameDurationUs = defaultControllerMinimumFrameDurationUs, }; /* Initial configuration of the platform, in case no config file is present */ @@ -1144,6 +1151,9 @@ int CameraData::loadPipelineConfiguration() frontendDevice()->setDequeueTimeout(config_.cameraTimeoutValue * 1ms); } + config_.controllerMinFrameDurationUs = + phConfig["controller_min_frame_duration_us"].get(config_.controllerMinFrameDurationUs); + return platformPipelineConfigure(root); } @@ -1172,6 +1182,8 @@ int CameraData::loadIPA(ipa::RPi::InitResult *result) } params.lensPresent = !!sensor_->focusLens(); + params.controllerMinFrameDurationUs = config_.controllerMinFrameDurationUs; + ret = platformInitIpa(params); if (ret) return ret; diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.h b/src/libcamera/pipeline/rpi/common/pipeline_base.h index 6257a934..597eb587 100644 --- a/src/libcamera/pipeline/rpi/common/pipeline_base.h +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.h @@ -169,6 +169,11 @@ public: * on frame durations. */ unsigned int cameraTimeoutValue; + /* + * The minimum frame duration between the IPA's calls to the + * algorithms themselves (in microseconds). + */ + float controllerMinFrameDurationUs; }; Config config_; diff --git a/src/libcamera/pipeline/rpi/pisp/data/example.yaml b/src/libcamera/pipeline/rpi/pisp/data/example.yaml index baf03be7..c5edbba0 100644 --- a/src/libcamera/pipeline/rpi/pisp/data/example.yaml +++ b/src/libcamera/pipeline/rpi/pisp/data/example.yaml @@ -36,5 +36,11 @@ # framebuffers required for its operation. # # "disable_hdr": false, + + # Limits the rate at which IPAs are called. The algorithms will + # be skipped until this many microseconds have elapsed since + # the last call. The default value represents a 30fps limit. + # + # "controller_min_frame_duration_us": 33333.333, } } diff --git a/src/libcamera/pipeline/rpi/vc4/data/example.yaml b/src/libcamera/pipeline/rpi/vc4/data/example.yaml index 27e54348..2ee2b864 100644 --- a/src/libcamera/pipeline/rpi/vc4/data/example.yaml +++ b/src/libcamera/pipeline/rpi/vc4/data/example.yaml @@ -37,5 +37,11 @@ # timeout value. # # "camera_timeout_value_ms": 0, + + # Limits the rate at which IPAs are called. The algorithms will + # be skipped until this many microseconds have elapsed since + # the last call. The default value represents a 30fps limit. + # + # "controller_min_frame_duration_us": 33333.333, } }