commit 67d610b92124dd8df432152360fe0eb22afa8f4b
Author: Kate Hsuan <hpa(a)redhat.com>
Date: Tue May 9 17:26:51 2023 +0800
Add the patch file
...k-Fixup-bytesused-field-when-writer-sends.patch | 106 +++++++++++++++++++++
1 file changed, 106 insertions(+)
---
diff --git a/0001-v4l2loopback-Fixup-bytesused-field-when-writer-sends.patch
b/0001-v4l2loopback-Fixup-bytesused-field-when-writer-sends.patch
new file mode 100644
index 0000000..70db1f4
--- /dev/null
+++ b/0001-v4l2loopback-Fixup-bytesused-field-when-writer-sends.patch
@@ -0,0 +1,106 @@
+From 702e4024f2bc460cd2fe880dd6e08f1c3b9a38d1 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede(a)redhat.com>
+Date: Mon, 8 May 2023 12:08:12 +0200
+Subject: [PATCH] v4l2loopback: Fixup bytesused field when writer sends a too
+ large value
+
+Gstreamer's v4l2sink is known to submit buffers with bytesused set to
+the length of the buffer instead of the size of the actual image-data
+within the buffer which is typically smaller due to buffer sizes
+being rounded op to a page-size:
+
+https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2532
+
+Despite this being a long standing issue and their being 2 merge-reqs:
+
+https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3713
+https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4527
+
+to try and fix this it looks like this is not going to get fixed
+in gst's v4l2sink anytime soon and even if once it is fixed many users
+will likely be using an older v4l2sink which still has this bug.
+
+These buffers with a too large bytes used value are causing issues
+with various apps which reject these buffers when reading from
+the v4l2loopback device, such as e.g. ffmpeg and firefox.
+
+Add a pix_format_has_valid_sizeimage flag which gets set from
+vidioc_s_fmt_out() if dev->pix_format.sizeimage is known to have just
+been set to a valid, fixed size (so this e.g. won't be set for MJPG).
+
+And then fix this issue by making vidioc_qbuf() truncate
+V4L2_BUF_TYPE_VIDEO_OUTPUT buffer's bytes_used value to
+dev->pix_format.sizeimage when this flag is set.
+
+Closes #190
+Closes #448
+Obsoletes #435
+---
+ v4l2loopback.c | 30 +++++++++++++++++++++++++++++-
+ 1 file changed, 29 insertions(+), 1 deletion(-)
+
+diff --git a/v4l2loopback.c b/v4l2loopback.c
+index 7858e31..2168239 100644
+--- a/v4l2loopback.c
++++ b/v4l2loopback.c
+@@ -297,6 +297,7 @@ struct v4l2_loopback_device {
+ struct video_device *vdev;
+ /* pixel and stream format */
+ struct v4l2_pix_format pix_format;
++ bool pix_format_has_valid_sizeimage;
+ struct v4l2_captureparm capture_param;
+ unsigned long frame_jiffies;
+
+@@ -543,6 +544,20 @@ static int v4l2l_fill_format(struct v4l2_format *fmt, int capture,
+ return 0;
+ }
+
++/* Checks if v4l2l_fill_format() has set a valid, fixed sizeimage val. */
++static bool v4l2l_pix_format_has_valid_sizeimage(struct v4l2_format *fmt)
++{
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
++ const struct v4l2_format_info *info;
++
++ info = v4l2_format_info(fmt->fmt.pix.pixelformat);
++ if (info && info->mem_planes == 1)
++ return true;
++#endif
++
++ return false;
++}
++
+ static int pix_format_eq(const struct v4l2_pix_format *ref,
+ const struct v4l2_pix_format *tgt, int strict)
+ {
+@@ -1220,6 +1235,8 @@ static int vidioc_s_fmt_out(struct file *file, void *priv,
+ ret = inner_try_setfmt(file, fmt);
+ if (!ret) {
+ dev->pix_format = fmt->fmt.pix;
++ dev->pix_format_has_valid_sizeimage =
++ v4l2l_pix_format_has_valid_sizeimage(fmt);
+ dprintk("s_fmt_out(%d) %d...%d\n", ret, dev->ready_for_capture,
+ dev->pix_format.sizeimage);
+ dprintk("outFOURCC=%s\n",
+@@ -1717,7 +1734,18 @@ static int vidioc_qbuf(struct file *file, void *fh, struct
v4l2_buffer *buf)
+ b->buffer.timestamp = buf->timestamp;
+ b->buffer.flags |= V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ }
+- b->buffer.bytesused = buf->bytesused;
++ if (dev->pix_format_has_valid_sizeimage) {
++ if (buf->bytesused >= dev->pix_format.sizeimage) {
++ b->buffer.bytesused = dev->pix_format.sizeimage;
++ } else {
++ dev_warn_ratelimited(&dev->vdev->dev, "warning queued output buffer
bytesused too small %d < %d\n",
++ buf->bytesused, dev->pix_format.sizeimage);
++ b->buffer.bytesused = buf->bytesused;
++ }
++ } else {
++ b->buffer.bytesused = buf->bytesused;
++ }
++
+ set_done(b);
+ buffer_written(dev, b);
+
+--
+2.40.1
+