[{"id":14724,"web_url":"https://patchwork.libcamera.org/comment/14724/","msgid":"<YAvu2XejF0TCk3N4@pendragon.ideasonboard.com>","date":"2021-01-23T09:39:37","subject":"Re: [libcamera-devel] [PATCH v3 6/8] android: jpeg: Configure\n\tthumbnailer based on request metadata","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Paul,\n\nThank you for the patch.\n\nOn Sat, Jan 23, 2021 at 02:17:02PM +0900, Paul Elder wrote:\n> Configure the thumbnailer based on the thumbnail parameters given by the\n> android request metadata. Only the thumbnail encoder needs to be\n> configured, and since it is only used at post-processing time, move the\n> configuration out of the post-processor constructor and into the\n> processing step.\n> \n> Also set the following android result metadata tags:\n> - ANDROID_JPEG_THUMBNAIL_SIZE\n> - ANDROID_JPEG_THUMBNAIL_QUALITY\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> \n> ---\n> New in v3\n> - split from \"android: Set result metadata and EXIF fields based on\n>   request\"\n> ---\n>  src/android/jpeg/post_processor_jpeg.cpp | 40 +++++++++++++++++-------\n>  src/android/jpeg/post_processor_jpeg.h   |  1 +\n>  src/android/jpeg/thumbnailer.cpp         | 25 ++-------------\n>  src/android/jpeg/thumbnailer.h           |  4 +--\n>  4 files changed, 34 insertions(+), 36 deletions(-)\n> \n> diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp\n> index b325a06a..e5e42d39 100644\n> --- a/src/android/jpeg/post_processor_jpeg.cpp\n> +++ b/src/android/jpeg/post_processor_jpeg.cpp\n> @@ -41,12 +41,6 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,\n>  \tstreamSize_ = outCfg.size;\n>  \n>  \tthumbnailer_.configure(inCfg.size, inCfg.pixelFormat);\n> -\tStreamConfiguration thCfg = inCfg;\n> -\tthCfg.size = thumbnailer_.size();\n> -\tif (thumbnailEncoder_.configure(thCfg) != 0) {\n> -\t\tLOG(JPEG, Error) << \"Failed to configure thumbnail encoder\";\n> -\t\treturn -EINVAL;\n> -\t}\n>  \n>  \tencoder_ = std::make_unique<EncoderLibJpeg>();\n>  \n> @@ -54,14 +48,20 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,\n>  }\n>  \n>  void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,\n> +\t\t\t\t\t  const Size &targetSize,\n>  \t\t\t\t\t  std::vector<unsigned char> *thumbnail)\n>  {\n>  \t/* Stores the raw scaled-down thumbnail bytes. */\n>  \tstd::vector<unsigned char> rawThumbnail;\n>  \n> -\tthumbnailer_.createThumbnail(source, &rawThumbnail);\n> +\tthumbnailer_.createThumbnail(source, targetSize, &rawThumbnail);\n> +\n> +\tStreamConfiguration thCfg;\n> +\tthCfg.size = targetSize;\n> +\tthCfg.pixelFormat = thumbnailer_.pixelFormat();\n> +\tint ret = thumbnailEncoder_.configure(thCfg);\n\nIt may make sense to also pass the size and format to the encoder's\nencode function, but that's a possible improvement on top.\n\n>  \n> -\tif (!rawThumbnail.empty()) {\n> +\tif (!rawThumbnail.empty() && !ret) {\n>  \t\t/*\n>  \t\t * \\todo Avoid value-initialization of all elements of the\n>  \t\t * vector.\n> @@ -125,10 +125,26 @@ int PostProcessorJpeg::process(const FrameBuffer &source,\n>  \t\t\t\t\t entry.data.i64, 1);\n>  \t}\n>  \n> -\tstd::vector<unsigned char> thumbnail;\n> -\tgenerateThumbnail(source, &thumbnail);\n> -\tif (!thumbnail.empty())\n> -\t\texif.setThumbnail(thumbnail, Exif::Compression::JPEG);\n> +\tret = requestMetadata.getEntry(ANDROID_JPEG_THUMBNAIL_SIZE, &entry);\n> +\tif (ret) {\n> +\t\tconst int32_t *data = entry.data.i32;\n> +\t\tSize thumbnailSize = { static_cast<uint32_t>(data[0]),\n> +\t\t\t\t       static_cast<uint32_t>(data[1]) };\n> +\n> +\t\tif (thumbnailSize != Size(0, 0)) {\n> +\t\t\tstd::vector<unsigned char> thumbnail;\n> +\t\t\tgenerateThumbnail(source, thumbnailSize, &thumbnail);\n> +\t\t\tif (!thumbnail.empty())\n> +\t\t\t\texif.setThumbnail(thumbnail, Exif::Compression::JPEG);\n> +\t\t}\n> +\n> +\t\tresultMetadata->addEntry(ANDROID_JPEG_THUMBNAIL_SIZE, data, 2);\n> +\n> +\t\t/* \\todo Use this quality as a parameter to the encoder */\n> +\t\tret = requestMetadata.getEntry(ANDROID_JPEG_THUMBNAIL_QUALITY, &entry);\n> +\t\tif (ret)\n> +\t\t\tresultMetadata->addEntry(ANDROID_JPEG_THUMBNAIL_QUALITY, entry.data.u8, 1);\n\nLine wrap ?\n\n> +\t}\n>  \n>  \tret = requestMetadata.getEntry(ANDROID_JPEG_GPS_COORDINATES, &entry);\n>  \tif (ret) {\n> diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h\n> index d721d1b9..660b79b4 100644\n> --- a/src/android/jpeg/post_processor_jpeg.h\n> +++ b/src/android/jpeg/post_processor_jpeg.h\n> @@ -31,6 +31,7 @@ public:\n>  \n>  private:\n>  \tvoid generateThumbnail(const libcamera::FrameBuffer &source,\n> +\t\t\t       const libcamera::Size &targetSize,\n>  \t\t\t       std::vector<unsigned char> *thumbnail);\n>  \n>  \tCameraDevice *const cameraDevice_;\n> diff --git a/src/android/jpeg/thumbnailer.cpp b/src/android/jpeg/thumbnailer.cpp\n> index 5374538a..f709d343 100644\n> --- a/src/android/jpeg/thumbnailer.cpp\n> +++ b/src/android/jpeg/thumbnailer.cpp\n> @@ -32,30 +32,11 @@ void Thumbnailer::configure(const Size &sourceSize, PixelFormat pixelFormat)\n>  \t\treturn;\n>  \t}\n>  \n> -\ttargetSize_ = computeThumbnailSize();\n> -\n>  \tvalid_ = true;\n>  }\n>  \n> -/*\n> - * The Exif specification recommends the width of the thumbnail to be a\n> - * multiple of 16 (section 4.8.1). Hence, compute the corresponding height\n> - * keeping the aspect ratio same as of the source.\n> - */\n> -Size Thumbnailer::computeThumbnailSize() const\n> -{\n> -\tunsigned int targetHeight;\n> -\tconstexpr unsigned int kTargetWidth = 160;\n> -\n> -\ttargetHeight = kTargetWidth * sourceSize_.height / sourceSize_.width;\n> -\n> -\tif (targetHeight & 1)\n> -\t\ttargetHeight++;\n> -\n> -\treturn Size(kTargetWidth, targetHeight);\n> -}\n> -\n>  void Thumbnailer::createThumbnail(const FrameBuffer &source,\n> +\t\t\t\t  const Size &targetSize,\n>  \t\t\t\t  std::vector<unsigned char> *destination)\n>  {\n>  \tMappedFrameBuffer frame(&source, PROT_READ);\n> @@ -73,8 +54,8 @@ void Thumbnailer::createThumbnail(const FrameBuffer &source,\n>  \n>  \tconst unsigned int sw = sourceSize_.width;\n>  \tconst unsigned int sh = sourceSize_.height;\n> -\tconst unsigned int tw = targetSize_.width;\n> -\tconst unsigned int th = targetSize_.height;\n> +\tconst unsigned int tw = targetSize.width;\n> +\tconst unsigned int th = targetSize.height;\n>  \n>  \tASSERT(tw % 2 == 0 && th % 2 == 0);\n>  \n> diff --git a/src/android/jpeg/thumbnailer.h b/src/android/jpeg/thumbnailer.h\n> index 98f11833..bbd9832d 100644\n> --- a/src/android/jpeg/thumbnailer.h\n> +++ b/src/android/jpeg/thumbnailer.h\n> @@ -20,15 +20,15 @@ public:\n>  \tvoid configure(const libcamera::Size &sourceSize,\n>  \t\t       libcamera::PixelFormat pixelFormat);\n>  \tvoid createThumbnail(const libcamera::FrameBuffer &source,\n> +\t\t\t     const libcamera::Size &targetSize,\n>  \t\t\t     std::vector<unsigned char> *dest);\n> -\tconst libcamera::Size &size() const { return targetSize_; }\n> +\tconst libcamera::PixelFormat &pixelFormat() const { return pixelFormat_; }\n>  \n>  private:\n>  \tlibcamera::Size computeThumbnailSize() const;\n\nThis should be dropped as the function is removed.\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n>  \n>  \tlibcamera::PixelFormat pixelFormat_;\n>  \tlibcamera::Size sourceSize_;\n> -\tlibcamera::Size targetSize_;\n>  \n>  \tbool valid_;\n>  };","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 85D30C0F2B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 23 Jan 2021 09:39:59 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 0831C68292;\n\tSat, 23 Jan 2021 10:39:59 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 93E306827C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 23 Jan 2021 10:39:57 +0100 (CET)","from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi\n\t[62.78.145.57])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F2C4D3E;\n\tSat, 23 Jan 2021 10:39:56 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NONvnEV3\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1611394797;\n\tbh=vNRw2rkdFVVyOC7eBug7RB60YY7jQlyqSfZypyC8I3o=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NONvnEV3T/PxR5FtjHYaUKCDySbgfs2Kv9betvn6Kmomc470LF7ygcvqnykO4ARtB\n\tSkSAOPOZ5kuDhQyJxfUDYt0ertlzPjJoC9PoDRizplXJp9Q6skhcIxjJW5t+XcsAcu\n\tGB7G+GRds2nZ3gz2uMo2twNYpfIqxEWBf5dDwI5E=","Date":"Sat, 23 Jan 2021 11:39:37 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Message-ID":"<YAvu2XejF0TCk3N4@pendragon.ideasonboard.com>","References":"<20210123051704.188117-1-paul.elder@ideasonboard.com>\n\t<20210123051704.188117-7-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20210123051704.188117-7-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v3 6/8] android: jpeg: Configure\n\tthumbnailer based on request metadata","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>","Cc":"libcamera-devel@lists.libcamera.org","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>"}}]