[libcamera-devel,08/12] android: post_processor: Use CameraBuffer API
diff mbox series

Message ID 20210226132932.165484-9-jacopo@jmondi.org
State Superseded
Headers show
Series
  • android: Support memory backends
Related show

Commit Message

Jacopo Mondi Feb. 26, 2021, 1:29 p.m. UTC
Use the newly introduced CameraBuffer class as the type for the
destination buffer in the PostProcessor class hierarchy in place of the
libcamera::MappedFrameBuffer one and use its API to retrieve the length
and the location of the CameraBuffer plane allocated for JPEG
post-processing.

Remove all the assumption on the underlying memory storage and only go
through the CameraBuffer API when dealing with memory buffers. To do so
rework the Encoder interface to use a raw pointer and an explicit size
to remove access to the Span<uint8_t> maps that serve as memory storage
for the current implementation but might not be ideal for other memory
backend.

Now that the whole PostProcessor hierarchy has been converted to use
the CameraBuffer API remove libcamera::MappedBuffer as base class
of the CameraBuffer interface and only reply on its interface.

Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
---
 src/android/camera_buffer.h              |  2 +-
 src/android/jpeg/encoder.h               |  4 +++-
 src/android/jpeg/encoder_libjpeg.cpp     | 19 ++++++++--------
 src/android/jpeg/encoder_libjpeg.h       |  4 ++--
 src/android/jpeg/post_processor_jpeg.cpp | 28 ++++++++++--------------
 src/android/jpeg/post_processor_jpeg.h   |  2 +-
 src/android/post_processor.h             |  4 +++-
 src/android/yuv/post_processor_yuv.cpp   | 20 ++++++++---------
 src/android/yuv/post_processor_yuv.h     |  4 ++--
 9 files changed, 42 insertions(+), 45 deletions(-)

Comments

Laurent Pinchart Feb. 28, 2021, 6:42 p.m. UTC | #1
Hi Jacopo,

Thank you for the patch.

On Fri, Feb 26, 2021 at 02:29:28PM +0100, Jacopo Mondi wrote:
> Use the newly introduced CameraBuffer class as the type for the
> destination buffer in the PostProcessor class hierarchy in place of the
> libcamera::MappedFrameBuffer one and use its API to retrieve the length
> and the location of the CameraBuffer plane allocated for JPEG
> post-processing.
> 
> Remove all the assumption on the underlying memory storage and only go
> through the CameraBuffer API when dealing with memory buffers. To do so
> rework the Encoder interface to use a raw pointer and an explicit size
> to remove access to the Span<uint8_t> maps that serve as memory storage
> for the current implementation but might not be ideal for other memory
> backend.
> 
> Now that the whole PostProcessor hierarchy has been converted to use
> the CameraBuffer API remove libcamera::MappedBuffer as base class
> of the CameraBuffer interface and only reply on its interface.
> 
> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
> ---
>  src/android/camera_buffer.h              |  2 +-
>  src/android/jpeg/encoder.h               |  4 +++-
>  src/android/jpeg/encoder_libjpeg.cpp     | 19 ++++++++--------
>  src/android/jpeg/encoder_libjpeg.h       |  4 ++--
>  src/android/jpeg/post_processor_jpeg.cpp | 28 ++++++++++--------------
>  src/android/jpeg/post_processor_jpeg.h   |  2 +-
>  src/android/post_processor.h             |  4 +++-
>  src/android/yuv/post_processor_yuv.cpp   | 20 ++++++++---------
>  src/android/yuv/post_processor_yuv.h     |  4 ++--
>  9 files changed, 42 insertions(+), 45 deletions(-)
> 
> diff --git a/src/android/camera_buffer.h b/src/android/camera_buffer.h
> index 2a91e6a3c9c1..b251e4514864 100644
> --- a/src/android/camera_buffer.h
> +++ b/src/android/camera_buffer.h
> @@ -11,7 +11,7 @@
>  
>  #include <libcamera/internal/buffer.h>
>  
> -class CameraBuffer : public libcamera::MappedBuffer
> +class CameraBuffer
>  {
>  public:
>  	CameraBuffer(buffer_handle_t camera3Buffer, int flags);
> diff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h
> index 8d449369869f..a3c47c09a06e 100644
> --- a/src/android/jpeg/encoder.h
> +++ b/src/android/jpeg/encoder.h
> @@ -11,6 +11,8 @@
>  #include <libcamera/span.h>
>  #include <libcamera/stream.h>
>  
> +#include "../camera_buffer.h"

This doesn't seem to be needed.

> +
>  class Encoder
>  {
>  public:
> @@ -18,7 +20,7 @@ public:
>  
>  	virtual int configure(const libcamera::StreamConfiguration &cfg) = 0;
>  	virtual int encode(const libcamera::FrameBuffer &source,
> -			   libcamera::Span<uint8_t> destination,
> +			   uint8_t *destination, size_t destinationSize,

Whenever we need to pass a pointer and a size, a span is the right tool.
It's its core purpose, grouping pointer and size together. This will not
support multi-planar buffers, but neither will a pointer and a size, so
the interface will need to be reworked later.

>  			   libcamera::Span<const uint8_t> exifData,
>  			   unsigned int quality) = 0;
>  };
> diff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp
> index f006e1d1999a..a965620703df 100644
> --- a/src/android/jpeg/encoder_libjpeg.cpp
> +++ b/src/android/jpeg/encoder_libjpeg.cpp
> @@ -177,8 +177,9 @@ void EncoderLibJpeg::compressNV(Span<const uint8_t> frame)
>  	}
>  }
>  
> -int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
> -			   Span<const uint8_t> exifData, unsigned int quality)
> +int EncoderLibJpeg::encode(const FrameBuffer &source, uint8_t *destination,
> +			   size_t destinationSize, Span<const uint8_t> exifData,
> +			   unsigned int quality)
>  {
>  	MappedFrameBuffer frame(&source, PROT_READ);
>  	if (!frame.isValid()) {
> @@ -187,15 +188,13 @@ int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
>  		return frame.error();
>  	}
>  
> -	return encode(frame.maps()[0], dest, exifData, quality);
> +	return encode(frame.maps()[0], destination, destinationSize, exifData, quality);
>  }
>  
> -int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,
> -			   Span<const uint8_t> exifData, unsigned int quality)
> +int EncoderLibJpeg::encode(Span<const uint8_t> src, uint8_t *destination,
> +			   size_t destinationSize, Span<const uint8_t> exifData,
> +			   unsigned int quality)
>  {
> -	unsigned char *destination = dest.data();
> -	unsigned long size = dest.size();
> -
>  	jpeg_set_quality(&compress_, quality, TRUE);
>  
>  	/*
> @@ -206,7 +205,7 @@ int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,
>  	 * \todo Implement our own custom memory destination to prevent
>  	 * reallocation and prefer failure with correct reporting.
>  	 */
> -	jpeg_mem_dest(&compress_, &destination, &size);
> +	jpeg_mem_dest(&compress_, &destination, &destinationSize);
>  
>  	jpeg_start_compress(&compress_, TRUE);
>  
> @@ -226,5 +225,5 @@ int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,
>  
>  	jpeg_finish_compress(&compress_);
>  
> -	return size;
> +	return destinationSize;
>  }
> diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
> index 838da7728382..bda5c16089df 100644
> --- a/src/android/jpeg/encoder_libjpeg.h
> +++ b/src/android/jpeg/encoder_libjpeg.h
> @@ -22,11 +22,11 @@ public:
>  
>  	int configure(const libcamera::StreamConfiguration &cfg) override;
>  	int encode(const libcamera::FrameBuffer &source,
> -		   libcamera::Span<uint8_t> destination,
> +		   uint8_t *destination, size_t destinationSize,
>  		   libcamera::Span<const uint8_t> exifData,
>  		   unsigned int quality) override;
>  	int encode(libcamera::Span<const uint8_t> source,
> -		   libcamera::Span<uint8_t> destination,
> +		   uint8_t *destination, size_t destinationSize,
>  		   libcamera::Span<const uint8_t> exifData,
>  		   unsigned int quality);
>  
> diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
> index ab5b63844067..d6eeb962e81d 100644
> --- a/src/android/jpeg/post_processor_jpeg.cpp
> +++ b/src/android/jpeg/post_processor_jpeg.cpp
> @@ -73,7 +73,9 @@ void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
>  		thumbnail->resize(rawThumbnail.size());
>  
>  		int jpeg_size = thumbnailEncoder_.encode(rawThumbnail,
> -							 *thumbnail, {}, quality);
> +							 thumbnail->data(),
> +							 thumbnail->size(),
> +							 {}, quality);
>  		thumbnail->resize(jpeg_size);
>  
>  		LOG(JPEG, Debug)
> @@ -83,13 +85,15 @@ void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
>  }
>  
>  int PostProcessorJpeg::process(const FrameBuffer &source,
> -			       libcamera::MappedBuffer *destination,
> +			       CameraBuffer *destination,
>  			       const CameraMetadata &requestMetadata,
>  			       CameraMetadata *resultMetadata)
>  {
>  	if (!encoder_)
>  		return 0;
>  
> +	ASSERT(destination->numPlanes() == 1);
> +
>  	camera_metadata_ro_entry_t entry;
>  	int ret;
>  
> @@ -172,27 +176,17 @@ int PostProcessorJpeg::process(const FrameBuffer &source,
>  	const uint8_t quality = ret ? *entry.data.u8 : 95;
>  	resultMetadata->addEntry(ANDROID_JPEG_QUALITY, &quality, 1);
>  
> -	int jpeg_size = encoder_->encode(source, destination->maps()[0],
> +	int jpeg_size = encoder_->encode(source, destination->plane(0),
> +					 destination->planeSize(0),

The CameraBuffer::plane() function should return a span, and I'd then
drop CameraBuffer::planeSize().

>  					 exif.data(), quality);
>  	if (jpeg_size < 0) {
>  		LOG(JPEG, Error) << "Failed to encode stream image";
>  		return jpeg_size;
>  	}
>  
> -	/*
> -	 * Fill in the JPEG blob header.
> -	 *
> -	 * The mapped size of the buffer is being returned as
> -	 * substantially larger than the requested JPEG_MAX_SIZE
> -	 * (which is referenced from maxJpegBufferSize_). Utilise
> -	 * this static size to ensure the correct offset of the blob is
> -	 * determined.
> -	 *
> -	 * \todo Investigate if the buffer size mismatch is an issue or
> -	 * expected behaviour.
> -	 */
> -	uint8_t *resultPtr = destination->maps()[0].data() +
> -			     cameraDevice_->maxJpegBufferSize() -
> +	/* Fill in the JPEG blob header. */
> +	uint8_t *resultPtr = destination->plane(0) +
> +			     destination->planeSize(0) -
>  			     sizeof(struct camera3_jpeg_blob);
>  	auto *blob = reinterpret_cast<struct camera3_jpeg_blob *>(resultPtr);
>  	blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
> diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h
> index 7689de73c664..5d2d4ab224b1 100644
> --- a/src/android/jpeg/post_processor_jpeg.h
> +++ b/src/android/jpeg/post_processor_jpeg.h
> @@ -25,7 +25,7 @@ public:
>  	int configure(const libcamera::StreamConfiguration &incfg,
>  		      const libcamera::StreamConfiguration &outcfg) override;
>  	int process(const libcamera::FrameBuffer &source,
> -		    libcamera::MappedBuffer *destination,
> +		    CameraBuffer *destination,
>  		    const CameraMetadata &requestMetadata,
>  		    CameraMetadata *resultMetadata) override;
>  
> diff --git a/src/android/post_processor.h b/src/android/post_processor.h
> index ac40d3414892..4944078b490c 100644
> --- a/src/android/post_processor.h
> +++ b/src/android/post_processor.h
> @@ -12,6 +12,8 @@
>  
>  #include <libcamera/internal/buffer.h>
>  
> +#include "camera_buffer.h"
> +

Maybe a forward declaration of CameraBuffer would be enough here ?

The rest of the patch looks good to me. With these issues addressed,

Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

>  class CameraMetadata;
>  
>  class PostProcessor
> @@ -22,7 +24,7 @@ public:
>  	virtual int configure(const libcamera::StreamConfiguration &inCfg,
>  			      const libcamera::StreamConfiguration &outCfg) = 0;
>  	virtual int process(const libcamera::FrameBuffer &source,
> -			    libcamera::MappedBuffer *destination,
> +			    CameraBuffer *destination,
>  			    const CameraMetadata &requestMetadata,
>  			    CameraMetadata *resultMetadata) = 0;
>  };
> diff --git a/src/android/yuv/post_processor_yuv.cpp b/src/android/yuv/post_processor_yuv.cpp
> index 1318349ad66b..f1487185a95a 100644
> --- a/src/android/yuv/post_processor_yuv.cpp
> +++ b/src/android/yuv/post_processor_yuv.cpp
> @@ -48,7 +48,7 @@ int PostProcessorYuv::configure(const StreamConfiguration &inCfg,
>  }
>  
>  int PostProcessorYuv::process(const FrameBuffer &source,
> -			      libcamera::MappedBuffer *destination,
> +			      CameraBuffer *destination,
>  			      [[maybe_unused]] const CameraMetadata &requestMetadata,
>  			      [[maybe_unused]] CameraMetadata *metadata)
>  {
> @@ -66,9 +66,9 @@ int PostProcessorYuv::process(const FrameBuffer &source,
>  				    sourceMapped.maps()[1].data(),
>  				    sourceStride_[1],
>  				    sourceSize_.width, sourceSize_.height,
> -				    destination->maps()[0].data(),
> +				    destination->plane(0),
>  				    destinationStride_[0],
> -				    destination->maps()[1].data(),
> +				    destination->plane(1),
>  				    destinationStride_[1],
>  				    destinationSize_.width,
>  				    destinationSize_.height,
> @@ -82,16 +82,16 @@ int PostProcessorYuv::process(const FrameBuffer &source,
>  }
>  
>  bool PostProcessorYuv::isValidBuffers(const FrameBuffer &source,
> -				      const libcamera::MappedBuffer &destination) const
> +				      const CameraBuffer &destination) const
>  {
>  	if (source.planes().size() != 2) {
>  		LOG(YUV, Error) << "Invalid number of source planes: "
>  				<< source.planes().size();
>  		return false;
>  	}
> -	if (destination.maps().size() != 2) {
> +	if (destination.numPlanes() != 2) {
>  		LOG(YUV, Error) << "Invalid number of destination planes: "
> -				<< destination.maps().size();
> +				<< destination.numPlanes();
>  		return false;
>  	}
>  
> @@ -106,12 +106,12 @@ bool PostProcessorYuv::isValidBuffers(const FrameBuffer &source,
>  			<< sourceLength_[1] << "}";
>  		return false;
>  	}
> -	if (destination.maps()[0].size() < destinationLength_[0] ||
> -	    destination.maps()[1].size() < destinationLength_[1]) {
> +	if (destination.planeSize(0) < destinationLength_[0] ||
> +	    destination.planeSize(1) < destinationLength_[1]) {
>  		LOG(YUV, Error)
>  			<< "The destination planes lengths are too small, actual size: {"
> -			<< destination.maps()[0].size() << ", "
> -			<< destination.maps()[1].size()
> +			<< destination.planeSize(0) << ", "
> +			<< destination.planeSize(1)
>  			<< "}, expected size: {"
>  			<< sourceLength_[0] << ", "
>  			<< sourceLength_[1] << "}";
> diff --git a/src/android/yuv/post_processor_yuv.h b/src/android/yuv/post_processor_yuv.h
> index c58b4cf790fc..f8b1ba23fa6c 100644
> --- a/src/android/yuv/post_processor_yuv.h
> +++ b/src/android/yuv/post_processor_yuv.h
> @@ -21,13 +21,13 @@ public:
>  	int configure(const libcamera::StreamConfiguration &incfg,
>  		      const libcamera::StreamConfiguration &outcfg) override;
>  	int process(const libcamera::FrameBuffer &source,
> -		    libcamera::MappedBuffer *destination,
> +		    CameraBuffer *destination,
>  		    const CameraMetadata &requestMetadata,
>  		    CameraMetadata *metadata) override;
>  
>  private:
>  	bool isValidBuffers(const libcamera::FrameBuffer &source,
> -			    const libcamera::MappedBuffer &destination) const;
> +			    const CameraBuffer &destination) const;
>  	void calculateLengths(const libcamera::StreamConfiguration &inCfg,
>  			      const libcamera::StreamConfiguration &outCfg);
>

Patch
diff mbox series

diff --git a/src/android/camera_buffer.h b/src/android/camera_buffer.h
index 2a91e6a3c9c1..b251e4514864 100644
--- a/src/android/camera_buffer.h
+++ b/src/android/camera_buffer.h
@@ -11,7 +11,7 @@ 
 
 #include <libcamera/internal/buffer.h>
 
-class CameraBuffer : public libcamera::MappedBuffer
+class CameraBuffer
 {
 public:
 	CameraBuffer(buffer_handle_t camera3Buffer, int flags);
diff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h
index 8d449369869f..a3c47c09a06e 100644
--- a/src/android/jpeg/encoder.h
+++ b/src/android/jpeg/encoder.h
@@ -11,6 +11,8 @@ 
 #include <libcamera/span.h>
 #include <libcamera/stream.h>
 
+#include "../camera_buffer.h"
+
 class Encoder
 {
 public:
@@ -18,7 +20,7 @@  public:
 
 	virtual int configure(const libcamera::StreamConfiguration &cfg) = 0;
 	virtual int encode(const libcamera::FrameBuffer &source,
-			   libcamera::Span<uint8_t> destination,
+			   uint8_t *destination, size_t destinationSize,
 			   libcamera::Span<const uint8_t> exifData,
 			   unsigned int quality) = 0;
 };
diff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp
index f006e1d1999a..a965620703df 100644
--- a/src/android/jpeg/encoder_libjpeg.cpp
+++ b/src/android/jpeg/encoder_libjpeg.cpp
@@ -177,8 +177,9 @@  void EncoderLibJpeg::compressNV(Span<const uint8_t> frame)
 	}
 }
 
-int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
-			   Span<const uint8_t> exifData, unsigned int quality)
+int EncoderLibJpeg::encode(const FrameBuffer &source, uint8_t *destination,
+			   size_t destinationSize, Span<const uint8_t> exifData,
+			   unsigned int quality)
 {
 	MappedFrameBuffer frame(&source, PROT_READ);
 	if (!frame.isValid()) {
@@ -187,15 +188,13 @@  int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,
 		return frame.error();
 	}
 
-	return encode(frame.maps()[0], dest, exifData, quality);
+	return encode(frame.maps()[0], destination, destinationSize, exifData, quality);
 }
 
-int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,
-			   Span<const uint8_t> exifData, unsigned int quality)
+int EncoderLibJpeg::encode(Span<const uint8_t> src, uint8_t *destination,
+			   size_t destinationSize, Span<const uint8_t> exifData,
+			   unsigned int quality)
 {
-	unsigned char *destination = dest.data();
-	unsigned long size = dest.size();
-
 	jpeg_set_quality(&compress_, quality, TRUE);
 
 	/*
@@ -206,7 +205,7 @@  int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,
 	 * \todo Implement our own custom memory destination to prevent
 	 * reallocation and prefer failure with correct reporting.
 	 */
-	jpeg_mem_dest(&compress_, &destination, &size);
+	jpeg_mem_dest(&compress_, &destination, &destinationSize);
 
 	jpeg_start_compress(&compress_, TRUE);
 
@@ -226,5 +225,5 @@  int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,
 
 	jpeg_finish_compress(&compress_);
 
-	return size;
+	return destinationSize;
 }
diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h
index 838da7728382..bda5c16089df 100644
--- a/src/android/jpeg/encoder_libjpeg.h
+++ b/src/android/jpeg/encoder_libjpeg.h
@@ -22,11 +22,11 @@  public:
 
 	int configure(const libcamera::StreamConfiguration &cfg) override;
 	int encode(const libcamera::FrameBuffer &source,
-		   libcamera::Span<uint8_t> destination,
+		   uint8_t *destination, size_t destinationSize,
 		   libcamera::Span<const uint8_t> exifData,
 		   unsigned int quality) override;
 	int encode(libcamera::Span<const uint8_t> source,
-		   libcamera::Span<uint8_t> destination,
+		   uint8_t *destination, size_t destinationSize,
 		   libcamera::Span<const uint8_t> exifData,
 		   unsigned int quality);
 
diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp
index ab5b63844067..d6eeb962e81d 100644
--- a/src/android/jpeg/post_processor_jpeg.cpp
+++ b/src/android/jpeg/post_processor_jpeg.cpp
@@ -73,7 +73,9 @@  void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
 		thumbnail->resize(rawThumbnail.size());
 
 		int jpeg_size = thumbnailEncoder_.encode(rawThumbnail,
-							 *thumbnail, {}, quality);
+							 thumbnail->data(),
+							 thumbnail->size(),
+							 {}, quality);
 		thumbnail->resize(jpeg_size);
 
 		LOG(JPEG, Debug)
@@ -83,13 +85,15 @@  void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,
 }
 
 int PostProcessorJpeg::process(const FrameBuffer &source,
-			       libcamera::MappedBuffer *destination,
+			       CameraBuffer *destination,
 			       const CameraMetadata &requestMetadata,
 			       CameraMetadata *resultMetadata)
 {
 	if (!encoder_)
 		return 0;
 
+	ASSERT(destination->numPlanes() == 1);
+
 	camera_metadata_ro_entry_t entry;
 	int ret;
 
@@ -172,27 +176,17 @@  int PostProcessorJpeg::process(const FrameBuffer &source,
 	const uint8_t quality = ret ? *entry.data.u8 : 95;
 	resultMetadata->addEntry(ANDROID_JPEG_QUALITY, &quality, 1);
 
-	int jpeg_size = encoder_->encode(source, destination->maps()[0],
+	int jpeg_size = encoder_->encode(source, destination->plane(0),
+					 destination->planeSize(0),
 					 exif.data(), quality);
 	if (jpeg_size < 0) {
 		LOG(JPEG, Error) << "Failed to encode stream image";
 		return jpeg_size;
 	}
 
-	/*
-	 * Fill in the JPEG blob header.
-	 *
-	 * The mapped size of the buffer is being returned as
-	 * substantially larger than the requested JPEG_MAX_SIZE
-	 * (which is referenced from maxJpegBufferSize_). Utilise
-	 * this static size to ensure the correct offset of the blob is
-	 * determined.
-	 *
-	 * \todo Investigate if the buffer size mismatch is an issue or
-	 * expected behaviour.
-	 */
-	uint8_t *resultPtr = destination->maps()[0].data() +
-			     cameraDevice_->maxJpegBufferSize() -
+	/* Fill in the JPEG blob header. */
+	uint8_t *resultPtr = destination->plane(0) +
+			     destination->planeSize(0) -
 			     sizeof(struct camera3_jpeg_blob);
 	auto *blob = reinterpret_cast<struct camera3_jpeg_blob *>(resultPtr);
 	blob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;
diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h
index 7689de73c664..5d2d4ab224b1 100644
--- a/src/android/jpeg/post_processor_jpeg.h
+++ b/src/android/jpeg/post_processor_jpeg.h
@@ -25,7 +25,7 @@  public:
 	int configure(const libcamera::StreamConfiguration &incfg,
 		      const libcamera::StreamConfiguration &outcfg) override;
 	int process(const libcamera::FrameBuffer &source,
-		    libcamera::MappedBuffer *destination,
+		    CameraBuffer *destination,
 		    const CameraMetadata &requestMetadata,
 		    CameraMetadata *resultMetadata) override;
 
diff --git a/src/android/post_processor.h b/src/android/post_processor.h
index ac40d3414892..4944078b490c 100644
--- a/src/android/post_processor.h
+++ b/src/android/post_processor.h
@@ -12,6 +12,8 @@ 
 
 #include <libcamera/internal/buffer.h>
 
+#include "camera_buffer.h"
+
 class CameraMetadata;
 
 class PostProcessor
@@ -22,7 +24,7 @@  public:
 	virtual int configure(const libcamera::StreamConfiguration &inCfg,
 			      const libcamera::StreamConfiguration &outCfg) = 0;
 	virtual int process(const libcamera::FrameBuffer &source,
-			    libcamera::MappedBuffer *destination,
+			    CameraBuffer *destination,
 			    const CameraMetadata &requestMetadata,
 			    CameraMetadata *resultMetadata) = 0;
 };
diff --git a/src/android/yuv/post_processor_yuv.cpp b/src/android/yuv/post_processor_yuv.cpp
index 1318349ad66b..f1487185a95a 100644
--- a/src/android/yuv/post_processor_yuv.cpp
+++ b/src/android/yuv/post_processor_yuv.cpp
@@ -48,7 +48,7 @@  int PostProcessorYuv::configure(const StreamConfiguration &inCfg,
 }
 
 int PostProcessorYuv::process(const FrameBuffer &source,
-			      libcamera::MappedBuffer *destination,
+			      CameraBuffer *destination,
 			      [[maybe_unused]] const CameraMetadata &requestMetadata,
 			      [[maybe_unused]] CameraMetadata *metadata)
 {
@@ -66,9 +66,9 @@  int PostProcessorYuv::process(const FrameBuffer &source,
 				    sourceMapped.maps()[1].data(),
 				    sourceStride_[1],
 				    sourceSize_.width, sourceSize_.height,
-				    destination->maps()[0].data(),
+				    destination->plane(0),
 				    destinationStride_[0],
-				    destination->maps()[1].data(),
+				    destination->plane(1),
 				    destinationStride_[1],
 				    destinationSize_.width,
 				    destinationSize_.height,
@@ -82,16 +82,16 @@  int PostProcessorYuv::process(const FrameBuffer &source,
 }
 
 bool PostProcessorYuv::isValidBuffers(const FrameBuffer &source,
-				      const libcamera::MappedBuffer &destination) const
+				      const CameraBuffer &destination) const
 {
 	if (source.planes().size() != 2) {
 		LOG(YUV, Error) << "Invalid number of source planes: "
 				<< source.planes().size();
 		return false;
 	}
-	if (destination.maps().size() != 2) {
+	if (destination.numPlanes() != 2) {
 		LOG(YUV, Error) << "Invalid number of destination planes: "
-				<< destination.maps().size();
+				<< destination.numPlanes();
 		return false;
 	}
 
@@ -106,12 +106,12 @@  bool PostProcessorYuv::isValidBuffers(const FrameBuffer &source,
 			<< sourceLength_[1] << "}";
 		return false;
 	}
-	if (destination.maps()[0].size() < destinationLength_[0] ||
-	    destination.maps()[1].size() < destinationLength_[1]) {
+	if (destination.planeSize(0) < destinationLength_[0] ||
+	    destination.planeSize(1) < destinationLength_[1]) {
 		LOG(YUV, Error)
 			<< "The destination planes lengths are too small, actual size: {"
-			<< destination.maps()[0].size() << ", "
-			<< destination.maps()[1].size()
+			<< destination.planeSize(0) << ", "
+			<< destination.planeSize(1)
 			<< "}, expected size: {"
 			<< sourceLength_[0] << ", "
 			<< sourceLength_[1] << "}";
diff --git a/src/android/yuv/post_processor_yuv.h b/src/android/yuv/post_processor_yuv.h
index c58b4cf790fc..f8b1ba23fa6c 100644
--- a/src/android/yuv/post_processor_yuv.h
+++ b/src/android/yuv/post_processor_yuv.h
@@ -21,13 +21,13 @@  public:
 	int configure(const libcamera::StreamConfiguration &incfg,
 		      const libcamera::StreamConfiguration &outcfg) override;
 	int process(const libcamera::FrameBuffer &source,
-		    libcamera::MappedBuffer *destination,
+		    CameraBuffer *destination,
 		    const CameraMetadata &requestMetadata,
 		    CameraMetadata *metadata) override;
 
 private:
 	bool isValidBuffers(const libcamera::FrameBuffer &source,
-			    const libcamera::MappedBuffer &destination) const;
+			    const CameraBuffer &destination) const;
 	void calculateLengths(const libcamera::StreamConfiguration &inCfg,
 			      const libcamera::StreamConfiguration &outCfg);