mirror of
https://code.videolan.org/videolan/vlc
synced 2024-10-07 03:56:28 +02:00
PulseAudio: sync at start
This commit is contained in:
parent
dd2f44693a
commit
2aea47cfbe
@ -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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user