mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
sink: Process rewind requests also when suspended.
When a rewind is requested on a sink input, the request parameters are stored in the pa_sink_input struct. The parameters are reset during rewind processing, and if the sink decides to ignore the rewind request due to being suspended, stale parameters are left in pa_sink_input. It's particularly problematic if the rewrite_bytes parameter is left at -1, because that will prevent all future rewind processing on that sink input. So, in order to avoid stale parameters, every rewind request needs to be processed, even if the sink is suspended. Reported-by: Uoti Urpala
This commit is contained in:
parent
4636f56090
commit
afbc9dbe49
14 changed files with 58 additions and 61 deletions
|
|
@ -1602,6 +1602,11 @@ static int process_rewind(struct userdata *u) {
|
||||||
size_t rewind_nbytes, unused_nbytes, limit_nbytes;
|
size_t rewind_nbytes, unused_nbytes, limit_nbytes;
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
|
|
||||||
|
if (!PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Figure out how much we shall rewind and reset the counter */
|
/* Figure out how much we shall rewind and reset the counter */
|
||||||
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
|
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
|
||||||
|
|
||||||
|
|
@ -1681,16 +1686,17 @@ static void thread_func(void *userdata) {
|
||||||
pa_log_debug("Loop");
|
pa_log_debug("Loop");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (PA_UNLIKELY(u->sink->thread_info.rewind_requested)) {
|
||||||
|
if (process_rewind(u) < 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Render some data and write it to the dsp */
|
/* Render some data and write it to the dsp */
|
||||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||||
int work_done;
|
int work_done;
|
||||||
pa_usec_t sleep_usec = 0;
|
pa_usec_t sleep_usec = 0;
|
||||||
pa_bool_t on_timeout = pa_rtpoll_timer_elapsed(u->rtpoll);
|
pa_bool_t on_timeout = pa_rtpoll_timer_elapsed(u->rtpoll);
|
||||||
|
|
||||||
if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
|
|
||||||
if (process_rewind(u) < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (u->use_mmap)
|
if (u->use_mmap)
|
||||||
work_done = mmap_write(u, &sleep_usec, revents & POLLOUT, on_timeout);
|
work_done = mmap_write(u, &sleep_usec, revents & POLLOUT, on_timeout);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -229,9 +229,8 @@ 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)
|
||||||
if (u->sink->thread_info.rewind_requested)
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
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;
|
||||||
|
|
|
||||||
|
|
@ -274,9 +274,6 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
|
||||||
pa_assert(sink);
|
pa_assert(sink);
|
||||||
|
|
||||||
if (PA_SINK_IS_OPENED(sink->pa_sink->thread_info.state)) {
|
if (PA_SINK_IS_OPENED(sink->pa_sink->thread_info.state)) {
|
||||||
if (sink->pa_sink->thread_info.rewind_requested)
|
|
||||||
pa_sink_process_rewind(sink->pa_sink, 0);
|
|
||||||
|
|
||||||
audio_chunk.memblock = pa_memblock_new_fixed(u->module->core->mempool, buf->mData, buf->mDataByteSize, FALSE);
|
audio_chunk.memblock = pa_memblock_new_fixed(u->module->core->mempool, buf->mData, buf->mDataByteSize, FALSE);
|
||||||
audio_chunk.length = buf->mDataByteSize;
|
audio_chunk.length = buf->mDataByteSize;
|
||||||
audio_chunk.index = 0;
|
audio_chunk.index = 0;
|
||||||
|
|
@ -658,8 +655,14 @@ static void thread_func(void *userdata) {
|
||||||
pa_thread_mq_install(&u->thread_mq);
|
pa_thread_mq_install(&u->thread_mq);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
coreaudio_sink *ca_sink;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
PA_LLIST_FOREACH(ca_sink, u->sinks) {
|
||||||
|
if (ca_sink->pa_sink->thread_info.rewind_requested)
|
||||||
|
pa_sink_process_rewind(ca_sink->pa_sink, 0);
|
||||||
|
}
|
||||||
|
|
||||||
ret = pa_rtpoll_run(u->rtpoll, TRUE);
|
ret = pa_rtpoll_run(u->rtpoll, TRUE);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
|
|
||||||
|
|
@ -307,9 +307,8 @@ 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)
|
||||||
if (u->sink->thread_info.rewind_requested)
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
pa_sink_process_rewind(u->sink, 0);
|
|
||||||
|
|
||||||
/* If no outputs are connected, render some data and drop it immediately. */
|
/* If no outputs are connected, render some data and drop it immediately. */
|
||||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && !u->thread_info.active_outputs) {
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state) && !u->thread_info.active_outputs) {
|
||||||
|
|
|
||||||
|
|
@ -213,9 +213,8 @@ 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)
|
||||||
if (u->sink->thread_info.rewind_requested)
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
pa_sink_process_rewind(u->sink, 0);
|
|
||||||
|
|
||||||
if (u->rtpoll_item) {
|
if (u->rtpoll_item) {
|
||||||
struct pollfd *pollfd;
|
struct pollfd *pollfd;
|
||||||
|
|
|
||||||
|
|
@ -136,11 +136,11 @@ static void process_rewind(struct userdata *u, pa_usec_t now) {
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
|
|
||||||
/* Figure out how much we shall rewind and reset the counter */
|
|
||||||
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
|
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
|
||||||
u->sink->thread_info.rewind_nbytes = 0;
|
|
||||||
|
|
||||||
pa_assert(rewind_nbytes > 0);
|
if (!PA_SINK_IS_OPENED(u->sink->thread_info.state) || rewind_nbytes <= 0)
|
||||||
|
goto do_nothing;
|
||||||
|
|
||||||
pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
|
pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
|
||||||
|
|
||||||
if (u->timestamp <= now)
|
if (u->timestamp <= now)
|
||||||
|
|
@ -207,21 +207,17 @@ static void thread_func(void *userdata) {
|
||||||
u->timestamp = pa_rtclock_now();
|
u->timestamp = pa_rtclock_now();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
pa_usec_t now = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
|
||||||
|
now = pa_rtclock_now();
|
||||||
|
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
process_rewind(u, now);
|
||||||
|
|
||||||
/* Render some data and drop it immediately */
|
/* Render some data and drop it immediately */
|
||||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||||
pa_usec_t now;
|
|
||||||
|
|
||||||
now = pa_rtclock_now();
|
|
||||||
|
|
||||||
if (u->sink->thread_info.rewind_requested) {
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,12 +180,11 @@ static void thread_func(void *userdata) {
|
||||||
|
|
||||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||||
|
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
|
||||||
/* Render some data and write it to the fifo */
|
/* Render some data and write it to the fifo */
|
||||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
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 (pollfd->revents) {
|
if (pollfd->revents) {
|
||||||
if (process_render(u) < 0)
|
if (process_render(u) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -587,9 +587,12 @@ static void process_rewind(struct userdata *u) {
|
||||||
|
|
||||||
pa_assert(u);
|
pa_assert(u);
|
||||||
|
|
||||||
/* Figure out how much we shall rewind and reset the counter */
|
if (!PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
|
rewind_nbytes = u->sink->thread_info.rewind_nbytes;
|
||||||
u->sink->thread_info.rewind_nbytes = 0;
|
|
||||||
|
|
||||||
if (rewind_nbytes > 0) {
|
if (rewind_nbytes > 0) {
|
||||||
pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
|
pa_log_debug("Requested to rewind %lu bytes.", (unsigned long) rewind_nbytes);
|
||||||
|
|
@ -625,13 +628,13 @@ static void thread_func(void *userdata) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Render some data and write it to the dsp */
|
/* Render some data and write it to the dsp */
|
||||||
|
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
process_rewind(u);
|
||||||
|
|
||||||
if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||||
pa_usec_t xtime0, ysleep_interval, xsleep_interval;
|
pa_usec_t xtime0, ysleep_interval, xsleep_interval;
|
||||||
uint64_t buffered_bytes;
|
uint64_t buffered_bytes;
|
||||||
|
|
||||||
if (u->sink->thread_info.rewind_requested)
|
|
||||||
process_rewind(u);
|
|
||||||
|
|
||||||
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
err = ioctl(u->fd, AUDIO_GETINFO, &info);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
pa_log("AUDIO_GETINFO ioctl failed: %s", pa_cstrerror(errno));
|
pa_log("AUDIO_GETINFO ioctl failed: %s", pa_cstrerror(errno));
|
||||||
|
|
|
||||||
|
|
@ -698,9 +698,8 @@ static void thread_func(void *userdata) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#ifdef TUNNEL_SINK
|
#ifdef TUNNEL_SINK
|
||||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state))
|
if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
|
||||||
if (PA_UNLIKELY(u->sink->thread_info.rewind_requested))
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
pa_sink_process_rewind(u->sink, 0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0)
|
||||||
|
|
|
||||||
|
|
@ -255,13 +255,16 @@ static void thread_func(void *userdata) {
|
||||||
int ret;
|
int ret;
|
||||||
pa_bool_t need_timer = FALSE;
|
pa_bool_t need_timer = FALSE;
|
||||||
|
|
||||||
if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
if (u->sink) {
|
||||||
if (u->sink->thread_info.rewind_requested)
|
if (u->sink->thread_info.rewind_requested)
|
||||||
pa_sink_process_rewind(u->sink, 0);
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
|
||||||
do_write(u);
|
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
||||||
need_timer = TRUE;
|
do_write(u);
|
||||||
|
need_timer = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
|
if (u->source && PA_SOURCE_IS_OPENED(u->source->thread_info.state)) {
|
||||||
do_read(u);
|
do_read(u);
|
||||||
need_timer = TRUE;
|
need_timer = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -891,9 +891,8 @@ static void thread_func(void *userdata) {
|
||||||
|
|
||||||
/* pa_log("loop"); */
|
/* pa_log("loop"); */
|
||||||
|
|
||||||
if (u->sink && PA_SINK_IS_OPENED(u->sink->thread_info.state))
|
if (u->sink && u->sink->thread_info.rewind_requested)
|
||||||
if (u->sink->thread_info.rewind_requested)
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
pa_sink_process_rewind(u->sink, 0);
|
|
||||||
|
|
||||||
/* Render some data and write it to the dsp */
|
/* Render some data and write it to the dsp */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -327,9 +327,8 @@ 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)
|
||||||
if (u->sink->thread_info.rewind_requested)
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
pa_sink_process_rewind(u->sink, 0);
|
|
||||||
|
|
||||||
if (u->rtpoll_item) {
|
if (u->rtpoll_item) {
|
||||||
struct pollfd *pollfd;
|
struct pollfd *pollfd;
|
||||||
|
|
|
||||||
|
|
@ -338,12 +338,11 @@ static void thread_func(void *userdata) {
|
||||||
|
|
||||||
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL);
|
||||||
|
|
||||||
|
if (u->sink->thread_info.rewind_requested)
|
||||||
|
pa_sink_process_rewind(u->sink, 0);
|
||||||
|
|
||||||
/* Render some data and write it to the fifo */
|
/* Render some data and write it to the fifo */
|
||||||
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
|
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 (pollfd->revents) {
|
if (pollfd->revents) {
|
||||||
if (process_render(u) < 0)
|
if (process_render(u) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
||||||
|
|
@ -928,9 +928,6 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) {
|
||||||
s->thread_info.rewind_nbytes = 0;
|
s->thread_info.rewind_nbytes = 0;
|
||||||
s->thread_info.rewind_requested = FALSE;
|
s->thread_info.rewind_requested = FALSE;
|
||||||
|
|
||||||
if (s->thread_info.state == PA_SINK_SUSPENDED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (nbytes > 0) {
|
if (nbytes > 0) {
|
||||||
pa_log_debug("Processing rewind...");
|
pa_log_debug("Processing rewind...");
|
||||||
if (s->flags & PA_SINK_DEFERRED_VOLUME)
|
if (s->flags & PA_SINK_DEFERRED_VOLUME)
|
||||||
|
|
@ -2898,9 +2895,6 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) {
|
||||||
pa_sink_assert_io_context(s);
|
pa_sink_assert_io_context(s);
|
||||||
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
pa_assert(PA_SINK_IS_LINKED(s->thread_info.state));
|
||||||
|
|
||||||
if (s->thread_info.state == PA_SINK_SUSPENDED)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (nbytes == (size_t) -1)
|
if (nbytes == (size_t) -1)
|
||||||
nbytes = s->thread_info.max_rewind;
|
nbytes = s->thread_info.max_rewind;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue