[libcamera-devel,v4,4/6] Move generateThumbnail from PostProcessorJpeg to Encoder
diff mbox series

Message ID 20220428095544.2795980-5-chenghaoyang@chromium.org
State Superseded
Headers show
Series
  • Add CrOS JEA implementation
Related show

Commit Message

Cheng-Hao Yang April 28, 2022, 9:55 a.m. UTC
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@chromium.org>
---
 src/android/jpeg/encoder.h               |  5 ++
 src/android/jpeg/encoder_libjpeg.cpp     | 70 +++++++++++++++++++++++-
 src/android/jpeg/encoder_libjpeg.h       | 18 +++++-
 src/android/jpeg/post_processor_jpeg.cpp | 54 +-----------------
 src/android/jpeg/post_processor_jpeg.h   | 11 +---
 5 files changed, 94 insertions(+), 64 deletions(-)

Patch
diff mbox series

diff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h
index b974d367..e76947d7 100644
--- a/src/android/jpeg/encoder.h
+++ b/src/android/jpeg/encoder.h
@@ -22,4 +22,9 @@  public:
 			   libcamera::Span<uint8_t> destination,
 			   libcamera::Span<const uint8_t> exifData,
 			   unsigned int quality) = 0;
+	virtual int 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 21a3b33d..d9a20b67 100644
--- a/src/android/jpeg/encoder_libjpeg.cpp
+++ b/src/android/jpeg/encoder_libjpeg.cpp
@@ -83,12 +83,23 @@  EncoderLibJpeg::~EncoderLibJpeg()
 
 int EncoderLibJpeg::configure(const StreamConfiguration &cfg)
 {
-	const struct JPEGPixelFormatInfo info = findPixelInfo(cfg.pixelFormat);
+	thumbnailer_.configure(cfg.size, cfg.pixelFormat);
+	pixelFormat_ = cfg.pixelFormat;
+	size_ = cfg.size;
+
+	return configureEncoder(pixelFormat_, size_);
+}
+
+int EncoderLibJpeg::configureEncoder(libcamera::PixelFormat pixelFormat,
+				     libcamera::Size size)
+{
+	const struct JPEGPixelFormatInfo info = findPixelInfo(pixelFormat);
+
 	if (info.colorSpace == JCS_UNKNOWN)
 		return -ENOTSUP;
 
-	compress_.image_width = cfg.size.width;
-	compress_.image_height = cfg.size.height;
+	compress_.image_width = size.width;
+	compress_.image_height = size.height;
 	compress_.in_color_space = info.colorSpace;
 
 	compress_.input_components = info.colorSpace == JCS_GRAYSCALE ? 1 : 3;
@@ -178,9 +189,62 @@  void EncoderLibJpeg::compressNV(const std::vector<Span<uint8_t>> &planes)
 	}
 }
 
+int EncoderLibJpeg::generateThumbnail(
+		      const libcamera::FrameBuffer &source,
+		      const libcamera::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);
+
+	int ret = configureEncoder(thumbnailer_.pixelFormat(), targetSize);
+
+	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 = encode(thumbnailPlanes, *thumbnail, {},
+				       quality);
+		thumbnail->resize(jpeg_size);
+
+		LOG(JPEG, Debug)
+			<< "Thumbnail compress returned "
+			<< jpeg_size << " bytes";
+
+		return jpeg_size;
+	}
+
+	return -1;
+}
+
 int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
 			   Span<const uint8_t> exifData, unsigned int quality)
 {
+	configureEncoder(pixelFormat_, size_);
+
 	MappedFrameBuffer frame(&source, MappedFrameBuffer::MapFlag::Read);
 	if (!frame.isValid()) {
 		LOG(JPEG, Error) << "Failed to map FrameBuffer : "
diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
index 1b3ac067..7b6131a4 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,15 +28,27 @@  public:
 		   libcamera::Span<uint8_t> destination,
 		   libcamera::Span<const uint8_t> exifData,
 		   unsigned int quality) override;
+	int generateThumbnail(
+			const libcamera::FrameBuffer &source,
+			const libcamera::Size &targetSize,
+			unsigned int quality,
+			std::vector<unsigned char> *thumbnail) override;
+
+private:
+	int configureEncoder(libcamera::PixelFormat pixelFormat,
+			     libcamera::Size size);
+
 	int encode(const std::vector<libcamera::Span<uint8_t>> &planes,
 		   libcamera::Span<uint8_t> destination,
 		   libcamera::Span<const uint8_t> exifData,
 		   unsigned int quality);
 
-private:
 	void compressRGB(const std::vector<libcamera::Span<uint8_t>> &planes);
 	void compressNV(const std::vector<libcamera::Span<uint8_t>> &planes);
 
+	libcamera::PixelFormat pixelFormat_;
+	libcamera::Size size_;
+
 	struct jpeg_compress_struct compress_;
 	struct jpeg_error_mgr jerr_;
 
@@ -42,4 +56,6 @@  private:
 
 	bool nv_;
 	bool nvSwap_;
+
+	Thumbnailer thumbnailer_;
 };
diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
index d72ebc3c..332ce1ca 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,8 +115,9 @@  void PostProcessorJpeg::process(Camera3RequestDescriptor::StreamBuffer *streamBu
 
 		if (thumbnailSize != Size(0, 0)) {
 			std::vector<unsigned char> thumbnail;
-			generateThumbnail(source, thumbnailSize, quality, &thumbnail);
-			if (!thumbnail.empty())
+			ret = encoder_->generateThumbnail(source,
+					thumbnailSize, quality, &thumbnail);
+			if (ret > 0 && !thumbnail.empty())
 				exif.setThumbnail(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"
+
 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_;
 };