libcamera: rkisp1: Integrate SensorConfiguration support

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.

The camera configuration will be marked as invalid when the sensor
configuration is supplied, if:
- Invalid sensor configuration (SensorConfiguration::isValid())
- Bit depth not supported by RkISP1 pipeline
- Sensor configuration output size is larger than maximum supported
  sensor's size on RkISP1 pipeline
- No matching sensor configuration output size supplied by the sensor

Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Stefan Klug <stefan.klug@ideasonboard.com>
Tested-by: Stefan Klug <stefan.klug@ideasonboard.com>
This commit is contained in:
Umang Jain 2024-10-08 15:49:18 +05:30
parent fc761ffe49
commit 047d647452
3 changed files with 80 additions and 12 deletions

View file

@ -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) {
if (!sensorConfig->isValid()) {
LOG(RkISP1, Error)
<< "Invalid sensor configuration request";
return Invalid;
}
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);
@ -514,7 +536,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_));
@ -524,7 +546,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_));
@ -535,7 +557,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_));
@ -546,7 +568,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_));
@ -723,7 +745,13 @@ 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;

View file

@ -251,8 +251,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();
Size resolution = filterSensorResolution(sensor);
@ -282,9 +284,14 @@ 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.
*/
if (sensorConfig && info.bitsPerPixel != sensorConfig->bitDepth)
continue;
if (info.bitsPerPixel > rawBitsPerPixel) {
rawBitsPerPixel = info.bitsPerPixel;
rawFormat = format;
@ -297,6 +304,9 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
}
}
if (sensorConfig && !found)
return CameraConfiguration::Invalid;
bool isRaw = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding ==
PixelFormatInfo::ColourEncodingRAW;
@ -319,11 +329,39 @@ 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 &&
sensorConfig->outputSize != sensorFormat.size)
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.
*/
Size sensorSize = sensorConfig->outputSize;
if (sensorSize > resolution)
return CameraConfiguration::Invalid;
uint32_t mbusCode = formatToMediaBus.at(rawFormat);
V4L2SubdeviceFormat sensorFormat =
sensor->getFormat({ mbusCode }, sensorSize);
if (sensorFormat.size != sensorSize)
return CameraConfiguration::Invalid;
minResolution = minResolution_.expandedToAspectRatio(sensorSize);
maxResolution = maxResolution_.boundedTo(sensorSize)
.boundedToAspectRatio(sensorSize);
} else {
/*
* Adjust the size based on the sensor resolution and absolute

View file

@ -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,