aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2011-09-24 09:46:55 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-12-11 08:23:30 -0500
commit66847ef013cc4ed3ae519360e7e4cbf531465ae8 (patch)
tree79651abe38091a5841e16ccbe0850834a1a9c66b /drivers/media
parent25738cbd72db53ca1c326bf94915d41086cb4297 (diff)
[media] uvcvideo: Add UVC timestamps support
UVC devices transmit a device timestamp along with video frames. Convert the timestamp to a host timestamp and use it to fill the V4L2 buffer timestamp field. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/uvc/uvc_queue.c12
-rw-r--r--drivers/media/video/uvc/uvc_video.c330
-rw-r--r--drivers/media/video/uvc/uvcvideo.h25
3 files changed, 367 insertions, 0 deletions
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 268be579aa72..518f77d3a4d8 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -104,10 +104,22 @@ static void uvc_buffer_queue(struct vb2_buffer *vb)
104 spin_unlock_irqrestore(&queue->irqlock, flags); 104 spin_unlock_irqrestore(&queue->irqlock, flags);
105} 105}
106 106
107static int uvc_buffer_finish(struct vb2_buffer *vb)
108{
109 struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
110 struct uvc_streaming *stream =
111 container_of(queue, struct uvc_streaming, queue);
112 struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
113
114 uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
115 return 0;
116}
117
107static struct vb2_ops uvc_queue_qops = { 118static struct vb2_ops uvc_queue_qops = {
108 .queue_setup = uvc_queue_setup, 119 .queue_setup = uvc_queue_setup,
109 .buf_prepare = uvc_buffer_prepare, 120 .buf_prepare = uvc_buffer_prepare,
110 .buf_queue = uvc_buffer_queue, 121 .buf_queue = uvc_buffer_queue,
122 .buf_finish = uvc_buffer_finish,
111}; 123};
112 124
113void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, 125void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 513ba30f8d57..c7e69b8f81c9 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -357,6 +357,329 @@ static int uvc_commit_video(struct uvc_streaming *stream,
357 return uvc_set_video_ctrl(stream, probe, 0); 357 return uvc_set_video_ctrl(stream, probe, 0);
358} 358}
359 359
360/* -----------------------------------------------------------------------------
361 * Clocks and timestamps
362 */
363
364static void
365uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
366 const __u8 *data, int len)
367{
368 struct uvc_clock_sample *sample;
369 unsigned int header_size;
370 bool has_pts = false;
371 bool has_scr = false;
372 unsigned long flags;
373 struct timespec ts;
374 u16 host_sof;
375 u16 dev_sof;
376
377 switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
378 case UVC_STREAM_PTS | UVC_STREAM_SCR:
379 header_size = 12;
380 has_pts = true;
381 has_scr = true;
382 break;
383 case UVC_STREAM_PTS:
384 header_size = 6;
385 has_pts = true;
386 break;
387 case UVC_STREAM_SCR:
388 header_size = 8;
389 has_scr = true;
390 break;
391 default:
392 header_size = 2;
393 break;
394 }
395
396 /* Check for invalid headers. */
397 if (len < header_size)
398 return;
399
400 /* Extract the timestamps:
401 *
402 * - store the frame PTS in the buffer structure
403 * - if the SCR field is present, retrieve the host SOF counter and
404 * kernel timestamps and store them with the SCR STC and SOF fields
405 * in the ring buffer
406 */
407 if (has_pts && buf != NULL)
408 buf->pts = get_unaligned_le32(&data[2]);
409
410 if (!has_scr)
411 return;
412
413 /* To limit the amount of data, drop SCRs with an SOF identical to the
414 * previous one.
415 */
416 dev_sof = get_unaligned_le16(&data[header_size - 2]);
417 if (dev_sof == stream->clock.last_sof)
418 return;
419
420 stream->clock.last_sof = dev_sof;
421
422 host_sof = usb_get_current_frame_number(stream->dev->udev);
423 ktime_get_ts(&ts);
424
425 /* The UVC specification allows device implementations that can't obtain
426 * the USB frame number to keep their own frame counters as long as they
427 * match the size and frequency of the frame number associated with USB
428 * SOF tokens. The SOF values sent by such devices differ from the USB
429 * SOF tokens by a fixed offset that needs to be estimated and accounted
430 * for to make timestamp recovery as accurate as possible.
431 *
432 * The offset is estimated the first time a device SOF value is received
433 * as the difference between the host and device SOF values. As the two
434 * SOF values can differ slightly due to transmission delays, consider
435 * that the offset is null if the difference is not higher than 10 ms
436 * (negative differences can not happen and are thus considered as an
437 * offset). The video commit control wDelay field should be used to
438 * compute a dynamic threshold instead of using a fixed 10 ms value, but
439 * devices don't report reliable wDelay values.
440 *
441 * See uvc_video_clock_host_sof() for an explanation regarding why only
442 * the 8 LSBs of the delta are kept.
443 */
444 if (stream->clock.sof_offset == (u16)-1) {
445 u16 delta_sof = (host_sof - dev_sof) & 255;
446 if (delta_sof >= 10)
447 stream->clock.sof_offset = delta_sof;
448 else
449 stream->clock.sof_offset = 0;
450 }
451
452 dev_sof = (dev_sof + stream->clock.sof_offset) & 2047;
453
454 spin_lock_irqsave(&stream->clock.lock, flags);
455
456 sample = &stream->clock.samples[stream->clock.head];
457 sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
458 sample->dev_sof = dev_sof;
459 sample->host_sof = host_sof;
460 sample->host_ts = ts;
461
462 /* Update the sliding window head and count. */
463 stream->clock.head = (stream->clock.head + 1) % stream->clock.size;
464
465 if (stream->clock.count < stream->clock.size)
466 stream->clock.count++;
467
468 spin_unlock_irqrestore(&stream->clock.lock, flags);
469}
470
471static int uvc_video_clock_init(struct uvc_streaming *stream)
472{
473 struct uvc_clock *clock = &stream->clock;
474
475 spin_lock_init(&clock->lock);
476 clock->head = 0;
477 clock->count = 0;
478 clock->size = 32;
479 clock->last_sof = -1;
480 clock->sof_offset = -1;
481
482 clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
483 GFP_KERNEL);
484 if (clock->samples == NULL)
485 return -ENOMEM;
486
487 return 0;
488}
489
490static void uvc_video_clock_cleanup(struct uvc_streaming *stream)
491{
492 kfree(stream->clock.samples);
493 stream->clock.samples = NULL;
494}
495
496/*
497 * uvc_video_clock_host_sof - Return the host SOF value for a clock sample
498 *
499 * Host SOF counters reported by usb_get_current_frame_number() usually don't
500 * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame
501 * schedule window. They can be limited to 8, 9 or 10 bits depending on the host
502 * controller and its configuration.
503 *
504 * We thus need to recover the SOF value corresponding to the host frame number.
505 * As the device and host frame numbers are sampled in a short interval, the
506 * difference between their values should be equal to a small delta plus an
507 * integer multiple of 256 caused by the host frame number limited precision.
508 *
509 * To obtain the recovered host SOF value, compute the small delta by masking
510 * the high bits of the host frame counter and device SOF difference and add it
511 * to the device SOF value.
512 */
513static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
514{
515 /* The delta value can be negative. */
516 s8 delta_sof;
517
518 delta_sof = (sample->host_sof - sample->dev_sof) & 255;
519
520 return (sample->dev_sof + delta_sof) & 2047;
521}
522
523/*
524 * uvc_video_clock_update - Update the buffer timestamp
525 *
526 * This function converts the buffer PTS timestamp to the host clock domain by
527 * going through the USB SOF clock domain and stores the result in the V4L2
528 * buffer timestamp field.
529 *
530 * The relationship between the device clock and the host clock isn't known.
531 * However, the device and the host share the common USB SOF clock which can be
532 * used to recover that relationship.
533 *
534 * The relationship between the device clock and the USB SOF clock is considered
535 * to be linear over the clock samples sliding window and is given by
536 *
537 * SOF = m * PTS + p
538 *
539 * Several methods to compute the slope (m) and intercept (p) can be used. As
540 * the clock drift should be small compared to the sliding window size, we
541 * assume that the line that goes through the points at both ends of the window
542 * is a good approximation. Naming those points P1 and P2, we get
543 *
544 * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS
545 * + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)
546 *
547 * or
548 *
549 * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1)
550 *
551 * to avoid loosing precision in the division. Similarly, the host timestamp is
552 * computed with
553 *
554 * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2)
555 *
556 * SOF values are coded on 11 bits by USB. We extend their precision with 16
557 * decimal bits, leading to a 11.16 coding.
558 *
559 * TODO: To avoid surprises with device clock values, PTS/STC timestamps should
560 * be normalized using the nominal device clock frequency reported through the
561 * UVC descriptors.
562 *
563 * Both the PTS/STC and SOF counters roll over, after a fixed but device
564 * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the
565 * sliding window size is smaller than the rollover period, differences computed
566 * on unsigned integers will produce the correct result. However, the p term in
567 * the linear relations will be miscomputed.
568 *
569 * To fix the issue, we subtract a constant from the PTS and STC values to bring
570 * PTS to half the 32 bit STC range. The sliding window STC values then fit into
571 * the 32 bit range without any rollover.
572 *
573 * Similarly, we add 2048 to the device SOF values to make sure that the SOF
574 * computed by (1) will never be smaller than 0. This offset is then compensated
575 * by adding 2048 to the SOF values used in (2). However, this doesn't prevent
576 * rollovers between (1) and (2): the SOF value computed by (1) can be slightly
577 * lower than 4096, and the host SOF counters can have rolled over to 2048. This
578 * case is handled by subtracting 2048 from the SOF value if it exceeds the host
579 * SOF value at the end of the sliding window.
580 *
581 * Finally we subtract a constant from the host timestamps to bring the first
582 * timestamp of the sliding window to 1s.
583 */
584void uvc_video_clock_update(struct uvc_streaming *stream,
585 struct v4l2_buffer *v4l2_buf,
586 struct uvc_buffer *buf)
587{
588 struct uvc_clock *clock = &stream->clock;
589 struct uvc_clock_sample *first;
590 struct uvc_clock_sample *last;
591 unsigned long flags;
592 struct timespec ts;
593 u32 delta_stc;
594 u32 y1, y2;
595 u32 x1, x2;
596 u32 mean;
597 u32 sof;
598 u32 div;
599 u32 rem;
600 u64 y;
601
602 spin_lock_irqsave(&clock->lock, flags);
603
604 if (clock->count < clock->size)
605 goto done;
606
607 first = &clock->samples[clock->head];
608 last = &clock->samples[(clock->head - 1) % clock->size];
609
610 /* First step, PTS to SOF conversion. */
611 delta_stc = buf->pts - (1UL << 31);
612 x1 = first->dev_stc - delta_stc;
613 x2 = last->dev_stc - delta_stc;
614 y1 = (first->dev_sof + 2048) << 16;
615 y2 = (last->dev_sof + 2048) << 16;
616
617 if (y2 < y1)
618 y2 += 2048 << 16;
619
620 y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2
621 - (u64)y2 * (u64)x1;
622 y = div_u64(y, x2 - x1);
623
624 sof = y;
625
626 uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
627 "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
628 stream->dev->name, buf->pts,
629 y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
630 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
631 x1, x2, y1, y2, clock->sof_offset);
632
633 /* Second step, SOF to host clock conversion. */
634 ts = timespec_sub(last->host_ts, first->host_ts);
635 x1 = (uvc_video_clock_host_sof(first) + 2048) << 16;
636 x2 = (uvc_video_clock_host_sof(last) + 2048) << 16;
637 y1 = NSEC_PER_SEC;
638 y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec;
639
640 if (x2 < x1)
641 x2 += 2048 << 16;
642
643 /* Interpolated and host SOF timestamps can wrap around at slightly
644 * different times. Handle this by adding or removing 2048 to or from
645 * the computed SOF value to keep it close to the SOF samples mean
646 * value.
647 */
648 mean = (x1 + x2) / 2;
649 if (mean - (1024 << 16) > sof)
650 sof += 2048 << 16;
651 else if (sof > mean + (1024 << 16))
652 sof -= 2048 << 16;
653
654 y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2
655 - (u64)y2 * (u64)x1;
656 y = div_u64(y, x2 - x1);
657
658 div = div_u64_rem(y, NSEC_PER_SEC, &rem);
659 ts.tv_sec = first->host_ts.tv_sec - 1 + div;
660 ts.tv_nsec = first->host_ts.tv_nsec + rem;
661 if (ts.tv_nsec >= NSEC_PER_SEC) {
662 ts.tv_sec++;
663 ts.tv_nsec -= NSEC_PER_SEC;
664 }
665
666 uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
667 "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
668 stream->dev->name,
669 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
670 y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
671 v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec,
672 x1, first->host_sof, first->dev_sof,
673 x2, last->host_sof, last->dev_sof, y1, y2);
674
675 /* Update the V4L2 buffer. */
676 v4l2_buf->timestamp.tv_sec = ts.tv_sec;
677 v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
678
679done:
680 spin_unlock_irqrestore(&stream->clock.lock, flags);
681}
682
360/* ------------------------------------------------------------------------ 683/* ------------------------------------------------------------------------
361 * Stream statistics 684 * Stream statistics
362 */ 685 */
@@ -637,6 +960,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
637 uvc_video_stats_update(stream); 960 uvc_video_stats_update(stream);
638 } 961 }
639 962
963 uvc_video_clock_decode(stream, buf, data, len);
640 uvc_video_stats_decode(stream, data, len); 964 uvc_video_stats_decode(stream, data, len);
641 965
642 /* Store the payload FID bit and return immediately when the buffer is 966 /* Store the payload FID bit and return immediately when the buffer is
@@ -1096,6 +1420,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
1096 1420
1097 if (free_buffers) 1421 if (free_buffers)
1098 uvc_free_urb_buffers(stream); 1422 uvc_free_urb_buffers(stream);
1423
1424 uvc_video_clock_cleanup(stream);
1099} 1425}
1100 1426
1101/* 1427/*
@@ -1225,6 +1551,10 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
1225 1551
1226 uvc_video_stats_start(stream); 1552 uvc_video_stats_start(stream);
1227 1553
1554 ret = uvc_video_clock_init(stream);
1555 if (ret < 0)
1556 return ret;
1557
1228 if (intf->num_altsetting > 1) { 1558 if (intf->num_altsetting > 1) {
1229 struct usb_host_endpoint *best_ep = NULL; 1559 struct usb_host_endpoint *best_ep = NULL;
1230 unsigned int best_psize = 3 * 1024; 1560 unsigned int best_psize = 3 * 1024;
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index e4d4b6d02024..e9c19f53e4a1 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -329,6 +329,8 @@ struct uvc_buffer {
329 void *mem; 329 void *mem;
330 unsigned int length; 330 unsigned int length;
331 unsigned int bytesused; 331 unsigned int bytesused;
332
333 u32 pts;
332}; 334};
333 335
334#define UVC_QUEUE_DISCONNECTED (1 << 0) 336#define UVC_QUEUE_DISCONNECTED (1 << 0)
@@ -455,6 +457,25 @@ struct uvc_streaming {
455 struct uvc_stats_frame frame; 457 struct uvc_stats_frame frame;
456 struct uvc_stats_stream stream; 458 struct uvc_stats_stream stream;
457 } stats; 459 } stats;
460
461 /* Timestamps support. */
462 struct uvc_clock {
463 struct uvc_clock_sample {
464 u32 dev_stc;
465 u16 dev_sof;
466 struct timespec host_ts;
467 u16 host_sof;
468 } *samples;
469
470 unsigned int head;
471 unsigned int count;
472 unsigned int size;
473
474 u16 last_sof;
475 u16 sof_offset;
476
477 spinlock_t lock;
478 } clock;
458}; 479};
459 480
460enum uvc_device_state { 481enum uvc_device_state {
@@ -527,6 +548,7 @@ struct uvc_driver {
527#define UVC_TRACE_STATUS (1 << 9) 548#define UVC_TRACE_STATUS (1 << 9)
528#define UVC_TRACE_VIDEO (1 << 10) 549#define UVC_TRACE_VIDEO (1 << 10)
529#define UVC_TRACE_STATS (1 << 11) 550#define UVC_TRACE_STATS (1 << 11)
551#define UVC_TRACE_CLOCK (1 << 12)
530 552
531#define UVC_WARN_MINMAX 0 553#define UVC_WARN_MINMAX 0
532#define UVC_WARN_PROBE_DEF 1 554#define UVC_WARN_PROBE_DEF 1
@@ -607,6 +629,9 @@ extern int uvc_probe_video(struct uvc_streaming *stream,
607 struct uvc_streaming_control *probe); 629 struct uvc_streaming_control *probe);
608extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, 630extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
609 __u8 intfnum, __u8 cs, void *data, __u16 size); 631 __u8 intfnum, __u8 cs, void *data, __u16 size);
632void uvc_video_clock_update(struct uvc_streaming *stream,
633 struct v4l2_buffer *v4l2_buf,
634 struct uvc_buffer *buf);
610 635
611/* Status */ 636/* Status */
612extern int uvc_status_init(struct uvc_device *dev); 637extern int uvc_status_init(struct uvc_device *dev);