From patchwork Mon Sep 6 23:04:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 13701 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 1181EBEFBE for ; Mon, 6 Sep 2021 23:05:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 1DE0269173; Tue, 7 Sep 2021 01:05:03 +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="qLtce0sm"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6513369167 for ; Tue, 7 Sep 2021 01:04:59 +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 0C79D891 for ; Tue, 7 Sep 2021 01:04:58 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1630969499; bh=SnYvx102aSYO0JZckMaGntaQZxQtSYhiDQYwOxKYTyE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=qLtce0sm39nXAQf8CIIrt6HKJaLJREn6zgVNhq5Lm0mV7oPXRPZa5xSbYyFT4WjfH q9NOvupARxAOWMTlWTipuzXW8T/dGRuP9ab0tMNl9IEomVw8PTloChbvV2dEx8whrN jkN5dUOXp+ug7qSoOiz3qCXJW8V3cUzEKP2ANV5c= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Date: Tue, 7 Sep 2021 02:04:35 +0300 Message-Id: <20210906230436.17106-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210906230436.17106-1-laurent.pinchart@ideasonboard.com> References: <20210906230436.17106-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 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 --- 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_;