[libcamera-devel,10/12] android: camera_device: Handle SCALER_CROP_REGION
diff mbox series

Message ID 20210105190522.682324-11-jacopo@jmondi.org
State Accepted
Delegated to: Jacopo Mondi
Headers show
Series
  • android: Exposure times + scaler crop + android metadata
Related show

Commit Message

Jacopo Mondi Jan. 5, 2021, 7:05 p.m. UTC
Handle the SCALER_CROP_REGION control and dynamic metadata by
translating it from the Android format to the associated libcamera
control when processing a request, and the other way around when
handling a request completion.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 src/android/camera_device.cpp | 52 +++++++++++++++++++++++++++++++----
 src/android/camera_device.h   |  2 ++
 src/android/camera_worker.h   |  1 +
 3 files changed, 49 insertions(+), 6 deletions(-)

Comments

Laurent Pinchart Jan. 11, 2021, 12:04 a.m. UTC | #1
Hi Jacopo,

Thank you for the patch.

On Tue, Jan 05, 2021 at 08:05:20PM +0100, Jacopo Mondi wrote:
> Handle the SCALER_CROP_REGION control and dynamic metadata by
> translating it from the Android format to the associated libcamera
> control when processing a request, and the other way around when
> handling a request completion.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  src/android/camera_device.cpp | 52 +++++++++++++++++++++++++++++++----
>  src/android/camera_device.h   |  2 ++
>  src/android/camera_worker.h   |  1 +
>  3 files changed, 49 insertions(+), 6 deletions(-)
> 
> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> index 99297270598f..5f5e6576365b 100644
> --- a/src/android/camera_device.cpp
> +++ b/src/android/camera_device.cpp
> @@ -1586,6 +1586,35 @@ FrameBuffer *CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer
>  	return new FrameBuffer(std::move(planes));
>  }
>  
> +int CameraDevice::processControls(camera3_capture_request_t *camera3Request,

Should the first argument be const ?

> +				  Camera3RequestDescriptor *descriptor)
> +{
> +	if (!camera3Request->settings)
> +		return 0;
> +
> +	/*
> +	 * Translate the Android controls to libcamera.
> +	 *
> +	 * \todo As soon as more controls are handled, this part should be
> +	 * broke out to a dedicated function.

s/broke/broken/

> +	 */
> +	const camera_metadata_t *camera3Settings = camera3Request->settings;
> +	camera_metadata_ro_entry_t entry;
> +	int ret = find_camera_metadata_ro_entry(camera3Settings,
> +						ANDROID_SCALER_CROP_REGION,
> +						&entry);
> +	if (!ret) {
> +		const int32_t *data = entry.data.i32;
> +		Rectangle cropRegion = { data[0], data[1],
> +					 static_cast<unsigned int>(data[2]),
> +					 static_cast<unsigned int>(data[3]) };

You could s/ = //, up to you.

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

> +		ControlList &controls = descriptor->request_->controls();
> +		controls.set(controls::ScalerCrop, cropRegion);
> +	}
> +
> +	return 0;
> +}
> +
>  int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Request)
>  {
>  	if (!camera3Request) {
> @@ -1697,7 +1726,14 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
>  						camera3Buffers[i].acquire_fence);
>  	}
>  
> -	/* Queue the request to the CameraWorker. */
> +	/*
> +	 * Translate controls from Android to libcamera and queue the request
> +	 * to the CameraWorker thread.
> +	 */
> +	int ret = processControls(camera3Request, descriptor);
> +	if (ret)
> +		return ret;
> +
>  	worker_.queueRequest(descriptor->request_.get());
>  
>  	return 0;
> @@ -1876,11 +1912,6 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
>  	const uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;
>  	resultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);
>  
> -	int32_t sensorSizes[] = {
> -		0, 0, 2560, 1920,
> -	};
> -	resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);
> -
>  	resultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
>  
>  	/* 33.3 msec */
> @@ -1911,6 +1942,15 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
>  					 &exposure, 1);
>  	}
>  
> +	if (metadata.contains(controls::ScalerCrop)) {
> +		Rectangle crop = metadata.get(controls::ScalerCrop);
> +		int32_t cropRect[] = {
> +			crop.x, crop.y, static_cast<int32_t>(crop.width),
> +			static_cast<int32_t>(crop.height),
> +		};
> +		resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, cropRect, 4);
> +	}
> +
>  	/*
>  	 * Return the result metadata pack even is not valid: get() will return
>  	 * nullptr.
> diff --git a/src/android/camera_device.h b/src/android/camera_device.h
> index 07d3a846f8e1..0874c80f1e66 100644
> --- a/src/android/camera_device.h
> +++ b/src/android/camera_device.h
> @@ -105,6 +105,8 @@ private:
>  	void notifyError(uint32_t frameNumber, camera3_stream_t *stream);
>  	CameraMetadata *requestTemplatePreview();
>  	libcamera::PixelFormat toPixelFormat(int format) const;
> +	int processControls(camera3_capture_request_t *camera3Request,
> +			    Camera3RequestDescriptor *descriptor);
>  	std::unique_ptr<CameraMetadata> getResultMetadata(
>  		Camera3RequestDescriptor *descriptor, int64_t timestamp);
>  
> diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h
> index 847a2fc4bd7c..6522f1d68a20 100644
> --- a/src/android/camera_worker.h
> +++ b/src/android/camera_worker.h
> @@ -25,6 +25,7 @@ public:
>  	CaptureRequest(libcamera::Camera *camera, uint64_t cookie);
>  
>  	const std::vector<int> &fences() const { return acquireFences_; }
> +	libcamera::ControlList &controls() { return request_->controls(); }
>  	const libcamera::ControlList &metadata() const
>  	{
>  		return request_->metadata();
Niklas Söderlund Jan. 18, 2021, 3:39 p.m. UTC | #2
Hi Jacopo,

Thanks for your work.

On 2021-01-05 20:05:20 +0100, Jacopo Mondi wrote:
> Handle the SCALER_CROP_REGION control and dynamic metadata by
> translating it from the Android format to the associated libcamera
> control when processing a request, and the other way around when
> handling a request completion.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  src/android/camera_device.cpp | 52 +++++++++++++++++++++++++++++++----
>  src/android/camera_device.h   |  2 ++
>  src/android/camera_worker.h   |  1 +
>  3 files changed, 49 insertions(+), 6 deletions(-)
> 
> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
> index 99297270598f..5f5e6576365b 100644
> --- a/src/android/camera_device.cpp
> +++ b/src/android/camera_device.cpp
> @@ -1586,6 +1586,35 @@ FrameBuffer *CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer
>  	return new FrameBuffer(std::move(planes));
>  }
>  
> +int CameraDevice::processControls(camera3_capture_request_t *camera3Request,
> +				  Camera3RequestDescriptor *descriptor)
> +{
> +	if (!camera3Request->settings)
> +		return 0;
> +
> +	/*
> +	 * Translate the Android controls to libcamera.
> +	 *
> +	 * \todo As soon as more controls are handled, this part should be
> +	 * broke out to a dedicated function.
> +	 */
> +	const camera_metadata_t *camera3Settings = camera3Request->settings;
> +	camera_metadata_ro_entry_t entry;
> +	int ret = find_camera_metadata_ro_entry(camera3Settings,
> +						ANDROID_SCALER_CROP_REGION,
> +						&entry);
> +	if (!ret) {
> +		const int32_t *data = entry.data.i32;
> +		Rectangle cropRegion = { data[0], data[1],
> +					 static_cast<unsigned int>(data[2]),
> +					 static_cast<unsigned int>(data[3]) };
> +		ControlList &controls = descriptor->request_->controls();
> +		controls.set(controls::ScalerCrop, cropRegion);
> +	}
> +
> +	return 0;
> +}
> +
>  int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Request)
>  {
>  	if (!camera3Request) {
> @@ -1697,7 +1726,14 @@ int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
>  						camera3Buffers[i].acquire_fence);
>  	}
>  
> -	/* Queue the request to the CameraWorker. */
> +	/*
> +	 * Translate controls from Android to libcamera and queue the request
> +	 * to the CameraWorker thread.
> +	 */
> +	int ret = processControls(camera3Request, descriptor);
> +	if (ret)
> +		return ret;

I like how the different blocks are falling into place, nice!

Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>

> +
>  	worker_.queueRequest(descriptor->request_.get());
>  
>  	return 0;
> @@ -1876,11 +1912,6 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
>  	const uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;
>  	resultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);
>  
> -	int32_t sensorSizes[] = {
> -		0, 0, 2560, 1920,
> -	};
> -	resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);
> -
>  	resultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
>  
>  	/* 33.3 msec */
> @@ -1911,6 +1942,15 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
>  					 &exposure, 1);
>  	}
>  
> +	if (metadata.contains(controls::ScalerCrop)) {
> +		Rectangle crop = metadata.get(controls::ScalerCrop);
> +		int32_t cropRect[] = {
> +			crop.x, crop.y, static_cast<int32_t>(crop.width),
> +			static_cast<int32_t>(crop.height),
> +		};
> +		resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, cropRect, 4);
> +	}
> +
>  	/*
>  	 * Return the result metadata pack even is not valid: get() will return
>  	 * nullptr.
> diff --git a/src/android/camera_device.h b/src/android/camera_device.h
> index 07d3a846f8e1..0874c80f1e66 100644
> --- a/src/android/camera_device.h
> +++ b/src/android/camera_device.h
> @@ -105,6 +105,8 @@ private:
>  	void notifyError(uint32_t frameNumber, camera3_stream_t *stream);
>  	CameraMetadata *requestTemplatePreview();
>  	libcamera::PixelFormat toPixelFormat(int format) const;
> +	int processControls(camera3_capture_request_t *camera3Request,
> +			    Camera3RequestDescriptor *descriptor);
>  	std::unique_ptr<CameraMetadata> getResultMetadata(
>  		Camera3RequestDescriptor *descriptor, int64_t timestamp);
>  
> diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h
> index 847a2fc4bd7c..6522f1d68a20 100644
> --- a/src/android/camera_worker.h
> +++ b/src/android/camera_worker.h
> @@ -25,6 +25,7 @@ public:
>  	CaptureRequest(libcamera::Camera *camera, uint64_t cookie);
>  
>  	const std::vector<int> &fences() const { return acquireFences_; }
> +	libcamera::ControlList &controls() { return request_->controls(); }
>  	const libcamera::ControlList &metadata() const
>  	{
>  		return request_->metadata();
> -- 
> 2.29.2
> 
> _______________________________________________
> libcamera-devel mailing list
> libcamera-devel@lists.libcamera.org
> https://lists.libcamera.org/listinfo/libcamera-devel

Patch
diff mbox series

diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 99297270598f..5f5e6576365b 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -1586,6 +1586,35 @@  FrameBuffer *CameraDevice::createFrameBuffer(const buffer_handle_t camera3buffer
 	return new FrameBuffer(std::move(planes));
 }
 
+int CameraDevice::processControls(camera3_capture_request_t *camera3Request,
+				  Camera3RequestDescriptor *descriptor)
+{
+	if (!camera3Request->settings)
+		return 0;
+
+	/*
+	 * Translate the Android controls to libcamera.
+	 *
+	 * \todo As soon as more controls are handled, this part should be
+	 * broke out to a dedicated function.
+	 */
+	const camera_metadata_t *camera3Settings = camera3Request->settings;
+	camera_metadata_ro_entry_t entry;
+	int ret = find_camera_metadata_ro_entry(camera3Settings,
+						ANDROID_SCALER_CROP_REGION,
+						&entry);
+	if (!ret) {
+		const int32_t *data = entry.data.i32;
+		Rectangle cropRegion = { data[0], data[1],
+					 static_cast<unsigned int>(data[2]),
+					 static_cast<unsigned int>(data[3]) };
+		ControlList &controls = descriptor->request_->controls();
+		controls.set(controls::ScalerCrop, cropRegion);
+	}
+
+	return 0;
+}
+
 int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Request)
 {
 	if (!camera3Request) {
@@ -1697,7 +1726,14 @@  int CameraDevice::processCaptureRequest(camera3_capture_request_t *camera3Reques
 						camera3Buffers[i].acquire_fence);
 	}
 
-	/* Queue the request to the CameraWorker. */
+	/*
+	 * Translate controls from Android to libcamera and queue the request
+	 * to the CameraWorker thread.
+	 */
+	int ret = processControls(camera3Request, descriptor);
+	if (ret)
+		return ret;
+
 	worker_.queueRequest(descriptor->request_.get());
 
 	return 0;
@@ -1876,11 +1912,6 @@  CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
 	const uint8_t lens_state = ANDROID_LENS_STATE_STATIONARY;
 	resultMetadata->addEntry(ANDROID_LENS_STATE, &lens_state, 1);
 
-	int32_t sensorSizes[] = {
-		0, 0, 2560, 1920,
-	};
-	resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, sensorSizes, 4);
-
 	resultMetadata->addEntry(ANDROID_SENSOR_TIMESTAMP, &timestamp, 1);
 
 	/* 33.3 msec */
