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:
parent
fc761ffe49
commit
047d647452
3 changed files with 80 additions and 12 deletions
|
@ -447,11 +447,12 @@ bool RkISP1CameraConfiguration::fitsAllPaths(const StreamConfiguration &cfg)
|
||||||
StreamConfiguration config;
|
StreamConfiguration config;
|
||||||
|
|
||||||
config = cfg;
|
config = cfg;
|
||||||
if (data_->mainPath_->validate(sensor, &config) != Valid)
|
if (data_->mainPath_->validate(sensor, sensorConfig, &config) != Valid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
config = cfg;
|
config = cfg;
|
||||||
if (data_->selfPath_ && data_->selfPath_->validate(sensor, &config) != Valid)
|
if (data_->selfPath_ &&
|
||||||
|
data_->selfPath_->validate(sensor, sensorConfig, &config) != Valid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -468,6 +469,27 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
|
||||||
|
|
||||||
status = validateColorSpaces(ColorSpaceFlag::StreamsShareColorSpace);
|
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. */
|
/* Cap the number of entries to the available streams. */
|
||||||
if (config_.size() > pathCount) {
|
if (config_.size() > pathCount) {
|
||||||
config_.resize(pathCount);
|
config_.resize(pathCount);
|
||||||
|
@ -514,7 +536,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
|
||||||
/* Try to match stream without adjusting configuration. */
|
/* Try to match stream without adjusting configuration. */
|
||||||
if (mainPathAvailable) {
|
if (mainPathAvailable) {
|
||||||
StreamConfiguration tryCfg = cfg;
|
StreamConfiguration tryCfg = cfg;
|
||||||
if (data_->mainPath_->validate(sensor, &tryCfg) == Valid) {
|
if (data_->mainPath_->validate(sensor, sensorConfig, &tryCfg) == Valid) {
|
||||||
mainPathAvailable = false;
|
mainPathAvailable = false;
|
||||||
cfg = tryCfg;
|
cfg = tryCfg;
|
||||||
cfg.setStream(const_cast<Stream *>(&data_->mainPathStream_));
|
cfg.setStream(const_cast<Stream *>(&data_->mainPathStream_));
|
||||||
|
@ -524,7 +546,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
|
||||||
|
|
||||||
if (selfPathAvailable) {
|
if (selfPathAvailable) {
|
||||||
StreamConfiguration tryCfg = cfg;
|
StreamConfiguration tryCfg = cfg;
|
||||||
if (data_->selfPath_->validate(sensor, &tryCfg) == Valid) {
|
if (data_->selfPath_->validate(sensor, sensorConfig, &tryCfg) == Valid) {
|
||||||
selfPathAvailable = false;
|
selfPathAvailable = false;
|
||||||
cfg = tryCfg;
|
cfg = tryCfg;
|
||||||
cfg.setStream(const_cast<Stream *>(&data_->selfPathStream_));
|
cfg.setStream(const_cast<Stream *>(&data_->selfPathStream_));
|
||||||
|
@ -535,7 +557,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
|
||||||
/* Try to match stream allowing adjusting configuration. */
|
/* Try to match stream allowing adjusting configuration. */
|
||||||
if (mainPathAvailable) {
|
if (mainPathAvailable) {
|
||||||
StreamConfiguration tryCfg = cfg;
|
StreamConfiguration tryCfg = cfg;
|
||||||
if (data_->mainPath_->validate(sensor, &tryCfg) == Adjusted) {
|
if (data_->mainPath_->validate(sensor, sensorConfig, &tryCfg) == Adjusted) {
|
||||||
mainPathAvailable = false;
|
mainPathAvailable = false;
|
||||||
cfg = tryCfg;
|
cfg = tryCfg;
|
||||||
cfg.setStream(const_cast<Stream *>(&data_->mainPathStream_));
|
cfg.setStream(const_cast<Stream *>(&data_->mainPathStream_));
|
||||||
|
@ -546,7 +568,7 @@ CameraConfiguration::Status RkISP1CameraConfiguration::validate()
|
||||||
|
|
||||||
if (selfPathAvailable) {
|
if (selfPathAvailable) {
|
||||||
StreamConfiguration tryCfg = cfg;
|
StreamConfiguration tryCfg = cfg;
|
||||||
if (data_->selfPath_->validate(sensor, &tryCfg) == Adjusted) {
|
if (data_->selfPath_->validate(sensor, sensorConfig, &tryCfg) == Adjusted) {
|
||||||
selfPathAvailable = false;
|
selfPathAvailable = false;
|
||||||
cfg = tryCfg;
|
cfg = tryCfg;
|
||||||
cfg.setStream(const_cast<Stream *>(&data_->selfPathStream_));
|
cfg.setStream(const_cast<Stream *>(&data_->selfPathStream_));
|
||||||
|
@ -723,7 +745,13 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c)
|
||||||
V4L2SubdeviceFormat format = config->sensorFormat();
|
V4L2SubdeviceFormat format = config->sensorFormat();
|
||||||
LOG(RkISP1, Debug) << "Configuring sensor with " << format;
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -251,8 +251,10 @@ RkISP1Path::generateConfiguration(const CameraSensor *sensor, const Size &size,
|
||||||
return cfg;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
|
CameraConfiguration::Status
|
||||||
StreamConfiguration *cfg)
|
RkISP1Path::validate(const CameraSensor *sensor,
|
||||||
|
std::optional<SensorConfiguration> &sensorConfig,
|
||||||
|
StreamConfiguration *cfg)
|
||||||
{
|
{
|
||||||
const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
|
const std::vector<unsigned int> &mbusCodes = sensor->mbusCodes();
|
||||||
Size resolution = filterSensorResolution(sensor);
|
Size resolution = filterSensorResolution(sensor);
|
||||||
|
@ -282,9 +284,14 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the raw format with the highest bits per pixel
|
* If the bits per pixel is supplied from the sensor
|
||||||
* for later usage.
|
* 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) {
|
if (info.bitsPerPixel > rawBitsPerPixel) {
|
||||||
rawBitsPerPixel = info.bitsPerPixel;
|
rawBitsPerPixel = info.bitsPerPixel;
|
||||||
rawFormat = format;
|
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 ==
|
bool isRaw = PixelFormatInfo::info(cfg->pixelFormat).colourEncoding ==
|
||||||
PixelFormatInfo::ColourEncodingRAW;
|
PixelFormatInfo::ColourEncodingRAW;
|
||||||
|
|
||||||
|
@ -319,11 +329,39 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
|
||||||
* size.
|
* size.
|
||||||
*/
|
*/
|
||||||
uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);
|
uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);
|
||||||
|
Size rawSize = sensorConfig ? sensorConfig->outputSize
|
||||||
|
: cfg->size;
|
||||||
|
|
||||||
V4L2SubdeviceFormat sensorFormat =
|
V4L2SubdeviceFormat sensorFormat =
|
||||||
sensor->getFormat({ mbusCode }, cfg->size);
|
sensor->getFormat({ mbusCode }, rawSize);
|
||||||
|
|
||||||
|
if (sensorConfig &&
|
||||||
|
sensorConfig->outputSize != sensorFormat.size)
|
||||||
|
return CameraConfiguration::Invalid;
|
||||||
|
|
||||||
minResolution = sensorFormat.size;
|
minResolution = sensorFormat.size;
|
||||||
maxResolution = 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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Adjust the size based on the sensor resolution and absolute
|
* Adjust the size based on the sensor resolution and absolute
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace libcamera {
|
||||||
class CameraSensor;
|
class CameraSensor;
|
||||||
class MediaDevice;
|
class MediaDevice;
|
||||||
class V4L2Subdevice;
|
class V4L2Subdevice;
|
||||||
|
class SensorConfiguration;
|
||||||
struct StreamConfiguration;
|
struct StreamConfiguration;
|
||||||
struct V4L2SubdeviceFormat;
|
struct V4L2SubdeviceFormat;
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ public:
|
||||||
const Size &resolution,
|
const Size &resolution,
|
||||||
StreamRole role);
|
StreamRole role);
|
||||||
CameraConfiguration::Status validate(const CameraSensor *sensor,
|
CameraConfiguration::Status validate(const CameraSensor *sensor,
|
||||||
|
std::optional<SensorConfiguration> &sensorConfig,
|
||||||
StreamConfiguration *cfg);
|
StreamConfiguration *cfg);
|
||||||
|
|
||||||
int configure(const StreamConfiguration &config,
|
int configure(const StreamConfiguration &config,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue