Fix libv4lconvert issues when stride > width (with some formats)

This commit is contained in:
Hans de Goede 2022-10-23 21:32:42 +02:00
parent 3e88f30b32
commit 8dbaa426a8
5 changed files with 489 additions and 1 deletions

View File

@ -0,0 +1,168 @@
From c5e108f7ef4f8ba7761ddc7bad8dc88f6cae82cc Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 16 Oct 2022 11:58:58 +0200
Subject: [PATCH v4l-utils 2/5] libv4lconvert: Fix
v4lconvert_yuv420_to_rgb/bgr24() not taking stride into account
The atomisp driver can generate V4L2_PIX_FMT_YUV420 buffers where
stride != width. Where as v4lconvert_yuv420_to_rgb/bgr24() assumed that
stride == width is always true.
Add a stride argument to v4lconvert_yuv420_to_rgb/bgr24() to fix this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
lib/libv4lconvert/libv4lconvert-priv.h | 4 ++--
lib/libv4lconvert/libv4lconvert.c | 12 +++++------
lib/libv4lconvert/rgbyuv.c | 30 ++++++++++++++++----------
3 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index 6b9128ce..495f726d 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -118,10 +118,10 @@ void v4lconvert_rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
const struct v4l2_format *src_fmt, int bgr, int yvu, int bpp);
void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst,
- int width, int height, int yvu);
+ int width, int height, int stride, int yvu);
void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dst,
- int width, int height, int yvu);
+ int width, int height, int stride, int yvu);
void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dst,
int width, int height, int stride);
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index e794ec00..e5d5ddde 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -905,11 +905,11 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
v4lconvert_yuv420_to_rgb24(data->convert_pixfmt_buf, dest, width,
- height, yvu);
+ height, bytesperline, yvu);
break;
case V4L2_PIX_FMT_BGR24:
v4lconvert_yuv420_to_bgr24(data->convert_pixfmt_buf, dest, width,
- height, yvu);
+ height, bytesperline, yvu);
break;
}
break;
@@ -1398,11 +1398,11 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
v4lconvert_yuv420_to_rgb24(src, dest, width,
- height, 0);
+ height, bytesperline, 0);
break;
case V4L2_PIX_FMT_BGR24:
v4lconvert_yuv420_to_bgr24(src, dest, width,
- height, 0);
+ height, bytesperline, 0);
break;
case V4L2_PIX_FMT_YUV420:
memcpy(dest, src, width * height * 3 / 2);
@@ -1422,11 +1422,11 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
v4lconvert_yuv420_to_rgb24(src, dest, width,
- height, 1);
+ height, bytesperline, 1);
break;
case V4L2_PIX_FMT_BGR24:
v4lconvert_yuv420_to_bgr24(src, dest, width,
- height, 1);
+ height, bytesperline, 1);
break;
case V4L2_PIX_FMT_YUV420:
v4lconvert_swap_uv(src, dest, fmt);
diff --git a/lib/libv4lconvert/rgbyuv.c b/lib/libv4lconvert/rgbyuv.c
index b54b4577..1ca821ab 100644
--- a/lib/libv4lconvert/rgbyuv.c
+++ b/lib/libv4lconvert/rgbyuv.c
@@ -93,7 +93,7 @@ void v4lconvert_rgb24_to_yuv420(const unsigned char *src, unsigned char *dest,
#define CLIP(color) (unsigned char)(((color) > 0xFF) ? 0xff : (((color) < 0) ? 0 : (color)))
void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest,
- int width, int height, int yvu)
+ int width, int height, int stride, int yvu)
{
int i, j;
@@ -101,11 +101,11 @@ void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest,
const unsigned char *usrc, *vsrc;
if (yvu) {
- vsrc = src + width * height;
- usrc = vsrc + (width * height) / 4;
+ vsrc = src + stride * height;
+ usrc = vsrc + (stride * height) / 4;
} else {
- usrc = src + width * height;
- vsrc = usrc + (width * height) / 4;
+ usrc = src + stride * height;
+ vsrc = usrc + (stride * height) / 4;
}
for (i = 0; i < height; i++) {
@@ -138,16 +138,20 @@ void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest,
usrc++;
vsrc++;
}
+ ysrc += stride - width;
/* Rewind u and v for next line */
if (!(i & 1)) {
usrc -= width / 2;
vsrc -= width / 2;
+ } else {
+ usrc += (stride - width) / 2;
+ vsrc += (stride - width) / 2;
}
}
}
void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest,
- int width, int height, int yvu)
+ int width, int height, int stride, int yvu)
{
int i, j;
@@ -155,11 +159,11 @@ void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest,
const unsigned char *usrc, *vsrc;
if (yvu) {
- vsrc = src + width * height;
- usrc = vsrc + (width * height) / 4;
+ vsrc = src + stride * height;
+ usrc = vsrc + (stride * height) / 4;
} else {
- usrc = src + width * height;
- vsrc = usrc + (width * height) / 4;
+ usrc = src + stride * height;
+ vsrc = usrc + (stride * height) / 4;
}
for (i = 0; i < height; i++) {
@@ -192,10 +196,14 @@ void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest,
usrc++;
vsrc++;
}
+ ysrc += stride - width;
/* Rewind u and v for next line */
- if (!(i&1)) {
+ if (!(i & 1)) {
usrc -= width / 2;
vsrc -= width / 2;
+ } else {
+ usrc += (stride - width) / 2;
+ vsrc += (stride - width) / 2;
}
}
}
--
2.37.3

View File

@ -0,0 +1,91 @@
From e864210793795a50b88e77af5b7d29e6bad584e8 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 16 Oct 2022 15:40:02 +0200
Subject: [PATCH v4l-utils 3/5] libv4lconvert: Fix
v4lconvert_rgb565_to_rgb/bgr24() not taking stride into account
The atomisp driver can generate V4L2_PIX_FMT_RGB565 buffers where
stride != width. Where as v4lconvert_rgb565_to_rgb/bgr24() assumed that
stride == width is always true.
Add a stride argument to v4lconvert_rgb565_to_rgb/bgr24() to fix this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
lib/libv4lconvert/libv4lconvert-priv.h | 4 ++--
lib/libv4lconvert/libv4lconvert.c | 4 ++--
lib/libv4lconvert/rgbyuv.c | 6 ++++--
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index 495f726d..f87a43a4 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -178,10 +178,10 @@ int v4lconvert_y10b_to_yuv420(struct v4lconvert_data *data,
const unsigned char *src, unsigned char *dest, int width, int height);
void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
- int width, int height);
+ int width, int height, int stride);
void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
- int width, int height);
+ int width, int height, int stride);
void v4lconvert_rgb565_to_yuv420(const unsigned char *src, unsigned char *dest,
const struct v4l2_format *src_fmt, int yvu);
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index e5d5ddde..77f9eca5 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -1282,10 +1282,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
}
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
- v4lconvert_rgb565_to_rgb24(src, dest, width, height);
+ v4lconvert_rgb565_to_rgb24(src, dest, width, height, bytesperline);
break;
case V4L2_PIX_FMT_BGR24:
- v4lconvert_rgb565_to_bgr24(src, dest, width, height);
+ v4lconvert_rgb565_to_bgr24(src, dest, width, height, bytesperline);
break;
case V4L2_PIX_FMT_YUV420:
v4lconvert_rgb565_to_yuv420(src, dest, fmt, 0);
diff --git a/lib/libv4lconvert/rgbyuv.c b/lib/libv4lconvert/rgbyuv.c
index 1ca821ab..f9017016 100644
--- a/lib/libv4lconvert/rgbyuv.c
+++ b/lib/libv4lconvert/rgbyuv.c
@@ -511,7 +511,7 @@ void v4lconvert_swap_uv(const unsigned char *src, unsigned char *dest,
}
void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int stride)
{
int j;
while (--height >= 0) {
@@ -525,11 +525,12 @@ void v4lconvert_rgb565_to_rgb24(const unsigned char *src, unsigned char *dest,
src += 2;
}
+ src += stride - 2 * width;
}
}
void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int stride)
{
int j;
while (--height >= 0) {
@@ -543,6 +544,7 @@ void v4lconvert_rgb565_to_bgr24(const unsigned char *src, unsigned char *dest,
src += 2;
}
+ src += stride - 2 * width;
}
}
--
2.37.3

View File

@ -0,0 +1,125 @@
From 8cbe059875452301c61db309d3087fb496b7223d Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 16 Oct 2022 16:04:13 +0200
Subject: [PATCH v4l-utils 4/5] libv4lconvert: Fix v4lconvert_nv12_*() not
taking stride into account
The atomisp driver can generate V4L2_PIX_FMT_NV12 buffers where
stride != width. Where as v4lconvert_nv12_*() assumed that
stride == width is always true.
Add a stride argument to v4lconvert_nv12_*() to fix this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
lib/libv4lconvert/libv4lconvert-priv.h | 4 ++--
lib/libv4lconvert/libv4lconvert.c | 8 ++++----
lib/libv4lconvert/rgbyuv.c | 18 +++++++++++++-----
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index f87a43a4..f361f2a0 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -287,10 +287,10 @@ 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);
+ int width, int height, int stride, int bgr);
void v4lconvert_nv12_to_yuv420(const unsigned char *src, unsigned char *dest,
- int width, int height, int yvu);
+ int width, int height, int stride, 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 77f9eca5..d0d38286 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -937,16 +937,16 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
case V4L2_PIX_FMT_NV12:
switch (dest_pix_fmt) {
case V4L2_PIX_FMT_RGB24:
- v4lconvert_nv12_to_rgb24(src, dest, width, height, 0);
+ v4lconvert_nv12_to_rgb24(src, dest, width, height, bytesperline, 0);
break;
case V4L2_PIX_FMT_BGR24:
- v4lconvert_nv12_to_rgb24(src, dest, width, height, 1);
+ v4lconvert_nv12_to_rgb24(src, dest, width, height, bytesperline, 1);
break;
case V4L2_PIX_FMT_YUV420:
- v4lconvert_nv12_to_yuv420(src, dest, width, height, 0);
+ v4lconvert_nv12_to_yuv420(src, dest, width, height, bytesperline, 0);
break;
case V4L2_PIX_FMT_YVU420:
- v4lconvert_nv12_to_yuv420(src, dest, width, height, 1);
+ v4lconvert_nv12_to_yuv420(src, dest, width, height, bytesperline, 1);
break;
}
break;
diff --git a/lib/libv4lconvert/rgbyuv.c b/lib/libv4lconvert/rgbyuv.c
index f9017016..e9fe6df9 100644
--- a/lib/libv4lconvert/rgbyuv.c
+++ b/lib/libv4lconvert/rgbyuv.c
@@ -857,11 +857,11 @@ void v4lconvert_hsv_to_rgb24(const unsigned char *src, unsigned char *dest,
}
void v4lconvert_nv12_to_rgb24(const unsigned char *src, unsigned char *dest,
- int width, int height, int bgr)
+ int width, int height, int stride, int bgr)
{
int i, j;
const unsigned char *ysrc = src;
- const unsigned char *uvsrc = src + width * height;
+ const unsigned char *uvsrc = src + stride * height;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j ++) {
@@ -879,18 +879,21 @@ void v4lconvert_nv12_to_rgb24(const unsigned char *src, unsigned char *dest,
uvsrc += 2;
}
+ ysrc += stride - width;
/* Rewind u and v for next line */
if (!(i&1))
uvsrc -= width;
+ else
+ uvsrc += stride - width;
}
}
void v4lconvert_nv12_to_yuv420(const unsigned char *src, unsigned char *dest,
- int width, int height, int yvu)
+ int width, int height, int stride, int yvu)
{
int i, j;
const unsigned char *ysrc = src;
- const unsigned char *uvsrc = src + width * height;
+ const unsigned char *uvsrc = src + stride * height;
unsigned char *ydst = dest;
unsigned char *udst, *vdst;
@@ -902,7 +905,7 @@ void v4lconvert_nv12_to_yuv420(const unsigned char *src, unsigned char *dest,
vdst = udst + ((width / 2) * (height / 2));
}
- for (i = 0; i < height; i++)
+ for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
*ydst++ = *ysrc++;
if (((i % 2) == 0) && ((j % 2) == 0)) {
@@ -910,4 +913,9 @@ void v4lconvert_nv12_to_yuv420(const unsigned char *src, unsigned char *dest,
*vdst++ = *uvsrc++;
}
}
+
+ ysrc += stride - width;
+ if ((i % 2) == 0)
+ uvsrc += stride - width;
+ }
}
--
2.37.3

View File

@ -0,0 +1,97 @@
From 2cfd6dc33d7f7743843e9ad65d31baef5508f636 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 16 Oct 2022 16:15:53 +0200
Subject: [PATCH v4l-utils 5/5] libv4lconvert: Fix v4lconvert_nv16_to_yuyv()
not taking stride into account
The atomisp driver can generate V4L2_PIX_FMT_NV16 buffers where
stride != width. Where as v4lconvert_nv16_to_yuyv() assumed that
stride == width is always true.
Add a stride argument to v4lconvert_nv16_to_yuyv() to fix this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
lib/libv4lconvert/libv4lconvert-priv.h | 2 +-
lib/libv4lconvert/libv4lconvert.c | 8 ++++----
lib/libv4lconvert/rgbyuv.c | 16 ++++++++++------
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/lib/libv4lconvert/libv4lconvert-priv.h b/lib/libv4lconvert/libv4lconvert-priv.h
index f361f2a0..00a03f9e 100644
--- a/lib/libv4lconvert/libv4lconvert-priv.h
+++ b/lib/libv4lconvert/libv4lconvert-priv.h
@@ -133,7 +133,7 @@ void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dst,
int width, int height, int stride, int yvu);
void v4lconvert_nv16_to_yuyv(const unsigned char *src, unsigned char *dest,
- int width, int height);
+ int width, int height, int stride);
void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dst,
int width, int height, int stride);
diff --git a/lib/libv4lconvert/libv4lconvert.c b/lib/libv4lconvert/libv4lconvert.c
index d0d38286..b07bf3ba 100644
--- a/lib/libv4lconvert/libv4lconvert.c
+++ b/lib/libv4lconvert/libv4lconvert.c
@@ -1445,10 +1445,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
if (!tmpbuf)
return v4lconvert_oom_error(data);
- v4lconvert_nv16_to_yuyv(src, tmpbuf, width, height);
+ v4lconvert_nv16_to_yuyv(src, tmpbuf, width, height, bytesperline);
src_pix_fmt = V4L2_PIX_FMT_YUYV;
src = tmpbuf;
- bytesperline = bytesperline * 2;
+ bytesperline = width * 2;
/* fall through */
}
case V4L2_PIX_FMT_YUYV:
@@ -1482,10 +1482,10 @@ static int v4lconvert_convert_pixfmt(struct v4lconvert_data *data,
return v4lconvert_oom_error(data);
/* Note NV61 is NV16 with U and V swapped so this becomes yvyu. */
- v4lconvert_nv16_to_yuyv(src, tmpbuf, width, height);
+ v4lconvert_nv16_to_yuyv(src, tmpbuf, width, height, bytesperline);
src_pix_fmt = V4L2_PIX_FMT_YVYU;
src = tmpbuf;
- bytesperline = bytesperline * 2;
+ bytesperline = width * 2;
/* fall through */
}
case V4L2_PIX_FMT_YVYU:
diff --git a/lib/libv4lconvert/rgbyuv.c b/lib/libv4lconvert/rgbyuv.c
index e9fe6df9..ce31a1ba 100644
--- a/lib/libv4lconvert/rgbyuv.c
+++ b/lib/libv4lconvert/rgbyuv.c
@@ -304,17 +304,21 @@ void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
}
void v4lconvert_nv16_to_yuyv(const unsigned char *src, unsigned char *dest,
- int width, int height)
+ int width, int height, int stride)
{
const unsigned char *y, *cbcr;
- int count = 0;
+ int i, j;
y = src;
- cbcr = src + width*height;
+ cbcr = src + stride * height;
- while (count++ < width*height) {
- *dest++ = *y++;
- *dest++ = *cbcr++;
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < width; j++) {
+ *dest++ = *y++;
+ *dest++ = *cbcr++;
+ }
+ y += stride - width;
+ cbcr += stride - width;
}
}
--
2.37.3

View File

@ -1,6 +1,6 @@
Name: v4l-utils
Version: 1.22.1
Release: 3%{?dist}
Release: 4%{?dist}
Summary: Utilities for video4linux and DVB devices
# libdvbv5, dvbv5 utils, ir-keytable and v4l2-sysfs-path are GPLv2 only
License: GPLv2+ and GPLv2
@ -8,6 +8,10 @@ URL: http://www.linuxtv.org/downloads/v4l-utils/
Source0: http://linuxtv.org/downloads/v4l-utils/v4l-utils-%{version}.tar.bz2
Patch0: 0001-utils-v4l2-TPG-Update-use-of-typeof.patch
Patch1: 0002-libv4lconvert-Fix-v4lconvert_yuv420_to_rgb-bgr24-not.patch
Patch2: 0003-libv4lconvert-Fix-v4lconvert_rgb565_to_rgb-bgr24-not.patch
Patch3: 0004-libv4lconvert-Fix-v4lconvert_nv12_-not-taking-stride.patch
Patch4: 0005-libv4lconvert-Fix-v4lconvert_nv16_to_yuyv-not-taking.patch
BuildRequires: alsa-lib-devel
BuildRequires: desktop-file-utils
@ -202,6 +206,9 @@ desktop-file-validate $RPM_BUILD_ROOT%{_datadir}/applications/qv4l2.desktop
%changelog
* Sun Oct 23 2022 Hans de Goede <hdegoede@redhat.com> - 1.22.1-4
- Fix libv4lconvert issues when stride > width (with some formats)
* Sat Jul 23 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.22.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild