Mercurial > mplayer.hg
comparison libmpdemux/tvi_v4l2.c @ 10653:d9dfbe5e1011
a/v sync improvements
author | henry |
---|---|
date | Mon, 18 Aug 2003 09:23:07 +0000 |
parents | dd2572331142 |
children | 1d991eb5cf02 |
comparison
equal
deleted
inserted
replaced
10652:b04560162c1f | 10653:d9dfbe5e1011 |
---|---|
105 long long audio_start_time; | 105 long long audio_start_time; |
106 int audio_buffer_size; | 106 int audio_buffer_size; |
107 int aud_skew_cnt; | 107 int aud_skew_cnt; |
108 unsigned char *audio_ringbuffer; | 108 unsigned char *audio_ringbuffer; |
109 long long *audio_skew_buffer; | 109 long long *audio_skew_buffer; |
110 long long *audio_skew_delta_buffer; | |
110 volatile int audio_head; | 111 volatile int audio_head; |
111 volatile int audio_tail; | 112 volatile int audio_tail; |
112 volatile int audio_cnt; | 113 volatile int audio_cnt; |
113 volatile long long audio_skew; | 114 volatile long long audio_skew; |
114 volatile double audio_skew_factor; | 115 volatile double audio_skew_factor; |
116 volatile int audio_drop; | 117 volatile int audio_drop; |
117 volatile int shutdown; | 118 volatile int shutdown; |
118 | 119 |
119 double audio_secs_per_block; | 120 double audio_secs_per_block; |
120 long long audio_skew_total; | 121 long long audio_skew_total; |
122 long long audio_skew_delta_total; | |
121 long audio_recv_blocks_total; | 123 long audio_recv_blocks_total; |
122 long audio_sent_blocks_total; | 124 long audio_sent_blocks_total; |
123 } priv_t; | 125 } priv_t; |
124 | 126 |
125 #include "tvi_def.h" | 127 #include "tvi_def.h" |
842 if (!tv_param_noaudio) { | 844 if (!tv_param_noaudio) { |
843 if (priv->audio_ringbuffer) | 845 if (priv->audio_ringbuffer) |
844 free(priv->audio_ringbuffer); | 846 free(priv->audio_ringbuffer); |
845 if (priv->audio_skew_buffer) | 847 if (priv->audio_skew_buffer) |
846 free(priv->audio_skew_buffer); | 848 free(priv->audio_skew_buffer); |
849 if (priv->audio_skew_delta_buffer) | |
850 free(priv->audio_skew_delta_buffer); | |
847 } | 851 } |
848 | 852 |
849 /* show some nice statistics ;-) */ | 853 /* show some nice statistics ;-) */ |
850 mp_msg(MSGT_TV, MSGL_INFO, | 854 mp_msg(MSGT_TV, MSGL_INFO, |
851 "%s: %d frames successfully processed, %d frames dropped.\n", | 855 "%s: %d frames successfully processed, %d frames dropped.\n", |
864 if (tv_param_immediate == 1) | 868 if (tv_param_immediate == 1) |
865 tv_param_noaudio = 1; | 869 tv_param_noaudio = 1; |
866 | 870 |
867 priv->audio_ringbuffer = NULL; | 871 priv->audio_ringbuffer = NULL; |
868 priv->audio_skew_buffer = NULL; | 872 priv->audio_skew_buffer = NULL; |
873 priv->audio_skew_delta_buffer = NULL; | |
869 | 874 |
870 /* Open the video device. */ | 875 /* Open the video device. */ |
871 priv->video_fd = open(priv->video_dev, O_RDWR); | 876 priv->video_fd = open(priv->video_dev, O_RDWR); |
872 if (priv->video_fd < 0) { | 877 if (priv->video_fd < 0) { |
873 mp_msg(MSGT_TV, MSGL_ERR, "%s: unable to open '%s': %s\n", | 878 mp_msg(MSGT_TV, MSGL_ERR, "%s: unable to open '%s': %s\n", |
1125 priv->audio_skew_buffer = (long long*)malloc(sizeof(long long)*priv->aud_skew_cnt); | 1130 priv->audio_skew_buffer = (long long*)malloc(sizeof(long long)*priv->aud_skew_cnt); |
1126 if (!priv->audio_skew_buffer) { | 1131 if (!priv->audio_skew_buffer) { |
1127 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno)); | 1132 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno)); |
1128 return 0; | 1133 return 0; |
1129 } | 1134 } |
1135 priv->audio_skew_delta_buffer = (long long*)malloc(sizeof(long long)*priv->aud_skew_cnt); | |
1136 if (!priv->audio_skew_delta_buffer) { | |
1137 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate skew buffer: %s\n", strerror(errno)); | |
1138 return 0; | |
1139 } | |
1130 | 1140 |
1131 priv->audio_ringbuffer = (unsigned char*)malloc(priv->audio_in.blocksize*priv->audio_buffer_size); | 1141 priv->audio_ringbuffer = (unsigned char*)malloc(priv->audio_in.blocksize*priv->audio_buffer_size); |
1132 if (!priv->audio_ringbuffer) { | 1142 if (!priv->audio_ringbuffer) { |
1133 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno)); | 1143 mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate audio buffer: %s\n", strerror(errno)); |
1134 return 0; | 1144 return 0; |
1141 priv->audio_tail = 0; | 1151 priv->audio_tail = 0; |
1142 priv->audio_cnt = 0; | 1152 priv->audio_cnt = 0; |
1143 priv->audio_drop = 0; | 1153 priv->audio_drop = 0; |
1144 priv->audio_skew = 0; | 1154 priv->audio_skew = 0; |
1145 priv->audio_skew_total = 0; | 1155 priv->audio_skew_total = 0; |
1156 priv->audio_skew_delta_total = 0; | |
1146 priv->audio_recv_blocks_total = 0; | 1157 priv->audio_recv_blocks_total = 0; |
1147 priv->audio_sent_blocks_total = 0; | 1158 priv->audio_sent_blocks_total = 0; |
1148 } | 1159 } |
1149 | 1160 |
1150 /* setup video parameters */ | 1161 /* setup video parameters */ |
1512 static void *audio_grabber(void *data) | 1523 static void *audio_grabber(void *data) |
1513 { | 1524 { |
1514 priv_t *priv = (priv_t*)data; | 1525 priv_t *priv = (priv_t*)data; |
1515 struct timeval tv; | 1526 struct timeval tv; |
1516 int i, audio_skew_ptr = 0; | 1527 int i, audio_skew_ptr = 0; |
1517 long long current_time, prev_skew = 0; | 1528 long long current_time, prev_skew = 0, prev_skew_uncorr = 0; |
1518 | 1529 |
1519 gettimeofday(&tv, NULL); | 1530 gettimeofday(&tv, NULL); |
1520 priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec; | 1531 priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec; |
1521 audio_in_start_capture(&priv->audio_in); | 1532 audio_in_start_capture(&priv->audio_in); |
1522 for (i = 0; i < priv->aud_skew_cnt; i++) | 1533 for (i = 0; i < priv->aud_skew_cnt; i++) |
1523 priv->audio_skew_buffer[i] = 0; | 1534 priv->audio_skew_buffer[i] = 0; |
1535 for (i = 0; i < priv->aud_skew_cnt; i++) | |
1536 priv->audio_skew_delta_buffer[i] = 0; | |
1524 | 1537 |
1525 for (; !priv->shutdown;) | 1538 for (; !priv->shutdown;) |
1526 { | 1539 { |
1527 // read_doublespeed(priv); | 1540 // read_doublespeed(priv); |
1528 if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0) | 1541 if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0) |
1547 | 1560 |
1548 priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr]; | 1561 priv->audio_skew_total -= priv->audio_skew_buffer[audio_skew_ptr]; |
1549 priv->audio_skew_buffer[audio_skew_ptr] = current_time | 1562 priv->audio_skew_buffer[audio_skew_ptr] = current_time |
1550 - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total; | 1563 - 1e6*priv->audio_secs_per_block*priv->audio_recv_blocks_total; |
1551 priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr]; | 1564 priv->audio_skew_total += priv->audio_skew_buffer[audio_skew_ptr]; |
1552 audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt; | |
1553 | 1565 |
1554 pthread_mutex_lock(&priv->skew_mutex); | 1566 pthread_mutex_lock(&priv->skew_mutex); |
1555 // linear interpolation - here we interpolate current skew value | 1567 // linear interpolation - here we interpolate current skew value |
1556 // from the moving average, which we expect to be in the middle | 1568 // from the moving average, which we expect to be in the middle |
1557 // of the interval | 1569 // of the interval |
1558 if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) { | 1570 if (priv->audio_recv_blocks_total > priv->aud_skew_cnt) { |
1559 priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt; | 1571 priv->audio_skew = priv->audio_skew_total/priv->aud_skew_cnt; |
1560 priv->audio_skew += (priv->audio_skew*priv->aud_skew_cnt)/(2*priv->audio_recv_blocks_total-priv->aud_skew_cnt); | 1572 // priv->audio_skew += (priv->audio_skew*priv->aud_skew_cnt)/(2*priv->audio_recv_blocks_total-priv->aud_skew_cnt); |
1561 } else { | 1573 } else { |
1562 // this smoothens the evolution of audio_skew at startup a bit | 1574 // this smoothens the evolution of audio_skew at startup a bit |
1563 priv->audio_skew = ((priv->aud_skew_cnt+priv->audio_recv_blocks_total)*priv->audio_skew_total)/(priv->aud_skew_cnt*priv->audio_recv_blocks_total); | 1575 priv->audio_skew = ((priv->aud_skew_cnt+priv->audio_recv_blocks_total)*priv->audio_skew_total)/(priv->aud_skew_cnt*priv->audio_recv_blocks_total); |
1564 } | 1576 } |
1565 // fprintf(stderr, "audio_skew = %lf\n", (double)priv->audio_skew/1e6); | 1577 |
1578 priv->audio_skew_delta_total -= priv->audio_skew_delta_buffer[audio_skew_ptr]; | |
1579 priv->audio_skew_delta_buffer[audio_skew_ptr] = priv->audio_skew - prev_skew_uncorr; | |
1580 priv->audio_skew_delta_total += priv->audio_skew_delta_buffer[audio_skew_ptr]; | |
1581 prev_skew_uncorr = priv->audio_skew; | |
1582 | |
1583 audio_skew_ptr = (audio_skew_ptr+1) % priv->aud_skew_cnt; | |
1584 | |
1585 priv->audio_skew += priv->audio_skew_delta_total/2; | |
1586 | |
1587 // fprintf(stderr, "audio_skew = %lf, delta = %lf\n", (double)priv->audio_skew/1e6, (double)priv->audio_skew_delta_total/1e6); | |
1566 // current skew factor (assuming linearity) | 1588 // current skew factor (assuming linearity) |
1567 // used for further interpolation in video_grabber | 1589 // used for further interpolation in video_grabber |
1568 // probably overkill but seems to be necessary for | 1590 // probably overkill but seems to be necessary for |
1569 // stress testing by dropping half of the audio frames ;) | 1591 // stress testing by dropping half of the audio frames ;) |
1570 // especially when using ALSA with large block sizes | 1592 // especially when using ALSA with large block sizes |