[libcamera-devel] [PATCH v3 5/6] libcamera: pipeline: raspberrypi: Implementation of digital zoom

Kieran Bingham kieran.bingham at ideasonboard.com
Mon Oct 5 22:54:34 CEST 2020


Hi David,

On 29/09/2020 17:39, David Plowman wrote:
> During configure() we update the SensorOutputSize to the correct value
> for this camera mode (which we also note internally) and work out the
> minimum crop size allowed by the ISP.
> 
> Whenever a new IspCrop request is received we check it's valid and
> apply it to the ISP V4L2 device. We also forward it to the IPA so that
> the IPA can return the values used in the image metadata.
> 
> Signed-off-by: David Plowman <david.plowman at raspberrypi.com>
> Reviewed-by: Jacopo Mondi <jacopo at jmondi.org>
> ---
>  include/libcamera/ipa/raspberrypi.h           |  1 +
>  src/ipa/raspberrypi/raspberrypi.cpp           |  7 +++
>  .../pipeline/raspberrypi/raspberrypi.cpp      | 47 +++++++++++++++++++
>  3 files changed, 55 insertions(+)
> 
> diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h
> index b3041591..9ef5f6fc 100644
> --- a/include/libcamera/ipa/raspberrypi.h
> +++ b/include/libcamera/ipa/raspberrypi.h
> @@ -60,6 +60,7 @@ static const ControlInfoMap Controls = {
>  	{ &controls::Saturation, ControlInfo(0.0f, 32.0f) },
>  	{ &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },
>  	{ &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },
> +	{ &controls::IspCrop, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },
>  };
>  
>  } /* namespace RPi */
> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
> index b0c7d1c1..dc73c20b 100644
> --- a/src/ipa/raspberrypi/raspberrypi.cpp
> +++ b/src/ipa/raspberrypi/raspberrypi.cpp
> @@ -699,6 +699,13 @@ void IPARPi::queueRequest(const ControlList &controls)
>  			break;
>  		}
>  
> +		case controls::ISP_CROP: {
> +			/* Just copy the information back. */
> +			Rectangle crop = ctrl.second.get<Rectangle>();
> +			libcameraMetadata_.set(controls::IspCrop, crop);
> +			break;
> +		}
> +
>  		default:
>  			LOG(IPARPI, Warning)
>  				<< "Ctrl " << controls::controls.at(ctrl.first)->name()
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> index d2bee150..4a6d0bf4 100644
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> @@ -193,6 +193,11 @@ public:
>  	bool flipsAlterBayerOrder_;
>  	BayerFormat::Order nativeBayerOrder_;
>  
> +	/* For handling digital zoom. */
> +	Size ispMinSize_;
> +	Size sensorOutputSize_;
> +	Rectangle lastIspCrop_;
> +
>  	unsigned int dropFrameCount_;
>  
>  private:
> @@ -587,6 +592,14 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)
>  	 */
>  	ret = data->isp_[Isp::Input].dev()->setFormat(&sensorFormat);
>  
> +	/*
> +	 * Update the SensorOutputSize to the correct value for this camera mode.
> +	 *
> +	 * \todo Move this property to CameraConfiguration when that
> +	 * feature will be made available and set it at validate() time
> +	 */
> +	data->properties_.set(properties::SensorOutputSize, sensorFormat.size);
> +
>  	/*
>  	 * See which streams are requested, and route the user
>  	 * StreamConfiguration appropriately.
> @@ -677,6 +690,16 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)
>  		return ret;
>  	}
>  
> +	/*
> +	 * Figure out the smallest selection the ISP will allow. We also store
> +	 * the output image size, in pixels, from the sensor. These will be
> +	 * used for digital zoom.
> +	 */
> +	Rectangle testCrop(0, 0, 1, 1);
> +	data->isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &testCrop);
> +	data->ispMinSize_ = testCrop.size();

I might have called testCrop minCrop, but I don't think that matters
much. testCrop is ok too.

Part of me is itching to say this should happen at camera creation time
or such, as I don't think it would change on any configure parameters?

But arguing against myself - that would then involve changing settings
on the device which we should avoid, and as this is used on the
per-frame controls, I think this is actually probably OK here. It's not
a big overhead for configure()


> +	data->sensorOutputSize_ = sensorFormat.size;
> +
>  	/* Adjust aspect ratio by providing crops on the input image. */
>  	Rectangle crop{ 0, 0, sensorFormat.size };
>  
> @@ -693,6 +716,8 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)
>  	crop.y = (sensorFormat.size.height - crop.height) >> 1;
>  	data->isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &crop);
>  
> +	data->lastIspCrop_ = crop;
> +
>  	ret = data->configureIPA(config);
>  	if (ret)
>  		LOG(RPI, Error) << "Failed to configure the IPA: " << ret;
> @@ -1588,6 +1613,28 @@ void RPiCameraData::tryRunPipeline()
>  	/* Take the first request from the queue and action the IPA. */
>  	Request *request = requestQueue_.front();
>  
> +	if (request->controls().contains(controls::IspCrop)) {
> +		Rectangle crop = request->controls().get<Rectangle>(controls::IspCrop);
> +		if (crop.width && crop.height) {
> +			/*
> +			 * The crop that we set must be:
> +			 * 1. At least as big as ispMinSize_, once that's been
> +			 *    enlarged to the same aspect ratio.
> +			 * 2. With the same mid-point, if possible.
> +			 * 3. But it can't go outside the sensor area.
> +			 */
> +			Size minSize = ispMinSize_.alignedUpToAspectRatio(crop.size());

I like how the helpers make this expressive, over the underlying
calculations.

> +			Size size = crop.size().expandedTo(minSize);
> +			crop = size.centredTo(crop).boundedTo(Rectangle(sensorOutputSize_));
> +
> +			if (crop != lastIspCrop_)
> +				isp_[Isp::Input].dev()->setSelection(V4L2_SEL_TGT_CROP, &crop);
> +			lastIspCrop_ = crop;
> +		}
> +
> +		request->controls().set(controls::IspCrop, lastIspCrop_);
> +	}
> +

Reviewed-by: Kieran Bingham <kieran.bingham at ideasonboard.com>

>  	/*
>  	 * Process all the user controls by the IPA. Once this is complete, we
>  	 * queue the ISP output buffer listed in the request to start the HW
> 

-- 
Regards
--
Kieran


More information about the libcamera-devel mailing list