Mercurial > mplayer.hg
changeset 9607:e2eaeb3cb089
correct small framerate fluctuations directly in the capture thread
author | henry |
---|---|
date | Sat, 15 Mar 2003 22:02:54 +0000 |
parents | 0197c1e933fe |
children | 7bc2ed398ccf |
files | libmpdemux/tvi_v4l.c |
diffstat | 1 files changed, 47 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpdemux/tvi_v4l.c Sat Mar 15 21:07:45 2003 +0000 +++ b/libmpdemux/tvi_v4l.c Sat Mar 15 22:02:54 2003 +0000 @@ -60,6 +60,7 @@ #define MAX_AUDIO_CHANNELS 10 #define VID_BUF_SIZE_IMMEDIATE 2 +#define VIDEO_AVG_BUFFER_SIZE 300 typedef struct { /* general */ @@ -111,6 +112,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ int i; int first = 1; int framecount; + int tolerance; /* start the capture process */ @@ -1256,6 +1276,8 @@ 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 @@ 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 @@ (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) {