summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/camera_device.cpp12
-rw-r--r--src/android/jpeg/post_processor_jpeg.cpp43
-rw-r--r--src/android/jpeg/post_processor_jpeg.h1
-rw-r--r--src/android/jpeg/thumbnailer.cpp25
-rw-r--r--src/android/jpeg/thumbnailer.h6
5 files changed, 44 insertions, 43 deletions
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp
index 89c5f2b8..8ea74233 100644
--- a/src/android/camera_device.cpp
+++ b/src/android/camera_device.cpp
@@ -708,7 +708,7 @@ std::tuple<uint32_t, uint32_t> CameraDevice::calculateStaticMetadataSize()
* Currently: 53 entries, 782 bytes of static metadata
*/
uint32_t numEntries = 53;
- uint32_t byteSize = 802;
+ uint32_t byteSize = 810;
/*
* Calculate space occupation in bytes for dynamically built metadata
@@ -1272,6 +1272,8 @@ const camera_metadata_t *CameraDevice::getStaticMetadata()
ANDROID_JPEG_SIZE,
ANDROID_JPEG_QUALITY,
ANDROID_JPEG_ORIENTATION,
+ ANDROID_JPEG_THUMBNAIL_QUALITY,
+ ANDROID_JPEG_THUMBNAIL_SIZE,
};
staticMetadata_->addEntry(ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
availableResultKeys.data(),
@@ -1918,7 +1920,7 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
/*
* \todo Keep this in sync with the actual number of entries.
- * Currently: 38 entries, 147 bytes
+ * Currently: 40 entries, 156 bytes
*
* Reserve more space for the JPEG metadata set by the post-processor.
* Currently:
@@ -1928,10 +1930,12 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor,
* ANDROID_JPEG_SIZE (int32_t) = 4 bytes
* ANDROID_JPEG_QUALITY (byte) = 1 byte
* ANDROID_JPEG_ORIENTATION (int32_t) = 4 bytes
- * Total bytes for JPEG metadata: 73
+ * ANDROID_JPEG_THUMBNAIL_QUALITY (byte) = 1 byte
+ * ANDROID_JPEG_THUMBNAIL_SIZE (int32 x 2) = 8 bytes
+ * Total bytes for JPEG metadata: 82
*/
std::unique_ptr<CameraMetadata> resultMetadata =
- std::make_unique<CameraMetadata>(38, 147);
+ std::make_unique<CameraMetadata>(40, 156);
if (!resultMetadata->isValid()) {
LOG(HAL, Error) << "Failed to allocate static metadata";
return nullptr;
diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
index 7e49e9d9..e990ba04 100644
--- a/src/android/jpeg/post_processor_jpeg.cpp
+++ b/src/android/jpeg/post_processor_jpeg.cpp
@@ -44,12 +44,6 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,
streamSize_ = outCfg.size;
thumbnailer_.configure(inCfg.size, inCfg.pixelFormat);
- StreamConfiguration thCfg = inCfg;
- thCfg.size = thumbnailer_.size();
- if (thumbnailEncoder_.configure(thCfg) != 0) {
- LOG(JPEG, Error) << "Failed to configure thumbnail encoder";
- return -EINVAL;
- }
encoder_ = std::make_unique<EncoderLibJpeg>();
@@ -57,14 +51,20 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,
}
void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
+ const Size &targetSize,
std::vector<unsigned char> *thumbnail)
{
/* Stores the raw scaled-down thumbnail bytes. */
std::vector<unsigned char> rawThumbnail;
- thumbnailer_.createThumbnail(source, &rawThumbnail);
+ thumbnailer_.createThumbnail(source, targetSize, &rawThumbnail);
- if (!rawThumbnail.empty()) {
+ StreamConfiguration thCfg;
+ thCfg.size = targetSize;
+ thCfg.pixelFormat = thumbnailer_.pixelFormat();
+ int ret = thumbnailEncoder_.configure(thCfg);
+
+ if (!rawThumbnail.empty() && !ret) {
/*
* \todo Avoid value-initialization of all elements of the
* vector.
@@ -129,6 +129,28 @@ int PostProcessorJpeg::process(const FrameBuffer &source,
entry.data.i64, 1);
}
+ ret = requestMetadata.getEntry(ANDROID_JPEG_THUMBNAIL_SIZE, &entry);
+ if (ret) {
+ const int32_t *data = entry.data.i32;
+ Size thumbnailSize = { static_cast<uint32_t>(data[0]),
+ static_cast<uint32_t>(data[1]) };
+
+ if (thumbnailSize != Size(0, 0)) {
+ std::vector<unsigned char> thumbnail;
+ generateThumbnail(source, thumbnailSize, &thumbnail);
+ if (!thumbnail.empty())
+ exif.setThumbnail(thumbnail, Exif::Compression::JPEG);
+ }
+
+ resultMetadata->addEntry(ANDROID_JPEG_THUMBNAIL_SIZE, data, 2);
+
+ /* \todo Use this quality as a parameter to the encoder */
+ ret = requestMetadata.getEntry(ANDROID_JPEG_THUMBNAIL_QUALITY, &entry);
+ if (ret)
+ resultMetadata->addEntry(ANDROID_JPEG_THUMBNAIL_QUALITY,
+ entry.data.u8, 1);
+ }
+
ret = requestMetadata.getEntry(ANDROID_JPEG_GPS_COORDINATES, &entry);
if (ret) {
exif.setGPSLocation(entry.data.d);
@@ -144,11 +166,6 @@ int PostProcessorJpeg::process(const FrameBuffer &source,
entry.data.u8, entry.count);
}
- std::vector<unsigned char> thumbnail;
- generateThumbnail(source, &thumbnail);
- if (!thumbnail.empty())
- exif.setThumbnail(thumbnail, Exif::Compression::JPEG);
-
if (exif.generate() != 0)
LOG(JPEG, Error) << "Failed to generate valid EXIF data";
diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h
index d721d1b9..660b79b4 100644
--- a/src/android/jpeg/post_processor_jpeg.h
+++ b/src/android/jpeg/post_processor_jpeg.h
@@ -31,6 +31,7 @@ public:
private:
void generateThumbnail(const libcamera::FrameBuffer &source,
+ const libcamera::Size &targetSize,
std::vector<unsigned char> *thumbnail);
CameraDevice *const cameraDevice_;
diff --git a/src/android/jpeg/thumbnailer.cpp b/src/android/jpeg/thumbnailer.cpp
index 5374538a..f709d343 100644
--- a/src/android/jpeg/thumbnailer.cpp
+++ b/src/android/jpeg/thumbnailer.cpp
@@ -32,30 +32,11 @@ void Thumbnailer::configure(const Size &sourceSize, PixelFormat pixelFormat)
return;
}
- targetSize_ = computeThumbnailSize();
-
valid_ = true;
}
-/*
- * The Exif specification recommends the width of the thumbnail to be a
- * multiple of 16 (section 4.8.1). Hence, compute the corresponding height
- * keeping the aspect ratio same as of the source.
- */
-Size Thumbnailer::computeThumbnailSize() const
-{
- unsigned int targetHeight;
- constexpr unsigned int kTargetWidth = 160;
-
- targetHeight = kTargetWidth * sourceSize_.height / sourceSize_.width;
-
- if (targetHeight & 1)
- targetHeight++;
-
- return Size(kTargetWidth, targetHeight);
-}
-
void Thumbnailer::createThumbnail(const FrameBuffer &source,
+ const Size &targetSize,
std::vector<unsigned char> *destination)
{
MappedFrameBuffer frame(&source, PROT_READ);
@@ -73,8 +54,8 @@ void Thumbnailer::createThumbnail(const FrameBuffer &source,
const unsigned int sw = sourceSize_.width;
const unsigned int sh = sourceSize_.height;
- const unsigned int tw = targetSize_.width;
- const unsigned int th = targetSize_.height;
+ const unsigned int tw = targetSize.width;
+ const unsigned int th = targetSize.height;
ASSERT(tw % 2 == 0 && th % 2 == 0);
diff --git a/src/android/jpeg/thumbnailer.h b/src/android/jpeg/thumbnailer.h
index 98f11833..4e9226c3 100644
--- a/src/android/jpeg/thumbnailer.h
+++ b/src/android/jpeg/thumbnailer.h
@@ -20,15 +20,13 @@ public:
void configure(const libcamera::Size &sourceSize,
libcamera::PixelFormat pixelFormat);
void createThumbnail(const libcamera::FrameBuffer &source,
+ const libcamera::Size &targetSize,
std::vector<unsigned char> *dest);
- const libcamera::Size &size() const { return targetSize_; }
+ const libcamera::PixelFormat &pixelFormat() const { return pixelFormat_; }
private:
- libcamera::Size computeThumbnailSize() const;
-
libcamera::PixelFormat pixelFormat_;
libcamera::Size sourceSize_;
- libcamera::Size targetSize_;
bool valid_;
};