diff options
author | Ricardo Ribalda Delgado <ricardo@ribalda.com> | 2019-04-17 13:41:35 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2019-04-18 13:03:23 +0200 |
commit | e30639edd74f12f8f58d8e9cf10d85a1f071a6c3 (patch) | |
tree | 25f7e054911ea0773c9eab057fd16f31e30a711d | |
parent | 4bbc3d0f15bc352fb1545ebce382f83398f2ec44 (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.h | 6 | ||||
-rw-r--r-- | lib/libv4lconvert/libv4lconvert.c | 19 | ||||
-rw-r--r-- | lib/libv4lconvert/rgbyuv.c | 56 |
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++; + } + } +} |