diff options
-rw-r--r-- | audio/decode/dec_audio.c | 13 | ||||
-rw-r--r-- | audio/decode/dec_audio.h | 2 | ||||
-rw-r--r-- | player/audio.c | 10 | ||||
-rw-r--r-- | player/video.c | 12 |
4 files changed, 23 insertions, 14 deletions
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 03172ed294..99c01b408e 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -177,11 +177,21 @@ static int decode_new_frame(struct dec_audio *da) da->pts += da->pts_offset / (double)da->waiting->rate; da->pts_offset = 0; } + double newpts = da->waiting->pts; // Keep the interpolated timestamp if it doesn't deviate more // than 1 ms from the real one. (MKV rounded timestamps.) if (da->pts == MP_NOPTS_VALUE || da->pts_offset != 0 || - fabs(da->pts - da->waiting->pts) > 0.001) + fabs(da->pts - newpts) > 0.001) { + // Attempt to detect jumps in PTS. Even for the lowest + // sample rates and with worst container rounded timestamp, + // this should be a margin more than enough. + if (da->pts != MP_NOPTS_VALUE && fabs(newpts - da->pts) > 0.1) + { + MP_WARN(da, "Invalid audio PTS: %f -> %f\n", + da->pts, newpts); + da->pts_reset = true; + } da->pts = da->waiting->pts; da->pts_offset = 0; } @@ -274,6 +284,7 @@ void audio_reset_decoding(struct dec_audio *d_audio) af_seek_reset(d_audio->afilter); d_audio->pts = MP_NOPTS_VALUE; d_audio->pts_offset = 0; + d_audio->pts_reset = false; if (d_audio->waiting) { talloc_free(d_audio->waiting); d_audio->waiting = NULL; diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h index 0f7f4d239d..a8c66fa67e 100644 --- a/audio/decode/dec_audio.h +++ b/audio/decode/dec_audio.h @@ -45,6 +45,8 @@ struct dec_audio { double pts; // number of samples output by decoder after last known pts int pts_offset; + // set every time a jump in timestamps is encountered + bool pts_reset; // For free use by the ad_driver void *priv; }; diff --git a/player/audio.c b/player/audio.c index 37d194833c..cc166ae0d3 100644 --- a/player/audio.c +++ b/player/audio.c @@ -487,11 +487,12 @@ static bool get_sync_samples(struct MPContext *mpctx, int *skip) double ptsdiff = written_pts - sync_pts; // Missing timestamp, or PTS reset, or just broken. - if (written_pts == MP_NOPTS_VALUE || fabs(ptsdiff) > 3600) { + if (written_pts == MP_NOPTS_VALUE) { MP_WARN(mpctx, "Failed audio resync.\n"); mpctx->audio_status = STATUS_FILLING; return true; } + ptsdiff = MPCLAMP(ptsdiff, -3600, 3600); int align = af_format_sample_alignment(out_format.format); *skip = (int)(-ptsdiff * play_samplerate) / align * align; @@ -544,6 +545,13 @@ void fill_audio_out_buffers(struct MPContext *mpctx, double endpts) return; // try again next iteration } + if (mpctx->d_video && d_audio->pts_reset) { + MP_VERBOSE(mpctx, "Reset playback due to audio timestamp reset.\n"); + reset_playback_state(mpctx); + mpctx->sleeptime = 0; + return; + } + struct mp_audio out_format = {0}; ao_get_format(mpctx->ao, &out_format); double play_samplerate = out_format.rate / mpctx->audio_speed; diff --git a/player/video.c b/player/video.c index 1005694abe..74d6eb32b9 100644 --- a/player/video.c +++ b/player/video.c @@ -563,22 +563,10 @@ static void handle_new_frame(struct MPContext *mpctx) if (mpctx->video_pts != MP_NOPTS_VALUE) { frame_time = pts - mpctx->video_pts; double tolerance = 15; - if (mpctx->demuxer->ts_resets_possible) { - // Fortunately no real framerate is likely to go below this. It - // still could be that the file is VFR, but the demuxer reports a - // higher rate, so account for the case of e.g. 60hz demuxer fps - // but 23hz actual fps. - double fps = 23.976; - if (mpctx->d_video->fps > 0 && mpctx->d_video->fps < fps) - fps = mpctx->d_video->fps; - tolerance = 3 * 1.0 / fps; - } if (frame_time <= 0 || frame_time >= tolerance) { // Assume a discontinuity. MP_WARN(mpctx, "Invalid video timestamp: %f -> %f\n", mpctx->video_pts, pts); - if (mpctx->d_audio && fabs(frame_time) > 1.0) - mpctx->audio_status = STATUS_SYNCING; frame_time = 0; } } |