[libcamera-devel] [PATCH v9 6/8] android: jpeg: Return an error code from generateThumbnail()

Laurent Pinchart laurent.pinchart at ideasonboard.com
Mon Jan 16 01:28:06 CET 2023


The usual way to signal errors in libcamera is to return an error code.
Change the Encoder::generateThumbnail() function to return an int
instead of signaling errors by not resizing the thumbnail vector. This
allows propagating error codes to the callers.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 src/android/jpeg/encoder.h               |  8 +--
 src/android/jpeg/encoder_libjpeg.cpp     | 70 +++++++++++++-----------
 src/android/jpeg/encoder_libjpeg.h       |  8 +--
 src/android/jpeg/post_processor_jpeg.cpp |  6 +-
 4 files changed, 48 insertions(+), 44 deletions(-)

diff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h
index 5f9ef890023a..d15f22e67830 100644
--- a/src/android/jpeg/encoder.h
+++ b/src/android/jpeg/encoder.h
@@ -22,8 +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;
+	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 9bbf1abbe09c..8f4df7899dfd 100644
--- a/src/android/jpeg/encoder_libjpeg.cpp
+++ b/src/android/jpeg/encoder_libjpeg.cpp
@@ -89,53 +89,57 @@ int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
 	return captureEncoder_.encode(frame.planes(), dest, exifData, quality);
 }
 
-void EncoderLibJpeg::generateThumbnail(const libcamera::FrameBuffer &source,
-				       const libcamera::Size &targetSize,
-				       unsigned int quality,
-				       std::vector<unsigned char> *thumbnail)
+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);
+	if (rawThumbnail.empty())
+		return -EINVAL;
 
 	StreamConfiguration thCfg;
 	thCfg.size = targetSize;
 	thCfg.pixelFormat = thumbnailer_.pixelFormat();
 	int ret = thumbnailEncoder_.configure(thCfg);
+	if (ret)
+		return ret;
 
-	if (!rawThumbnail.empty() && !ret) {
-		/*
-		 * \todo Avoid value-initialization of all elements of the
-		 * vector.
-		 */
-		thumbnail->resize(rawThumbnail.size());
+	/*
+	 * \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 });
+	/*
+	 * 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);
+	int jpegSize = thumbnailEncoder_.encode(thumbnailPlanes, *thumbnail,
+						{}, quality);
+	thumbnail->resize(jpegSize);
 
-		LOG(JPEG, Debug)
-			<< "Thumbnail compress returned "
-			<< jpegSize << " bytes";
-	}
+	LOG(JPEG, Debug)
+		<< "Thumbnail compress returned "
+		<< jpegSize << " bytes";
+
+	return 0;
 }
 
 EncoderLibJpeg::Encoder::Encoder()
diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
index a022a72e02bf..9cff4f1b42e3 100644
--- a/src/android/jpeg/encoder_libjpeg.h
+++ b/src/android/jpeg/encoder_libjpeg.h
@@ -28,10 +28,10 @@ public:
 		   libcamera::Span<uint8_t> destination,
 		   libcamera::Span<const uint8_t> exifData,
 		   unsigned int quality) override;
-	void generateThumbnail(const libcamera::FrameBuffer &source,
-			       const libcamera::Size &targetSize,
-			       unsigned int quality,
-			       std::vector<unsigned char> *thumbnail) override;
+	int generateThumbnail(const libcamera::FrameBuffer &source,
+			      const libcamera::Size &targetSize,
+			      unsigned int quality,
+			      std::vector<unsigned char> *thumbnail) override;
 
 private:
 	class Encoder
diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
index 69b18a2e5945..5df89383e1af 100644
--- a/src/android/jpeg/post_processor_jpeg.cpp
+++ b/src/android/jpeg/post_processor_jpeg.cpp
@@ -115,9 +115,9 @@ void PostProcessorJpeg::process(Camera3RequestDescriptor::StreamBuffer *streamBu
 
 		if (thumbnailSize != Size(0, 0)) {
 			std::vector<unsigned char> thumbnail;
-			encoder_->generateThumbnail(source, thumbnailSize,
-						    quality, &thumbnail);
-			if (!thumbnail.empty())
+			ret = encoder_->generateThumbnail(source, thumbnailSize,
+							  quality, &thumbnail);
+			if (!ret)
 				exif.setThumbnail(std::move(thumbnail), Exif::Compression::JPEG);
 		}
 
-- 
Regards,

Laurent Pinchart



More information about the libcamera-devel mailing list