summaryrefslogtreecommitdiffstats
path: root/stream/tvi_v4l2.c
diff options
context:
space:
mode:
authoriive <iive@b3059339-0415-0410-9bf9-f77b7e298cf2>2014-06-10 15:41:02 +0000
committerwm4 <wm4@nowhere>2014-06-12 00:28:58 +0200
commite302e1da5820224829a771b5d366689dc9420748 (patch)
tree51e0791e2dd967cab82eca784d69620f50f115cc /stream/tvi_v4l2.c
parent8f60de98beef61c3631819a4e3a4be1ec56da00d (diff)
downloadmpv-e302e1da5820224829a771b5d366689dc9420748.tar.bz2
mpv-e302e1da5820224829a771b5d366689dc9420748.tar.xz
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 <jarekczek at poczta onet pl>. 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
Diffstat (limited to 'stream/tvi_v4l2.c')
-rw-r--r--stream/tvi_v4l2.c60
1 files changed, 48 insertions, 12 deletions
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);
}