[PATCH v2 8/9] android: Add JpegExifMetadata to store tags setting into Exif

Harvey Yang chenghaoyang at chromium.org
Wed Nov 27 10:25:58 CET 2024


From: Han-Lin Chen <hanlinchen at chromium.org>

With partial result, some metadata, which needs to be added into Exif,
may be sent back to framework earlier before Jpeg post-processing.
Add a type JpegExifMetadata associated with StreamBuffer to store the values,
so Jpeg post-processing doesn't need to reference to current metadata.

Signed-off-by: Han-Lin Chen <hanlinchen at chromium.org>
Co-developed-by: Harvey Yang <chenghaoyang at chromium.org>
Signed-off-by: Harvey Yang <chenghaoyang at chromium.org>
---
 src/android/camera_device.cpp            | 26 ++++++++++++++++++++++++
 src/android/camera_device.h              |  2 ++
 src/android/camera_request.h             |  6 ++++++
 src/android/camera_stream.h              |  4 ++++
 src/android/jpeg/post_processor_jpeg.cpp | 12 ++++++-----
 5 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 9fd851bc8..e085e18b2 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -1250,6 +1250,10 @@ void CameraDevice::requestComplete(Request *request)
 		CameraStream *stream = iter->first;
 		StreamBuffer *buffer = iter->second;
 
+		if (stream->isJpegStream()) {
+			generateJpegExifMetadata(descriptor, buffer);
+		}
+
 		FrameBuffer *src = request->findBuffer(stream->stream());
 		if (!src) {
 			LOG(HAL, Error) << "Failed to find a source stream buffer";
@@ -1443,6 +1447,28 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream,
 	callbacks_->notify(callbacks_, &notify);
 }
 
+/*
+ * Set jpeg metadata used to generate EXIF in the JPEG post processing.
+ */
+void CameraDevice::generateJpegExifMetadata(Camera3RequestDescriptor *request,
+					    StreamBuffer *buffer) const
+{
+	const ControlList &metadata = request->request_->metadata();
+	auto &jpegExifMetadata = buffer->jpegExifMetadata;
+	jpegExifMetadata.emplace(StreamBuffer::JpegExifMetadata());
+
+	const int64_t exposureTime = metadata.get(controls::ExposureTime).value_or(0);
+	jpegExifMetadata->sensorExposureTime = exposureTime;
+
+	/*
+	 * todo: Android Sensitivity should only include analog gain X digital
+	 * gain from sensor. Digital gain on ISP shouldn't be included.
+	 * Calculate sensitivity accordingly when we can differentiate
+	 * the source of digital gains.
+	 */
+	jpegExifMetadata->sensorSensitivityISO = 100;
+}
+
 /*
  * Produce a set of fixed result metadata.
  */
diff --git a/src/android/camera_device.h b/src/android/camera_device.h
index 815a695d1..3c46ff918 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -102,6 +102,8 @@ private:
 	void sendCaptureResult(Camera3RequestDescriptor *request) const;
 	void setBufferStatus(StreamBuffer &buffer,
 			     StreamBuffer::Status status);
+	void generateJpegExifMetadata(Camera3RequestDescriptor *request,
+				      StreamBuffer *buffer) const;
 	std::unique_ptr<CameraMetadata> getResultMetadata(
 		const Camera3RequestDescriptor &descriptor) const;
 
diff --git a/src/android/camera_request.h b/src/android/camera_request.h
index bd75d4595..bd87b36fd 100644
--- a/src/android/camera_request.h
+++ b/src/android/camera_request.h
@@ -44,6 +44,11 @@ public:
 	StreamBuffer(StreamBuffer &&);
 	StreamBuffer &operator=(StreamBuffer &&);
 
+	struct JpegExifMetadata {
+		int64_t sensorExposureTime;
+		int32_t sensorSensitivityISO;
+	};
+
 	CameraStream *stream;
 	buffer_handle_t *camera3Buffer;
 	std::unique_ptr<HALFrameBuffer> frameBuffer;
@@ -51,6 +56,7 @@ public:
 	Status status = Status::Success;
 	const libcamera::FrameBuffer *srcBuffer = nullptr;
 	std::unique_ptr<CameraBuffer> dstBuffer;
+	std::optional<JpegExifMetadata> jpegExifMetadata;
 	Camera3RequestDescriptor *request;
 
 private:
diff --git a/src/android/camera_stream.h b/src/android/camera_stream.h
index 30f64f690..47cd7ab85 100644
--- a/src/android/camera_stream.h
+++ b/src/android/camera_stream.h
@@ -125,6 +125,10 @@ public:
 	const libcamera::StreamConfiguration &configuration() const;
 	libcamera::Stream *stream() const;
 	CameraStream *sourceStream() const { return sourceStream_; }
+	bool isJpegStream() const
+	{
+		return camera3Stream_->format == HAL_PIXEL_FORMAT_BLOB;
+	}
 
 	int configure();
 	int process(StreamBuffer *streamBuffer);
diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
index f5a90785d..48782b574 100644
--- a/src/android/jpeg/post_processor_jpeg.cpp
+++ b/src/android/jpeg/post_processor_jpeg.cpp
@@ -112,8 +112,11 @@ void PostProcessorJpeg::process(StreamBuffer *streamBuffer)
 
 	const FrameBuffer &source = *streamBuffer->srcBuffer;
 	CameraBuffer *destination = streamBuffer->dstBuffer.get();
+	const std::optional<StreamBuffer::JpegExifMetadata> &jpegExifMetadata =
+		streamBuffer->jpegExifMetadata;
 
 	ASSERT(destination->numPlanes() == 1);
+	ASSERT(jpegExifMetadata.has_value());
 
 	const CameraMetadata &requestMetadata = streamBuffer->request->settings_;
 	CameraMetadata *resultMetadata = streamBuffer->request->resultMetadata_.get();
@@ -139,15 +142,14 @@ void PostProcessorJpeg::process(StreamBuffer *streamBuffer)
 	 */
 	exif.setTimestamp(std::time(nullptr), 0ms);
 
-	ret = resultMetadata->getEntry(ANDROID_SENSOR_EXPOSURE_TIME, &entry);
-	exif.setExposureTime(ret ? *entry.data.i64 : 0);
+	/* Exif requires nsec for exposure time */
+	exif.setExposureTime(jpegExifMetadata->sensorExposureTime * 1000);
+	exif.setISO(jpegExifMetadata->sensorSensitivityISO);
+
 	ret = requestMetadata.getEntry(ANDROID_LENS_APERTURE, &entry);
 	if (ret)
 		exif.setAperture(*entry.data.f);
 
-	ret = resultMetadata->getEntry(ANDROID_SENSOR_SENSITIVITY, &entry);
-	exif.setISO(ret ? *entry.data.i32 : 100);
-
 	exif.setFlash(Exif::Flash::FlashNotPresent);
 	exif.setWhiteBalance(Exif::WhiteBalance::Auto);
 
-- 
2.47.0.338.g60cca15819-goog



More information about the libcamera-devel mailing list