Skip to content

Commit

Permalink
audio: move back PTS jump detection to before filter chain
Browse files Browse the repository at this point in the history
The recent changes to player/audio.c moved PTS jump detection to after
audio filtering. This was mostly done for convenience, because dataflow
between decoder and filters was made "automatic", and jump detection
would have to be done as filter. Now move it back to after decoders,
again out of convenience. The future direction is to make the dataflow
between filters and AO automatic, so this is a bit in the way. Another
reason is that speed changes tend to cause jumps - these are legitimate,
but get annoying quickly.
  • Loading branch information
wm4 authored and kevmitch committed Feb 14, 2018
1 parent 562f563 commit 02f9087
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 21 deletions.
14 changes: 13 additions & 1 deletion filters/f_decoder_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ static void reset_decoder(struct priv *p)
p->last_format = p->fixed_format = (struct mp_image_params){0};
p->public.dropped_frames = 0;
p->public.attempt_framedrops = 0;
p->public.pts_reset = false;
p->packets_without_output = 0;
mp_frame_unref(&p->packet);
talloc_free(p->new_segment);
Expand Down Expand Up @@ -402,9 +403,20 @@ static void process_audio_frame(struct priv *p, struct mp_aframe *aframe)
if (p->pts != MP_NOPTS_VALUE)
MP_STATS(p, "value %f audio-pts-err", p->pts - frame_pts);

double diff = fabs(p->pts - frame_pts);

// 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 (p->pts != MP_NOPTS_VALUE && diff > 0.1) {
MP_WARN(p, "Invalid audio PTS: %f -> %f\n", p->pts, frame_pts);
if (diff >= 5)
p->public.pts_reset = true;
}

// Keep the interpolated timestamp if it doesn't deviate more
// than 1 ms from the real one. (MKV rounded timestamps.)
if (p->pts == MP_NOPTS_VALUE || fabs(p->pts - frame_pts) > 0.001)
if (p->pts == MP_NOPTS_VALUE || diff > 0.001)
p->pts = frame_pts;
}

Expand Down
3 changes: 3 additions & 0 deletions filters/f_decoder_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ struct mp_decoder_wrapper {

// Prefer spdif wrapper over real decoders.
bool try_spdif;

// A pts reset was observed (audio only, heuristic).
bool pts_reset;
};

// Create the decoder wrapper for the given stream, plus underlying decoder.
Expand Down
23 changes: 4 additions & 19 deletions player/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,6 @@ void update_playback_speed(struct MPContext *mpctx)
static void ao_chain_reset_state(struct ao_chain *ao_c)
{
ao_c->last_out_pts = MP_NOPTS_VALUE;
ao_c->pts_reset = false;
TA_FREEP(&ao_c->output_frame);
ao_c->out_eof = false;

Expand Down Expand Up @@ -658,21 +657,6 @@ static bool copy_output(struct MPContext *mpctx, struct ao_chain *ao_c,
if (frame.type == MP_FRAME_AUDIO) {
ao_c->output_frame = frame.data;
ao_c->out_eof = false;

double pts = mp_aframe_get_pts(ao_c->output_frame);
if (pts != MP_NOPTS_VALUE) {
// 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.
double desync = pts - ao_c->last_out_pts;
if (ao_c->last_out_pts != MP_NOPTS_VALUE && fabs(desync) > 0.1)
{
MP_WARN(ao_c, "Invalid audio PTS: %f -> %f\n",
ao_c->last_out_pts, pts);
if (desync >= 5)
ao_c->pts_reset = true;
}
}
ao_c->last_out_pts = mp_aframe_end_pts(ao_c->output_frame);
} else if (frame.type == MP_FRAME_EOF) {
ao_c->out_eof = true;
Expand Down Expand Up @@ -786,8 +770,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
// (if AO is set due to gapless from previous file, then we can try to
// filter normally until the filter tells us to change the AO)
if (!mpctx->ao) {
// Probe the initial audio format. Returns AD_OK (and does nothing) if
// the format is already known.
// Probe the initial audio format.
mp_pin_out_request_data(ao_c->filter->f->pins[1]);
reinit_audio_filters_and_output(mpctx);
return; // try again next iteration
Expand All @@ -799,7 +782,9 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
return;
}

if (mpctx->vo_chain && ao_c->pts_reset) {
if (mpctx->vo_chain && ao_c->track && ao_c->track->dec &&
ao_c->track->dec->pts_reset)
{
MP_VERBOSE(mpctx, "Reset playback due to audio timestamp reset.\n");
reset_playback_state(mpctx);
mp_wakeup_core(mpctx);
Expand Down
1 change: 0 additions & 1 deletion player/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ struct ao_chain {
struct mp_log *log;

bool spdif_passthrough, spdif_failed;
bool pts_reset;

struct mp_output_chain *filter;

Expand Down

0 comments on commit 02f9087

Please sign in to comment.