diff --git a/mpvcore/player/audio.c b/mpvcore/player/audio.c index 042e6d66c3..ec2f039531 100644 --- a/mpvcore/player/audio.c +++ b/mpvcore/player/audio.c @@ -303,7 +303,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize) if (hrseek) ptsdiff = written_pts - mpctx->hrseek_pts; else - ptsdiff = written_pts - mpctx->d_video->pts - mpctx->delay + ptsdiff = written_pts - mpctx->video_next_pts - mpctx->delay - mpctx->audio_delay; samples = ptsdiff * real_samplerate; diff --git a/mpvcore/player/mp_core.h b/mpvcore/player/mp_core.h index c1fbf737f3..4aabf6a991 100644 --- a/mpvcore/player/mp_core.h +++ b/mpvcore/player/mp_core.h @@ -248,6 +248,9 @@ typedef struct MPContext { // the same value if the status line is updated at a time where no new // video frame is shown. double last_av_difference; + /* Timestamp of the latest image that was queued on the VO, but not yet + * to be flipped. */ + double video_next_pts; /* timestamp of video frame currently visible on screen * (or at least queued to be flipped by VO) */ double video_pts; diff --git a/mpvcore/player/playloop.c b/mpvcore/player/playloop.c index 650f164f05..9ec62834b4 100644 --- a/mpvcore/player/playloop.c +++ b/mpvcore/player/playloop.c @@ -173,6 +173,7 @@ static void seek_reset(struct MPContext *mpctx, bool reset_ao) video_reset_decoding(mpctx->d_video); vo_seek_reset(mpctx->video_out); mpctx->video_pts = MP_NOPTS_VALUE; + mpctx->video_next_pts = MP_NOPTS_VALUE; mpctx->delay = 0; mpctx->time_frame = 0; } @@ -616,7 +617,7 @@ static void adjust_sync(struct MPContext *mpctx, double frame_time) return; double a_pts = written_audio_pts(mpctx) - mpctx->delay; - double v_pts = mpctx->d_video->pts; + double v_pts = mpctx->video_next_pts; double av_delay = a_pts - v_pts; // Try to sync vo_flip() so it will *finish* at given time av_delay += mpctx->last_vo_flip_duration; @@ -1010,7 +1011,7 @@ void run_playloop(struct MPContext *mpctx) } if (endpts != MP_NOPTS_VALUE) - video_left &= mpctx->d_video->pts < endpts; + video_left &= mpctx->video_next_pts < endpts; handle_heartbeat_cmd(mpctx); @@ -1064,7 +1065,7 @@ void run_playloop(struct MPContext *mpctx) //=================== FLIP PAGE (VIDEO BLT): ====================== vo_new_frame_imminent(vo); - mpctx->video_pts = mpctx->d_video->pts; + mpctx->video_pts = mpctx->video_next_pts; mpctx->last_vo_pts = mpctx->video_pts; mpctx->playback_pts = mpctx->video_pts; update_subtitles(mpctx); diff --git a/mpvcore/player/video.c b/mpvcore/player/video.c index 45cfd6ebf4..a758995c09 100644 --- a/mpvcore/player/video.c +++ b/mpvcore/player/video.c @@ -145,6 +145,7 @@ int reinit_video_chain(struct MPContext *mpctx) mpctx->restart_playback = true; mpctx->sync_audio_to_video = !sh->attached_picture; mpctx->delay = 0; + mpctx->video_next_pts = MP_NOPTS_VALUE; mpctx->vo_pts_history_seek_ts++; vo_seek_reset(mpctx->video_out); @@ -277,7 +278,7 @@ static double update_video_attached_pic(struct MPContext *mpctx) if (decoded_frame) filter_video(mpctx, decoded_frame); load_next_vo_frame(mpctx, true); - d_video->pts = MP_NOPTS_VALUE; + mpctx->video_next_pts = MP_NOPTS_VALUE; return 0; } @@ -320,29 +321,16 @@ double update_video(struct MPContext *mpctx, double endpts) return 0; } mpctx->hrseek_active = false; - d_video->pts = pts; - if (d_video->last_pts == MP_NOPTS_VALUE) { - d_video->last_pts = d_video->pts; - } else if (d_video->last_pts > d_video->pts) { - MP_WARN(mpctx, "Decreasing video pts: %f < %f\n", - d_video->pts, d_video->last_pts); - /* If the difference in pts is small treat it as jitter around the - * right value (possibly caused by incorrect timestamp ordering) and - * just show this frame immediately after the last one. - * Treat bigger differences as timestamp resets and start counting - * timing of later frames from the position of this one. */ - if (d_video->last_pts - d_video->pts > 0.5) - d_video->last_pts = d_video->pts; - else - d_video->pts = d_video->last_pts; - } else if (d_video->pts >= d_video->last_pts + 60) { + double last_pts = mpctx->video_next_pts; + if (last_pts == MP_NOPTS_VALUE) + last_pts = pts; + double frame_time = MPMAX(0, pts - last_pts); + if (frame_time >= 60) { // Assume a PTS difference >= 60 seconds is a discontinuity. - MP_WARN(mpctx, "Jump in video pts: %f -> %f\n", - d_video->last_pts, d_video->pts); - d_video->last_pts = d_video->pts; + MP_WARN(mpctx, "Jump in video pts: %f -> %f\n", last_pts, pts); + frame_time = 0; } - double frame_time = d_video->pts - d_video->last_pts; - d_video->last_pts = d_video->pts; + mpctx->video_next_pts = pts; if (mpctx->d_audio) mpctx->delay -= frame_time; return frame_time; diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 402bb805ef..1802e19fbf 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -69,7 +69,6 @@ void video_reset_decoding(struct dec_video *d_video) d_video->codec_dts = MP_NOPTS_VALUE; d_video->sorted_pts = MP_NOPTS_VALUE; d_video->unsorted_pts = MP_NOPTS_VALUE; - d_video->pts = MP_NOPTS_VALUE; } int video_vd_control(struct dec_video *d_video, int cmd, void *arg) @@ -358,9 +357,14 @@ struct mp_image *video_decode(struct dec_video *d_video, pts += frame_time; } + if (d_video->decoded_pts != MP_NOPTS_VALUE && pts < d_video->decoded_pts) { + mp_msg(MSGT_DECVIDEO, MSGL_WARN, "Decreasing video pts: %f < %f\n", + pts, d_video->decoded_pts); + pts = d_video->decoded_pts; + } + mpi->pts = pts; d_video->decoded_pts = pts; - d_video->pts = pts; return mpi; } diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index 9117fceefd..d411717a32 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -65,9 +65,6 @@ struct dec_video { // Final PTS of previously decoded image double decoded_pts; - // PTS of the last decoded frame (often overwritten by player) - double pts; - float stream_aspect; // aspect ratio in media headers (DVD IFO files) int i_bps; // == bitrate (compressed bytes/sec) float fps; // FPS from demuxer or from user override