From patchwork Mon Aug 31 08:46:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Konovalov X-Patchwork-Id: 9435 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 D491EBF019 for ; Mon, 31 Aug 2020 08:47:19 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2C39562919; Mon, 31 Aug 2020 10:47:19 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="J5k0agJO"; dkim-atps=neutral Received: from mail-lj1-x241.google.com (mail-lj1-x241.google.com [IPv6:2a00:1450:4864:20::241]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8C78C60376 for ; Mon, 31 Aug 2020 10:47:18 +0200 (CEST) Received: by mail-lj1-x241.google.com with SMTP id c2so1604105ljj.12 for ; Mon, 31 Aug 2020 01:47:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=wvvZ9t7LSLOO5MS0bgUpqIuWDGl6eYU25kSszgRyD+0=; b=J5k0agJOXd263s3JLV0KYCEvnbOTNvQ8nNysSruzoUmddtR3KMvG6WHevDUgN8k6us nHPtiBNYByEPNJDDTkVckycKxuWohYpXEsN1+dpUx3coR8E2yy3gPi4cixk+OC5Cx+50 QkEZ7HQwa480G2mXwhPzrW2Ng5BO4ay9Cy/yykLw92QXTYzhLjTQcwQ9+UDyXmcGk8Rz w53QCdoiw3o0/bg/SgX5T3vXyyHABviZCBLvlVmufZXnUlfKsOosuFwNbHMSKuDYXCF9 bagp4fk60CiZpsR092Bt5qwvuY+WqlLU7/D98/VJLgUC2mDvRQg2LJNPLl9z15dTeYzN 64LQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=wvvZ9t7LSLOO5MS0bgUpqIuWDGl6eYU25kSszgRyD+0=; b=YzEg8uKtzZR5F9tQ8XpsSgly640AHIpoFUKZmi9IGwgdjzkiOqDwUwv2CINkuA7fSz H/uHIO3qPz2PnAfNhsNcCYQJgP6aey4rWVVbcno97u38HsMmhCHUJZ1XFoMqlmFfriq9 K/dzxtxQdQI+/yJ7dhp5gZiwPk/Dk2PJGSZziN7g/rzJq0VouUAGSd0q2Gx5BAFFuEdD gXyvtrYyyDACvkgFqOYG6LFFtBLOrM9CQnoGe04K5xvKvp5kNQQn9x3aGWTNnlzULi1C iulEBl6pweZd1MuPHU/T6WcCnRgCq5BXJKKJh+uzJKk7Dl02fEqNYDwiLdG9rxBs7ful TIcA== X-Gm-Message-State: AOAM530gR9R1KRAm8BGG3JgQlmnL45kyyGit+mGoDiPMA9t/IQGxFl4W /yObz3FymuPFrE/Kg6dT05ihDe0wuUQN5Q== X-Google-Smtp-Source: ABdhPJzD7jBT9ovl7u3C4tmb+aPEEI/D/bDgdBGHl6ETB6tIPCON2owlJ7nOYvBC78bGNYAZ1rwCrA== X-Received: by 2002:a05:651c:c6:: with SMTP id 6mr166727ljr.237.1598863637208; Mon, 31 Aug 2020 01:47:17 -0700 (PDT) Received: from localhost.localdomain (37-144-159-139.broadband.corbina.ru. [37.144.159.139]) by smtp.googlemail.com with ESMTPSA id r7sm320061lfn.84.2020.08.31.01.47.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 31 Aug 2020 01:47:16 -0700 (PDT) From: Andrey Konovalov To: libcamera-devel@lists.libcamera.org Date: Mon, 31 Aug 2020 11:46:45 +0300 Message-Id: <20200831084645.20683-1-andrey.konovalov@linaro.org> X-Mailer: git-send-email 2.17.1 Subject: [libcamera-devel] [RFC PATCH] qcam: format_converter: add 10 and 12 bit packed raw Bayer formats 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: , MIME-Version: 1.0 Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" No interpolation is used to get more speed by the price of lower image quality. In qcam format_converter is used for viewfinder only, and in this case lower lag is more important than the image quality. Signed-off-by: Andrey Konovalov --- Only SRGGB10P and SRGGB12P formats were tested (the ones I can get from the camera sensor I am currently using) src/qcam/format_converter.cpp | 118 ++++++++++++++++++++++++++++++++++ src/qcam/format_converter.h | 14 ++++ 2 files changed, 132 insertions(+) diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp index 4b9722d..c9f94d3 100644 --- a/src/qcam/format_converter.cpp +++ b/src/qcam/format_converter.cpp @@ -136,6 +136,62 @@ int FormatConverter::configure(const libcamera::PixelFormat &format, formatFamily_ = MJPEG; break; + case libcamera::formats::SRGGB10_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 0; + bpp_numer_ = 4; + bpp_denom_ = 5; + break; + + case libcamera::formats::SGRBG10_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 1; + bpp_numer_ = 4; + bpp_denom_ = 5; + break; + + case libcamera::formats::SGBRG10_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 2; + bpp_numer_ = 4; + bpp_denom_ = 5; + break; + + case libcamera::formats::SBGGR10_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 3; + bpp_numer_ = 4; + bpp_denom_ = 5; + break; + + case libcamera::formats::SRGGB12_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 0; + bpp_numer_ = 2; + bpp_denom_ = 3; + break; + + case libcamera::formats::SGRBG12_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 1; + bpp_numer_ = 2; + bpp_denom_ = 3; + break; + + case libcamera::formats::SGBRG12_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 2; + bpp_numer_ = 2; + bpp_denom_ = 3; + break; + + case libcamera::formats::SBGGR12_CSI2P: + formatFamily_ = RAW_CSI2P; + r_pos_ = 3; + bpp_numer_ = 2; + bpp_denom_ = 3; + break; + default: return -EINVAL; }; @@ -163,9 +219,71 @@ void FormatConverter::convert(const unsigned char *src, size_t size, case NV: convertNV(src, dst->bits()); break; + case RAW_CSI2P: + convertRAW_CSI2P(src, dst->bits()); + break; }; } +/* + * The pixels are processed in groups of 4 (2 by 2 squares), and the + * assumption is that height_ and width_ are even numbers. + */ +void FormatConverter::convertRAW_CSI2P(const unsigned char *src, + unsigned char *dst) +{ + unsigned int r_pos, b_pos, g1_pos, g2_pos; + unsigned char r, g1, g2, b; + unsigned int s_linelen = width_ * bpp_denom_ / bpp_numer_; + unsigned int d_linelen = width_ * 4; + + /* + * Calculate the offsets of the color values in the src buffer. + * g1 is green value from the even (upper) line, g2 is the green + * value from the odd (lower) line. + */ + if ( r_pos_ > 1) { + r_pos = r_pos_ - 2 + s_linelen; + b_pos = 3 - r_pos_; + } else { + r_pos = r_pos_; + b_pos = 1 - r_pos_ + s_linelen; + } + g1_pos = (r_pos == 0 || b_pos == 0) ? 1 : 0; + g2_pos = 1 - g1_pos + s_linelen; + + for (unsigned int y = 0; y < height_; y += 2) { + for (unsigned x = 0; x < width_; x += bpp_numer_) { + for (unsigned int i = 0; i < bpp_numer_ ; i += 2) { + /* read the colors for the current 2x2 group: */ + r = src[r_pos]; + g1 = src[g1_pos]; + g2 = src[g2_pos]; + b = src[b_pos]; + src += 2; + /* two left pixels of the four: */ + dst[0] = dst[0 + d_linelen] = b; + dst[1] = g1; + dst[1 + d_linelen] = g2; + dst[2] = dst[2 + d_linelen] = r; + dst[3] = dst[3 + d_linelen] = 0xff; + dst += 4; + /* two right pixels of the four: */ + dst[0] = dst[0 + d_linelen] = b; + dst[1] = g1; + dst[1 + d_linelen] = g2; + dst[2] = dst[2 + d_linelen] = r; + dst[3] = dst[3 + d_linelen] = 0xff; + dst += 4; + } + src += bpp_denom_ - bpp_numer_; + } + /* move to the next even line: */ + src += s_linelen; + dst += d_linelen; + } +} + static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b) { int c = y - 16; diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h index e389b24..5d4f31f 100644 --- a/src/qcam/format_converter.h +++ b/src/qcam/format_converter.h @@ -26,11 +26,13 @@ private: enum FormatFamily { MJPEG, NV, + RAW_CSI2P, RGB, YUV, }; void convertNV(const unsigned char *src, unsigned char *dst); + void convertRAW_CSI2P(const unsigned char *src, unsigned char *dst); void convertRGB(const unsigned char *src, unsigned char *dst); void convertYUV(const unsigned char *src, unsigned char *dst); @@ -45,6 +47,18 @@ private: unsigned int vertSubSample_; bool nvSwap_; + /* RAW Bayer CSI2P parameters */ + /* + * Bytes per pixel is a fractional number, and is represented by + * integer numerator and denominator. + */ + unsigned int bpp_numer_; + unsigned int bpp_denom_; + /* + * Unsigned int r_pos_ from RGB parameters is reused; blue + * and green positions are deduced from the red one. + */ + /* RGB parameters */ unsigned int bpp_; unsigned int r_pos_;