Message ID | 20210125071444.26252-7-paul.elder@ideasonboard.com |
---|---|
State | Superseded |
Delegated to: | Paul Elder |
Headers | show |
Series |
|
Related | show |
Hi Paul, On Mon, Jan 25, 2021 at 04:14:42PM +0900, Paul Elder wrote: > Configure the thumbnailer based on the thumbnail parameters given by the > android request metadata. Only the thumbnail encoder needs to be > configured, and since it is only used at post-processing time, move the > configuration out of the post-processor constructor and into the > processing step. > > Also set the following android result metadata tags: > - ANDROID_JPEG_THUMBNAIL_SIZE > - ANDROID_JPEG_THUMBNAIL_QUALITY > > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > --- > Changes in v4: > - cosmetic changes > > New in v3 > - split from "android: Set result metadata and EXIF fields based on > request" > --- > src/android/camera_device.cpp | 6 ++-- > src/android/jpeg/post_processor_jpeg.cpp | 43 +++++++++++++++++------- > src/android/jpeg/post_processor_jpeg.h | 1 + > src/android/jpeg/thumbnailer.cpp | 25 ++------------ > src/android/jpeg/thumbnailer.h | 6 ++-- > 5 files changed, 40 insertions(+), 41 deletions(-) > > diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp > index 2cd3c8a1..3068f89f 100644 > --- a/src/android/camera_device.cpp > +++ b/src/android/camera_device.cpp > @@ -1915,7 +1915,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: ANDROID_JPEG_SIZE (int32_t), ANDROID_JPEG_QUALITY (byte), > @@ -1923,11 +1923,13 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor, > * ANDROID_JPEG_GPS_PROCESSING_METHOD (byte x 32) = 32 bytes > * ANDROID_JPEG_GPS_TIMESTAMP (int64) = 8 bytes > * ANDROID_JPEG_ORIENTATION (int32_t) = 3 entries, 9 bytes. > + * ANDROID_JPEG_THUMBNAIL_QUALITY (byte) = 1 byte > + * ANDROID_JPEG_THUMBNAIL_SIZE (int32 x 2) = 8 bytes Same comment as the previous patch. The new tags should be added to availableResultKeys and the static metadata pack size updated accordingly. > * ANDROID_LENS_APERTURE (float) = 4 bytes > * ANDROID_LENS_FOCAL_LENGTH (float) = 4 bytes > */ > 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 10c71a47..d35fe361 100644 > --- a/src/android/jpeg/post_processor_jpeg.cpp > +++ b/src/android/jpeg/post_processor_jpeg.cpp > @@ -43,12 +43,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>(); > > @@ -56,14 +50,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. > @@ -127,6 +127,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); > @@ -142,11 +164,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_; > }; > -- > 2.27.0 > > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 2cd3c8a1..3068f89f 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -1915,7 +1915,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: ANDROID_JPEG_SIZE (int32_t), ANDROID_JPEG_QUALITY (byte), @@ -1923,11 +1923,13 @@ CameraDevice::getResultMetadata(Camera3RequestDescriptor *descriptor, * ANDROID_JPEG_GPS_PROCESSING_METHOD (byte x 32) = 32 bytes * ANDROID_JPEG_GPS_TIMESTAMP (int64) = 8 bytes * ANDROID_JPEG_ORIENTATION (int32_t) = 3 entries, 9 bytes. + * ANDROID_JPEG_THUMBNAIL_QUALITY (byte) = 1 byte + * ANDROID_JPEG_THUMBNAIL_SIZE (int32 x 2) = 8 bytes * ANDROID_LENS_APERTURE (float) = 4 bytes * ANDROID_LENS_FOCAL_LENGTH (float) = 4 bytes */ 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 10c71a47..d35fe361 100644 --- a/src/android/jpeg/post_processor_jpeg.cpp +++ b/src/android/jpeg/post_processor_jpeg.cpp @@ -43,12 +43,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>(); @@ -56,14 +50,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. @@ -127,6 +127,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); @@ -142,11 +164,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_; };