]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: uvcvideo: Do not add samples if dev_sof has not changed
authorRicardo Ribalda <ribalda@chromium.org>
Wed, 13 May 2026 11:49:24 +0000 (11:49 +0000)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Thu, 21 May 2026 19:14:08 +0000 (21:14 +0200)
We only save relevant samples into the circular buffer. If the data is
very similar to the previous one, exit early, this allows us to avoid
some expensive operations such as usb_get_current_frame_number().

Suggested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Tested-by: Yunke Cao <yunkec@google.com>
Reviewed-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Link: https://patch.msgid.link/20260513-uvc-hwtimestamp-v3-5-7a64838b0b02@chromium.org
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
drivers/media/usb/uvc/uvcvideo.h

index 09d6baf87ec5e7f2361e1301d4b669bad5fa0129..c104ffe3b3c10020189dd7afac122ce89294a3d4 100644 (file)
@@ -524,7 +524,7 @@ static void uvc_video_clock_add_sample(struct uvc_clock *clock,
 
        spin_lock_irqsave(&clock->lock, flags);
 
-       if (clock->count > 0 && clock->last_sof > sample->dev_sof) {
+       if (clock->count > 0 && clock->last_sof_processed > sample->dev_sof) {
                /*
                 * Remove data from the circular buffer that is older than the
                 * last SOF overflow. We only support one SOF overflow per
@@ -599,7 +599,12 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
        if (!has_scr)
                return;
 
-       sample.dev_sof = get_unaligned_le16(&data[header_size - 2]);
+       sample.dev_sof = get_unaligned_le16(&data[header_size - 2]) & 2047;
+       /* If the sample SOF is identical to the previous one, quit early. */
+       if (stream->clock.last_sof_raw == sample.dev_sof)
+               return;
+       stream->clock.last_sof_raw = sample.dev_sof;
+
        sample.dev_stc = get_unaligned_le32(&data[header_size - 6]);
 
        /*
@@ -678,19 +683,20 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
         * all the data packets of the same frame contains the same SOF. In that
         * case only the first one will match the host_sof.
         */
-       if (sof_diff(sample.dev_sof, stream->clock.last_sof) <=
+       if (sof_diff(sample.dev_sof, stream->clock.last_sof_processed) <=
            (UVC_MIN_HW_TIMESTAMP_DIFF / stream->clock.size))
                return;
 
        uvc_video_clock_add_sample(&stream->clock, &sample);
-       stream->clock.last_sof = sample.dev_sof;
+       stream->clock.last_sof_processed = sample.dev_sof;
 }
 
 static void uvc_video_clock_reset(struct uvc_clock *clock)
 {
        clock->head = 0;
        clock->count = 0;
-       clock->last_sof = -1;
+       clock->last_sof_processed = -1;
+       clock->last_sof_raw = -1;
        clock->last_sof_overflow = -1;
        clock->sof_offset = -1;
 }
index 4ba35727e954e05785981495c37055b9e79f665f..b6bcee4a222fa01e4cf05b26f846129aa2f50234 100644 (file)
@@ -522,7 +522,8 @@ struct uvc_streaming {
                unsigned int size;
                unsigned int last_sof_overflow;
 
-               u16 last_sof;
+               u16 last_sof_processed;
+               u16 last_sof_raw;
                u16 sof_offset;
 
                u8 last_scr[6];