From e302e1da5820224829a771b5d366689dc9420748 Mon Sep 17 00:00:00 2001 From: iive Date: Tue, 10 Jun 2014 15:41:02 +0000 Subject: tv: use correct timestamps Squashed from the following mplayer-svn commits. The '#' is removed from the bug ID to prevent github from doing something stupid. Instead of adding the mplayer configure check for clock_gettime(), the POSIX identifiers are used for checking presence of the function. Use correct type of timestamps when recording from v4l2. Fix 2176 Patch by Jarek Czekalski . git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@37222 b3059339-0415-0410-9bf9-f77b7e298cf2 Allow building of v4l2 without clock_gettime(). Add overly verbose message in case monotone timestamps are required by the kernel. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@37223 b3059339-0415-0410-9bf9-f77b7e298cf2 --- stream/tvi_v4l2.c | 60 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 12 deletions(-) (limited to 'stream') diff --git a/stream/tvi_v4l2.c b/stream/tvi_v4l2.c index 6980ceb349..361b115b37 100644 --- a/stream/tvi_v4l2.c +++ b/stream/tvi_v4l2.c @@ -68,6 +68,13 @@ known issues: #define v4l2_munmap munmap #endif +// flag introduced in kernel 3.10 +#ifndef V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC +#define V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC 0x2000 +#endif + +#define HAVE_CLOCK_GETTIME (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) + #define info tvi_info_v4l2 static tvi_handle_t *tvi_init_v4l2(struct mp_log *log, tv_param_t* tv_param); /* information about this file */ @@ -107,8 +114,10 @@ typedef struct priv { struct map *map; int mapcount; int frames; - volatile long long first_frame; - long long curr_frame; + volatile long long first_frame; ///< number of useconds + long long curr_frame; ///< usec, using kernel timestamps + int clk_id; /**< clk_id from clock_gettime + used in frame timestamps */ /* audio video interleaving ;-) */ volatile int streamon; pthread_t audio_grabber_thread; @@ -495,6 +504,30 @@ static int getstd(priv_t *priv) return 0; } +#if HAVE_CLOCK_GETTIME +/* +** Gets current timestamp, using specified clock id. +** @return number of microseconds. +*/ +static long long get_curr_timestamp(int clk_id) +{ + struct timespec ts; + clock_gettime(clk_id, &ts); + return (long long)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; +} +#else +/* +** Gets current timestamp, using system time. +** @return number of microseconds. +*/ +static long long get_curr_timestamp(int clk_id) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (long long)tv.tv_sec * 1000000 + tv.tv_usec; +} +#endif + /***********************************************************************\ * * * * @@ -1366,6 +1399,13 @@ static int start(priv_t *priv) return 0; } priv->map[i].len = priv->map[i].buf.length; +#ifdef HAVE_CLOCK_GETTIME + priv->clk_id = (priv->map[i].buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) + ? CLOCK_MONOTONIC : CLOCK_REALTIME; +#else + if (priv->map[i].buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) + mp_msg(MSGT_TV, MSGL_WARN, "MPlayer compiled without clock_gettime() that is needed to handle monotone video timestamps from the kernel. Expect desync.\n"); +#endif /* count up to make sure this is correct everytime */ priv->mapcount++; @@ -1641,13 +1681,11 @@ static int get_video_framesize(priv_t *priv) static void *audio_grabber(void *data) { priv_t *priv = (priv_t*)data; - struct timeval tv; int i, audio_skew_ptr = 0; long long current_time, prev_skew = 0, prev_skew_uncorr = 0; - long long start_time_avg; + long long start_time_avg, curr_timestamp; - gettimeofday(&tv, NULL); - start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec; + start_time_avg = priv->audio_start_time = get_curr_timestamp(priv->clk_id); audio_in_start_capture(&priv->audio_in); for (i = 0; i < priv->aud_skew_cnt; i++) priv->audio_skew_buffer[i] = 0; @@ -1661,21 +1699,19 @@ static void *audio_grabber(void *data) pthread_mutex_lock(&priv->skew_mutex); if (priv->first_frame == 0) { // there is no first frame yet (unlikely to happen) - gettimeofday(&tv, NULL); - start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec; + start_time_avg = priv->audio_start_time = get_curr_timestamp(priv->clk_id); // fprintf(stderr, "warning - first frame not yet available!\n"); pthread_mutex_unlock(&priv->skew_mutex); continue; } pthread_mutex_unlock(&priv->skew_mutex); - gettimeofday(&tv, NULL); - priv->audio_recv_blocks_total++; - current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_start_time; + curr_timestamp = get_curr_timestamp(priv->clk_id); + current_time = curr_timestamp - priv->audio_start_time; if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) { - start_time_avg += (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_usecs_per_block*priv->audio_recv_blocks_total; + start_time_avg += curr_timestamp - priv->audio_usecs_per_block*priv->audio_recv_blocks_total; priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1); } -- cgit v1.2.3