[libcamera-devel,v8,5/7] Move generateThumbnail from PostProcessorJpeg to Encoder
diff mbox series

Message ID 20221214093330.3345421-6-chenghaoyang@google.com
State New
Headers show
Series
  • Add CrOS JEA implementation
Related show

Commit Message

Harvey Yang Dec. 14, 2022, 9:33 a.m. UTC
From: Harvey Yang <chenghaoyang@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@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(-)

Comments

Laurent Pinchart Jan. 15, 2023, 11:34 p.m. UTC | #1
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@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@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@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_;
>  };

Patch
diff mbox series

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);
+		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"
+
 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_;
 };