Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where does v4l2_buffer->timestamp value starts counting?

Tags:

v4l2

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.

like image 836
Frankie Avatar asked Apr 22 '12 08:04

Frankie


People also ask

What is the buffer timestamps?

The buffer timestamp has been taken when the exposure of the frame has begun. This is only valid for the V4L2_BUF_TYPE_VIDEO_CAPTURE buffer type. 3.6.7. Timecodes The struct v4l2_timecode structure is designed to hold a SMPTE 12M or similar timecode. (struct struct timeval timestamps are stored in struct v4l2_buffer field timestamp .)

What is v4l2_buf_flag_timestamp_copy?

The V4L2_BUF_FLAG_TIMESTAMP_COPY timestamp type which is used by e.g. on mem-to-mem devices is an exception to the rule: the timestamp source flags are copied from the OUTPUT video buffer to the CAPTURE video buffer. Number of the buffer, set by the application except when calling VIDIOC_DQBUF, then it is set by the driver.

How does V4L2 handle buffer size?

Interactions between formats, controls and buffers V4L2 exposes parameters that influence the buffer size, or the way data is laid out in the buffer. Those parameters are exposed through both formats and controls.

How to test the type of timestamp in Linux?

To test the timestamp type, mask out bits not belonging to timestamp type by performing a logical and operation with buffer flags and timestamp mask. Unknown timestamp type. This type is used by drivers before Linux 3.9 and may be either monotonic (see below) or realtime (wall clock).


2 Answers

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).

like image 154
dseifert Avatar answered Sep 30 '22 21:09

dseifert


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);
like image 28
Matt S. Avatar answered Sep 30 '22 21:09

Matt S.