Hi Ricardo, Thank you for the patch. On Mon, Jun 10, 2024 at 07:17:48PM +0000, Ricardo Ribalda wrote: > In UVC 1.5 we get a single clock value per frame. With the current > buffer size of 32, FPS slowers than 32 might roll-over twice. > > The current code cannot handle two roll-over and provide invalid > timestamps. > > Revome all the samples from the circular buffer that are more than two > rollovers old, so the algorithm always provides good timestamps. > > Note that we are removing values that are more than one second old, > which means that there is enough distance between the two points that > we use for the interpolation to provide good values. > > Tested-by: HungNien Chen <hn.chen@xxxxxxxxxxxxx> > Reviewed-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx> > Reviewed-by: Tomasz Figa <tfiga@xxxxxxxxxxxx> > Signed-off-by: Ricardo Ribalda <ribalda@xxxxxxxxxxxx> Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > --- > drivers/media/usb/uvc/uvc_video.c | 23 +++++++++++++++++++++++ > drivers/media/usb/uvc/uvcvideo.h | 1 + > 2 files changed, 24 insertions(+) > > diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c > index 76a375fe47dc..869876afdcce 100644 > --- a/drivers/media/usb/uvc/uvc_video.c > +++ b/drivers/media/usb/uvc/uvc_video.c > @@ -471,8 +471,30 @@ static void uvc_video_clock_add_sample(struct uvc_clock *clock, > { > unsigned long flags; > > + /* > + * If we write new data on the position where we had the last > + * overflow, remove the overflow pointer. There is no SOF overflow > + * in the whole circular buffer. > + */ > + if (clock->head == clock->last_sof_overflow) > + clock->last_sof_overflow = -1; > + > spin_lock_irqsave(&clock->lock, flags); > > + /* Handle SOF overflows. */ > + if (clock->count > 0 && clock->last_sof > sample->dev_sof) { > + /* > + * Remove data from the circular buffer that is older than the > + * last SOF overflow. We only support one SOF overflow per > + * circular buffer. > + */ > + if (clock->last_sof_overflow != -1) > + clock->count = (clock->head - clock->last_sof_overflow > + + clock->size) % clock->size; > + clock->last_sof_overflow = clock->head; > + } > + > + /* Add sample. */ > memcpy(&clock->samples[clock->head], sample, sizeof(*sample)); > clock->head = (clock->head + 1) % clock->size; > clock->count = min(clock->count + 1, clock->size); > @@ -605,6 +627,7 @@ static void uvc_video_clock_reset(struct uvc_clock *clock) > clock->head = 0; > clock->count = 0; > clock->last_sof = -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 e5b12717016f..f21207debd54 100644 > --- a/drivers/media/usb/uvc/uvcvideo.h > +++ b/drivers/media/usb/uvc/uvcvideo.h > @@ -501,6 +501,7 @@ struct uvc_streaming { > unsigned int head; > unsigned int count; > unsigned int size; > + unsigned int last_sof_overflow; > > u16 last_sof; > u16 sof_offset; > -- Regards, Laurent Pinchart