From 3b6806281e16cb41fa3fd3485684e6d85dadba01 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 11 Apr 2023 17:17:08 +0200 Subject: [PATCH] Add 2 patches for some critical bugs. --- ...ver-runnable-when-we-add-a-runnable-.patch | 37 ++++++++ 0002-alsa-fix-capture-timings-and-drift.patch | 95 +++++++++++++++++++ pipewire.spec | 7 +- 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 0001-context-make-driver-runnable-when-we-add-a-runnable-.patch create mode 100644 0002-alsa-fix-capture-timings-and-drift.patch diff --git a/0001-context-make-driver-runnable-when-we-add-a-runnable-.patch b/0001-context-make-driver-runnable-when-we-add-a-runnable-.patch new file mode 100644 index 0000000..2c4fcfb --- /dev/null +++ b/0001-context-make-driver-runnable-when-we-add-a-runnable-.patch @@ -0,0 +1,37 @@ +From 73916bf64b339eb603d22c8564b639bef43624af Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Tue, 11 Apr 2023 16:31:44 +0200 +Subject: [PATCH 1/2] context: make driver runnable when we add a runnable node + +Explicitly make the driver runnable when we add a runnable node to it. + +We have to do this because the runnable node might not be directly linked +to this driver. + +In the case of the echo-canceler, for example, a playback stream +can be linked to the sink before the echo canceled virtual sink. +All echo-cancel nodes are added to a source driver, which would not be +activated because there is no direct path from the playback stream +to the source river. + +Fixes #3145 +--- + src/pipewire/context.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/pipewire/context.c b/src/pipewire/context.c +index 23a8286e3..6683c5a19 100644 +--- a/src/pipewire/context.c ++++ b/src/pipewire/context.c +@@ -943,6 +943,8 @@ static void move_to_driver(struct pw_context *context, struct spa_list *nodes, + spa_list_consume(n, nodes, sort_link) { + spa_list_remove(&n->sort_link); + ++ driver->runnable |= n->runnable; ++ + pw_log_debug(" follower: %p %s runnable:%u driver-runnable:%u", n, n->name, + n->runnable, driver->runnable); + pw_impl_node_set_driver(n, driver); +-- +2.39.2 + diff --git a/0002-alsa-fix-capture-timings-and-drift.patch b/0002-alsa-fix-capture-timings-and-drift.patch new file mode 100644 index 0000000..089a614 --- /dev/null +++ b/0002-alsa-fix-capture-timings-and-drift.patch @@ -0,0 +1,95 @@ +From c5d21a41592d465a0c1d8511480f3a4a0dc0621b Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Mon, 10 Apr 2023 15:02:29 +0200 +Subject: [PATCH 2/2] alsa: fix capture timings and drift + +Don't reschedule a timeout when we have less samples available than the +target but only reschedule when we have less that the required amount we +need to read. This ensures that we hover around the target level and the +timeouts/rate matching adapts correctly. Previously we would only rate +match if the have at least the target amount of samples, which would +then always result in a possitive rate adjustment and cause drift. + +For capture, make sure that there is at least 32 samples of headroom +when we are not using IRQ mode to handle jitter in the timer wakeup. + +For capture of batch devices this results in (for a 1024 quantum) a +target buffer fill level of 1024 + 512, and we will read if there are at +least 1024 samples available. + +For non-batch devices we aim for a target buffer fill level of 1024 + 32 +and read if there are at least 1024 samples available. +--- + spa/plugins/alsa/alsa-pcm.c | 30 ++++++++++++++++++------------ + 1 file changed, 18 insertions(+), 12 deletions(-) + +diff --git a/spa/plugins/alsa/alsa-pcm.c b/spa/plugins/alsa/alsa-pcm.c +index 7ddd980f8..b3debcc3c 100644 +--- a/spa/plugins/alsa/alsa-pcm.c ++++ b/spa/plugins/alsa/alsa-pcm.c +@@ -1616,10 +1616,17 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_ + } + + state->headroom = state->default_headroom; +- /* If tsched is disabled, we know the pointers are updated when we wake +- * up, so we don't need the additional headroom */ +- if (is_batch && !state->disable_tsched) +- state->headroom += period_size; ++ if (!state->disable_tsched) { ++ /* If tsched is disabled, we know the pointers are updated when we wake ++ * up, so we don't need the additional headroom */ ++ if (is_batch) ++ state->headroom += period_size; ++ /* add 32 extra samples of headroom to handle jitter in capture */ ++ if (state->stream == SND_PCM_STREAM_CAPTURE) ++ state->headroom = SPA_MAX(state->headroom, 32u); ++ } ++ ++ + + state->max_delay = state->buffer_frames / 2; + if (spa_strstartswith(state->props.device, "a52") || +@@ -1921,9 +1928,7 @@ static int get_status(struct state *state, uint64_t current_time, + *delay = state->buffer_frames - avail; + } else { + *delay = avail; +- *target = SPA_MAX(*target, state->read_size); +- if (state->matching) +- *target += 32; ++ *target = SPA_MAX(*target, state->read_size + state->headroom); + } + *target = SPA_CLAMP(*target, state->min_delay, state->max_delay); + return 0; +@@ -2002,8 +2007,8 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram + state->clock->next_nsec = state->next_time; + } + +- spa_log_trace_fp(state->log, "%p: follower:%d %"PRIu64" %f %ld %f %f %u", +- state, follower, current_time, corr, delay, err, state->threshold * corr, ++ spa_log_trace_fp(state->log, "%p: follower:%d %"PRIu64" %f %ld %ld %f %f %u", ++ state, follower, current_time, corr, delay, target, err, state->threshold * corr, + state->threshold); + + return 0; +@@ -2478,14 +2483,15 @@ static int handle_capture(struct state *state, uint64_t current_time, + int res; + struct spa_io_buffers *io; + +- if (SPA_UNLIKELY(delay < target)) { +- spa_log_trace(state->log, "%p: early wakeup %ld %ld", state, delay, target); ++ if (SPA_UNLIKELY(delay < state->read_size)) { ++ spa_log_trace(state->log, "%p: early wakeup %ld %ld %d", state, delay, target, ++ state->read_size); + state->next_time = current_time + (target - delay) * SPA_NSEC_PER_SEC / + state->rate; + return -EAGAIN; + } + +- if (SPA_UNLIKELY(res = update_time(state, current_time, delay, target, false)) < 0) ++ if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, false)) < 0)) + return res; + + if ((res = spa_alsa_read(state)) < 0) +-- +2.39.2 + diff --git a/pipewire.spec b/pipewire.spec index 60b8c8d..947e10f 100644 --- a/pipewire.spec +++ b/pipewire.spec @@ -9,7 +9,7 @@ %global ms_version 0.4.2 # For rpmdev-bumpspec and releng automation -%global baserelease 1 +%global baserelease 2 #global snapdate 20210107 #global gitcommit b17db2cebc1a5ab2c01851d29c05f79cd2f262bb @@ -63,6 +63,8 @@ Source0: https://gitlab.freedesktop.org/pipewire/pipewire/-/archive/%{ver %endif ## upstream patches +Patch0001: 0001-context-make-driver-runnable-when-we-add-a-runnable-.patch +Patch0002: 0002-alsa-fix-capture-timings-and-drift.patch ## upstreamable patches @@ -605,6 +607,9 @@ systemctl --no-reload preset --global pipewire.socket >/dev/null 2>&1 || : %{_libdir}/pipewire-%{apiversion}/libpipewire-module-x11-bell.so %changelog +* Tue Apr 11 2023 Wim Taymans - 0.3.68-2 +- Add 2 patches for some critical bugs. + * Thu Apr 6 2023 Wim Taymans - 0.3.68-1 - Update version to 0.3.68 - Enable gstreamer-device-provider (rhbz#2183691)