android: Set result metadata and EXIF fields based on request metadata

Set the following android result metadata:
- ANDROID_LENS_FOCAL_LENGTH
- ANDROID_LENS_APERTURE
- ANDROID_JPEG_GPS_TIMESTAMP
- ANDROID_JPEG_GPS_COORDINATES
- ANDROID_JPEG_GPS_PROCESSING_METHOD

And the following EXIF fields:
- GPSDatestamp
- GPSTimestamp
- GPSLocation
  - GPSLatitudeRef
  - GPSLatitude
  - GPSLongitudeRef
  - GPSLongitude
  - GPSAltitudeRef
  - GPSAltitude
- GPSProcessingMethod
- FocalLength
- ExposureTime
- FNumber
- ISO
- Flash
- WhiteBalance
- SubsecTime
- SubsecTimeOriginal
- SubsecTimeDigitized

Based on android request metadata.

This allows the following CTS tests to pass:
- android.hardware.camera2.cts.StillCaptureTest#testFocalLengths
- android.hardware.camera2.cts.StillCaptureTest#testJpegExif

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Paul Elder 2021-01-23 13:54:28 +09:00
parent 229653a59b
commit abfabdd6e7
6 changed files with 89 additions and 21 deletions

View file

@ -83,17 +83,26 @@ void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
int PostProcessorJpeg::process(const FrameBuffer &source,
Span<uint8_t> destination,
CameraMetadata *metadata)
const CameraMetadata &requestMetadata,
CameraMetadata *resultMetadata)
{
if (!encoder_)
return 0;
camera_metadata_ro_entry_t entry;
int ret;
/* Set EXIF metadata for various tags. */
Exif exif;
/* \todo Set Make and Model from external vendor tags. */
exif.setMake("libcamera");
exif.setModel("cameraModel");
exif.setOrientation(cameraDevice_->orientation());
exif.setMake(cameraDevice_->maker());
exif.setModel(cameraDevice_->model());
ret = requestMetadata.getEntry(ANDROID_JPEG_ORIENTATION, &entry);
const uint32_t jpegOrientation = ret ? *entry.data.i32 : 0;
resultMetadata->addEntry(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
exif.setOrientation(jpegOrientation);
exif.setSize(streamSize_);
/*
* We set the frame's EXIF timestamp as the time of encode.
@ -102,6 +111,39 @@ int PostProcessorJpeg::process(const FrameBuffer &source,
*/
exif.setTimestamp(std::time(nullptr), 0ms);
/* \todo Get this information from libcamera::Request::metadata */
exif.setExposureTime(0);
ret = requestMetadata.getEntry(ANDROID_LENS_APERTURE, &entry);
if (ret)
exif.setAperture(*entry.data.f);
exif.setISO(100);
exif.setFlash(Exif::Flash::FlashNotPresent);
exif.setWhiteBalance(Exif::WhiteBalance::Auto);
exif.setFocalLength(1.0);
ret = requestMetadata.getEntry(ANDROID_JPEG_GPS_TIMESTAMP, &entry);
if (ret) {
exif.setGPSDateTimestamp(*entry.data.i64);
resultMetadata->addEntry(ANDROID_JPEG_GPS_TIMESTAMP,
entry.data.i64, 1);
}
ret = requestMetadata.getEntry(ANDROID_JPEG_GPS_COORDINATES, &entry);
if (ret) {
exif.setGPSLocation(entry.data.d);
resultMetadata->addEntry(ANDROID_JPEG_GPS_COORDINATES,
entry.data.d, 3);
}
ret = requestMetadata.getEntry(ANDROID_JPEG_GPS_PROCESSING_METHOD, &entry);
if (ret) {
std::string method(entry.data.u8, entry.data.u8 + entry.count);
exif.setGPSMethod(method);
resultMetadata->addEntry(ANDROID_JPEG_GPS_PROCESSING_METHOD,
entry.data.u8, entry.count);
}
std::vector<unsigned char> thumbnail;
generateThumbnail(source, &thumbnail);
if (!thumbnail.empty())
@ -136,13 +178,12 @@ int PostProcessorJpeg::process(const FrameBuffer &source,
blob->jpeg_size = jpeg_size;
/* Update the JPEG result Metadata. */
metadata->addEntry(ANDROID_JPEG_SIZE, &jpeg_size, 1);
resultMetadata->addEntry(ANDROID_JPEG_SIZE, &jpeg_size, 1);
const uint32_t jpeg_quality = 95;
metadata->addEntry(ANDROID_JPEG_QUALITY, &jpeg_quality, 1);
const uint32_t jpeg_orientation = 0;
metadata->addEntry(ANDROID_JPEG_ORIENTATION, &jpeg_orientation, 1);
/* \todo Configure JPEG encoder with this */
ret = requestMetadata.getEntry(ANDROID_JPEG_QUALITY, &entry);
const uint8_t jpegQuality = ret ? *entry.data.u8 : 95;
resultMetadata->addEntry(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
return 0;
}