From patchwork Tue Sep 7 00:20:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13707 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 57B91BDC71 for ; Tue, 7 Sep 2021 00:21:16 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 77E7369171; Tue, 7 Sep 2021 02:21:12 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kAWTBHdL"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 934C56916B for ; Tue, 7 Sep 2021 02:21:08 +0200 (CEST) Received: from pendragon.lan (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 35BB0891 for ; Tue, 7 Sep 2021 02:21:08 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630974068; bh=SnYvx102aSYO0JZckMaGntaQZxQtSYhiDQYwOxKYTyE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kAWTBHdLN4mo4hT4DqxWhMOmBzmaqnefGXLA260OCZ4mJSg09iJSZD2IOx2+2pxSf DqQ3rihMY9S8sazVaq4rAhl+CahvgWETjLmMwdkH7PfEPoCFsA0bsgmBmUmb6ISDcP gMjfrekB+pGnhFYHA04qmO5NSi6PLSQ66mxv1gEI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 7 Sep 2021 03:20:43 +0300 Message-Id: <20210907002044.7319-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210907002044.7319-1-laurent.pinchart@ideasonboard.com> References: <20210907002044.7319-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 4/5] qcam: format_converter: Add fully-planar YUV formats support X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Add support for the YUV420, YVU420 and YUV420 formats supported by libcamera. YUV420 can be produced by the Raspberry Pi pipeline handler, being able to display it is useful for testing. Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham Reviewed-by: Paul Elder --- src/qcam/format_converter.cpp | 66 +++++++++++++++++++++++++++++++++++ src/qcam/format_converter.h | 2 ++ 2 files changed, 68 insertions(+) diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp index 7979ea8a77ff..d4d3223bc698 100644 --- a/src/qcam/format_converter.cpp +++ b/src/qcam/format_converter.cpp @@ -8,6 +8,7 @@ #include "format_converter.h" #include +#include #include @@ -141,6 +142,25 @@ int FormatConverter::configure(const libcamera::PixelFormat &format, cb_pos_ = 1; break; + case libcamera::formats::YUV420: + formatFamily_ = YUVPlanar; + horzSubSample_ = 2; + vertSubSample_ = 2; + nvSwap_ = false; + break; + case libcamera::formats::YVU420: + formatFamily_ = YUVPlanar; + horzSubSample_ = 2; + vertSubSample_ = 2; + nvSwap_ = true; + break; + case libcamera::formats::YUV422: + formatFamily_ = YUVPlanar; + horzSubSample_ = 2; + vertSubSample_ = 1; + nvSwap_ = false; + break; + case libcamera::formats::MJPEG: formatFamily_ = MJPEG; break; @@ -172,6 +192,9 @@ void FormatConverter::convert(const Image *src, size_t size, QImage *dst) case YUVSemiPlanar: convertYUVSemiPlanar(src, dst->bits()); break; + case YUVPlanar: + convertYUVPlanar(src, dst->bits()); + break; }; } @@ -247,6 +270,49 @@ void FormatConverter::convertYUVPacked(const Image *srcImage, unsigned char *dst } } +void FormatConverter::convertYUVPlanar(const Image *srcImage, unsigned char *dst) +{ + unsigned int c_stride = stride_ / horzSubSample_; + unsigned int c_inc = horzSubSample_ == 1 ? 1 : 0; + const unsigned char *src_y = srcImage->data(0).data(); + const unsigned char *src_cb = srcImage->data(1).data(); + const unsigned char *src_cr = srcImage->data(2).data(); + int r, g, b; + + if (nvSwap_) + std::swap(src_cb, src_cr); + + for (unsigned int y = 0; y < height_; y++) { + const unsigned char *line_y = src_y + y * stride_; + const unsigned char *line_cb = src_cb + (y / vertSubSample_) * + c_stride; + const unsigned char *line_cr = src_cr + (y / vertSubSample_) * + c_stride; + + for (unsigned int x = 0; x < width_; x += 2) { + yuv_to_rgb(*line_y, *line_cb, *line_cr, &r, &g, &b); + dst[0] = b; + dst[1] = g; + dst[2] = r; + dst[3] = 0xff; + line_y++; + line_cb += c_inc; + line_cr += c_inc; + dst += 4; + + yuv_to_rgb(*line_y, *line_cb, *line_cr, &r, &g, &b); + dst[0] = b; + dst[1] = g; + dst[2] = r; + dst[3] = 0xff; + line_y++; + line_cb += 1; + line_cr += 1; + dst += 4; + } + } +} + void FormatConverter::convertYUVSemiPlanar(const Image *srcImage, unsigned char *dst) { unsigned int c_stride = stride_ * (2 / horzSubSample_); diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h index 9ce2cc6da7f2..9da2df5d294b 100644 --- a/src/qcam/format_converter.h +++ b/src/qcam/format_converter.h @@ -29,11 +29,13 @@ private: MJPEG, RGB, YUVPacked, + YUVPlanar, YUVSemiPlanar, }; void convertRGB(const Image *src, unsigned char *dst); void convertYUVPacked(const Image *src, unsigned char *dst); + void convertYUVPlanar(const Image *src, unsigned char *dst); void convertYUVSemiPlanar(const Image *src, unsigned char *dst); libcamera::PixelFormat format_;