From: Ricardo Ribalda Date: Wed, 13 May 2026 11:49:24 +0000 (+0000) Subject: media: uvcvideo: Do not add samples if dev_sof has not changed X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0491c93a510c32eaf8ed404b99a447e10c30291e;p=thirdparty%2Fkernel%2Flinux.git media: uvcvideo: Do not add samples if dev_sof has not changed 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 Signed-off-by: Ricardo Ribalda Tested-by: Yunke Cao Reviewed-by: Hans de Goede Link: https://patch.msgid.link/20260513-uvc-hwtimestamp-v3-5-7a64838b0b02@chromium.org Signed-off-by: Hans de Goede Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 09d6baf87ec5..c104ffe3b3c1 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -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; } diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index 4ba35727e954..b6bcee4a222f 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -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];