[PATCH v2 2/2] libcamera: rkisp1: Integrate SensorConfiguration support
Umang Jain
umang.jain at ideasonboard.com
Thu Oct 3 15:57:40 CEST 2024
Integrate the RkISP1 pipeline handler to support sensor configuration
provided by applications through CameraConfiguration::sensorConfig.
The SensorConfiguration must be validated on both RkISP1Path (mainPath
and selfPath), so the parameters of RkISP1Path::validate() have been
updated to include sensorConfig.
Finally, if the sensor configuration fails to apply, the camera
configuration validation will be marked as invalid.
Signed-off-by: Umang Jain <umang.jain at ideasonboard.com>
---
src/libcamera/pipeline/rkisp1/rkisp1.cpp | 68 ++++++++++++++++---
src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 45 ++++++++++--
src/libcamera/pipeline/rkisp1/rkisp1_path.h | 2 +
3 files changed, 100 insertions(+), 15 deletions(-)
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 6cee7893..95e70603 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -447,11 +447,12 @@ bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg)
StreamConfiguration config;
config = cfg;
- if (data_->mainPath_->validate(sensor, &config) != Valid)
+ if (data_->mainPath_->validate(sensor, sensorConfig, &config) != Valid)
return false;
config = cfg;
- if (data_->selfPath_ && data_->selfPath_->validate(sensor, &config) != Valid)
+ if (data_->selfPath_ &&
+ data_->selfPath_->validate(sensor, sensorConfig, &config) != Valid)
return false;
return true;
@@ -468,6 +469,27 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
status = validateColorSpaces(ColorSpaceFlag::StreamsShareColorSpace);
+ /*
+ * Make sure that if a sensor configuration has been requested it
+ * is valid.
+ */
+ if (sensorConfig && !sensorConfig->isValid()) {
+ LOG(RkISP1, Error)
+ << "Invalid sensor configuration request";
+
+ return Invalid;
+ }
+
+ if (sensorConfig) {
+ std::optional<unsigned int> bitDepth = sensorConfig->bitDepth;
+ if (bitDepth != 8 && bitDepth != 10 && bitDepth != 12) {
+ LOG(RkISP1, Error)
+ << "Invalid sensor configuration bit depth";
+
+ return Invalid;
+ }
+ }
+
/* Cap the number of entries to the available streams. */
if (config_.size() > pathCount) {
config_.resize(pathCount);
@@ -513,7 +535,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
/* Try to match stream without adjusting configuration. */
if (mainPathAvailable) {
StreamConfiguration tryCfg = cfg;
- if (data_->mainPath_->validate(sensor, &tryCfg) == Valid) {
+ if (data_->mainPath_->validate(sensor, sensorConfig, &tryCfg) == Valid) {
mainPathAvailable = false;
cfg = tryCfg;
cfg.setStream(const_cast<Stream *>(&data_->mainPathStream_));
@@ -523,7 +545,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
if (selfPathAvailable) {
StreamConfiguration tryCfg = cfg;
- if (data_->selfPath_->validate(sensor, &tryCfg) == Valid) {
+ if (data_->selfPath_->validate(sensor, sensorConfig, &tryCfg) == Valid) {
selfPathAvailable = false;
cfg = tryCfg;
cfg.setStream(const_cast<Stream *>(&data_->selfPathStream_));
@@ -534,7 +556,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
/* Try to match stream allowing adjusting configuration. */
if (mainPathAvailable) {
StreamConfiguration tryCfg = cfg;
- if (data_->mainPath_->validate(sensor, &tryCfg) == Adjusted) {
+ if (data_->mainPath_->validate(sensor, sensorConfig, &tryCfg) == Adjusted) {
mainPathAvailable = false;
cfg = tryCfg;
cfg.setStream(const_cast<Stream *>(&data_->mainPathStream_));
@@ -545,7 +567,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
if (selfPathAvailable) {
StreamConfiguration tryCfg = cfg;
- if (data_->selfPath_->validate(sensor, &tryCfg) == Adjusted) {
+ if (data_->selfPath_->validate(sensor, sensorConfig, &tryCfg) == Adjusted) {
selfPathAvailable = false;
cfg = tryCfg;
cfg.setStream(const_cast<Stream *>(&data_->selfPathStream_));
@@ -562,26 +584,47 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
/* Select the sensor format. */
PixelFormat rawFormat;
+ Size rawSize;
Size maxSize;
for (const StreamConfiguration &cfg : config_) {
- if (cfg.pixelFormat.isRaw())
+ if (cfg.pixelFormat.isRaw()) {
rawFormat = cfg.pixelFormat;
+ rawSize = cfg.size;
+ }
maxSize = std::max(maxSize, cfg.size);
}
+ if (rawFormat.isValid() && sensorConfig) {
+ const PixelFormatInfo &info = PixelFormatInfo::info(rawFormat);
+ if (sensorConfig->outputSize != rawSize ||
+ sensorConfig->bitDepth != info.bitsPerPixel)
+ return Invalid;
+ }
+
std::vector<unsigned int> mbusCodes;
+ Size sz = maxSize;
if (rawFormat.isValid()) {
mbusCodes = { rawFormats.at(rawFormat) };
+ sz = rawSize;
+ } else if (sensorConfig) {
+ /* sensorConfig has been validated by RkISP1Path::validate(). */
+ for (const auto &value : rawFormats) {
+ const PixelFormatInfo &info = PixelFormatInfo::info(value.first);
+ if (info.bitsPerPixel == sensorConfig->bitDepth)
+ mbusCodes.push_back(value.second);
+ }
+
+ sz = sensorConfig->outputSize;
} else {
std::transform(rawFormats.begin(), rawFormats.end(),
std::back_inserter(mbusCodes),
[](const auto &value) { return value.second; });
}
- sensorFormat_ = sensor->getFormat(mbusCodes, maxSize);
+ sensorFormat_ = sensor->getFormat(mbusCodes, sz);
if (sensorFormat_.size.isNull())
sensorFormat_.size = sensor->resolution();
@@ -721,7 +764,14 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
V4L2SubdeviceFormat format = config->sensorFormat();
LOG(RkISP1, Debug) << "Configuring sensor with " << format;
- ret = sensor->setFormat(&format, config->combinedTransform());
+ if (config->sensorConfig) {
+ ret = sensor->applyConfiguration(*config->sensorConfig,
+ config->combinedTransform(),
+ &format);
+ } else {
+ ret = sensor->setFormat(&format, config->combinedTransform());
+ }
+
if (ret < 0)
return ret;
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index e7f1f12a..93c7c7dc 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -250,8 +250,10 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
return cfg;
}
-CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
- StreamConfiguration *cfg)
+CameraConfiguration::Status
+RkISP1Path::validate(const CameraSensor *sensor,
+ std::optional<SensorConfiguration> &sensorConfig,
+ StreamConfiguration *cfg)
{
const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
@@ -278,11 +280,18 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
continue;
/*
- * Store the raw format with the highest bits per pixel
- * for later usage.
+ * If the bits per pixel is supplied from the sensor
+ * configuration, choose a raw format that complies with
+ * it. Otherwise, store the raw format with the highest
+ * bits per pixel for later usage.
*/
const PixelFormatInfo &info = PixelFormatInfo::info(format);
- if (info.bitsPerPixel > rawBitsPerPixel) {
+
+ if (sensorConfig &&
+ info.bitsPerPixel == sensorConfig->bitDepth) {
+ rawFormat = format;
+ rawBitsPerPixel = info.bitsPerPixel;
+ } else if (info.bitsPerPixel > rawBitsPerPixel) {
rawBitsPerPixel = info.bitsPerPixel;
rawFormat = format;
}
@@ -315,11 +324,35 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
* size.
*/
uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);
+ Size rawSize = sensorConfig ? sensorConfig->outputSize
+ : cfg->size;
V4L2SubdeviceFormat sensorFormat =
- sensor->getFormat({ mbusCode }, cfg->size);
+ sensor->getFormat({ mbusCode }, rawSize);
+
+ if (sensorConfig &&
+ sensorFormat.size != sensorConfig->outputSize)
+ return CameraConfiguration::Invalid;
minResolution = sensorFormat.size;
maxResolution = sensorFormat.size;
+ } else if (sensorConfig) {
+ /*
+ * We have already ensured 'rawFormat' has the matching bit
+ * depth with sensorConfig.bitDepth hence, only validate the
+ * sensorConfig's output size here.
+ * */
+ uint32_t mbusCode = formatToMediaBus.at(rawFormat);
+ Size sensorSize = sensorConfig->outputSize;
+
+ V4L2SubdeviceFormat sensorFormat =
+ sensor->getFormat({ mbusCode }, sensorSize);
+
+ if (sensorFormat.size != sensorSize)
+ return CameraConfiguration::Invalid;
+
+ minResolution = minResolution_.expandedToAspectRatio(sensorSize);
+ maxResolution = maxResolution_.boundedToAspectRatio(sensorSize)
+ .boundedTo(sensorSize);
} else {
Size resolution = filterSensorResolution(sensor);
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.h b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
index 777fcae7..ce9a5666 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.h
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.h
@@ -27,6 +27,7 @@ namespace libcamera {
class CameraSensor;
class MediaDevice;
class V4L2Subdevice;
+class SensorConfiguration;
struct StreamConfiguration;
struct V4L2SubdeviceFormat;
@@ -44,6 +45,7 @@ public:
const Size &resolution,
StreamRole role);
CameraConfiguration::Status validate(const CameraSensor *sensor,
+ std::optional<SensorConfiguration> &sensorConfig,
StreamConfiguration *cfg);
int configure(const StreamConfiguration &config,
--
2.45.2
More information about the libcamera-devel
mailing list