Where does v4l2_buffer->timestamp value starts counting?
Asked Answered
L

2

8

I am trying to use v4l2_buffer's timestamp value (type timeval) to synchronize images captured from a UVC webcam to external events.

However the timestamp is not the same as the system time, or the up time, etc:

printf("image captured at %ld, %ld\n",
   buffer->timestamp.tv_sec, 
   buffer->timestamp.tv_usec);

struct timeval tv;
gettimeofday(&tv, 0);
printf("current time %ld, %ld\n", tv.tv_sec, tv.tv_usec);

Results in

image captured at 367746, 476270
current time 1335083395, 11225

My uptime is 10 days.

Lilialiliaceous answered 22/4, 2012 at 8:36 Comment(0)
L
8

According to http://comments.gmane.org/gmane.linux.drivers.video-input-infrastructure/39892 some v4l2 drivers (including the UVC one) do not use the realtime clock (wall time) but rather a monotonic clock that counts from a not specified point in time. On Linux, this is the boot time (i.e. uptime), however (and I suspect this is the cause of your mismatch) only the time that the computer was actually running (i.e. this clock does not run when the computer is suspended).

Latitudinarian answered 22/4, 2012 at 17:3 Comment(1)
Dead link , please fixBug
P
4

If you have the OP's problem, and you're trying to get to epoch timestamps for each frame, you can use the code snippet below to do so.

#include <time.h>
#include <math.h>

//////////////////////
//setup: 

    long getEpochTimeShift(){
        struct timeval epochtime;
        struct timespec  vsTime;

        gettimeofday(&epochtime, NULL);
        clock_gettime(CLOCK_MONOTONIC, &vsTime);

        long uptime_ms = vsTime.tv_sec* 1000 + (long)  round( vsTime.tv_nsec/ 1000000.0);
        long epoch_ms =  epochtime.tv_sec * 1000  + (long) round( epochtime.tv_usec/1000.0);
        return epoch_ms - uptime_ms;
    }

    //stick this somewhere so that it runs once, on the startup of your capture process
    //  noting, if you hibernate a laptop, you might need to recalc this if you don't restart 
    //  the process after dehibernation
    long toEpochOffset_ms = getEpochTimeShift();


//////////////////////
//...somewhere in your capture loop: 

    struct v4l2_buffer buf;

    //make the v4l call to  xioctl(fd, VIDIOC_DQBUF, &buf)

    //then: 
    long temp_ms = 1000 * buf.timestamp.tv_sec + (long) round(  buf.timestamp.tv_usec / 1000.0);
    long epochTimeStamp_ms = temp_ms + toEpochOffset_ms ;

    printf( "the frame's timestamp in epoch ms is: %ld", epochTimeStamp_ms);
Peyton answered 27/6, 2015 at 10:29 Comment(1)
Is there a way to get the two different kinds of times in a way guaranteed to be (nearly) simultaneous? An interrupt that stores both clocks?Wivinia

© 2022 - 2024 — McMap. All rights reserved.