mirror of https://github.com/mpv-player/mpv
video: replace d_video->pts field, change PTS jump checks
The d_video->pts field was a bit strange. The code overwrote it multiple times (on decoding, on filtering, then once again...), and it wasn't really clear what purpose this field had exactly. Replace it with the mpctx->video_next_pts field, which is relatively unambiguous. Move the decreasing PTS check to dec_video.c. This means it acts on decoder output, not on filter output. (Just like in the previous commit, assume the filter chain is sane.) Drop the jitter vs. reset semantics; the dec_video.c determined PTS never goes backwards, and demuxer timestamps don't "jitter".
This commit is contained in:
parent
5d97ac229a
commit
aa73ac8db8
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue