From d31dae772de6c2f53514d1ac58426c26bf6ff165 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 14 Sep 2023 11:53:52 +0200 Subject: [PATCH] Update version to 0.3.80 Revert webrtc echo-cancel updates until fedora has newer version. --- ...tc-Bump-to-webrtc-audio-processing-1.patch | 243 ++++++++++++++++++ pipewire.spec | 10 +- sources | 2 +- 3 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 0001-Revert-aec-webrtc-Bump-to-webrtc-audio-processing-1.patch diff --git a/0001-Revert-aec-webrtc-Bump-to-webrtc-audio-processing-1.patch b/0001-Revert-aec-webrtc-Bump-to-webrtc-audio-processing-1.patch new file mode 100644 index 0000000..f3a4844 --- /dev/null +++ b/0001-Revert-aec-webrtc-Bump-to-webrtc-audio-processing-1.patch @@ -0,0 +1,243 @@ +From c9914a9f5ead68d67ce7ca56a69d627fbffc3a26 Mon Sep 17 00:00:00 2001 +From: Wim Taymans +Date: Thu, 14 Sep 2023 11:27:11 +0200 +Subject: [PATCH] Revert "aec-webrtc: Bump to webrtc-audio-processing-1" + +This reverts commit c842ef7071d175903df478538bbc1a39440f1b11. +--- + .gitignore | 1 - + meson.build | 4 +- + spa/plugins/aec/aec-webrtc.cpp | 136 +++++++++++++++++++---- + subprojects/webrtc-audio-processing.wrap | 8 -- + 4 files changed, 118 insertions(+), 31 deletions(-) + delete mode 100644 subprojects/webrtc-audio-processing.wrap + +diff --git a/.gitignore b/.gitignore +index 2ebb460fd..aa606d659 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -18,7 +18,6 @@ subprojects/gtest.wrap + subprojects/libyaml.wrap + subprojects/libyaml + subprojects/libcamera +-subprojects/webrtc-audio-processing + + # Created by https://www.gitignore.io/api/vim + +diff --git a/meson.build b/meson.build +index 756a2ff4c..fce4b9477 100644 +--- a/meson.build ++++ b/meson.build +@@ -375,8 +375,8 @@ summary({'gstreamer-device-provider': gst_dp_found}, bool_yn: true, section: 'Ba + + cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', get_option('gstreamer-device-provider').allowed()) + +-webrtc_dep = dependency('webrtc-audio-processing-1', +- version : ['>= 1.2' ], ++webrtc_dep = dependency('webrtc-audio-processing', ++ version : ['>= 0.2', '< 1.0'], + 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()) +diff --git a/spa/plugins/aec/aec-webrtc.cpp b/spa/plugins/aec/aec-webrtc.cpp +index 44719275f..cb19392c4 100644 +--- a/spa/plugins/aec/aec-webrtc.cpp ++++ b/spa/plugins/aec/aec-webrtc.cpp +@@ -13,7 +13,9 @@ + #include + #include + +-#include ++#include ++#include ++#include + + struct impl_data { + struct spa_handle handle; +@@ -39,6 +41,53 @@ static bool webrtc_get_spa_bool(const struct spa_dict *args, const char *key, bo + return default_value; + } + ++ ++/* [ 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; ++} ++ + 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) +@@ -46,33 +95,69 @@ static int webrtc_init2(void *object, const struct spa_dict *args, + auto impl = static_cast(object); + int res; + ++ bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true); ++ bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true); + 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); + + // 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); + ++ // 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); ++ + // FIXME: Intelligibility enhancer is not currently supported + // This filter will modify playback buffer (when calling ProcessReverseStream), but now + // playback buffer modifications are discarded. + +- webrtc::AudioProcessing::Config config; +- config.echo_canceller.enabled = true; +- // FIXME: Example code enables both gain controllers, but that seems sus +- config.gain_controller1.enabled = gain_control; +- config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::Mode::kAdaptiveDigital; +- config.gain_controller1.analog_level_minimum = 0; +- config.gain_controller1.analog_level_maximum = 255; +- config.gain_controller2.enabled = gain_control; +- config.high_pass_filter.enabled = high_pass_filter; +- config.noise_suppression.enabled = noise_suppression; +- config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kHigh; +- // FIXME: expose pre/postamp gain +- config.transient_suppression.enabled = transient_suppression; +- config.voice_detection.enabled = voice_detection; ++ 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)); ++ } ++ } + + webrtc::ProcessingConfig pconfig = {{ + webrtc::StreamConfig(rec_info->rate, rec_info->channels, false), /* input stream */ +@@ -81,15 +166,26 @@ static int webrtc_init2(void *object, const struct spa_dict *args, + webrtc::StreamConfig(play_info->rate, play_info->channels, false), /* reverse output stream */ + }}; + +- auto apm = std::unique_ptr(webrtc::AudioProcessingBuilder().Create()); +- +- apm->ApplyConfig(config); +- ++ auto apm = std::unique_ptr(webrtc::AudioProcessing::Create(config)); + if ((res = apm->Initialize(pconfig)) != webrtc::AudioProcessing::kNoError) { + spa_log_error(impl->log, "Error initialising webrtc audio processing module: %d", res); + return -EINVAL; + } + ++ 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); + impl->apm = std::move(apm); + impl->rec_info = *rec_info; + impl->out_info = *out_info; +diff --git a/subprojects/webrtc-audio-processing.wrap b/subprojects/webrtc-audio-processing.wrap +deleted file mode 100644 +index 1382212d6..000000000 +--- a/subprojects/webrtc-audio-processing.wrap ++++ /dev/null +@@ -1,8 +0,0 @@ +-[wrap-git] +-directory = webrtc-audio-processing +-url = https://gitlab.freedesktop.org/pulseaudio/webrtc-audio-processing.git +-push-url = git@gitlab.freedesktop.org:pulseaudio/webrtc-audio-processing.git +-revision = v1.3 +- +-[provide] +-dependency_names = webrtc-audio-coding-1, webrtc-audio-processing-1 +-- +2.41.0 + diff --git a/pipewire.spec b/pipewire.spec index 4cb44a6..4ee8ebf 100644 --- a/pipewire.spec +++ b/pipewire.spec @@ -1,6 +1,6 @@ %global majorversion 0 %global minorversion 3 -%global microversion 79 +%global microversion 80 %global apiversion 0.3 %global spaversion 0.2 @@ -80,7 +80,7 @@ Source1: pipewire.sysusers ## upstreamable patches ## fedora patches - +Patch0001: 0001-Revert-aec-webrtc-Bump-to-webrtc-audio-processing-1.patch BuildRequires: gettext BuildRequires: meson >= 0.59.0 @@ -505,6 +505,7 @@ systemctl --no-reload preset --global pipewire.socket >/dev/null 2>&1 || : %{_bindir}/pipewire %{_bindir}/pipewire-avb %{_bindir}/pipewire-aes67 +%{_bindir}/pipewire-vulkan %{_mandir}/man1/pipewire.1* %dir %{_datadir}/pipewire/ %{_datadir}/pipewire/pipewire.conf @@ -515,6 +516,7 @@ systemctl --no-reload preset --global pipewire.socket >/dev/null 2>&1 || : %{_datadir}/pipewire/filter-chain/*.conf %{_datadir}/pipewire/pipewire-avb.conf %{_datadir}/pipewire/pipewire-aes67.conf +%{_datadir}/pipewire/pipewire-vulkan.conf %{_mandir}/man5/pipewire.conf.5* %config(noreplace) %{_sysconfdir}/security/limits.d/*.conf %{_sysusersdir}/pipewire.conf @@ -721,6 +723,10 @@ systemctl --no-reload preset --global pipewire.socket >/dev/null 2>&1 || : %endif %changelog +* Thu Sep 14 2023 Wim Taymans - 0.3.80-1 +- Update version to 0.3.80 +- Revert webrtc echo-cancel updates until fedora has newer version. + * Tue Aug 29 2023 Wim Taymans - 0.3.79-1 - Update version to 0.3.79 diff --git a/sources b/sources index eb6f47c..df248fe 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (pipewire-0.3.79.tar.gz) = 39e94f44069d3103f4d1991ab0bed62922122bd096ab0a4595ecd3ff7590154c0c7acc1b737f05eb22a8885184626eefe334267acaad9e11ad9ee9e9f5ed24e7 +SHA512 (pipewire-0.3.80.tar.gz) = b8b1df0034d23d782c94cbafb2f7e4030b26c3370e2f2ce2b1b86d51d3313a23247a186871a81c247e2454ca772f9edc9db8cf08bc3adc0a62fe9191ed238aee