From cf1cbc64f05bd8e08734853098b4f8898a8669fe Mon Sep 17 00:00:00 2001 From: cinerea0 Date: Thu, 14 Sep 2023 20:45:02 -0400 Subject: [PATCH] pipewire: update to 0.3.80 --- srcpkgs/pipewire/patches/no-LIB-token.patch | 27 --- .../pipewire/patches/support-old-webrtc.patch | 226 ++++++++++++++++++ srcpkgs/pipewire/template | 4 +- 3 files changed, 228 insertions(+), 29 deletions(-) delete mode 100644 srcpkgs/pipewire/patches/no-LIB-token.patch create mode 100644 srcpkgs/pipewire/patches/support-old-webrtc.patch diff --git a/srcpkgs/pipewire/patches/no-LIB-token.patch b/srcpkgs/pipewire/patches/no-LIB-token.patch deleted file mode 100644 index 6573e2aeb7f45..0000000000000 --- a/srcpkgs/pipewire/patches/no-LIB-token.patch +++ /dev/null @@ -1,27 +0,0 @@ -As void doesn't support multiarch, remove the glibc specific $LIB dynamic string -token, which otherwise breaks musl. -diff --git a/meson.build.orig b/meson.build -index 7172ee4..7af3373 100644 ---- a/meson.build -+++ b/meson.build -@@ -39,19 +39,7 @@ pipewire_configdir = pipewire_sysconfdir / 'pipewire' - pipewire_confdatadir = pipewire_datadir / 'pipewire' - modules_install_dir = pipewire_libdir / pipewire_name - --if host_machine.system() == 'linux' -- # glibc ld.so interprets ${LIB} in a library loading path with an -- # appropriate value for the current architecture, typically something -- # like lib, lib64 or lib/x86_64-linux-gnu. -- # This allows the same pw-jack script to work for both 32- and 64-bit -- # applications on biarch/multiarch distributions, by setting something -- # like LD_LIBRARY_PATH='/usr/${LIB}/pipewire-0.3/jack'. -- # Note that ${LIB} is a special token expanded by the runtime linker, -- # not an environment variable, and must be passed through literally. -- modules_install_dir_dlopen = prefix / '${LIB}' / pipewire_name --else -- modules_install_dir_dlopen = modules_install_dir --endif -+modules_install_dir_dlopen = modules_install_dir - - spa_plugindir = pipewire_libdir / spa_name - spa_datadir = pipewire_datadir / spa_name diff --git a/srcpkgs/pipewire/patches/support-old-webrtc.patch b/srcpkgs/pipewire/patches/support-old-webrtc.patch new file mode 100644 index 0000000000000..96eab2142de5d --- /dev/null +++ b/srcpkgs/pipewire/patches/support-old-webrtc.patch @@ -0,0 +1,226 @@ +# Allows building with webrtc above and below v1, will be in v0.3.81 +# Upstream: https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/1f1c308c9766312e684f0b53fc2d1422c7414d31 +diff --git a/meson.build b/meson.build +index 756a2ff4c5253baf6e6dc4cda74a9abb818a9465..ff09002cb8565bbdcd020763e27abdd2e909994f 100644 +--- a/meson.build ++++ b/meson.build +@@ -377,9 +377,17 @@ cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', get_option('gstreamer-device-provide + + webrtc_dep = dependency('webrtc-audio-processing-1', + version : ['>= 1.2' ], +- required : get_option('echo-cancel-webrtc')) +-summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') +-cdata.set('HAVE_WEBRTC', webrtc_dep.found()) ++ required : false) ++cdata.set('HAVE_WEBRTC1', webrtc_dep.found()) ++if webrtc_dep.found() ++ summary({'WebRTC Echo Canceling >= 1.2': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') ++else ++ webrtc_dep = dependency('webrtc-audio-processing', ++ version : ['>= 0.2', '< 1.0'], ++ required : get_option('echo-cancel-webrtc')) ++ cdata.set('HAVE_WEBRTC', webrtc_dep.found()) ++ summary({'WebRTC Echo Canceling < 1.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') ++endif + + # On FreeBSD and MidnightBSD, epoll-shim library is required for eventfd() and timerfd() + epoll_shim_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd' +diff --git a/spa/plugins/aec/aec-webrtc.cpp b/spa/plugins/aec/aec-webrtc.cpp +index 44719275fc4bece08907e6589c7c93e993ebe222..1fb34dd8c3e5b3cd4f5af33bd1bca44fc444c24a 100644 +--- a/spa/plugins/aec/aec-webrtc.cpp ++++ b/spa/plugins/aec/aec-webrtc.cpp +@@ -3,6 +3,8 @@ + /* SPDX-FileCopyrightText: Copyright © 2021 Arun Raghavan */ + /* SPDX-License-Identifier: MIT */ + ++#include "config.h" ++ + #include + #include + +@@ -13,7 +15,13 @@ + #include + #include + ++#ifdef HAVE_WEBRTC ++#include ++#include ++#include ++#else + #include ++#endif + + struct impl_data { + struct spa_handle handle; +@@ -39,6 +47,54 @@ static bool webrtc_get_spa_bool(const struct spa_dict *args, const char *key, bo + return default_value; + } + ++#ifdef HAVE_WEBRTC ++/* [ f0 f1 f2 ] */ ++static int parse_point(struct spa_json *it, float (&f)[3]) ++{ ++ struct spa_json arr; ++ int i, res; ++ ++ if (spa_json_enter_array(it, &arr) <= 0) ++ return -EINVAL; ++ ++ for (i = 0; i < 3; i++) { ++ if ((res = spa_json_get_float(&arr, &f[i])) <= 0) ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++/* [ point1 point2 ... ] */ ++static int parse_mic_geometry(struct impl_data *impl, const char *mic_geometry, ++ std::vector& geometry) ++{ ++ int res; ++ size_t i; ++ struct spa_json it[2]; ++ ++ spa_json_init(&it[0], mic_geometry, strlen(mic_geometry)); ++ if (spa_json_enter_array(&it[0], &it[1]) <= 0) { ++ spa_log_error(impl->log, "Error: webrtc.mic-geometry expects an array"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < geometry.size(); i++) { ++ float f[3]; ++ ++ if ((res = parse_point(&it[1], f)) < 0) { ++ spa_log_error(impl->log, "Error: can't parse webrtc.mic-geometry points: %d", res); ++ return res; ++ } ++ ++ spa_log_info(impl->log, "mic %zd position: (%g %g %g)", i, f[0], f[1], f[2]); ++ geometry[i].c[0] = f[0]; ++ geometry[i].c[1] = f[1]; ++ geometry[i].c[2] = f[2]; ++ } ++ return 0; ++} ++#endif ++ + static int webrtc_init2(void *object, const struct spa_dict *args, + struct spa_audio_info_raw *rec_info, struct spa_audio_info_raw *out_info, + struct spa_audio_info_raw *play_info) +@@ -48,9 +104,18 @@ static int webrtc_init2(void *object, const struct spa_dict *args, + + bool high_pass_filter = webrtc_get_spa_bool(args, "webrtc.high_pass_filter", true); + bool noise_suppression = webrtc_get_spa_bool(args, "webrtc.noise_suppression", true); +- bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true); + bool voice_detection = webrtc_get_spa_bool(args, "webrtc.voice_detection", true); +- ++#ifdef HAVE_WEBRTC ++ bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true); ++ bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true); ++ // Disable experimental flags by default ++ bool experimental_agc = webrtc_get_spa_bool(args, "webrtc.experimental_agc", false); ++ bool experimental_ns = webrtc_get_spa_bool(args, "webrtc.experimental_ns", false); ++ ++ bool beamforming = webrtc_get_spa_bool(args, "webrtc.beamforming", false); ++#else ++ bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true); ++#endif + // Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech, + // result in very poor performance, disable by default + bool gain_control = webrtc_get_spa_bool(args, "webrtc.gain_control", false); +@@ -59,6 +124,51 @@ static int webrtc_init2(void *object, const struct spa_dict *args, + // This filter will modify playback buffer (when calling ProcessReverseStream), but now + // playback buffer modifications are discarded. + ++#ifdef HAVE_WEBRTC ++ webrtc::Config config; ++ config.Set(new webrtc::ExtendedFilter(extended_filter)); ++ config.Set(new webrtc::DelayAgnostic(delay_agnostic)); ++ config.Set(new webrtc::ExperimentalAgc(experimental_agc)); ++ config.Set(new webrtc::ExperimentalNs(experimental_ns)); ++ ++ if (beamforming) { ++ std::vector geometry(rec_info->channels); ++ const char *mic_geometry, *target_direction; ++ ++ /* The beamformer gives a single mono channel */ ++ out_info->channels = 1; ++ out_info->position[0] = SPA_AUDIO_CHANNEL_MONO; ++ ++ if ((mic_geometry = spa_dict_lookup(args, "webrtc.mic-geometry")) == NULL) { ++ spa_log_error(impl->log, "Error: webrtc.beamforming requires webrtc.mic-geometry"); ++ return -EINVAL; ++ } ++ ++ if ((res = parse_mic_geometry(impl, mic_geometry, geometry)) < 0) ++ return res; ++ ++ if ((target_direction = spa_dict_lookup(args, "webrtc.target-direction")) != NULL) { ++ webrtc::SphericalPointf direction(0.0f, 0.0f, 0.0f); ++ struct spa_json it; ++ float f[3]; ++ ++ spa_json_init(&it, target_direction, strlen(target_direction)); ++ if (parse_point(&it, f) < 0) { ++ spa_log_error(impl->log, "Error: can't parse target-direction %s", ++ target_direction); ++ return -EINVAL; ++ } ++ ++ direction.s[0] = f[0]; ++ direction.s[1] = f[1]; ++ direction.s[2] = f[2]; ++ ++ config.Set(new webrtc::Beamforming(true, geometry, direction)); ++ } else { ++ config.Set(new webrtc::Beamforming(true, geometry)); ++ } ++ } ++#else + webrtc::AudioProcessing::Config config; + config.echo_canceller.enabled = true; + // FIXME: Example code enables both gain controllers, but that seems sus +@@ -73,6 +183,7 @@ static int webrtc_init2(void *object, const struct spa_dict *args, + // FIXME: expose pre/postamp gain + config.transient_suppression.enabled = transient_suppression; + config.voice_detection.enabled = voice_detection; ++#endif + + webrtc::ProcessingConfig pconfig = {{ + webrtc::StreamConfig(rec_info->rate, rec_info->channels, false), /* input stream */ +@@ -81,15 +192,35 @@ static int webrtc_init2(void *object, const struct spa_dict *args, + webrtc::StreamConfig(play_info->rate, play_info->channels, false), /* reverse output stream */ + }}; + ++#ifdef HAVE_WEBRTC ++ auto apm = std::unique_ptr(webrtc::AudioProcessing::Create(config)); ++#else + auto apm = std::unique_ptr(webrtc::AudioProcessingBuilder().Create()); + + apm->ApplyConfig(config); ++#endif + + if ((res = apm->Initialize(pconfig)) != webrtc::AudioProcessing::kNoError) { + spa_log_error(impl->log, "Error initialising webrtc audio processing module: %d", res); + return -EINVAL; + } + ++#ifdef HAVE_WEBRTC ++ apm->high_pass_filter()->Enable(high_pass_filter); ++ // Always disable drift compensation since PipeWire will already do ++ // drift compensation on all sinks and sources linked to this echo-canceler ++ apm->echo_cancellation()->enable_drift_compensation(false); ++ apm->echo_cancellation()->Enable(true); ++ // TODO: wire up supression levels to args ++ apm->echo_cancellation()->set_suppression_level(webrtc::EchoCancellation::kHighSuppression); ++ apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kHigh); ++ apm->noise_suppression()->Enable(noise_suppression); ++ apm->voice_detection()->Enable(voice_detection); ++ // TODO: wire up AGC parameters to args ++ apm->gain_control()->set_analog_level_limits(0, 255); ++ apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital); ++ apm->gain_control()->Enable(gain_control); ++#endif + impl->apm = std::move(apm); + impl->rec_info = *rec_info; + impl->out_info = *out_info; diff --git a/srcpkgs/pipewire/template b/srcpkgs/pipewire/template index cfd82f3046b0f..7e35683d89daa 100644 --- a/srcpkgs/pipewire/template +++ b/srcpkgs/pipewire/template @@ -1,6 +1,6 @@ # Template file for 'pipewire' pkgname=pipewire -version=0.3.79 +version=0.3.80 revision=1 build_style=meson configure_args=" @@ -35,7 +35,7 @@ license="MIT" homepage="https://pipewire.org/" changelog="https://gitlab.freedesktop.org/pipewire/pipewire/-/raw/master/NEWS" distfiles="https://gitlab.freedesktop.org/pipewire/pipewire/-/archive/${version}/pipewire-${version}.tar.gz" -checksum=d5808abaf6e56b1f268a468dafc2fe9ca9efcc7cfea19f6d47ad5769271afce9 +checksum=0bbaf3d46649ac2217f0bbf68dda7e62f1f2cf6b7f3025e364cf7205d1499ef9 make_dirs="/var/lib/pipewire 0755 _pipewire _pipewire" system_accounts="_pipewire"