[FFmpeg-devel] [PATCH 4/9] ffplay: fix external time sync mode
Marton Balint
cus at passwd.hu
Sun Oct 14 19:11:49 CEST 2012
We now initalize the external clock to 0 and, we use the system clock to
regulate the timings of audio and video in external clock sync mode. We
recover from external clock sync loss, when the delay to external clock is
bigger than AV_NOSYNC_THRESHOLD.
Signed-off-by: Marton Balint <cus at passwd.hu>
---
ffplay.c | 31 ++++++++++++++++++++++++++-----
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/ffplay.c b/ffplay.c
index 1e42fc8..070bfda 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -153,8 +153,9 @@ typedef struct VideoState {
int audio_stream;
int av_sync_type;
- double external_clock; /* external clock base */
- int64_t external_clock_time;
+ double external_clock; ///< external clock base
+ double external_clock_drift; ///< external clock base - time (av_gettime) at which we updated external_clock
+ int64_t external_clock_time; ///< last reference time
double audio_clock;
double audio_diff_cum; /* used for AV difference average computation */
@@ -1044,9 +1045,11 @@ static double get_video_clock(VideoState *is)
/* get the current external clock value */
static double get_external_clock(VideoState *is)
{
- int64_t ti;
- ti = av_gettime();
- return is->external_clock + ((ti - is->external_clock_time) * 1e-6);
+ if (is->paused) {
+ return is->external_clock;
+ } else {
+ return is->external_clock_drift + av_gettime() / 1000000.0;
+ }
}
/* get the current master clock value */
@@ -1070,6 +1073,19 @@ static double get_master_clock(VideoState *is)
return val;
}
+static void update_external_clock_pts(VideoState *is, double pts)
+{
+ is->external_clock_time = av_gettime();
+ is->external_clock = pts;
+ is->external_clock_drift = pts - is->external_clock_time / 1000000.0;
+}
+
+static void check_external_clock_sync(VideoState *is, double pts) {
+ if (fabs(get_external_clock(is) - pts) > AV_NOSYNC_THRESHOLD) {
+ update_external_clock_pts(is, pts);
+ }
+}
+
/* seek in the stream */
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int seek_by_bytes)
{
@@ -1093,6 +1109,7 @@ static void stream_toggle_pause(VideoState *is)
}
is->video_current_pts_drift = is->video_current_pts - av_gettime() / 1000000.0;
}
+ update_external_clock_pts(is, get_external_clock(is));
is->paused = !is->paused;
}
@@ -1159,6 +1176,7 @@ static void update_video_pts(VideoState *is, double pts, int64_t pos) {
is->video_current_pts_drift = is->video_current_pts - time;
is->video_current_pos = pos;
is->frame_last_pts = pts;
+ check_external_clock_sync(is, is->video_current_pts);
}
/* called to display each frame */
@@ -2116,6 +2134,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
/* Let's assume the audio driver that is used by SDL has two periods. */
is->audio_current_pts = is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / bytes_per_sec;
is->audio_current_pts_drift = is->audio_current_pts - audio_callback_time / 1000000.0;
+ check_external_clock_sync(is, is->audio_current_pts);
}
static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params)
@@ -2548,6 +2567,7 @@ static int read_thread(void *arg)
packet_queue_put(&is->videoq, &flush_pkt);
}
}
+ update_external_clock_pts(is, (seek_target + ic->start_time) / (double)AV_TIME_BASE);
is->seek_req = 0;
eof = 0;
}
@@ -2677,6 +2697,7 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
is->continue_read_thread = SDL_CreateCond();
+ update_external_clock_pts(is, 0.0);
is->audio_current_pts_drift = -av_gettime() / 1000000.0;
is->video_current_pts_drift = is->audio_current_pts_drift;
is->av_sync_type = av_sync_type;
--
1.7.10.4
More information about the ffmpeg-devel
mailing list