[vlc-commits] aout: fix potential live loop
Rémi Denis-Courmont
git at videolan.org
Tue Nov 13 20:36:03 CET 2012
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue Nov 13 21:12:51 2012 +0200| [17b69f2d41f4c71ac51b9196684d3024173983c6] | committer: Rémi Denis-Courmont
aout: fix potential live loop
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=17b69f2d41f4c71ac51b9196684d3024173983c6
---
src/audio_output/dec.c | 78 +++++++++++++++++++++++++++++-------------------
1 file changed, 47 insertions(+), 31 deletions(-)
diff --git a/src/audio_output/dec.c b/src/audio_output/dec.c
index 4857a99..87310e6 100644
--- a/src/audio_output/dec.c
+++ b/src/audio_output/dec.c
@@ -270,7 +270,6 @@ static void aout_DecSynchronize (audio_output_t *aout, mtime_t dec_pts,
aout_owner_t *owner = aout_owner (aout);
mtime_t aout_pts, drift;
-retry:
/**
* Depending on the drift between the actual and intended playback times,
* the audio core may ignore the drift, trigger upsampling or downsampling,
@@ -289,46 +288,52 @@ retry:
*/
if (aout_OutputTimeGet (aout, &aout_pts) != 0)
return; /* nothing can be done if timing is unknown */
-
drift = aout_pts - dec_pts;
- if (drift < (owner->sync.discontinuity ? 0
- : -3 * input_rate * AOUT_MAX_PTS_ADVANCE / INPUT_RATE_DEFAULT))
- { /* If the audio output is very early (which is rare other than during
- * prebuffering), hold with silence. */
- if (!owner->sync.discontinuity)
- msg_Err (aout, "playback way too early (%"PRId64"): "
- "playing silence", drift);
- aout_StopResampling (aout);
- aout_DecSilence (aout, -drift);
- owner->sync.discontinuity = false;
- drift = 0;
- }
- else
+ /* Late audio output.
+ * This can happen due to insufficient caching, scheduling jitter
+ * or bug in the decoder. Ideally, the output would seek backward. But that
+ * is not portable, not supported by some hardware and often unsafe/buggy
+ * where supported. The other alternative is to flush the buffers
+ * completely. */
if (drift > (owner->sync.discontinuity ? 0
: +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)
- 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);
+ aout_OutputFlush (aout, false);
+
aout_StopResampling (aout);
owner->sync.end = VLC_TS_INVALID;
- aout_OutputFlush (aout, false);
- goto retry; /* may be too early now... retry */
+ owner->sync.discontinuity = true;
+
+ /* 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)
- {
- 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.discontinuity)
+ msg_Warn (aout, "playback way too early (%"PRId64"): "
+ "playing silence", drift);
+ aout_DecSilence (aout, -drift);
+
+ aout_StopResampling (aout);
+ owner->sync.discontinuity = true;
+ drift = 0;
}
- else
+
+ /* Resampling */
+
if (drift > +AOUT_MAX_PTS_DELAY)
{
if (owner->sync.resamp_type == AOUT_RESAMPLING_NONE)
@@ -340,6 +345,17 @@ retry:
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)
return; /* Everything is fine. Nothing to do. */
@@ -368,8 +384,8 @@ retry:
if (llabs (drift) > 2 * owner->sync.resamp_start_drift)
{ /* If the drift is ever increasing, then something is seriously wrong.
* Cease resampling and hope for the best. */
- msg_Err (aout, "timing screwed (drift: %"PRId64" us): "
- "stopping resampling", drift);
+ msg_Warn (aout, "timing screwed (drift: %"PRId64" us): "
+ "stopping resampling", drift);
aout_StopResampling (aout);
}
}
More information about the vlc-commits
mailing list