[vlc-commits] PulseAudio: sync at start
Rémi Denis-Courmont
git at videolan.org
Mon Jul 18 18:50:19 CEST 2011
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Jul 18 18:32:31 2011 +0300| [2aea47cfbe916a57b8775f8463f5ffaa32df1eef] | committer: Rémi Denis-Courmont
PulseAudio: sync at start
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2aea47cfbe916a57b8775f8463f5ffaa32df1eef
---
modules/audio_output/pulse.c | 96 +++++++++++++++++++++++++++---------------
1 files changed, 62 insertions(+), 34 deletions(-)
diff --git a/modules/audio_output/pulse.c b/modules/audio_output/pulse.c
index 5113637..4927fa3 100644
--- a/modules/audio_output/pulse.c
+++ b/modules/audio_output/pulse.c
@@ -203,9 +203,12 @@ static void stream_suspended_cb(pa_stream *s, void *userdata)
static void stream_underflow_cb(pa_stream *s, void *userdata)
{
aout_instance_t *aout = userdata;
+ pa_operation *op;
- msg_Dbg(aout, "underflow");
- (void) s;
+ msg_Warn(aout, "underflow");
+ op = pa_stream_cork(s, 1, NULL, NULL);
+ if (op != NULL)
+ pa_operation_unref(op);
}
static int stream_wait(pa_threaded_mainloop *mainloop, pa_stream *stream)
@@ -252,6 +255,17 @@ static void Play(aout_instance_t *aout)
aout_sys_t *sys = aout->output.p_sys;
pa_stream *s = sys->stream;
+ /* This function is called exactly once per block in the output FIFO. */
+ block_t *block = aout_FifoPop(&aout->output.fifo);
+ assert (block != NULL);
+
+ const void *ptr = data_convert(&block);
+ if (unlikely(ptr == NULL))
+ return;
+
+ size_t len = block->i_buffer;
+ mtime_t pts = block->i_pts + block->i_length;
+
/* Note: The core already holds the output FIFO lock at this point.
* Therefore we must not under any circumstances (try to) acquire the
* output FIFO lock while the PulseAudio threaded main loop lock is held
@@ -260,7 +274,41 @@ static void Play(aout_instance_t *aout)
pa_threaded_mainloop_lock(sys->mainloop);
if (pa_stream_is_corked(s) > 0) {
- pa_operation *op = pa_stream_cork(s, 0, NULL, NULL);
+ /* Start or resume the stream. Zeroes are prepended to sync.
+ * This does not really work because PulseAudio latency measurement is
+ * garbage at start. */
+ pa_operation *op;
+ pa_usec_t latency;
+ int negative;
+
+ if (pa_stream_get_latency(s, &latency, &negative) == 0)
+ msg_Dbg(aout, "starting with %c%"PRIu64" us latency",
+ negative ? '-' : '+', latency);
+ else
+ latency = negative = 0;
+
+ mtime_t advance = block->i_pts - mdate();
+ if (negative)
+ advance += latency;
+ else
+ advance -= latency;
+
+ if (advance > 0) {
+ size_t nb = (advance * aout->output.output.i_rate) / CLOCK_FREQ;
+ size_t size = aout->output.output.i_bytes_per_frame;
+ float *zeroes = calloc (nb, size);
+
+ msg_Dbg(aout, "prepending %zu zeroes", nb);
+ if (likely(zeroes != NULL))
+ if (pa_stream_write(s, zeroes, nb * size, free, 0,
+ PA_SEEK_RELATIVE) < 0)
+ free(zeroes);
+ }
+
+ op = pa_stream_cork(s, 0, NULL, NULL);
+ if (op != NULL)
+ pa_operation_unref(op);
+ op = pa_stream_trigger(s, NULL, NULL);
if (op != NULL)
pa_operation_unref(op);
msg_Dbg(aout, "uncorking");
@@ -274,27 +322,9 @@ static void Play(aout_instance_t *aout)
}
#endif
- /* This function is called exactly once per block in the output FIFO, so
- * this for-loop is not necessary.
- * If this function is changed to not always dequeue blocks, be sure to
- * limit the queue size to a reasonable limit to avoid huge leaks. */
- for (;;) {
- block_t *block = aout_FifoPop(&aout->output.fifo);
- if (block == NULL)
- break;
-
- const void *ptr = data_convert(&block);
- if (unlikely(ptr == NULL))
- break;
-
- size_t len = block->i_buffer;
- //mtime_t pts = block->i_pts, duration = block->i_length;
-
- if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0)
- {
- error(aout, "cannot write", sys->context);
- block_Release(block);
- }
+ if (pa_stream_write(s, ptr, len, data_free, 0, PA_SEEK_RELATIVE) < 0) {
+ error(aout, "cannot write", sys->context);
+ block_Release(block);
}
pa_threaded_mainloop_unlock(sys->mainloop);
@@ -308,14 +338,12 @@ static void Pause(aout_instance_t *aout, bool b_paused, mtime_t i_date)
aout_sys_t *sys = aout->output.p_sys;
pa_stream *s = sys->stream;
- /* Note: The core already holds the output FIFO lock at this point.
- * Therefore we must not under any circumstances (try to) acquire the
- * output FIFO lock while the PulseAudio threaded main loop lock is held
- * (including from PulseAudio stream callbacks). Otherwise lock inversion
- * will take place, and sooner or later a deadlock. */
+ if (!b_paused)
+ return; /* nothing to do - yet */
+
pa_threaded_mainloop_lock(sys->mainloop);
- pa_operation *op = pa_stream_cork(s, b_paused ? 1 : 0, NULL, NULL);
+ pa_operation *op = pa_stream_cork(s, 1, NULL, NULL);
if (op != NULL)
pa_operation_unref(op);
@@ -490,15 +518,15 @@ static int Open(vlc_object_t *obj)
}
/* Stream parameters */
- const pa_stream_flags_t flags = PA_STREAM_INTERPOLATE_TIMING
- | PA_STREAM_AUTO_TIMING_UPDATE
- | PA_STREAM_START_CORKED;
+ const pa_stream_flags_t flags = PA_STREAM_START_CORKED
+ //| PA_STREAM_INTERPOLATE_TIMING
+ | PA_STREAM_AUTO_TIMING_UPDATE;
const uint32_t byterate = pa_bytes_per_second(&ss);
struct pa_buffer_attr attr;
attr.maxlength = -1;
attr.tlength = byterate * AOUT_MAX_PREPARE_TIME / CLOCK_FREQ;
- attr.prebuf = -1;
+ attr.prebuf = 0; /* trigger manually */
attr.minreq = -1;
attr.fragsize = 0; /* not used for output */
More information about the vlc-commits
mailing list