[pulseaudio-commits] src/modules
Tanu Kaskinen
tanuk at kemper.freedesktop.org
Sun Nov 5 13:24:11 UTC 2017
src/modules/alsa/alsa-sink.c | 39 ++++++++++++++++++++-------------------
1 file changed, 20 insertions(+), 19 deletions(-)
New commits:
commit 83e12c43b110fc45056b625ea005b96d231dd415
Author: Tanu Kaskinen <tanuk at iki.fi>
Date: Tue Oct 31 15:29:25 2017 +0200
alsa-sink: update max_rewind when updating the latency
Previously max_rewind was always set to the full hw buffer size, but
the actual maximum rewind amount is limited to the part of the hw buffer
that is in use.
The rewind request that was done when lowering the sink latency had to
be moved to happen before updating max_rewind.
The practical benefit of this change: When using a filter source on a
monitor source, the filter source latency is increased by max_rewind.
Without this change the max_rewind of an alsa sink is often
unnecessarily high, which leads to unnecessarily high latency with
filter sources.
Monitor sources themselves don't suffer from the latency issue, because
they use the current sink latency instead of max_rewind for the extra
buffer that they keep to deal with rewinds.
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 96fd02ae..7936cfac 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -969,13 +969,15 @@ static int suspend(struct userdata *u) {
}
/* Called from IO context */
-static int update_sw_params(struct userdata *u) {
+static int update_sw_params(struct userdata *u, bool may_need_rewind) {
+ size_t old_unused;
snd_pcm_uframes_t avail_min;
int err;
pa_assert(u);
/* Use the full buffer if no one asked us for anything specific */
+ old_unused = u->hwbuf_unused;
u->hwbuf_unused = 0;
if (u->use_tsched) {
@@ -1019,9 +1021,21 @@ static int update_sw_params(struct userdata *u) {
return err;
}
+ /* If we're lowering the latency, we need to do a rewind, because otherwise
+ * we might end up in a situation where the hw buffer contains more data
+ * than the new configured latency. The rewind has to be requested before
+ * updating max_rewind, because the rewind amount is limited to max_rewind.
+ *
+ * If may_need_rewind is false, it means that we're just starting playback,
+ * and rewinding is never needed in that situation. */
+ if (may_need_rewind && u->hwbuf_unused > old_unused) {
+ pa_log_debug("Requesting rewind due to latency change.");
+ pa_sink_request_rewind(u->sink, (size_t) -1);
+ }
+
pa_sink_set_max_request_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
- if (pa_alsa_pcm_is_hw(u->pcm_handle))
- pa_sink_set_max_rewind_within_thread(u->sink, u->hwbuf_size);
+ if (pa_alsa_pcm_is_hw(u->pcm_handle))
+ pa_sink_set_max_rewind_within_thread(u->sink, u->hwbuf_size - u->hwbuf_unused);
else {
pa_log_info("Disabling rewind_within_thread for device %s", u->device_name);
pa_sink_set_max_rewind_within_thread(u->sink, 0);
@@ -1122,7 +1136,7 @@ static int unsuspend(struct userdata *u) {
goto fail;
}
- if (update_sw_params(u) < 0)
+ if (update_sw_params(u, false) < 0)
goto fail;
if (build_pollfd(u) < 0)
@@ -1518,7 +1532,6 @@ static int sink_set_port_cb(pa_sink *s, pa_device_port *p) {
static void sink_update_requested_latency_cb(pa_sink *s) {
struct userdata *u = s->userdata;
- size_t before;
pa_assert(u);
pa_assert(u->use_tsched); /* only when timer scheduling is used
* we can dynamically adjust the
@@ -1527,19 +1540,7 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
if (!u->pcm_handle)
return;
- before = u->hwbuf_unused;
- update_sw_params(u);
-
- /* Let's check whether we now use only a smaller part of the
- buffer then before. If so, we need to make sure that subsequent
- rewinds are relative to the new maximum fill level and not to the
- current fill level. Thus, let's do a full rewind once, to clear
- things up. */
-
- if (u->hwbuf_unused > before) {
- pa_log_debug("Requesting rewind due to latency change.");
- pa_sink_request_rewind(s, (size_t) -1);
- }
+ update_sw_params(u, true);
}
static pa_idxset* sink_get_formats(pa_sink *s) {
@@ -2396,7 +2397,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
reserve_update(u);
- if (update_sw_params(u) < 0)
+ if (update_sw_params(u, false) < 0)
goto fail;
if (u->ucm_context) {
More information about the pulseaudio-commits
mailing list