summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-01-09 20:27:03 +0100
committerwm4 <wm4@nowhere>2016-01-09 20:39:28 +0100
commitbd5a02d080076b6de6cc4696795a24a5326c6d4f (patch)
treea75493176a5e54bd6c60b541ccf10c0475f8c229 /player
parent2a80680d95fd86242579ad4dcaa752f481945b4e (diff)
downloadmpv-bd5a02d080076b6de6cc4696795a24a5326c6d4f.tar.bz2
mpv-bd5a02d080076b6de6cc4696795a24a5326c6d4f.tar.xz
player: detect audio PTS jumps, make video PTS heuristic less aggressive
This is another attempt at making files with sparse video frames work better. The problem is that you generally can't know whether a jump in video timestamps is just a (very) long video frame, or a timestamp reset. Due to the existence of files with sparse video frames (new frame only every few seconds or longer), every heuristic will be arbitrary (in general, at least). But we can use the fact that if video is continuous, audio should also be continuous. Audio discontinuities can be easily detected, and if that happens, reset some of the playback state. The way the playback state is reset is rather radical (resets decoders as well), but it's just better not to cause too much obscure stuff to happen here. If the A/V sync code were to be rewritten, it should probably strictly use PTS values (not this strange time_frame/delay stuff), which would make it much easier to detect such situations and to react to them.
Diffstat (limited to 'player')
-rw-r--r--player/audio.c10
-rw-r--r--player/video.c12
2 files changed, 9 insertions, 13 deletions
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;
}
}