[libcamera-devel,v2,5/7] android: Add JpegExifMetadata to store tags setting into Exif
diff mbox series

Message ID 20220812090838.1784703-6-hanlinchen@chromium.org
State New
Headers show
Series
  • Implement Android Partial Result Featrue
Related show

Commit Message

Hanlin Chen Aug. 12, 2022, 9:08 a.m. UTC
With partial result, some metadata needed to adding 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 for the them.

Signed-off-by: Han-Lin Chen <hanlinchen@chromium.org>
---
 src/android/camera_device.cpp            | 27 ++++++++++++++++++++++++
 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 | 13 ++++++------
 5 files changed, 46 insertions(+), 6 deletions(-)

Patch
diff mbox series

diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 0248f146..a14d5de9 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -1221,6 +1221,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";
@@ -1410,6 +1414,29 @@  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());
+
+	jpegExifMetadata->sensorExposureTime = 0;
+	if (metadata.contains(controls::ExposureTime)) {
+		jpegExifMetadata->sensorExposureTime = metadata.get(controls::ExposureTime) * 1000ULL;
+	}
+
+	/*
+	 * todo: Android Sensitivity = analog gain X digital gain only on sensor.
+	 * Digital gain on ISP shouldn't be included. Calculate sensitivity
+	 * accordingingly 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 9eb7221b..7b279895 100644
--- a/src/android/camera_device.h
+++ b/src/android/camera_device.h
@@ -97,6 +97,8 @@  private:
 		LIBCAMERA_TSA_EXCLUDES(descriptorsMutex_);
 	void sendCaptureResults() LIBCAMERA_TSA_REQUIRES(descriptorsMutex_);
 	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 5aa4eea8..f91de955 100644
--- a/src/android/camera_request.h
+++ b/src/android/camera_request.h
@@ -42,6 +42,11 @@  public:
 	StreamBuffer(StreamBuffer &&);
 	StreamBuffer &operator=(StreamBuffer &&);
 
+	struct JpegExifMetadata {
+		int64_t sensorExposureTime;
+		int32_t sensorSensitivityISO;
+	};
+
 	CameraStream *stream;
 	buffer_handle_t *camera3Buffer;
 	std::unique_ptr<libcamera::FrameBuffer> frameBuffer;
@@ -50,6 +55,7 @@  public:
 	libcamera::FrameBuffer *internalBuffer = nullptr;
 	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 c3b2e325..fc50d412 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 b9ba38ce..7e3713f5 100644
--- a/src/android/jpeg/post_processor_jpeg.cpp
+++ b/src/android/jpeg/post_processor_jpeg.cpp
@@ -104,8 +104,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();
@@ -131,15 +134,13 @@  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.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);
 
@@ -152,6 +153,7 @@  void PostProcessorJpeg::process(StreamBuffer *streamBuffer)
 					 *entry.data.i64);
 	}
 
+	std::vector<unsigned char> thumbnail;
 	ret = requestMetadata.getEntry(ANDROID_JPEG_THUMBNAIL_SIZE, &entry);
 	if (ret) {
 		const int32_t *data = entry.data.i32;
@@ -163,7 +165,6 @@  void PostProcessorJpeg::process(StreamBuffer *streamBuffer)
 		resultMetadata->addEntry(ANDROID_JPEG_THUMBNAIL_QUALITY, quality);
 
 		if (thumbnailSize != Size(0, 0)) {
-			std::vector<unsigned char> thumbnail;
 			generateThumbnail(source, thumbnailSize, quality, &thumbnail);
 			if (!thumbnail.empty())
 				exif.setThumbnail(thumbnail, Exif::Compression::JPEG);