{"id":11401,"url":"https://patchwork.libcamera.org/api/patches/11401/?format=json","web_url":"https://patchwork.libcamera.org/patch/11401/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20210226132932.165484-9-jacopo@jmondi.org>","date":"2021-02-26T13:29:28","name":"[libcamera-devel,08/12] android: post_processor: Use CameraBuffer API","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"6881b2b019d3776702e3f33007e56f65ef105a32","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/?format=json","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/11401/mbox/","series":[{"id":1731,"url":"https://patchwork.libcamera.org/api/series/1731/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=1731","date":"2021-02-26T13:29:20","name":"android: Support memory backends","version":1,"mbox":"https://patchwork.libcamera.org/series/1731/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/11401/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/11401/checks/","tags":{},"headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id EAD65BD1F1\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 26 Feb 2021 13:29:22 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6A02968A78;\n\tFri, 26 Feb 2021 14:29:22 +0100 (CET)","from relay12.mail.gandi.net (relay12.mail.gandi.net\n\t[217.70.178.232])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7A4D668A73\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Feb 2021 14:29:16 +0100 (CET)","from uno.LocalDomain (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay12.mail.gandi.net (Postfix) with ESMTPSA id 34B1A200005\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 26 Feb 2021 13:29:16 +0000 (UTC)"],"From":"Jacopo Mondi <jacopo@jmondi.org>","To":"libcamera-devel@lists.libcamera.org","Date":"Fri, 26 Feb 2021 14:29:28 +0100","Message-Id":"<20210226132932.165484-9-jacopo@jmondi.org>","X-Mailer":"git-send-email 2.30.0","In-Reply-To":"<20210226132932.165484-1-jacopo@jmondi.org>","References":"<20210226132932.165484-1-jacopo@jmondi.org>","MIME-Version":"1.0","Subject":"[libcamera-devel] [PATCH 08/12] android: post_processor: Use\n\tCameraBuffer API","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"},"content":"Use the newly introduced CameraBuffer class as the type for the\ndestination buffer in the PostProcessor class hierarchy in place of the\nlibcamera::MappedFrameBuffer one and use its API to retrieve the length\nand the location of the CameraBuffer plane allocated for JPEG\npost-processing.\n\nRemove all the assumption on the underlying memory storage and only go\nthrough the CameraBuffer API when dealing with memory buffers. To do so\nrework the Encoder interface to use a raw pointer and an explicit size\nto remove access to the Span<uint8_t> maps that serve as memory storage\nfor the current implementation but might not be ideal for other memory\nbackend.\n\nNow that the whole PostProcessor hierarchy has been converted to use\nthe CameraBuffer API remove libcamera::MappedBuffer as base class\nof the CameraBuffer interface and only reply on its interface.\n\nSigned-off-by: Jacopo Mondi <jacopo@jmondi.org>\n---\n src/android/camera_buffer.h              |  2 +-\n src/android/jpeg/encoder.h               |  4 +++-\n src/android/jpeg/encoder_libjpeg.cpp     | 19 ++++++++--------\n src/android/jpeg/encoder_libjpeg.h       |  4 ++--\n src/android/jpeg/post_processor_jpeg.cpp | 28 ++++++++++--------------\n src/android/jpeg/post_processor_jpeg.h   |  2 +-\n src/android/post_processor.h             |  4 +++-\n src/android/yuv/post_processor_yuv.cpp   | 20 ++++++++---------\n src/android/yuv/post_processor_yuv.h     |  4 ++--\n 9 files changed, 42 insertions(+), 45 deletions(-)","diff":"diff --git a/src/android/camera_buffer.h b/src/android/camera_buffer.h\nindex 2a91e6a3c9c1..b251e4514864 100644\n--- a/src/android/camera_buffer.h\n+++ b/src/android/camera_buffer.h\n@@ -11,7 +11,7 @@\n \n #include <libcamera/internal/buffer.h>\n \n-class CameraBuffer : public libcamera::MappedBuffer\n+class CameraBuffer\n {\n public:\n \tCameraBuffer(buffer_handle_t camera3Buffer, int flags);\ndiff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h\nindex 8d449369869f..a3c47c09a06e 100644\n--- a/src/android/jpeg/encoder.h\n+++ b/src/android/jpeg/encoder.h\n@@ -11,6 +11,8 @@\n #include <libcamera/span.h>\n #include <libcamera/stream.h>\n \n+#include \"../camera_buffer.h\"\n+\n class Encoder\n {\n public:\n@@ -18,7 +20,7 @@ public:\n \n \tvirtual int configure(const libcamera::StreamConfiguration &cfg) = 0;\n \tvirtual int encode(const libcamera::FrameBuffer &source,\n-\t\t\t   libcamera::Span<uint8_t> destination,\n+\t\t\t   uint8_t *destination, size_t destinationSize,\n \t\t\t   libcamera::Span<const uint8_t> exifData,\n \t\t\t   unsigned int quality) = 0;\n };\ndiff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp\nindex f006e1d1999a..a965620703df 100644\n--- a/src/android/jpeg/encoder_libjpeg.cpp\n+++ b/src/android/jpeg/encoder_libjpeg.cpp\n@@ -177,8 +177,9 @@ void EncoderLibJpeg::compressNV(Span<const uint8_t> frame)\n \t}\n }\n \n-int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,\n-\t\t\t   Span<const uint8_t> exifData, unsigned int quality)\n+int EncoderLibJpeg::encode(const FrameBuffer &source, uint8_t *destination,\n+\t\t\t   size_t destinationSize, Span<const uint8_t> exifData,\n+\t\t\t   unsigned int quality)\n {\n \tMappedFrameBuffer frame(&source, PROT_READ);\n \tif (!frame.isValid()) {\n@@ -187,15 +188,13 @@ int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,\n \t\treturn frame.error();\n \t}\n \n-\treturn encode(frame.maps()[0], dest, exifData, quality);\n+\treturn encode(frame.maps()[0], destination, destinationSize, exifData, quality);\n }\n \n-int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,\n-\t\t\t   Span<const uint8_t> exifData, unsigned int quality)\n+int EncoderLibJpeg::encode(Span<const uint8_t> src, uint8_t *destination,\n+\t\t\t   size_t destinationSize, Span<const uint8_t> exifData,\n+\t\t\t   unsigned int quality)\n {\n-\tunsigned char *destination = dest.data();\n-\tunsigned long size = dest.size();\n-\n \tjpeg_set_quality(&compress_, quality, TRUE);\n \n \t/*\n@@ -206,7 +205,7 @@ int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,\n \t * \\todo Implement our own custom memory destination to prevent\n \t * reallocation and prefer failure with correct reporting.\n \t */\n-\tjpeg_mem_dest(&compress_, &destination, &size);\n+\tjpeg_mem_dest(&compress_, &destination, &destinationSize);\n \n \tjpeg_start_compress(&compress_, TRUE);\n \n@@ -226,5 +225,5 @@ int EncoderLibJpeg::encode(Span<const uint8_t> src, Span<uint8_t> dest,\n \n \tjpeg_finish_compress(&compress_);\n \n-\treturn size;\n+\treturn destinationSize;\n }\ndiff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h\nindex 838da7728382..bda5c16089df 100644\n--- a/src/android/jpeg/encoder_libjpeg.h\n+++ b/src/android/jpeg/encoder_libjpeg.h\n@@ -22,11 +22,11 @@ public:\n \n \tint configure(const libcamera::StreamConfiguration &cfg) override;\n \tint encode(const libcamera::FrameBuffer &source,\n-\t\t   libcamera::Span<uint8_t> destination,\n+\t\t   uint8_t *destination, size_t destinationSize,\n \t\t   libcamera::Span<const uint8_t> exifData,\n \t\t   unsigned int quality) override;\n \tint encode(libcamera::Span<const uint8_t> source,\n-\t\t   libcamera::Span<uint8_t> destination,\n+\t\t   uint8_t *destination, size_t destinationSize,\n \t\t   libcamera::Span<const uint8_t> exifData,\n \t\t   unsigned int quality);\n \ndiff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp\nindex ab5b63844067..d6eeb962e81d 100644\n--- a/src/android/jpeg/post_processor_jpeg.cpp\n+++ b/src/android/jpeg/post_processor_jpeg.cpp\n@@ -73,7 +73,9 @@ void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,\n \t\tthumbnail->resize(rawThumbnail.size());\n \n \t\tint jpeg_size = thumbnailEncoder_.encode(rawThumbnail,\n-\t\t\t\t\t\t\t *thumbnail, {}, quality);\n+\t\t\t\t\t\t\t thumbnail->data(),\n+\t\t\t\t\t\t\t thumbnail->size(),\n+\t\t\t\t\t\t\t {}, quality);\n \t\tthumbnail->resize(jpeg_size);\n \n \t\tLOG(JPEG, Debug)\n@@ -83,13 +85,15 @@ void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,\n }\n \n int PostProcessorJpeg::process(const FrameBuffer &source,\n-\t\t\t       libcamera::MappedBuffer *destination,\n+\t\t\t       CameraBuffer *destination,\n \t\t\t       const CameraMetadata &requestMetadata,\n \t\t\t       CameraMetadata *resultMetadata)\n {\n \tif (!encoder_)\n \t\treturn 0;\n \n+\tASSERT(destination->numPlanes() == 1);\n+\n \tcamera_metadata_ro_entry_t entry;\n \tint ret;\n \n@@ -172,27 +176,17 @@ int PostProcessorJpeg::process(const FrameBuffer &source,\n \tconst uint8_t quality = ret ? *entry.data.u8 : 95;\n \tresultMetadata->addEntry(ANDROID_JPEG_QUALITY, &quality, 1);\n \n-\tint jpeg_size = encoder_->encode(source, destination->maps()[0],\n+\tint jpeg_size = encoder_->encode(source, destination->plane(0),\n+\t\t\t\t\t destination->planeSize(0),\n \t\t\t\t\t exif.data(), quality);\n \tif (jpeg_size < 0) {\n \t\tLOG(JPEG, Error) << \"Failed to encode stream image\";\n \t\treturn jpeg_size;\n \t}\n \n-\t/*\n-\t * Fill in the JPEG blob header.\n-\t *\n-\t * The mapped size of the buffer is being returned as\n-\t * substantially larger than the requested JPEG_MAX_SIZE\n-\t * (which is referenced from maxJpegBufferSize_). Utilise\n-\t * this static size to ensure the correct offset of the blob is\n-\t * determined.\n-\t *\n-\t * \\todo Investigate if the buffer size mismatch is an issue or\n-\t * expected behaviour.\n-\t */\n-\tuint8_t *resultPtr = destination->maps()[0].data() +\n-\t\t\t     cameraDevice_->maxJpegBufferSize() -\n+\t/* Fill in the JPEG blob header. */\n+\tuint8_t *resultPtr = destination->plane(0) +\n+\t\t\t     destination->planeSize(0) -\n \t\t\t     sizeof(struct camera3_jpeg_blob);\n \tauto *blob = reinterpret_cast<struct camera3_jpeg_blob *>(resultPtr);\n \tblob->jpeg_blob_id = CAMERA3_JPEG_BLOB_ID;\ndiff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h\nindex 7689de73c664..5d2d4ab224b1 100644\n--- a/src/android/jpeg/post_processor_jpeg.h\n+++ b/src/android/jpeg/post_processor_jpeg.h\n@@ -25,7 +25,7 @@ public:\n \tint configure(const libcamera::StreamConfiguration &incfg,\n \t\t      const libcamera::StreamConfiguration &outcfg) override;\n \tint process(const libcamera::FrameBuffer &source,\n-\t\t    libcamera::MappedBuffer *destination,\n+\t\t    CameraBuffer *destination,\n \t\t    const CameraMetadata &requestMetadata,\n \t\t    CameraMetadata *resultMetadata) override;\n \ndiff --git a/src/android/post_processor.h b/src/android/post_processor.h\nindex ac40d3414892..4944078b490c 100644\n--- a/src/android/post_processor.h\n+++ b/src/android/post_processor.h\n@@ -12,6 +12,8 @@\n \n #include <libcamera/internal/buffer.h>\n \n+#include \"camera_buffer.h\"\n+\n class CameraMetadata;\n \n class PostProcessor\n@@ -22,7 +24,7 @@ public:\n \tvirtual int configure(const libcamera::StreamConfiguration &inCfg,\n \t\t\t      const libcamera::StreamConfiguration &outCfg) = 0;\n \tvirtual int process(const libcamera::FrameBuffer &source,\n-\t\t\t    libcamera::MappedBuffer *destination,\n+\t\t\t    CameraBuffer *destination,\n \t\t\t    const CameraMetadata &requestMetadata,\n \t\t\t    CameraMetadata *resultMetadata) = 0;\n };\ndiff --git a/src/android/yuv/post_processor_yuv.cpp b/src/android/yuv/post_processor_yuv.cpp\nindex 1318349ad66b..f1487185a95a 100644\n--- a/src/android/yuv/post_processor_yuv.cpp\n+++ b/src/android/yuv/post_processor_yuv.cpp\n@@ -48,7 +48,7 @@ int PostProcessorYuv::configure(const StreamConfiguration &inCfg,\n }\n \n int PostProcessorYuv::process(const FrameBuffer &source,\n-\t\t\t      libcamera::MappedBuffer *destination,\n+\t\t\t      CameraBuffer *destination,\n \t\t\t      [[maybe_unused]] const CameraMetadata &requestMetadata,\n \t\t\t      [[maybe_unused]] CameraMetadata *metadata)\n {\n@@ -66,9 +66,9 @@ int PostProcessorYuv::process(const FrameBuffer &source,\n \t\t\t\t    sourceMapped.maps()[1].data(),\n \t\t\t\t    sourceStride_[1],\n \t\t\t\t    sourceSize_.width, sourceSize_.height,\n-\t\t\t\t    destination->maps()[0].data(),\n+\t\t\t\t    destination->plane(0),\n \t\t\t\t    destinationStride_[0],\n-\t\t\t\t    destination->maps()[1].data(),\n+\t\t\t\t    destination->plane(1),\n \t\t\t\t    destinationStride_[1],\n \t\t\t\t    destinationSize_.width,\n \t\t\t\t    destinationSize_.height,\n@@ -82,16 +82,16 @@ int PostProcessorYuv::process(const FrameBuffer &source,\n }\n \n bool PostProcessorYuv::isValidBuffers(const FrameBuffer &source,\n-\t\t\t\t      const libcamera::MappedBuffer &destination) const\n+\t\t\t\t      const CameraBuffer &destination) const\n {\n \tif (source.planes().size() != 2) {\n \t\tLOG(YUV, Error) << \"Invalid number of source planes: \"\n \t\t\t\t<< source.planes().size();\n \t\treturn false;\n \t}\n-\tif (destination.maps().size() != 2) {\n+\tif (destination.numPlanes() != 2) {\n \t\tLOG(YUV, Error) << \"Invalid number of destination planes: \"\n-\t\t\t\t<< destination.maps().size();\n+\t\t\t\t<< destination.numPlanes();\n \t\treturn false;\n \t}\n \n@@ -106,12 +106,12 @@ bool PostProcessorYuv::isValidBuffers(const FrameBuffer &source,\n \t\t\t<< sourceLength_[1] << \"}\";\n \t\treturn false;\n \t}\n-\tif (destination.maps()[0].size() < destinationLength_[0] ||\n-\t    destination.maps()[1].size() < destinationLength_[1]) {\n+\tif (destination.planeSize(0) < destinationLength_[0] ||\n+\t    destination.planeSize(1) < destinationLength_[1]) {\n \t\tLOG(YUV, Error)\n \t\t\t<< \"The destination planes lengths are too small, actual size: {\"\n-\t\t\t<< destination.maps()[0].size() << \", \"\n-\t\t\t<< destination.maps()[1].size()\n+\t\t\t<< destination.planeSize(0) << \", \"\n+\t\t\t<< destination.planeSize(1)\n \t\t\t<< \"}, expected size: {\"\n \t\t\t<< sourceLength_[0] << \", \"\n \t\t\t<< sourceLength_[1] << \"}\";\ndiff --git a/src/android/yuv/post_processor_yuv.h b/src/android/yuv/post_processor_yuv.h\nindex c58b4cf790fc..f8b1ba23fa6c 100644\n--- a/src/android/yuv/post_processor_yuv.h\n+++ b/src/android/yuv/post_processor_yuv.h\n@@ -21,13 +21,13 @@ public:\n \tint configure(const libcamera::StreamConfiguration &incfg,\n \t\t      const libcamera::StreamConfiguration &outcfg) override;\n \tint process(const libcamera::FrameBuffer &source,\n-\t\t    libcamera::MappedBuffer *destination,\n+\t\t    CameraBuffer *destination,\n \t\t    const CameraMetadata &requestMetadata,\n \t\t    CameraMetadata *metadata) override;\n \n private:\n \tbool isValidBuffers(const libcamera::FrameBuffer &source,\n-\t\t\t    const libcamera::MappedBuffer &destination) const;\n+\t\t\t    const CameraBuffer &destination) const;\n \tvoid calculateLengths(const libcamera::StreamConfiguration &inCfg,\n \t\t\t      const libcamera::StreamConfiguration &outCfg);\n \n","prefixes":["libcamera-devel","08/12"]}