aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Ribalda Delgado <ricardo@ribalda.com>2019-04-17 13:41:35 +0200
committerHans de Goede <hdegoede@redhat.com>2019-04-18 13:03:23 +0200
commite30639edd74f12f8f58d8e9cf10d85a1f071a6c3 (patch)
tree25f7e054911ea0773c9eab057fd16f31e30a711d
parent4bbc3d0f15bc352fb1545ebce382f83398f2ec44 (diff)
libv4lconvert: Add support for V4L2_PIX_FMT_NV12
NV12 is a two-plane version YUV 4:2:0, where the U and V components are subsampled 2x2. Signed-off-by: Ricardo Ribalda Delgado <ricardo@ribalda.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--lib/libv4lconvert/libv4lconvert-priv.h6
-rw-r--r--lib/libv4lconvert/libv4lconvert.c19
-rw-r--r--lib/libv4lconvert/rgbyuv.c56
3 files changed, 81 insertions, 0 deletions
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index 5286a9b1..ce5970c9 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -286,6 +286,12 @@ void v4lconvert_hm12_to_yuv420(const unsigned char *src,
void v4lconvert_hsv_to_rgb24(const unsigned char *src, unsigned char *dest,
int width, int height, int bgr, int Xin, unsigned char hsv_enc);
+void v4lconvert_nv12_to_rgb24(const unsigned char *src, unsigned char *dest,
+ int width, int height, int bgr);
+
+void v4lconvert_nv12_to_yuv420(const unsigned char *src, unsigned char *dest,
+ int width, int height, int yvu);
+
void v4lconvert_rotate90(unsigned char *src, unsigned char *dest,
struct v4l2_format *fmt);
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index 379e5087..5945be43 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -139,6 +139,7 @@ static const struct v4lconvert_pixfmt supported_src_pixfmts[] = {
{ V4L2_PIX_FMT_SN9C20X_I420, 12, 6, 3, 1 },
{ V4L2_PIX_FMT_M420, 12, 6, 3, 1 },
{ V4L2_PIX_FMT_HM12, 12, 6, 3, 1 },
+ { V4L2_PIX_FMT_NV12, 12, 6, 3, 1 },
{ V4L2_PIX_FMT_CPIA1, 0, 6, 3, 1 },
/* JPEG and variants */
{ V4L2_PIX_FMT_MJPEG, 0, 7, 7, 0 },
@@ -932,6 +933,24 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
}
break;
+ /* NV12 formats */
+ case V4L2_PIX_FMT_NV12:
+ switch (dest_pix_fmt) {
+ case V4L2_PIX_FMT_RGB24:
+ v4lconvert_nv12_to_rgb24(src, dest, width, height, 0);
+ break;
+ case V4L2_PIX_FMT_BGR24:
+ v4lconvert_nv12_to_rgb24(src, dest, width, height, 1);
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ v4lconvert_nv12_to_yuv420(src, dest, width, height, 0);
+ break;
+ case V4L2_PIX_FMT_YVU420:
+ v4lconvert_nv12_to_yuv420(src, dest, width, height, 1);
+ break;
+ }
+ break;
+
/* compressed bayer formats */
case V4L2_PIX_FMT_SPCA561:
case V4L2_PIX_FMT_SN9C10X:
diff --git a/lib/libv4lconvert/rgbyuv.c b/lib/libv4lconvert/rgbyuv.c
index 02c8cb5b..79bc0bdb 100644
--- a/lib/libv4lconvert/rgbyuv.c
+++ b/lib/libv4lconvert/rgbyuv.c
@@ -845,3 +845,59 @@ void v4lconvert_hsv_to_rgb24(const unsigned char *src, unsigned char *dest,
src += bppIN;
}
}
+
+void v4lconvert_nv12_to_rgb24(const unsigned char *src, unsigned char *dest,
+ int width, int height, int bgr)
+{
+ int i, j;
+ const unsigned char *ysrc = src;
+ const unsigned char *uvsrc = src + width * height;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j ++) {
+ if (bgr) {
+ *dest++ = YUV2B(*ysrc, *uvsrc, *(uvsrc + 1));
+ *dest++ = YUV2G(*ysrc, *uvsrc, *(uvsrc + 1));
+ *dest++ = YUV2R(*ysrc, *uvsrc, *(uvsrc + 1));
+ } else {
+ *dest++ = YUV2R(*ysrc, *uvsrc, *(uvsrc + 1));
+ *dest++ = YUV2G(*ysrc, *uvsrc, *(uvsrc + 1));
+ *dest++ = YUV2B(*ysrc, *uvsrc, *(uvsrc + 1));
+ }
+ ysrc++;
+ if (j&1)
+ uvsrc += 2;
+ }
+
+ /* Rewind u and v for next line */
+ if (!(i&1))
+ uvsrc -= width;
+ }
+}
+
+void v4lconvert_nv12_to_yuv420(const unsigned char *src, unsigned char *dest,
+ int width, int height, int yvu)
+{
+ int i, j;
+ const unsigned char *ysrc = src;
+ const unsigned char *uvsrc = src + width * height;
+ unsigned char *ydst = dest;
+ unsigned char *udst, *vdst;
+
+ if (yvu) {
+ vdst = ydst + width * height;
+ udst = vdst + ((width / 2) * (height / 2));
+ } else {
+ udst = ydst + width * height;
+ vdst = udst + ((width / 2) * (height / 2));
+ }
+
+ for (i = 0; i < height; i++)
+ for (j = 0; i < width; j++) {
+ *ydst++ = *ysrc++;
+ if (((i % 2) == 0) && ((j % 2) == 0)) {
+ *udst++ = *uvsrc++;
+ *vdst++ = *uvsrc++;
+ }
+ }
+}

Privacy Policy