@@ -1911,6 +1942,15 @@  CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
 					 &exposure, 1);
 	}
 
+	if (metadata.contains(controls::ScalerCrop)) {
+		Rectangle crop = metadata.get(controls::ScalerCrop);
+		int32_t cropRect[] = {
+			crop.x, crop.y, static_cast<int32_t>(crop.width),
+			static_cast<int32_t>(crop.height),
+		};
+		resultMetadata->addEntry(ANDROID_SCALER_CROP_REGION, cropRect, 4);
+	}
+
 	/*
 	 * Return the result metadata pack even is not valid: get() will return
 	 * nullptr.
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index 07d3a846f8e1..0874c80f1e66 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -105,6 +105,8 @@  private:
 	void notifyError(uint32_t frameNumber, camera3_stream_t *stream);
 	CameraMetadata *requestTemplatePreview();
 	libcamera::PixelFormat toPixelFormat(int format) const;
+	int processControls(camera3_capture_request_t *camera3Request,
+			    Camera3RequestDescriptor *descriptor);
 	std::unique_ptr<CameraMetadata> getResultMetadata(
 		Camera3RequestDescriptor *descriptor, int64_t timestamp);
 
diff --git a/src/android/camera_worker.h b/src/android/camera_worker.h
index 847a2fc4bd7c..6522f1d68a20 100644
--- a/src/android/camera_worker.h
+++ b/src/android/camera_worker.h
@@ -25,6 +25,7 @@  public:
 	CaptureRequest(libcamera::Camera *camera, uint64_t cookie);
 
 	const std::vector<int> &fences() const { return acquireFences_; }
+	libcamera::ControlList &controls() { return request_->controls(); }
 	const libcamera::ControlList &metadata() const
 	{
 		return request_->metadata();