Commit 17b69f2d authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: fix potential live loop

parent bdd77785
...@@ -270,7 +270,6 @@ static void aout_DecSynchronize (audio_output_t *aout, mtime_t dec_pts, ...@@ -270,7 +270,6 @@ static void aout_DecSynchronize (audio_output_t *aout, mtime_t dec_pts,
aout_owner_t *owner = aout_owner (aout); aout_owner_t *owner = aout_owner (aout);
mtime_t aout_pts, drift; mtime_t aout_pts, drift;
retry:
/** /**
* Depending on the drift between the actual and intended playback times, * Depending on the drift between the actual and intended playback times,
* the audio core may ignore the drift, trigger upsampling or downsampling, * the audio core may ignore the drift, trigger upsampling or downsampling,
...@@ -289,46 +288,52 @@ retry: ...@@ -289,46 +288,52 @@ retry:
*/ */
if (aout_OutputTimeGet (aout, &aout_pts) != 0) if (aout_OutputTimeGet (aout, &aout_pts) != 0)
return; /* nothing can be done if timing is unknown */ return; /* nothing can be done if timing is unknown */
drift = aout_pts - dec_pts; drift = aout_pts - dec_pts;
if (drift < (owner->sync.discontinuity ? 0 /* Late audio output.
: -3 * input_rate * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT)) * This can happen due to insufficient caching, scheduling jitter
{ /* If the audio output is very early (which is rare other than during * or bug in the decoder. Ideally, the output would seek backward. But that
* prebuffering), hold with silence. */ * is not portable, not supported by some hardware and often unsafe/buggy
if (!owner->sync.discontinuity) * where supported. The other alternative is to flush the buffers
msg_Err (aout, "playback way too early (%"PRId64"): " * completely. */
"playing silence", drift);
aout_StopResampling (aout);
aout_DecSilence (aout, -drift);
owner->sync.discontinuity = false;
drift = 0;
}
else
if (drift > (owner->sync.discontinuity ? 0 if (drift > (owner->sync.discontinuity ? 0
: +3 * input_rate * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT)) : +3 * input_rate * AOUT_MAX_PTS_DELAY / INPUT_RATE_DEFAULT))
{ /* If the audio output is very late, drop the buffers. {
* This should make some room and advance playback quickly. */
if (!owner->sync.discontinuity) if (!owner->sync.discontinuity)
msg_Err (aout, "playback way too late (%"PRId64"): " msg_Warn (aout, "playback way too late (%"PRId64"): "
"flushing buffers", drift);
else
msg_Dbg (aout, "playback too late (%"PRId64"): "
"flushing buffers", drift); "flushing buffers", drift);
aout_OutputFlush (aout, false);
aout_StopResampling (aout); aout_StopResampling (aout);
owner->sync.end = VLC_TS_INVALID; owner->sync.end = VLC_TS_INVALID;
aout_OutputFlush (aout, false); owner->sync.discontinuity = true;
goto retry; /* may be too early now... retry */
/* Now the output might be too early... Recheck. */
if (aout_OutputTimeGet (aout, &aout_pts) != 0)
return; /* nothing can be done if timing is unknown */
drift = aout_pts - dec_pts;
} }
if (drift < -AOUT_MAX_PTS_ADVANCE) /* Early audio output.
* This is rare except at startup when the buffers are still empty. */
if (drift < (owner->sync.discontinuity ? 0
: -3 * input_rate * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT))
{ {
if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE) if (!owner->sync.discontinuity)
{ msg_Warn (aout, "playback way too early (%"PRId64"): "
msg_Warn (aout, "playback too early (%"PRId64"): down-sampling", "playing silence", drift);
drift); aout_DecSilence (aout, -drift);
owner->sync.resamp_start_drift = -drift;
} aout_StopResampling (aout);
owner->sync.resamp_type = AOUT_RESAMPLING_DOWN; owner->sync.discontinuity = true;
drift = 0;
} }
else
/* Resampling */
if (drift > +AOUT_MAX_PTS_DELAY) if (drift > +AOUT_MAX_PTS_DELAY)
{ {
if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE) if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE)
...@@ -340,6 +345,17 @@ retry: ...@@ -340,6 +345,17 @@ retry:
owner->sync.resamp_type = AOUT_RESAMPLING_UP; owner->sync.resamp_type = AOUT_RESAMPLING_UP;
} }
if (drift < -AOUT_MAX_PTS_ADVANCE)
{
if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE)
{
msg_Warn (aout, "playback too early (%"PRId64"): down-sampling",
drift);
owner->sync.resamp_start_drift = -drift;
}
owner->sync.resamp_type = AOUT_RESAMPLING_DOWN;
}
if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE) if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE)
return; /* Everything is fine. Nothing to do. */ return; /* Everything is fine. Nothing to do. */
...@@ -368,8 +384,8 @@ retry: ...@@ -368,8 +384,8 @@ retry:
if (llabs (drift) > 2 * owner->sync.resamp_start_drift) if (llabs (drift) > 2 * owner->sync.resamp_start_drift)
{ /* If the drift is ever increasing, then something is seriously wrong. { /* If the drift is ever increasing, then something is seriously wrong.
* Cease resampling and hope for the best. */ * Cease resampling and hope for the best. */
msg_Err (aout, "timing screwed (drift: %"PRId64" us): " msg_Warn (aout, "timing screwed (drift: %"PRId64" us): "
"stopping resampling", drift); "stopping resampling", drift);
aout_StopResampling (aout); aout_StopResampling (aout);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment