]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
media: uvcvideo: Fix buffer sequence in frame gaps
authorRicardo Ribalda <ribalda@chromium.org>
Mon, 23 Mar 2026 09:53:53 +0000 (09:53 +0000)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Tue, 12 May 2026 05:30:53 +0000 (07:30 +0200)
In UVC, the FID flips with every frame. For every FID flip, we increase
the stream sequence number.

Now, if a FID flips multiple times and there is no data transferred between
the flips, the buffer sequence number will be set to the value of the
stream sequence number after the first flip.

Userspace uses the buffer sequence number to determine if there have been
missing frames. With the current behaviour, userspace will think that the
gap is in the wrong location.

This patch modifies uvc_video_decode_start() to provide the correct buffer
sequence number and timestamp.

Cc: stable@kernel.org
Fixes: 650b95feee35 ("[media] uvcvideo: Generate discontinuous sequence numbers when frames are lost")
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/usb/uvc/uvc_video.c

index 3182f5e9d9a0962cb597d8ae79bfd5a3702e6dc2..62db4db4e565c37a8362c0cf983c02c7d328d546 100644 (file)
@@ -1223,6 +1223,19 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
                stream->sequence++;
                if (stream->sequence)
                        uvc_video_stats_update(stream);
+
+               /*
+                * On a FID flip initialize sequence number and timestamp.
+                *
+                * The driver already takes care of injecting FID flips for
+                * UVC_QUIRK_STREAM_NO_FID and UVC_QUIRK_MJPEG_NO_EOF.
+                */
+               if (buf) {
+                       buf->buf.field = V4L2_FIELD_NONE;
+                       buf->buf.sequence = stream->sequence;
+                       buf->buf.vb2_buf.timestamp =
+                                       ktime_to_ns(uvc_video_get_time());
+               }
        }
 
        uvc_video_clock_decode(stream, buf, data, len);
@@ -1263,10 +1276,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
                        return -ENODATA;
                }
 
-               buf->buf.field = V4L2_FIELD_NONE;
-               buf->buf.sequence = stream->sequence;
-               buf->buf.vb2_buf.timestamp = ktime_to_ns(uvc_video_get_time());
-
                /* TODO: Handle PTS and SCR. */
                buf->state = UVC_BUF_STATE_ACTIVE;
        }