[PATCH v2 8/9] android: Add JpegExifMetadata to store tags setting into Exif
Jacopo Mondi
jacopo.mondi at ideasonboard.com
Thu Nov 28 16:35:26 CET 2024
Hi Harvey
On Wed, Nov 27, 2024 at 09:25:58AM +0000, Harvey Yang wrote:
> 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);
> + }
> +
no {} for single line statements
> 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_, ¬ify);
> }
>
> +/*
> + * 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
\todo
> + * gain from sensor. Digital gain on ISP shouldn't be included.
mmm, I guess how the gain is split between analogue and digital on the
sensor is up to the IPA implementation, and currently I only see vc4
handling it and it sets it on the ISP.
I wonder if you couldn't simply use AnalogueGain here
> + * 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());
This means it's not optional, isn't it ?
>
> 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);
> +
StreamBuffer has a pointer to the Camera3RequestDescriptor it belongs
to. From there you could get the Request metadata as you currently do
in CameraDevice::generateJpegExifMetadata().
What is the advantage of caching the jpegExifMetadata at
CameraDevice::requestComplete() time ?
Thanks
j
> 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