[{"id":14761,"web_url":"https://patchwork.libcamera.org/comment/14761/","msgid":"<20210125121343.luprxui3lzprerl3@uno.localdomain>","date":"2021-01-25T12:13:43","subject":"Re: [libcamera-devel] [PATCH v4 8/8] android: jpeg: Set thumbnail\n\tand JPEG quality based on request","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Paul,\n\nOn Mon, Jan 25, 2021 at 04:14:44PM +0900, Paul Elder wrote:\n> Set the thumbnail quality and the JPEG quality based on the android\n> request metadata.\n>\n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nLooks good!\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n>\n> ---\n> Changes in v4:\n> - set jpeg quality to 95 by default\n>\n> New in v3\n> ---\n>  src/android/jpeg/encoder.h               |  3 ++-\n>  src/android/jpeg/encoder_libjpeg.cpp     | 10 ++++-----\n>  src/android/jpeg/encoder_libjpeg.h       |  8 ++++----\n>  src/android/jpeg/post_processor_jpeg.cpp | 26 +++++++++++-------------\n>  src/android/jpeg/post_processor_jpeg.h   |  1 +\n>  5 files changed, 24 insertions(+), 24 deletions(-)\n>\n> diff --git a/src/android/jpeg/encoder.h b/src/android/jpeg/encoder.h\n> index 027233dc..8d449369 100644\n> --- a/src/android/jpeg/encoder.h\n> +++ b/src/android/jpeg/encoder.h\n> @@ -19,7 +19,8 @@ public:\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   libcamera::Span<const uint8_t> exifData) = 0;\n> +\t\t\t   libcamera::Span<const uint8_t> exifData,\n> +\t\t\t   unsigned int quality) = 0;\n>  };\n>\n>  #endif /* __ANDROID_JPEG_ENCODER_H__ */\n> diff --git a/src/android/jpeg/encoder_libjpeg.cpp b/src/android/jpeg/encoder_libjpeg.cpp\n> index aed919b9..f006e1d1 100644\n> --- a/src/android/jpeg/encoder_libjpeg.cpp\n> +++ b/src/android/jpeg/encoder_libjpeg.cpp\n> @@ -68,7 +68,6 @@ const struct JPEGPixelFormatInfo &findPixelInfo(const PixelFormat &format)\n>  } /* namespace */\n>\n>  EncoderLibJpeg::EncoderLibJpeg()\n> -\t: quality_(95)\n>  {\n>  \t/* \\todo Expand error handling coverage with a custom handler. */\n>  \tcompress_.err = jpeg_std_error(&jerr_);\n> @@ -94,7 +93,6 @@ int EncoderLibJpeg::configure(const StreamConfiguration &cfg)\n>  \tcompress_.input_components = info.colorSpace == JCS_GRAYSCALE ? 1 : 3;\n>\n>  \tjpeg_set_defaults(&compress_);\n> -\tjpeg_set_quality(&compress_, quality_, TRUE);\n>\n>  \tpixelFormatInfo_ = &info.pixelFormatInfo;\n>\n> @@ -180,7 +178,7 @@ void EncoderLibJpeg::compressNV(Span<const uint8_t> frame)\n>  }\n>\n>  int EncoderLibJpeg::encode(const FrameBuffer &source, Span<uint8_t> dest,\n> -\t\t\t   Span<const uint8_t> exifData)\n> +\t\t\t   Span<const uint8_t> exifData, unsigned int quality)\n>  {\n>  \tMappedFrameBuffer frame(&source, PROT_READ);\n>  \tif (!frame.isValid()) {\n> @@ -189,15 +187,17 @@ 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);\n> +\treturn encode(frame.maps()[0], dest, 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)\n> +\t\t\t   Span<const uint8_t> exifData, 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>  \t * The jpeg_mem_dest will reallocate if the required size is not\n>  \t * sufficient. That means the output won't be written to the correct\n> diff --git a/src/android/jpeg/encoder_libjpeg.h b/src/android/jpeg/encoder_libjpeg.h\n> index 070f56f8..838da772 100644\n> --- a/src/android/jpeg/encoder_libjpeg.h\n> +++ b/src/android/jpeg/encoder_libjpeg.h\n> @@ -23,10 +23,12 @@ public:\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   libcamera::Span<const uint8_t> exifData) override;\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   libcamera::Span<const uint8_t> exifData);\n> +\t\t   libcamera::Span<const uint8_t> exifData,\n> +\t\t   unsigned int quality);\n>\n>  private:\n>  \tvoid compressRGB(libcamera::Span<const uint8_t> frame);\n> @@ -35,8 +37,6 @@ private:\n>  \tstruct jpeg_compress_struct compress_;\n>  \tstruct jpeg_error_mgr jerr_;\n>\n> -\tunsigned int quality_;\n> -\n>  \tconst libcamera::PixelFormatInfo *pixelFormatInfo_;\n>\n>  \tbool nv_;\n> diff --git a/src/android/jpeg/post_processor_jpeg.cpp b/src/android/jpeg/post_processor_jpeg.cpp\n> index d35fe361..f52a791a 100644\n> --- a/src/android/jpeg/post_processor_jpeg.cpp\n> +++ b/src/android/jpeg/post_processor_jpeg.cpp\n> @@ -51,6 +51,7 @@ int PostProcessorJpeg::configure(const StreamConfiguration &inCfg,\n>\n>  void PostProcessorJpeg::generateThumbnail(const FrameBuffer &source,\n>  \t\t\t\t\t  const Size &targetSize,\n> +\t\t\t\t\t  unsigned int quality,\n>  \t\t\t\t\t  std::vector<unsigned char> *thumbnail)\n>  {\n>  \t/* Stores the raw scaled-down thumbnail bytes. */\n> @@ -71,7 +72,7 @@ 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, {});\n> +\t\t\t\t\t\t\t *thumbnail, {}, quality);\n>  \t\tthumbnail->resize(jpeg_size);\n>\n>  \t\tLOG(JPEG, Debug)\n> @@ -133,20 +134,18 @@ int PostProcessorJpeg::process(const FrameBuffer &source,\n>  \t\tSize thumbnailSize = { static_cast<uint32_t>(data[0]),\n>  \t\t\t\t       static_cast<uint32_t>(data[1]) };\n>\n> +\t\tret = requestMetadata.getEntry(ANDROID_JPEG_THUMBNAIL_QUALITY, &entry);\n> +\t\tuint8_t quality = ret ? *entry.data.u8 : 95;\n> +\t\tresultMetadata->addEntry(ANDROID_JPEG_THUMBNAIL_QUALITY, &quality, 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\tgenerateThumbnail(source, thumbnailSize, quality, &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,\n> -\t\t\t\t\t\t entry.data.u8, 1);\n>  \t}\n>\n>  \tret = requestMetadata.getEntry(ANDROID_JPEG_GPS_COORDINATES, &entry);\n> @@ -167,7 +166,11 @@ int PostProcessorJpeg::process(const FrameBuffer &source,\n>  \tif (exif.generate() != 0)\n>  \t\tLOG(JPEG, Error) << \"Failed to generate valid EXIF data\";\n>\n> -\tint jpeg_size = encoder_->encode(source, destination, exif.data());\n> +\tret = requestMetadata.getEntry(ANDROID_JPEG_QUALITY, &entry);\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, exif.data(), quality);\n>  \tif (jpeg_size < 0) {\n>  \t\tLOG(JPEG, Error) << \"Failed to encode stream image\";\n>  \t\treturn jpeg_size;\n> @@ -195,10 +198,5 @@ int PostProcessorJpeg::process(const FrameBuffer &source,\n>  \t/* Update the JPEG result Metadata. */\n>  \tresultMetadata->addEntry(ANDROID_JPEG_SIZE, &jpeg_size, 1);\n>\n> -\t/* \\todo Configure JPEG encoder with this */\n> -\tret = requestMetadata.getEntry(ANDROID_JPEG_QUALITY, &entry);\n> -\tconst uint32_t jpegQuality = ret ? *entry.data.u8 : 95;\n> -\tresultMetadata->addEntry(ANDROID_JPEG_QUALITY, &jpegQuality, 1);\n> -\n>  \treturn 0;\n>  }\n> diff --git a/src/android/jpeg/post_processor_jpeg.h b/src/android/jpeg/post_processor_jpeg.h\n> index 660b79b4..d2dfa450 100644\n> --- a/src/android/jpeg/post_processor_jpeg.h\n> +++ b/src/android/jpeg/post_processor_jpeg.h\n> @@ -32,6 +32,7 @@ public:\n>  private:\n>  \tvoid generateThumbnail(const libcamera::FrameBuffer &source,\n>  \t\t\t       const libcamera::Size &targetSize,\n> +\t\t\t       unsigned int quality,\n>  \t\t\t       std::vector<unsigned char> *thumbnail);\n>\n>  \tCameraDevice *const cameraDevice_;\n> --\n> 2.27.0\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","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 AE336BD808\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 25 Jan 2021 12:13:30 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 12CBB682C7;\n\tMon, 25 Jan 2021 13:13:30 +0100 (CET)","from relay1-d.mail.gandi.net (relay1-d.mail.gandi.net\n\t[217.70.183.193])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 118EE682BB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 25 Jan 2021 13:13:28 +0100 (CET)","from uno.localdomain (93-34-118-233.ip49.fastwebnet.it\n\t[93.34.118.233]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay1-d.mail.gandi.net (Postfix) with ESMTPSA id 8A9CF240010;\n\tMon, 25 Jan 2021 12:13:27 +0000 (UTC)"],"X-Originating-IP":"93.34.118.233","Date":"Mon, 25 Jan 2021 13:13:43 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Paul Elder <paul.elder@ideasonboard.com>","Message-ID":"<20210125121343.luprxui3lzprerl3@uno.localdomain>","References":"<20210125071444.26252-1-paul.elder@ideasonboard.com>\n\t<20210125071444.26252-9-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20210125071444.26252-9-paul.elder@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v4 8/8] android: jpeg: Set thumbnail\n\tand JPEG quality based on request","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>"}}]