mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-31 22:25:33 -04:00
make sure to call process_rewind() under all circumstances before we do the next loop iteration
This commit is contained in:
parent
1e36b57b13
commit
eab1cb8df9
10 changed files with 69 additions and 39 deletions
|
|
@ -882,7 +882,7 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
|
||||||
|
|
||||||
if (u->hwbuf_unused_frames > before) {
|
if (u->hwbuf_unused_frames > before) {
|
||||||
pa_log_debug("Requesting rewind due to latency change.");
|
pa_log_debug("Requesting rewind due to latency change.");
|
||||||
pa_sink_request_rewind(s, 0);
|
pa_sink_request_rewind(s, (size_t) -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -967,9 +967,12 @@ static void thread_func(void *userdata) {
|
||||||
int work_done;
|
int work_done;
|
||||||
pa_usec_t sleep_usec;
|
pa_usec_t sleep_usec;
|
||||||
|
|
||||||
if (u->sink->thread_info.rewind_nbytes > 0)
|
if (u->sink->thread_info.rewind_requested) {
|
||||||
if (process_rewind(u) < 0)
|
if (u->sink->thread_info.rewind_nbytes <= 0)
|
||||||
goto fail;
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
else if (process_rewind(u) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (u->use_mmap)
|
if (u->use_mmap)
|
||||||
work_done = mmap_write(u, &sleep_usec);
|
work_done = mmap_write(u, &sleep_usec);
|
||||||
|
|
|
||||||
|
|
@ -410,7 +410,6 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
|
||||||
struct output *o;
|
struct output *o;
|
||||||
|
|
||||||
pa_sink_input_assert_ref(i);
|
pa_sink_input_assert_ref(i);
|
||||||
pa_assert(nbytes > 0);
|
|
||||||
pa_assert_se(o = i->userdata);
|
pa_assert_se(o = i->userdata);
|
||||||
|
|
||||||
pa_memblockq_rewind(o->memblockq, nbytes);
|
pa_memblockq_rewind(o->memblockq, nbytes);
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,10 @@ static void thread_func(void *userdata) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
|
||||||
if (u->rtpoll_item) {
|
if (u->rtpoll_item) {
|
||||||
struct pollfd *pollfd;
|
struct pollfd *pollfd;
|
||||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,10 @@ static void thread_func(void *userdata) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
|
||||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,8 +204,12 @@ static void thread_func(void *userdata) {
|
||||||
|
|
||||||
now = pa_rtclock_usec();
|
now = pa_rtclock_usec();
|
||||||
|
|
||||||
if (u->sink->thread_info.rewind_nbytes > 0)
|
if (u->sink->thread_info.rewind_requested) {
|
||||||
process_rewind(u, now);
|
if (u->sink->thread_info.rewind_nbytes > 0)
|
||||||
|
process_rewind(u, now);
|
||||||
|
else
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (u->timestamp <= now)
|
if (u->timestamp <= now)
|
||||||
process_render(u, now);
|
process_render(u, now);
|
||||||
|
|
|
||||||
|
|
@ -184,8 +184,12 @@ static void thread_func(void *userdata) {
|
||||||
/* Render some data and write it to the fifo */
|
/* Render some data and write it to the fifo */
|
||||||
if (u->sink->thread_info.state == PA_SINK_RUNNING) {
|
if (u->sink->thread_info.state == PA_SINK_RUNNING) {
|
||||||
|
|
||||||
if (u->sink->thread_info.rewind_nbytes > 0)
|
if (u->sink->thread_info.rewind_requested) {
|
||||||
process_rewind(u);
|
if (u->sink->thread_info.rewind_nbytes > 0)
|
||||||
|
process_rewind(u);
|
||||||
|
else
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (pollfd->revents) {
|
if (pollfd->revents) {
|
||||||
if (process_render(u) < 0)
|
if (process_render(u) < 0)
|
||||||
|
|
|
||||||
|
|
@ -605,6 +605,12 @@ static void thread_func(void *userdata) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
#ifdef TUNNEL_SINK
|
||||||
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -491,12 +491,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa
|
||||||
i->thread_info.state == PA_SINK_INPUT_CORKED ||
|
i->thread_info.state == PA_SINK_INPUT_CORKED ||
|
||||||
i->thread_info.state == PA_SINK_INPUT_DRAINED);
|
i->thread_info.state == PA_SINK_INPUT_DRAINED);
|
||||||
|
|
||||||
/* If there's still some rewrite request the handle, but the sink
|
|
||||||
didn't do this for us, we do it here. However, since the sink
|
|
||||||
apparently doesn't support rewinding, we pass 0 here. This still
|
|
||||||
allows rewinding through the render buffer. */
|
|
||||||
pa_sink_input_process_rewind(i, 0);
|
|
||||||
|
|
||||||
block_size_max_sink_input = i->thread_info.resampler ?
|
block_size_max_sink_input = i->thread_info.resampler ?
|
||||||
pa_resampler_max_block_size(i->thread_info.resampler) :
|
pa_resampler_max_block_size(i->thread_info.resampler) :
|
||||||
pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sample_spec);
|
pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sample_spec);
|
||||||
|
|
@ -633,18 +627,13 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec *
|
||||||
|
|
||||||
/* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
|
/* pa_log_debug("dropping %lu", (unsigned long) nbytes); */
|
||||||
|
|
||||||
/* If there's still some rewrite request the handle, but the sink
|
|
||||||
didn't do this for us, we do it here. However, since the sink
|
|
||||||
apparently doesn't support rewinding, we pass 0 here. This still
|
|
||||||
allows rewinding through the render buffer. */
|
|
||||||
pa_sink_input_process_rewind(i, 0);
|
|
||||||
|
|
||||||
pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
|
pa_memblockq_drop(i->thread_info.render_memblockq, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from thread context */
|
/* Called from thread context */
|
||||||
void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
|
void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) {
|
||||||
size_t lbq;
|
size_t lbq;
|
||||||
|
pa_bool_t called;
|
||||||
pa_sink_input_assert_ref(i);
|
pa_sink_input_assert_ref(i);
|
||||||
|
|
||||||
pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
|
pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state));
|
||||||
|
|
@ -685,6 +674,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
|
||||||
/* Tell the implementor */
|
/* Tell the implementor */
|
||||||
if (i->process_rewind)
|
if (i->process_rewind)
|
||||||
i->process_rewind(i, amount);
|
i->process_rewind(i, amount);
|
||||||
|
called = TRUE;
|
||||||
|
|
||||||
/* Convert back to to sink domain */
|
/* Convert back to to sink domain */
|
||||||
if (i->thread_info.resampler)
|
if (i->thread_info.resampler)
|
||||||
|
|
@ -703,6 +693,10 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!called)
|
||||||
|
if (i->process_rewind)
|
||||||
|
i->process_rewind(i, 0);
|
||||||
|
|
||||||
i->thread_info.rewrite_nbytes = 0;
|
i->thread_info.rewrite_nbytes = 0;
|
||||||
i->thread_info.rewrite_flush = FALSE;
|
i->thread_info.rewrite_flush = FALSE;
|
||||||
}
|
}
|
||||||
|
|
@ -1143,6 +1137,8 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
|
||||||
pa_sink_input_assert_ref(i);
|
pa_sink_input_assert_ref(i);
|
||||||
pa_assert(i->thread_info.rewrite_nbytes == 0);
|
pa_assert(i->thread_info.rewrite_nbytes == 0);
|
||||||
|
|
||||||
|
/* pa_log_debug("request rewrite %lu", (unsigned long) nbytes); */
|
||||||
|
|
||||||
/* We don't take rewind requests while we are corked */
|
/* We don't take rewind requests while we are corked */
|
||||||
if (i->thread_info.state == PA_SINK_INPUT_CORKED)
|
if (i->thread_info.state == PA_SINK_INPUT_CORKED)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1184,6 +1180,9 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
|
||||||
|
|
||||||
if (nbytes > lbq)
|
if (nbytes > lbq)
|
||||||
pa_sink_request_rewind(i->sink, nbytes - lbq);
|
pa_sink_request_rewind(i->sink, nbytes - lbq);
|
||||||
|
else
|
||||||
|
/* This call will make sure process_rewind() is called later */
|
||||||
|
pa_sink_request_rewind(i->sink, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,7 @@ pa_sink* pa_sink_new(
|
||||||
s->thread_info.soft_muted = FALSE;
|
s->thread_info.soft_muted = FALSE;
|
||||||
s->thread_info.state = s->state;
|
s->thread_info.state = s->state;
|
||||||
s->thread_info.rewind_nbytes = 0;
|
s->thread_info.rewind_nbytes = 0;
|
||||||
|
s->thread_info.rewind_requested = FALSE;
|
||||||
s->thread_info.max_rewind = 0;
|
s->thread_info.max_rewind = 0;
|
||||||
s->thread_info.max_request = 0;
|
s->thread_info.max_request = 0;
|
||||||
s->thread_info.requested_latency_valid = FALSE;
|
s->thread_info.requested_latency_valid = FALSE;
|
||||||
|
|
@ -454,21 +455,20 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
|
||||||
pa_sink_assert_ref(s);
|
pa_sink_assert_ref(s);
|
||||||
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
||||||
|
|
||||||
/* Make sure the sink code already reset the counter! */
|
s->thread_info.rewind_nbytes = 0;
|
||||||
pa_assert(s->thread_info.rewind_nbytes <= 0);
|
s->thread_info.rewind_requested = FALSE;
|
||||||
|
|
||||||
if (nbytes <= 0)
|
if (nbytes > 0)
|
||||||
return;
|
pa_log_debug("Processing rewind...");
|
||||||
|
|
||||||
pa_log_debug("Processing rewind...");
|
|
||||||
|
|
||||||
while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
|
while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) {
|
||||||
pa_sink_input_assert_ref(i);
|
pa_sink_input_assert_ref(i);
|
||||||
pa_sink_input_process_rewind(i, nbytes);
|
pa_sink_input_process_rewind(i, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state))
|
if (nbytes > 0)
|
||||||
pa_source_process_rewind(s->monitor_source, nbytes);
|
if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state))
|
||||||
|
pa_source_process_rewind(s->monitor_source, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from IO thread context */
|
/* Called from IO thread context */
|
||||||
|
|
@ -620,7 +620,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
|
||||||
|
|
||||||
pa_sink_ref(s);
|
pa_sink_ref(s);
|
||||||
|
|
||||||
s->thread_info.rewind_nbytes = 0;
|
pa_assert(!s->thread_info.rewind_requested);
|
||||||
|
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
|
length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec);
|
||||||
|
|
@ -696,7 +697,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
|
||||||
|
|
||||||
pa_sink_ref(s);
|
pa_sink_ref(s);
|
||||||
|
|
||||||
s->thread_info.rewind_nbytes = 0;
|
pa_assert(!s->thread_info.rewind_requested);
|
||||||
|
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||||
|
|
||||||
length = target->length;
|
length = target->length;
|
||||||
block_size_max = pa_mempool_block_size_max(s->core->mempool);
|
block_size_max = pa_mempool_block_size_max(s->core->mempool);
|
||||||
|
|
@ -774,7 +776,8 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
|
||||||
|
|
||||||
pa_sink_ref(s);
|
pa_sink_ref(s);
|
||||||
|
|
||||||
s->thread_info.rewind_nbytes = 0;
|
pa_assert(!s->thread_info.rewind_requested);
|
||||||
|
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||||
|
|
||||||
l = target->length;
|
l = target->length;
|
||||||
d = 0;
|
d = 0;
|
||||||
|
|
@ -800,7 +803,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
|
||||||
pa_assert(pa_frame_aligned(length, &s->sample_spec));
|
pa_assert(pa_frame_aligned(length, &s->sample_spec));
|
||||||
pa_assert(result);
|
pa_assert(result);
|
||||||
|
|
||||||
s->thread_info.rewind_nbytes = 0;
|
pa_assert(!s->thread_info.rewind_requested);
|
||||||
|
pa_assert(s->thread_info.rewind_nbytes == 0);
|
||||||
|
|
||||||
/*** This needs optimization ***/
|
/*** This needs optimization ***/
|
||||||
|
|
||||||
|
|
@ -1067,7 +1071,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
|
||||||
pa_sink_input_unref(i);
|
pa_sink_input_unref(i);
|
||||||
|
|
||||||
pa_sink_invalidate_requested_latency(s);
|
pa_sink_invalidate_requested_latency(s);
|
||||||
pa_sink_request_rewind(s, 0);
|
pa_sink_request_rewind(s, (size_t) -1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1112,7 +1116,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
|
||||||
pa_sink_invalidate_requested_latency(s);
|
pa_sink_invalidate_requested_latency(s);
|
||||||
|
|
||||||
pa_log_debug("Requesting rewind due to started move");
|
pa_log_debug("Requesting rewind due to started move");
|
||||||
pa_sink_request_rewind(s, 0);
|
pa_sink_request_rewind(s, (size_t) -1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1162,13 +1166,13 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
|
||||||
case PA_SINK_MESSAGE_SET_VOLUME:
|
case PA_SINK_MESSAGE_SET_VOLUME:
|
||||||
s->thread_info.soft_volume = *((pa_cvolume*) userdata);
|
s->thread_info.soft_volume = *((pa_cvolume*) userdata);
|
||||||
|
|
||||||
pa_sink_request_rewind(s, 0);
|
pa_sink_request_rewind(s, (size_t) -1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case PA_SINK_MESSAGE_SET_MUTE:
|
case PA_SINK_MESSAGE_SET_MUTE:
|
||||||
s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
|
s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata);
|
||||||
|
|
||||||
pa_sink_request_rewind(s, 0);
|
pa_sink_request_rewind(s, (size_t) -1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case PA_SINK_MESSAGE_GET_VOLUME:
|
case PA_SINK_MESSAGE_GET_VOLUME:
|
||||||
|
|
@ -1309,15 +1313,17 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
|
||||||
pa_sink_assert_ref(s);
|
pa_sink_assert_ref(s);
|
||||||
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
||||||
|
|
||||||
if (nbytes <= 0)
|
if (nbytes == (size_t) -1)
|
||||||
nbytes = s->thread_info.max_rewind;
|
nbytes = s->thread_info.max_rewind;
|
||||||
|
|
||||||
nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
|
nbytes = PA_MIN(nbytes, s->thread_info.max_rewind);
|
||||||
|
|
||||||
if (nbytes <= s->thread_info.rewind_nbytes)
|
if (s->thread_info.rewind_requested &&
|
||||||
|
nbytes <= s->thread_info.rewind_nbytes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s->thread_info.rewind_nbytes = nbytes;
|
s->thread_info.rewind_nbytes = nbytes;
|
||||||
|
s->thread_info.rewind_requested = TRUE;
|
||||||
|
|
||||||
if (s->request_rewind)
|
if (s->request_rewind)
|
||||||
s->request_rewind(s);
|
s->request_rewind(s);
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ struct pa_sink {
|
||||||
|
|
||||||
/* Maximum of what clients requested to rewind in this cycle */
|
/* Maximum of what clients requested to rewind in this cycle */
|
||||||
size_t rewind_nbytes;
|
size_t rewind_nbytes;
|
||||||
|
pa_bool_t rewind_requested;
|
||||||
|
|
||||||
pa_usec_t min_latency; /* we won't go below this latency */
|
pa_usec_t min_latency; /* we won't go below this latency */
|
||||||
pa_usec_t max_latency; /* An upper limit for the latencies */
|
pa_usec_t max_latency; /* An upper limit for the latencies */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue