aboutsummaryrefslogtreecommitdiffhomepage
path: root/audio/decode
diff options
context:
space:
mode:
authorGravatar wm4 <wm4@nowhere>2016-01-09 20:27:03 +0100
committerGravatar wm4 <wm4@nowhere>2016-01-09 20:39:28 +0100
commitbd5a02d080076b6de6cc4696795a24a5326c6d4f (patch)
treea75493176a5e54bd6c60b541ccf10c0475f8c229 /audio/decode
parent2a80680d95fd86242579ad4dcaa752f481945b4e (diff)
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 'audio/decode')
-rw-r--r--audio/decode/dec_audio.c13
-rw-r--r--audio/decode/dec_audio.h2
2 files changed, 14 insertions, 1 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;
};