diff options
-rw-r--r-- | ffplay.c | 85 |
1 files changed, 46 insertions, 39 deletions
@@ -1005,12 +1005,56 @@ static void stream_pause(VideoState *is) } } +static double compute_frame_delay(double frame_current_pts, VideoState *is) +{ + double actual_delay, delay, sync_threshold, ref_clock, diff; + + /* compute nominal delay */ + delay = frame_current_pts - is->frame_last_pts; + if (delay <= 0 || delay >= 10.0) { + /* if incorrect delay, use previous one */ + delay = is->frame_last_delay; + } + is->frame_last_delay = delay; + is->frame_last_pts = frame_current_pts; + + /* update delay to follow master synchronisation source */ + if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) || + is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) { + /* if video is slave, we try to correct big delays by + duplicating or deleting a frame */ + ref_clock = get_master_clock(is); + diff = frame_current_pts - ref_clock; + + /* skip or repeat frame. We take into account the + delay to compute the threshold. I still don't know + if it is the best guess */ + sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay); + if (fabs(diff) < AV_NOSYNC_THRESHOLD) { + if (diff <= -sync_threshold) + delay = 0; + else if (diff >= sync_threshold) + delay = 2 * delay; + } + } + + is->frame_timer += delay; + /* compute the REAL delay (we need to do that to avoid + long term errors */ + actual_delay = is->frame_timer - (av_gettime() / 1000000.0); + if (actual_delay < 0.010) { + /* XXX: should skip picture */ + actual_delay = 0.010; + } + + return actual_delay; +} + /* called to display each frame */ static void video_refresh_timer(void *opaque) { VideoState *is = opaque; VideoPicture *vp; - double actual_delay, delay, sync_threshold, ref_clock, diff; SubPicture *sp, *sp2; @@ -1026,45 +1070,8 @@ static void video_refresh_timer(void *opaque) is->video_current_pts = vp->pts; is->video_current_pts_time = av_gettime(); - /* compute nominal delay */ - delay = vp->pts - is->frame_last_pts; - if (delay <= 0 || delay >= 10.0) { - /* if incorrect delay, use previous one */ - delay = is->frame_last_delay; - } - is->frame_last_delay = delay; - is->frame_last_pts = vp->pts; - - /* update delay to follow master synchronisation source */ - if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) || - is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK)) { - /* if video is slave, we try to correct big delays by - duplicating or deleting a frame */ - ref_clock = get_master_clock(is); - diff = vp->pts - ref_clock; - - /* skip or repeat frame. We take into account the - delay to compute the threshold. I still don't know - if it is the best guess */ - sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay); - if (fabs(diff) < AV_NOSYNC_THRESHOLD) { - if (diff <= -sync_threshold) - delay = 0; - else if (diff >= sync_threshold) - delay = 2 * delay; - } - } - - is->frame_timer += delay; - /* compute the REAL delay (we need to do that to avoid - long term errors */ - actual_delay = is->frame_timer - (av_gettime() / 1000000.0); - if (actual_delay < 0.010) { - /* XXX: should skip picture */ - actual_delay = 0.010; - } /* launch timer for next picture */ - schedule_refresh(is, (int)(actual_delay * 1000 + 0.5)); + schedule_refresh(is, (int)(compute_frame_delay(vp->pts, is) * 1000 + 0.5)); #if defined(DEBUG_SYNC) printf("video: delay=%0.3f actual_delay=%0.3f pts=%0.3f A-V=%f\n", |