diff --git a/ffplay.c b/ffplay.c index c998b5d446..81ded546c8 100644 --- a/ffplay.c +++ b/ffplay.c @@ -197,6 +197,8 @@ typedef struct VideoState { double frame_timer; double frame_last_pts; double frame_last_duration; + double frame_last_dropped_pts; + int64_t frame_last_dropped_pos; double video_clock; ///pictq_mutex); } +static void update_video_pts(VideoState *is, double pts, int64_t pos) { + double time = av_gettime() / 1000000.0; + /* update current video pts */ + is->video_current_pts = pts; + is->video_current_pts_drift = is->video_current_pts - time; + is->video_current_pos = pos; + is->frame_last_pts = pts; +} + /* called to display each frame */ static void video_refresh(void *opaque) { VideoState *is = opaque; VideoPicture *vp; + double time; SubPicture *sp, *sp2; if (is->video_st) { retry: if (is->pictq_size == 0) { + SDL_LockMutex(is->pictq_mutex); + if (is->frame_last_dropped_pts != AV_NOPTS_VALUE && is->frame_last_dropped_pts > is->frame_last_pts) { + update_video_pts(is, is->frame_last_dropped_pts, is->frame_last_dropped_pos); + is->frame_last_dropped_pts = AV_NOPTS_VALUE; + } + SDL_UnlockMutex(is->pictq_mutex); //nothing to do, no picture to display in the que } else { - double time= av_gettime()/1000000.0; double last_duration, duration, delay; /* dequeue the picture */ vp = &is->pictq[is->pictq_rindex]; @@ -1133,17 +1150,16 @@ retry: } delay = compute_target_delay(is->frame_last_duration, is); + time= av_gettime()/1000000.0; if(time < is->frame_timer + delay) return; - is->frame_last_pts = vp->pts; if (delay > 0) is->frame_timer += delay * FFMAX(1, floor((time-is->frame_timer) / delay)); - /* update current video pts */ - is->video_current_pts = vp->pts; - is->video_current_pts_drift = is->video_current_pts - time; - is->video_current_pos = vp->pos; + SDL_LockMutex(is->pictq_mutex); + update_video_pts(is, vp->pts, vp->pos); + SDL_UnlockMutex(is->pictq_mutex); if(is->pictq_size > 1) { VideoPicture *nextvp= &is->pictq[(is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE]; @@ -1448,17 +1464,20 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke SDL_CondWait(is->pictq_cond, is->pictq_mutex); } is->video_current_pos = -1; - SDL_UnlockMutex(is->pictq_mutex); - is->frame_last_pts = AV_NOPTS_VALUE; is->frame_last_duration = 0; is->frame_timer = (double)av_gettime() / 1000000.0; + is->frame_last_dropped_pts = AV_NOPTS_VALUE; + SDL_UnlockMutex(is->pictq_mutex); + return 0; } avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt); if (got_picture) { + int ret = 1; + if (decoder_reorder_pts == -1) { *pts = frame->best_effort_timestamp; } else if (decoder_reorder_pts) { @@ -1471,8 +1490,25 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke *pts = 0; } - return 1; + if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) || is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK) && + (framedrop>0 || (framedrop && is->audio_st))) { + SDL_LockMutex(is->pictq_mutex); + if (is->frame_last_pts != AV_NOPTS_VALUE && *pts) { + double clockdiff = get_video_clock(is) - get_master_clock(is); + double dpts = av_q2d(is->video_st->time_base) * *pts; + double ptsdiff = dpts - is->frame_last_pts; + if (fabs(clockdiff) < AV_NOSYNC_THRESHOLD && + ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD && + clockdiff + ptsdiff < 0) { //TODO: Substract approxiamte time of filter + is->frame_last_dropped_pos = pkt->pos; + is->frame_last_dropped_pts = dpts; + ret = 0; + } + } + SDL_UnlockMutex(is->pictq_mutex); + } + return ret; } return 0; }