[v4,1/1] libcamera: rkisp1: Integrate SensorConfiguration support
diff mbox series

Message ID 20241004122103.89807-2-umang.jain@ideasonboard.com
State Accepted
Headers show
Series
  • rkisp1: Integrate sensorConfiguration
Related show

Commit Message

Umang Jain Oct. 4, 2024, 12:21 p.m. UTC
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
- RAW stream configuration size doesn't matches sensor configuration
  output size
- Sensor configuration output size is larger than maximum supported
  sensor configuration on RkISP1 pipeline
- No matching sensor configuration output size supplied by the sensor

Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
---
 src/libcamera/pipeline/rkisp1/rkisp1.cpp      | 42 ++++++++++++++---
 src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 47 +++++++++++++++++--
 src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  2 +
 3 files changed, 79 insertions(+), 12 deletions(-)

Comments

Jacopo Mondi Oct. 8, 2024, 8:54 a.m. UTC | #1
Hi Umang

On Fri, Oct 04, 2024 at 05:51:03PM GMT, Umang Jain wrote:
> 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
> - RAW stream configuration size doesn't matches sensor configuration
>   output size
> - Sensor configuration output size is larger than maximum supported
>   sensor configuration on RkISP1 pipeline
> - No matching sensor configuration output size supplied by the sensor
>
> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
> ---
>  src/libcamera/pipeline/rkisp1/rkisp1.cpp      | 42 ++++++++++++++---
>  src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 47 +++++++++++++++++--
>  src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  2 +
>  3 files changed, 79 insertions(+), 12 deletions(-)
>
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index c02c7cf3..42961c12 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) {
> +		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;
>
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> index feb6d89f..c51554bc 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
> @@ -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,13 +329,40 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
>  		 * size while ensuring the output size doesn't exceed ISP limits.
>  		 */
>  		uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);
> +		Size rawSize = sensorConfig ? sensorConfig->outputSize
> +					    : cfg->size;
>  		cfg->size.boundTo(resolution);
>
>  		V4L2SubdeviceFormat sensorFormat =
> -			sensor->getFormat({ mbusCode }, cfg->size);
> +			sensor->getFormat({ mbusCode }, rawSize);
> +
> +		if (sensorConfig &&
> +		    reqCfg.size != sensorConfig->outputSize)

Should this be reqCfg or sensorFormat ?

If checking sensorConfig->outputSize agains "reqCfg" you're validating
that the requested RAW stream configuration has the desired sensor
output size.

If checking sensorFormat->size instead you're validating that the
requested sensorConfig->outputSize is supported by the sensor
natively.

I think this should be the latter, if reqCfg->size doesn't match the
sensorConfig->outputSize it will later be adjusted to it, and I think
that's fine (as long as we return Adjusted), but we should make sure
sensorFormat->size is exactly what has been requested with
sensorConfig ?

> +			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;


Ah ok, I was about to suggest to move this just after initializing
'resolution', but in case of isRaw we don't go through the ISP, so the
ISP max input constraint doesn't apply

> +
> +		uint32_t mbusCode = formatToMediaBus.at(rawFormat);
> +		V4L2SubdeviceFormat sensorFormat =
> +			sensor->getFormat({ mbusCode }, sensorSize);
> +
> +		if (sensorFormat.size != sensorSize)
> +			return CameraConfiguration::Invalid;

That's what I was suggesting to do in the raw case as well

One small push and we should be there!
Thanks
  j

> +
> +		minResolution = minResolution_.expandedToAspectRatio(sensorSize);
> +		maxResolution = maxResolution_.boundedTo(sensorSize)
> +					      .boundedToAspectRatio(sensorSize);
>  	} else {
>  		/*
>  		 * Adjust the size based on the sensor resolution and absolute
> 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
>
Umang Jain Oct. 8, 2024, 9:47 a.m. UTC | #2
Hi Jacopo

On 08/10/24 2:24 pm, Jacopo Mondi wrote:
> Hi Umang
>
> On Fri, Oct 04, 2024 at 05:51:03PM GMT, Umang Jain wrote:
>> 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
>> - RAW stream configuration size doesn't matches sensor configuration
>>    output size
>> - Sensor configuration output size is larger than maximum supported
>>    sensor configuration on RkISP1 pipeline
>> - No matching sensor configuration output size supplied by the sensor
>>
>> Signed-off-by: Umang Jain <umang.jain@ideasonboard.com>
>> ---
>>   src/libcamera/pipeline/rkisp1/rkisp1.cpp      | 42 ++++++++++++++---
>>   src/libcamera/pipeline/rkisp1/rkisp1_path.cpp | 47 +++++++++++++++++--
>>   src/libcamera/pipeline/rkisp1/rkisp1_path.h   |  2 +
>>   3 files changed, 79 insertions(+), 12 deletions(-)
>>
>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> index c02c7cf3..42961c12 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) {
>> +		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;
>>
>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>> index feb6d89f..c51554bc 100644
>> --- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
>> @@ -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,13 +329,40 @@ CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
>>   		 * size while ensuring the output size doesn't exceed ISP limits.
>>   		 */
>>   		uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);
>> +		Size rawSize = sensorConfig ? sensorConfig->outputSize
>> +					    : cfg->size;
>>   		cfg->size.boundTo(resolution);
>>
>>   		V4L2SubdeviceFormat sensorFormat =
>> -			sensor->getFormat({ mbusCode }, cfg->size);
>> +			sensor->getFormat({ mbusCode }, rawSize);
>> +
>> +		if (sensorConfig &&
>> +		    reqCfg.size != sensorConfig->outputSize)
> Should this be reqCfg or sensorFormat ?
>
> If checking sensorConfig->outputSize agains "reqCfg" you're validating
> that the requested RAW stream configuration has the desired sensor
> output size.
>
> If checking sensorFormat->size instead you're validating that the
> requested sensorConfig->outputSize is supported by the sensor
> natively.
>
> I think this should be the latter, if reqCfg->size doesn't match the
> sensorConfig->outputSize it will later be adjusted to it, and I think
> that's fine (as long as we return Adjusted), but we should make sure
> sensorFormat->size is exactly what has been requested with
> sensorConfig ?

you're absolutely correct here. It should be sensorFormat, not refCfg, 
as reqCfg can get adjusted.

Will address in v5.
>
>> +			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;
>
> Ah ok, I was about to suggest to move this just after initializing
> 'resolution', but in case of isRaw we don't go through the ISP, so the
> ISP max input constraint doesn't apply
>
>> +
>> +		uint32_t mbusCode = formatToMediaBus.at(rawFormat);
>> +		V4L2SubdeviceFormat sensorFormat =
>> +			sensor->getFormat({ mbusCode }, sensorSize);
>> +
>> +		if (sensorFormat.size != sensorSize)
>> +			return CameraConfiguration::Invalid;
> That's what I was suggesting to do in the raw case as well
>
> One small push and we should be there!
> Thanks
>    j
>
>> +
>> +		minResolution = minResolution_.expandedToAspectRatio(sensorSize);
>> +		maxResolution = maxResolution_.boundedTo(sensorSize)
>> +					      .boundedToAspectRatio(sensorSize);
>>   	} else {
>>   		/*
>>   		 * Adjust the size based on the sensor resolution and absolute
>> 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
>>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index c02c7cf3..42961c12 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) {
+		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;
 
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
index feb6d89f..c51554bc 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
@@ -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,13 +329,40 @@  CameraConfiguration::Status RkISP1Path::validate(const CameraSensor *sensor,
 		 * size while ensuring the output size doesn't exceed ISP limits.
 		 */
 		uint32_t mbusCode = formatToMediaBus.at(cfg->pixelFormat);
+		Size rawSize = sensorConfig ? sensorConfig->outputSize
+					    : cfg->size;
 		cfg->size.boundTo(resolution);
 
 		V4L2SubdeviceFormat sensorFormat =
-			sensor->getFormat({ mbusCode }, cfg->size);
+			sensor->getFormat({ mbusCode }, rawSize);
+
+		if (sensorConfig &&
+		    reqCfg.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.
+		 */
+		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
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,