comparison stream/tvi_v4l2.c @ 37126:6db1f7a10803

Use correct type of timestamps when recording from v4l2. Fix #2176 Patch by Jarek Czekalski <jarekczek at poczta onet pl>.
author iive
date Tue, 10 Jun 2014 15:41:02 +0000
parents 389d43c448b3
children ca7e13830a05
comparison
equal deleted inserted replaced
37125:1236e38abf90 37126:6db1f7a10803
61 #include "libmpcodecs/dec_teletext.h" 61 #include "libmpcodecs/dec_teletext.h"
62 #include "libaf/af_format.h" 62 #include "libaf/af_format.h"
63 #include "tv.h" 63 #include "tv.h"
64 #include "audio_in.h" 64 #include "audio_in.h"
65 65
66 // flag introduced in kernel 3.10
67 #ifndef V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
68 #define V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC 0x2000
69 #endif
70
66 #define info tvi_info_v4l2 71 #define info tvi_info_v4l2
67 static tvi_handle_t *tvi_init_v4l2(tv_param_t* tv_param); 72 static tvi_handle_t *tvi_init_v4l2(tv_param_t* tv_param);
68 /* information about this file */ 73 /* information about this file */
69 const tvi_info_t tvi_info_v4l2 = { 74 const tvi_info_t tvi_info_v4l2 = {
70 tvi_init_v4l2, 75 tvi_init_v4l2,
107 struct v4l2_standard standard; 112 struct v4l2_standard standard;
108 struct v4l2_tuner tuner; 113 struct v4l2_tuner tuner;
109 struct map *map; 114 struct map *map;
110 int mapcount; 115 int mapcount;
111 int frames; 116 int frames;
112 volatile long long first_frame; 117 volatile long long first_frame; ///< number of useconds
113 long long curr_frame; 118 long long curr_frame; ///< usec, using kernel timestamps
119 int clk_id; /**< clk_id from clock_gettime
120 used in frame timestamps */
114 /* audio video interleaving ;-) */ 121 /* audio video interleaving ;-) */
115 volatile int streamon; 122 volatile int streamon;
116 pthread_t audio_grabber_thread; 123 pthread_t audio_grabber_thread;
117 pthread_mutex_t skew_mutex; 124 pthread_mutex_t skew_mutex;
118 125
486 } 493 }
487 } while (priv->standard.id != id); 494 } while (priv->standard.id != id);
488 return 0; 495 return 0;
489 } 496 }
490 497
498 /*
499 ** Gets current timestamp, using specified clock id.
500 ** @return number of microseconds.
501 */
502 static long long get_curr_timestamp(int clk_id)
503 {
504 struct timespec ts;
505 clock_gettime(clk_id, &ts);
506 return (long long)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
507 }
508
491 /***********************************************************************\ 509 /***********************************************************************\
492 * * 510 * *
493 * * 511 * *
494 * Interface to mplayer * 512 * Interface to mplayer *
495 * * 513 * *
1529 info.short_name, strerror(errno)); 1547 info.short_name, strerror(errno));
1530 priv->map[i].len = 0; 1548 priv->map[i].len = 0;
1531 return 0; 1549 return 0;
1532 } 1550 }
1533 priv->map[i].len = priv->map[i].buf.length; 1551 priv->map[i].len = priv->map[i].buf.length;
1552 priv->clk_id = (priv->map[i].buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)
1553 ? CLOCK_MONOTONIC : CLOCK_REALTIME;
1534 /* count up to make sure this is correct everytime */ 1554 /* count up to make sure this is correct everytime */
1535 priv->mapcount++; 1555 priv->mapcount++;
1536 1556
1537 if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) { 1557 if (ioctl(priv->video_fd, VIDIOC_QBUF, &(priv->map[i].buf)) < 0) {
1538 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n", 1558 mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl queue buffer failed: %s\n",
1832 #endif 1852 #endif
1833 1853
1834 static void *audio_grabber(void *data) 1854 static void *audio_grabber(void *data)
1835 { 1855 {
1836 priv_t *priv = (priv_t*)data; 1856 priv_t *priv = (priv_t*)data;
1837 struct timeval tv;
1838 int i, audio_skew_ptr = 0; 1857 int i, audio_skew_ptr = 0;
1839 long long current_time, prev_skew = 0, prev_skew_uncorr = 0; 1858 long long current_time, prev_skew = 0, prev_skew_uncorr = 0;
1840 long long start_time_avg; 1859 long long start_time_avg, curr_timestamp;
1841 1860
1842 gettimeofday(&tv, NULL); 1861 start_time_avg = priv->audio_start_time = get_curr_timestamp(priv->clk_id);
1843 start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
1844 audio_in_start_capture(&priv->audio_in); 1862 audio_in_start_capture(&priv->audio_in);
1845 for (i = 0; i < priv->aud_skew_cnt; i++) 1863 for (i = 0; i < priv->aud_skew_cnt; i++)
1846 priv->audio_skew_buffer[i] = 0; 1864 priv->audio_skew_buffer[i] = 0;
1847 for (i = 0; i < priv->aud_skew_cnt; i++) 1865 for (i = 0; i < priv->aud_skew_cnt; i++)
1848 priv->audio_skew_delta_buffer[i] = 0; 1866 priv->audio_skew_delta_buffer[i] = 0;
1856 continue; 1874 continue;
1857 #endif 1875 #endif
1858 pthread_mutex_lock(&priv->skew_mutex); 1876 pthread_mutex_lock(&priv->skew_mutex);
1859 if (priv->first_frame == 0) { 1877 if (priv->first_frame == 0) {
1860 // there is no first frame yet (unlikely to happen) 1878 // there is no first frame yet (unlikely to happen)
1861 gettimeofday(&tv, NULL); 1879 start_time_avg = priv->audio_start_time = get_curr_timestamp(priv->clk_id);
1862 start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
1863 // fprintf(stderr, "warning - first frame not yet available!\n"); 1880 // fprintf(stderr, "warning - first frame not yet available!\n");
1864 pthread_mutex_unlock(&priv->skew_mutex); 1881 pthread_mutex_unlock(&priv->skew_mutex);
1865 continue; 1882 continue;
1866 } 1883 }
1867 pthread_mutex_unlock(&priv->skew_mutex); 1884 pthread_mutex_unlock(&priv->skew_mutex);
1868 1885
1869 gettimeofday(&tv, NULL);
1870
1871 priv->audio_recv_blocks_total++; 1886 priv->audio_recv_blocks_total++;
1872 current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_start_time; 1887 curr_timestamp = get_curr_timestamp(priv->clk_id);
1888 current_time = curr_timestamp - priv->audio_start_time;
1873 1889
1874 if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) { 1890 if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) {
1875 start_time_avg += (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_usecs_per_block*priv->audio_recv_blocks_total; 1891 start_time_avg += curr_timestamp - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
1876 priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1); 1892 priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1);
1877 } 1893 }
1878 1894
1879 // fprintf(stderr, "spb = %f, bs = %d, skew = %f\n", priv->audio_secs_per_block, priv->audio_in.blocksize, 1895 // fprintf(stderr, "spb = %f, bs = %d, skew = %f\n", priv->audio_secs_per_block, priv->audio_in.blocksize,
1880 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6); 1896 // (double)(current_time - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total)/1e6);