diff --git a/ffplay.c b/ffplay.c index b4394e3619..ad3e36cb06 100644 --- a/ffplay.c +++ b/ffplay.c @@ -176,6 +176,7 @@ typedef struct VideoState { double external_clock_speed; ///< speed of the external clock double audio_clock; + int audio_clock_serial; double audio_diff_cum; /* used for AV difference average computation */ double audio_diff_avg_coef; double audio_diff_threshold; @@ -238,6 +239,7 @@ typedef struct VideoState { double video_current_pts_drift; // video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts int64_t video_current_pos; // current displayed file pos double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity + int video_clock_serial; VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; int pictq_size, pictq_rindex, pictq_windex; SDL_mutex *pictq_mutex; @@ -1079,6 +1081,8 @@ static void video_display(VideoState *is) /* get the current audio clock value */ static double get_audio_clock(VideoState *is) { + if (is->audio_clock_serial != is->audioq.serial) + return NAN; if (is->paused) { return is->audio_current_pts; } else { @@ -1089,6 +1093,8 @@ static double get_audio_clock(VideoState *is) /* get the current video clock value */ static double get_video_clock(VideoState *is) { + if (is->video_clock_serial != is->videoq.serial) + return NAN; if (is->paused) { return is->video_current_pts; } else { @@ -1230,7 +1236,7 @@ static double compute_target_delay(double delay, VideoState *is) 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 (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) { if (diff <= -sync_threshold) delay = 0; else if (diff >= sync_threshold) @@ -1281,6 +1287,7 @@ static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial is->video_current_pts_drift = is->video_current_pts - time; is->video_current_pos = pos; is->frame_last_pts = pts; + is->video_clock_serial = serial; if (is->videoq.serial == serial) check_external_clock_sync(is, is->video_current_pts); } @@ -1677,7 +1684,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke 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 && + if (!isnan(clockdiff) && fabs(clockdiff) < AV_NOSYNC_THRESHOLD && ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD && clockdiff + ptsdiff - is->frame_last_filter_delay < 0) { is->frame_last_dropped_pos = pkt->pos; @@ -2038,7 +2045,7 @@ static int synchronize_audio(VideoState *is, int nb_samples) diff = get_audio_clock(is) - get_master_clock(is); - if (fabs(diff) < AV_NOSYNC_THRESHOLD) { + if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) { is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum; if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) { /* not enough measures to have a correct estimate */ @@ -2224,6 +2231,7 @@ static int audio_decode_frame(VideoState *is) /* if update the audio clock with the pts */ if (pkt->pts != AV_NOPTS_VALUE) { is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts; + is->audio_clock_serial = is->audio_pkt_temp_serial; } } } @@ -2265,7 +2273,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; - if (is->audioq.serial == is->audio_pkt_temp_serial) + if (is->audioq.serial == is->audio_clock_serial) check_external_clock_sync(is, is->audio_current_pts); } @@ -2851,6 +2859,8 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) update_external_clock_speed(is, 1.0); is->audio_current_pts_drift = -av_gettime() / 1000000.0; is->video_current_pts_drift = is->audio_current_pts_drift; + is->audio_clock_serial = -1; + is->video_clock_serial = -1; is->av_sync_type = av_sync_type; is->read_tid = SDL_CreateThread(read_thread, is); if (!is->read_tid) { @@ -3033,6 +3043,8 @@ static void event_loop(VideoState *cur_stream) stream_seek(cur_stream, pos, incr, 1); } else { pos = get_master_clock(cur_stream); + if (isnan(pos)) + pos = (double)cur_stream->seek_pos / AV_TIME_BASE; pos += incr; if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE) pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;