[libcamera-devel] [PATCH v8 5/7] Move generateThumbnail from PostProcessorJpeg to Encoder
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Mon Jan 16 00:34:11 CET 2023
Hi Harvey,
Thank you for the patch.
On Wed, Dec 14, 2022 at 09:33:28AM +0000, Harvey Yang via libcamera-devel wrote:
> From: Harvey Yang <chenghaoyang at chromium.org>
>
> In the following patch, generateThumbnail will have a different
> implementation in the jea encoder. Therefore, this patch moves the
> generateThumbnail function from PostProcessorJpeg to Encoder.
>
> Signed-off-by: Harvey Yang <chenghaoyang at chromium.org>
> ---
> src/android/jpeg/encoder.h | 4 ++
> src/android/jpeg/encoder_libjpeg.cpp | 54 +++++++++++++++++++++---
> src/android/jpeg/encoder_libjpeg.h | 15 ++++---
> src/android/jpeg/post_processor_jpeg.cpp | 52 +----------------------
> src/android/jpeg/post_processor_jpeg.h | 11 +----
> 5 files changed, 66 insertions(+), 70 deletions(-)
>
> diff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h
> index b974d367..5f9ef890 100644
> --- a/src/android/jpeg/encoder.h
> +++ b/src/android/jpeg/encoder.h
> @@ -22,4 +22,8 @@ public:
> libcamera::Span<uint8_t> destination,
> libcamera::Span<const uint8_t> exifData,
> unsigned int quality) = 0;
> + virtual void generateThumbnail(const libcamera::FrameBuffer &source,
> + const libcamera::Size &targetSize,
> + unsigned int quality,
> + std::vector<unsigned char> *thumbnail) = 0;
> };
> diff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp
> index d849547f..cc5f37be 100644
> --- a/src/android/jpeg/encoder_libjpeg.cpp
> +++ b/src/android/jpeg/encoder_libjpeg.cpp
> @@ -74,7 +74,7 @@ EncoderLibJpeg::~EncoderLibJpeg() = default;
>
> int EncoderLibJpeg::configure(const StreamConfiguration &cfg)
> {
> - return encoder_.configure(cfg);
> + return captureEncoder_.configure(cfg);
> }
>
> EncoderLibJpeg::Encoder::Encoder()
> @@ -197,14 +197,56 @@ int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
> return frame.error();
> }
>
> - return encoder_.encode(frame.planes(), dest, exifData, quality);
> + return captureEncoder_.encode(frame.planes(), dest, exifData, quality);
> }
>
> -int EncoderLibJpeg::encode(const std::vector<Span<uint8_t>> &src,
> - Span<uint8_t> dest, Span<const uint8_t> exifData,
> - unsigned int quality)
> +void EncoderLibJpeg::generateThumbnail(const libcamera::FrameBuffer &source,
> + const libcamera::Size &targetSize,
> + unsigned int quality,
> + std::vector<unsigned char> *thumbnail)
> {
> - return encoder_.encode(src, std::move(dest), std::move(exifData), quality);
> + /* Stores the raw scaled-down thumbnail bytes. */
> + std::vector<unsigned char> rawThumbnail;
> +
> + thumbnailer_.createThumbnail(source, targetSize, &rawThumbnail);
> +
> + 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.
> + */
> + thumbnail->resize(rawThumbnail.size());
> +
> + /*
> + * Split planes manually as the encoder expects a vector of
> + * planes.
> + *
> + * \todo Pass a vector of planes directly to
> + * Thumbnailer::createThumbnailer above and remove the manual
> + * planes split from here.
> + */
> + std::vector<Span<uint8_t>> thumbnailPlanes;
> + const PixelFormatInfo &formatNV12 =
> + PixelFormatInfo::info(formats::NV12);
> + size_t yPlaneSize = formatNV12.planeSize(targetSize, 0);
> + size_t uvPlaneSize = formatNV12.planeSize(targetSize, 1);
> + thumbnailPlanes.push_back({ rawThumbnail.data(), yPlaneSize });
> + thumbnailPlanes.push_back({ rawThumbnail.data() + yPlaneSize,
> + uvPlaneSize });
> +
> + int jpegSize = thumbnailEncoder_.encode(thumbnailPlanes, *thumbnail, {},
> + quality);
Nitpicking,
int jpegSize = thumbnailEncoder_.encode(thumbnailPlanes, *thumbnail,
{}, quality);
> + thumbnail->resize(jpegSize);
> +
> + LOG(JPEG, Debug)
> + << "Thumbnail compress returned "
> + << jpegSize << " bytes";
> + }
> }
>
> int EncoderLibJpeg::Encoder::encode(const std::vector<Span<uint8_t>> &src,
> diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
> index 97182b96..fa077b8d 100644
> --- a/src/android/jpeg/encoder_libjpeg.h
> +++ b/src/android/jpeg/encoder_libjpeg.h
> @@ -15,6 +15,8 @@
>
> #include <jpeglib.h>
>
> +#include "thumbnailer.h"
> +
> class EncoderLibJpeg : public Encoder
> {
> public:
> @@ -26,10 +28,10 @@ public:
> libcamera::Span<uint8_t> destination,
> libcamera::Span<const uint8_t> exifData,
> unsigned int quality) override;
> - int encode(const std::vector<libcamera::Span<uint8_t>> &planes,
> - libcamera::Span<uint8_t> destination,
> - libcamera::Span<const uint8_t> exifData,
> - unsigned int quality);
> + void generateThumbnail(const libcamera::FrameBuffer &source,
> + const libcamera::Size &targetSize,
> + unsigned int quality,
> + std::vector<unsigned char> *thumbnail) override;
>
> private:
> class Encoder
> @@ -57,5 +59,8 @@ private:
> bool nvSwap_;
> };
>
> - Encoder encoder_;
> + Encoder captureEncoder_;
> + Encoder thumbnailEncoder_;
> +
> + Thumbnailer thumbnailer_;
> };
> diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
> index 0cf56716..69b18a2e 100644
> --- a/src/android/jpeg/post_processor_jpeg.cpp
> +++ b/src/android/jpeg/post_processor_jpeg.cpp
> @@ -44,60 +44,11 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,
>
> streamSize_ = outCfg.size;
>
> - thumbnailer_.configure(inCfg.size, inCfg.pixelFormat);
> -
> encoder_ = std::make_unique<EncoderLibJpeg>();
>
> return encoder_->configure(inCfg);
> }
>
> -void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
> - const Size &targetSize,
> - unsigned int quality,
> - std::vector<unsigned char> *thumbnail)
> -{
> - /* Stores the raw scaled-down thumbnail bytes. */
> - std::vector<unsigned char> rawThumbnail;
> -
> - thumbnailer_.createThumbnail(source, targetSize, &rawThumbnail);
> -
> - 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.
> - */
> - thumbnail->resize(rawThumbnail.size());
> -
> - /*
> - * Split planes manually as the encoder expects a vector of
> - * planes.
> - *
> - * \todo Pass a vector of planes directly to
> - * Thumbnailer::createThumbnailer above and remove the manual
> - * planes split from here.
> - */
> - std::vector<Span<uint8_t>> thumbnailPlanes;
> - const PixelFormatInfo &formatNV12 = PixelFormatInfo::info(formats::NV12);
> - size_t yPlaneSize = formatNV12.planeSize(targetSize, 0);
> - size_t uvPlaneSize = formatNV12.planeSize(targetSize, 1);
> - thumbnailPlanes.push_back({ rawThumbnail.data(), yPlaneSize });
> - thumbnailPlanes.push_back({ rawThumbnail.data() + yPlaneSize, uvPlaneSize });
> -
> - int jpeg_size = thumbnailEncoder_.encode(thumbnailPlanes,
> - *thumbnail, {}, quality);
> - thumbnail->resize(jpeg_size);
> -
> - LOG(JPEG, Debug)
> - << "Thumbnail compress returned "
> - << jpeg_size << " bytes";
> - }
> -}
> -
> void PostProcessorJpeg::process(Camera3RequestDescriptor::StreamBuffer *streamBuffer)
> {
> ASSERT(encoder_);
> @@ -164,7 +115,8 @@ void PostProcessorJpeg::process(Camera3RequestDescriptor::StreamBuffer *streamBu
>
> if (thumbnailSize != Size(0, 0)) {
> std::vector<unsigned char> thumbnail;
> - generateThumbnail(source, thumbnailSize, quality, &thumbnail);
> + encoder_->generateThumbnail(source, thumbnailSize,
> + quality, &thumbnail);
> if (!thumbnail.empty())
> exif.setThumbnail(std::move(thumbnail), Exif::Compression::JPEG);
> }
> diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h
> index 98309b01..55b23d7d 100644
> --- a/src/android/jpeg/post_processor_jpeg.h
> +++ b/src/android/jpeg/post_processor_jpeg.h
> @@ -8,11 +8,11 @@
> #pragma once
>
> #include "../post_processor.h"
> -#include "encoder_libjpeg.h"
> -#include "thumbnailer.h"
>
> #include <libcamera/geometry.h>
>
> +#include "encoder.h"
> +
This can be replaced by a forward declaration.
No need to resubmit for just this, I can also handle it when applying,
adding my
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> class CameraDevice;
>
> class PostProcessorJpeg : public PostProcessor
> @@ -25,14 +25,7 @@ public:
> void process(Camera3RequestDescriptor::StreamBuffer *streamBuffer) override;
>
> private:
> - void generateThumbnail(const libcamera::FrameBuffer &source,
> - const libcamera::Size &targetSize,
> - unsigned int quality,
> - std::vector<unsigned char> *thumbnail);
> -
> CameraDevice *const cameraDevice_;
> std::unique_ptr<Encoder> encoder_;
> libcamera::Size streamSize_;
> - EncoderLibJpeg thumbnailEncoder_;
> - Thumbnailer thumbnailer_;
> };
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list