[FFmpeg-cvslog] ffplay: fix external time sync mode

Marton Balint git at videolan.org
Sun Oct 21 19:02:12 CEST 2012


ffmpeg | branch: master | Marton Balint <cus at passwd.hu> | Sat Oct  6 23:55:29 2012 +0200| [77bd595ad2ff339f46d63b15a9040e4b1a70b378] | committer: Marton Balint

ffplay: fix external time sync mode

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>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=77bd595ad2ff339f46d63b15a9040e4b1a70b378
---

 ffplay.c |   31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/ffplay.c b/ffplay.c
index 917883e..d9f751c 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;



More information about the ffmpeg-cvslog mailing list