vlc | branch: master | Rémi Denis-Courmont <[email protected]> | 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); } } _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
