summaryrefslogtreecommitdiff
path: root/src/qcam/format_converter.cpp
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2019-05-04 16:29:54 -0400
committerPaul Elder <paul.elder@ideasonboard.com>2019-05-07 09:27:07 -0400
commitb9a47058eb46281dd0c365b9e18a323994791498 (patch)
tree58db1183d23b5236493523738baf66844949f8d8 /src/qcam/format_converter.cpp
parentb09b13dbf6921a5474b847ba940f0c38e3e37c71 (diff)
qcam: format_converter: Add NV formats support
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 <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/qcam/format_converter.cpp')
-rw-r--r--src/qcam/format_converter.cpp99
1 files changed, 89 insertions, 10 deletions
diff --git a/src/qcam/format_converter.cpp b/src/qcam/format_converter.cpp
index 192767c2..86b03b2c 100644
--- a/src/qcam/format_converter.cpp
+++ b/src/qcam/format_converter.cpp
@@ -31,6 +31,42 @@ int FormatConverter::configure(unsigned int format, unsigned int width,
unsigned int height)
{
switch (format) {
+ 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_BGR24:
formatFamily_ = RGB;
r_pos_ = 2;
@@ -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 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;
+ const unsigned char *src_c = src + width_ * height_;
+ int r, g, b;
+
+ for (unsigned int y = 0; y < height_; y++) {
+ const unsigned char *src_y = src + y * width_;
+ const unsigned char *src_cb = src_c + (y / vertSubSample_) *
+ c_stride + cb_pos;
+ const unsigned char *src_cr = src_c + (y / vertSubSample_) *
+ c_stride + cr_pos;
+
+ for (unsigned int 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;