Re: [PATCH] libv4lconvert: Add support for V4L2_PIX_FMT_NV12

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Ricardo,

On 16-04-19 14:02, Ricardo Ribalda Delgado wrote:
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@xxxxxxxxxxx>

Your patch looks good to me, but it pushed the array-size of
the supported_src_pixfmts array over 64 entries (right now it is
exactly 64 entries big).

Which breaks supported_src_formats as that is only 64 bits big:

struct v4lconvert_data {
        int fd;
	...
        int64_t supported_src_formats; /* bitfield */


See e.g. :

                for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++)
                        if (fmt.pixelformat == supported_src_pixfmts[j].fmt)
                                break;

                if (j < ARRAY_SIZE(supported_src_pixfmts)) {
                        data->supported_src_formats |= 1ULL << j;

I believe this is best fixed by a preparation patch which introduces the
bit-ops from the kernel for this:

include/asm-generic/bitops/non-atomic.h:

static inline void __set_bit(int nr, volatile unsigned long *addr)
{
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

        *p  |= mask;
}

static inline void __clear_bit(int nr, volatile unsigned long *addr)
{
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);

        *p &= ~mask;
}

static inline int test_bit(int nr, const volatile unsigned long *addr)
{
        return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
}

So you will have to change your patch into a 2 patch patch-set with
the first patch introducing  set_bit / clear_bit / test_bit helpers
modelled after the kernel and changing the declaration of
supported_src_formats to:

	unsigned long supported_src_formats[128 / BITS_PER_LONG];

Thanks & Regards,

Hans









---
The code has ben tested with qv4l2 and vivid.
v4lconvert_nv12_to_yuv420 has not been tested!!, any suggestions for
how to do it?

Thanks!
  lib/libv4lconvert/libv4lconvert-priv.h |  6 +++
  lib/libv4lconvert/libv4lconvert.c      | 19 +++++++++
  lib/libv4lconvert/rgbyuv.c             | 56 ++++++++++++++++++++++++++
  3 files changed, 81 insertions(+)

diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index a8046ce2..c45b086e 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -285,6 +285,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 78fb3432..2111d19f 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -116,6 +116,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 },
@@ -902,6 +903,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..bfe3b15f 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++;
+			}
+		}
+}




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux