summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authorhenry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-03-15 22:02:54 +0000
committerhenry <henry@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-03-15 22:02:54 +0000
commit62b166e62dc85b20135767c33af8d8aabdc655e0 (patch)
treeb5bee04499d8b73b9e6b1073a94766b868970d11 /libmpdemux
parent0b38aaf6ec23466515af065e94626a1eec01a506 (diff)
downloadmpv-62b166e62dc85b20135767c33af8d8aabdc655e0.tar.bz2
mpv-62b166e62dc85b20135767c33af8d8aabdc655e0.tar.xz
correct small framerate fluctuations directly in the capture thread
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9608 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/tvi_v4l.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/libmpdemux/tvi_v4l.c b/libmpdemux/tvi_v4l.c
index 02fd27c4ea..e9c7359abc 100644
--- a/libmpdemux/tvi_v4l.c
+++ b/libmpdemux/tvi_v4l.c
@@ -60,6 +60,7 @@ static tvi_info_t info = {
#define MAX_AUDIO_CHANNELS 10
#define VID_BUF_SIZE_IMMEDIATE 2
+#define VIDEO_AVG_BUFFER_SIZE 300
typedef struct {
/* general */
@@ -111,6 +112,9 @@ typedef struct {
volatile int video_buffer_size_current;
unsigned char **video_ringbuffer;
long long *video_timebuffer;
+ long long *video_avg_buffer;
+ int video_avg_ptr;
+ int video_interval_sum;
volatile int video_head;
volatile int video_tail;
volatile int video_cnt;
@@ -404,6 +408,7 @@ static int init(priv_t *priv)
priv->video_ringbuffer = NULL;
priv->video_timebuffer = NULL;
+ priv->video_avg_buffer = NULL;
priv->audio_ringbuffer = NULL;
priv->audio_skew_buffer = NULL;
@@ -582,6 +587,8 @@ static int uninit(priv_t *priv)
if (priv->video_timebuffer)
free(priv->video_timebuffer);
+ if (priv->video_avg_buffer)
+ free(priv->video_avg_buffer);
if (!tv_param_noaudio) {
if (priv->audio_ringbuffer)
free(priv->audio_ringbuffer);
@@ -762,6 +769,18 @@ static int start(priv_t *priv)
mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate time buffer: %s\n", strerror(errno));
return 0;
}
+ priv->video_avg_buffer = (long long*)malloc(sizeof(long long) * VIDEO_AVG_BUFFER_SIZE);
+ if (!priv->video_avg_buffer) {
+ mp_msg(MSGT_TV, MSGL_ERR, "cannot allocate period buffer: %s\n", strerror(errno));
+ return 0;
+ }
+ priv->video_interval_sum = (1e6/priv->fps)*VIDEO_AVG_BUFFER_SIZE;
+ for (i = 0; i < VIDEO_AVG_BUFFER_SIZE; i++) {
+ priv->video_avg_buffer[i] = 1e6/priv->fps;
+ }
+
+ priv->video_avg_ptr = 0;
+
priv->video_head = 0;
priv->video_tail = 0;
priv->video_cnt = 0;
@@ -1243,6 +1262,7 @@ static void *video_grabber(void *data)
int i;
int first = 1;
int framecount;
+ int tolerance;
/* start the capture process */
@@ -1256,6 +1276,8 @@ static void *video_grabber(void *data)
prev_interval = 0;
prev_skew = 0;
+ tolerance = priv->nbuf*2;
+
for (framecount = 0; !priv->shutdown;)
{
for (i = 0; i < priv->nbuf && !priv->shutdown; i++, framecount++) {
@@ -1302,6 +1324,25 @@ static void *video_grabber(void *data)
mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta ~ %.1lf fps\n",
(double)1e6/(interval - prev_interval));
}
+
+ // correct the rate fluctuations on a small scale
+ if ((interval - prev_interval < (long long)0.95e6/priv->fps)
+ || (interval - prev_interval > (long long)1.05e6/priv->fps) ) {
+ if (tolerance > 0) {
+ mp_msg(MSGT_TV, MSGL_DBG3, "correcting timestamp\n");
+ interval = prev_interval + priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;
+ tolerance--;
+ } else {
+ mp_msg(MSGT_TV, MSGL_DBG3, "bad - frames were dropped\n");
+ tolerance = priv->nbuf*2;
+ }
+ } else {
+ if (tolerance < priv->nbuf*2) {
+ mp_msg(MSGT_TV, MSGL_DBG3, "fluctuation overcome\n");
+ }
+ tolerance = priv->nbuf*2;
+ }
+
}
// interpolate the skew in time
@@ -1323,9 +1364,14 @@ static void *video_grabber(void *data)
(double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);
mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);
+ priv->video_interval_sum -= priv->video_avg_buffer[priv->video_avg_ptr];
+ priv->video_avg_buffer[priv->video_avg_ptr++] = interval-prev_interval;
+ priv->video_interval_sum += interval-prev_interval;
+ if (priv->video_avg_ptr >= VIDEO_AVG_BUFFER_SIZE) priv->video_avg_ptr = 0;
+
prev_skew = skew;
prev_interval = interval;
-
+
/* allocate a new buffer, if needed */
pthread_mutex_lock(&priv->video_buffer_mutex);
if (priv->video_buffer_size_current < priv->video_buffer_size_max) {