From patchwork Mon May 6 20:15:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1161 Return-Path: Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9020560E63 for ; Mon, 6 May 2019 22:15:36 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 7F238115F; Mon, 6 May 2019 22:15:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1557173736; bh=tmRxzJV3lTiNIIItR6qG7wfVGpb0rmD0IWQS01wB06g=; h=From:To:Cc:Subject:Date:From; b=Ei8c6RS0fh8XFhhzB7/RAvac/8JbjMyJA6doOkPDqpDKJXD0aR4INgwQFOovmoEEd vvsuo2ti+FOl8xzNkO3c6b/6E/YUQu4/QkT7JFO6KTAKMiaaJAj7eVYeLb8JEG9MpN p5N9hA4Y3P36FW338uDmuVa2n0hVvVwTHpIXzA08= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 6 May 2019 16:15:27 -0400 Message-Id: <20190506201528.24445-1-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 1/2] qcam: format_converter: Add formatFamily enum X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2019 20:15:36 -0000 It is not sustainable to add a new flag for every new video format family (eg. YUYV, RGB, NV, MJPEG, etc), so add a formatFamily enum to indicate these in the FormatConverter. Note that formats are grouped into families based on if they are able to share a set of parameters for conversion. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- Changes in v2: rename enum formatFamily to enum FormatFamily src/qcam/format_converter.cpp | 27 ++++++++++++++++----------- src/qcam/format_converter.h | 11 ++++++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp index d9088c3..192767c 100644 --- a/src/qcam/format_converter.cpp +++ b/src/qcam/format_converter.cpp @@ -32,48 +32,48 @@ int FormatConverter::configure(unsigned int format, unsigned int width, { switch (format) { case V4L2_PIX_FMT_BGR24: - yuv_ = false; + formatFamily_ = RGB; r_pos_ = 2; g_pos_ = 1; b_pos_ = 0; bpp_ = 3; break; case V4L2_PIX_FMT_RGB24: - yuv_ = false; + formatFamily_ = RGB; r_pos_ = 0; g_pos_ = 1; b_pos_ = 2; bpp_ = 3; break; case V4L2_PIX_FMT_ARGB32: - yuv_ = false; + formatFamily_ = RGB; r_pos_ = 1; g_pos_ = 2; b_pos_ = 3; bpp_ = 4; break; case V4L2_PIX_FMT_VYUY: - yuv_ = true; + formatFamily_ = YUV; y_pos_ = 1; cb_pos_ = 2; break; case V4L2_PIX_FMT_YVYU: - yuv_ = true; + formatFamily_ = YUV; y_pos_ = 0; cb_pos_ = 3; break; case V4L2_PIX_FMT_UYVY: - yuv_ = true; + formatFamily_ = YUV; y_pos_ = 1; cb_pos_ = 0; break; case V4L2_PIX_FMT_YUYV: - yuv_ = true; + formatFamily_ = YUV; y_pos_ = 0; cb_pos_ = 1; break; case V4L2_PIX_FMT_MJPEG: - yuv_ = false; + formatFamily_ = MJPEG; break; default: return -EINVAL; @@ -89,12 +89,17 @@ int FormatConverter::configure(unsigned int format, unsigned int width, void FormatConverter::convert(const unsigned char *src, size_t size, QImage *dst) { - if (format_ == V4L2_PIX_FMT_MJPEG) + switch (formatFamily_) { + case MJPEG: dst->loadFromData(src, size, "JPEG"); - else if (yuv_) + break; + case YUV: convertYUV(src, dst->bits()); - else + break; + case RGB: convertRGB(src, dst->bits()); + break; + }; } void FormatConverter::convertRGB(const unsigned char *src, unsigned char *dst) diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h index 76cd9f1..c18871e 100644 --- a/src/qcam/format_converter.h +++ b/src/qcam/format_converter.h @@ -14,6 +14,12 @@ class QImage; class FormatConverter { public: + enum FormatFamily { + MJPEG, + RGB, + YUV, + }; + int configure(unsigned int format, unsigned int width, unsigned int height); @@ -27,12 +33,15 @@ private: unsigned int width_; unsigned int height_; + enum FormatFamily formatFamily_; + + /* RGB parameters */ unsigned int bpp_; unsigned int r_pos_; unsigned int g_pos_; unsigned int b_pos_; - bool yuv_; + /* YUV parameters */ unsigned int y_pos_; unsigned int cb_pos_; }; From patchwork Mon May 6 20:15:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 1162 Return-Path: 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 3B6AE60E63 for ; Mon, 6 May 2019 22:15:37 +0200 (CEST) Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 72728124B; Mon, 6 May 2019 22:15:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1557173736; bh=0B7HvSx2+neaInLbb2VQ84YrUHw4F2cT4TAgIGFQA1A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ifdymx7ThuNETCx/sFI3swMErBxH3R2mN/c4BoddVoILxZUb7VUQi3MJuM28OpWNc 5aXsl8TpD30aOxufksQrGwHZ7DVWiJFQb02NKl9TtWXGyuYELDtpVKNZAMJT7224cE CdoRliBabudlGVcTFnx2VAYpZkHALNNnzAp1eHMo= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Mon, 6 May 2019 16:15:28 -0400 Message-Id: <20190506201528.24445-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190506201528.24445-1-paul.elder@ideasonboard.com> References: <20190506201528.24445-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v2 2/2] qcam: format_converter: Add NV formats support X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 May 2019 20:15:37 -0000 Add support for some NV formats: - V4L2_PIX_FMT_NV12, V4L2_PIX_FMT_NV21 - V4L2_PIX_FMT_NV16, V4L2_PIX_FMT_NV61 - V4L2_PIX_FMT_NV24, V4L2_PIX_FMT_NV42 Signed-off-by: Paul Elder --- Changes in v2: - reorder functions in format_converter.cpp to match format_converter.h (move yuv_to_rgb() to be before all specialized convert functions) - renamed NV conversion parameters from xDownSample_ and yDownSample_ to horzSubSample_ and vertSubSample_, respectively - unrolled the loop and simplify some of the calculations in convertNV() and achieved a 1.67 speedup compared to v1 src/qcam/format_converter.cpp | 99 +++++++++++++++++++++++++++++++---- src/qcam/format_converter.h | 7 +++ 2 files changed, 96 insertions(+), 10 deletions(-) diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp index 192767c..eab222f 100644 --- a/src/qcam/format_converter.cpp +++ b/src/qcam/format_converter.cpp @@ -72,6 +72,42 @@ int FormatConverter::configure(unsigned int format, unsigned int width, y_pos_ = 0; cb_pos_ = 1; break; + case V4L2_PIX_FMT_NV12: + formatFamily_ = NV; + horzSubSample_ = 2; + vertSubSample_ = 2; + nvSwap_ = false; + break; + case V4L2_PIX_FMT_NV21: + formatFamily_ = NV; + horzSubSample_ = 2; + vertSubSample_ = 2; + nvSwap_ = true; + break; + case V4L2_PIX_FMT_NV16: + formatFamily_ = NV; + horzSubSample_ = 2; + vertSubSample_ = 1; + nvSwap_ = false; + break; + case V4L2_PIX_FMT_NV61: + formatFamily_ = NV; + horzSubSample_ = 2; + vertSubSample_ = 1; + nvSwap_ = true; + break; + case V4L2_PIX_FMT_NV24: + formatFamily_ = NV; + horzSubSample_ = 1; + vertSubSample_ = 1; + nvSwap_ = false; + break; + case V4L2_PIX_FMT_NV42: + formatFamily_ = NV; + horzSubSample_ = 1; + vertSubSample_ = 1; + nvSwap_ = true; + break; case V4L2_PIX_FMT_MJPEG: formatFamily_ = MJPEG; break; @@ -99,9 +135,62 @@ void FormatConverter::convert(const unsigned char *src, size_t size, case RGB: convertRGB(src, dst->bits()); break; + case NV: + convertNV(src, dst->bits()); + break; }; } +static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b) +{ + int c = y - 16; + int d = u - 128; + int e = v - 128; + *r = CLIP(( 298 * c + 409 * e + 128) >> RGBSHIFT); + *g = CLIP(( 298 * c - 100 * d - 208 * e + 128) >> RGBSHIFT); + *b = CLIP(( 298 * c + 516 * d + 128) >> RGBSHIFT); +} + +void FormatConverter::convertNV(const unsigned char *src, unsigned char *dst) +{ + unsigned int x, y; + int r, g, b; + + unsigned int c_stride = width_ * (2 / horzSubSample_); + unsigned int c_inc = horzSubSample_ == 1 ? 2 : 0; + unsigned int cb_pos = nvSwap_ ? 1 : 0; + unsigned int cr_pos = nvSwap_ ? 0 : 1; + unsigned int base = width_ * height_; + + for (y = 0; y < height_; y++) { + unsigned char *src_y = (unsigned char *)src + y * width_; + unsigned char *src_cb = (unsigned char *)src + base + (y / vertSubSample_) * c_stride + cb_pos; + unsigned char *src_cr = (unsigned char *)src + base + (y / vertSubSample_) * c_stride + cr_pos; + + for (x = 0; x < width_; x += 2) { + yuv_to_rgb(*src_y, *src_cb, *src_cr, &r, &g, &b); + dst[0] = b; + dst[1] = g; + dst[2] = r; + dst[3] = 0xff; + src_y++; + src_cb += c_inc; + src_cr += c_inc; + dst += 4; + + yuv_to_rgb(*src_y, *src_cb, *src_cr, &r, &g, &b); + dst[0] = b; + dst[1] = g; + dst[2] = r; + dst[3] = 0xff; + src_y++; + src_cb += 2; + src_cr += 2; + dst += 4; + } + } +} + void FormatConverter::convertRGB(const unsigned char *src, unsigned char *dst) { unsigned int x, y; @@ -124,16 +213,6 @@ void FormatConverter::convertRGB(const unsigned char *src, unsigned char *dst) } } -static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b) -{ - int c = y - 16; - int d = u - 128; - int e = v - 128; - *r = CLIP(( 298 * c + 409 * e + 128) >> RGBSHIFT); - *g = CLIP(( 298 * c - 100 * d - 208 * e + 128) >> RGBSHIFT); - *b = CLIP(( 298 * c + 516 * d + 128) >> RGBSHIFT); -} - void FormatConverter::convertYUV(const unsigned char *src, unsigned char *dst) { unsigned int src_x, src_y, dst_x, dst_y; diff --git a/src/qcam/format_converter.h b/src/qcam/format_converter.h index c18871e..ad67081 100644 --- a/src/qcam/format_converter.h +++ b/src/qcam/format_converter.h @@ -16,6 +16,7 @@ class FormatConverter public: enum FormatFamily { MJPEG, + NV, RGB, YUV, }; @@ -26,6 +27,7 @@ public: void convert(const unsigned char *src, size_t size, QImage *dst); private: + void convertNV(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); @@ -35,6 +37,11 @@ private: enum FormatFamily formatFamily_; + /* NV parameters */ + unsigned int horzSubSample_; + unsigned int vertSubSample_; + bool nvSwap_; + /* RGB parameters */ unsigned int bpp_; unsigned int r_pos_;