From 3d88c20d9e76e0da07cbc9c7bb1246ed3bd40afa Mon Sep 17 00:00:00 2001 From: Victor Gaydov Date: Wed, 24 Jan 2024 19:33:25 +0400 Subject: [PATCH] gh-675 Rework pipeline configs - Replace LatencyMonitorConfig w/ LatencyConfig, which may be also used for FeedbackMonitor - Move target_latency to LatencyConfig - Use single deduce_defaults() method instead of multiple deduce_xxx() calls for each parameter - Extract ResamplerConfig and move deducing default backend to it - Invoke deduce_defaults() when constructing pipelines --- .../roc_audio/builtin_resampler.cpp | 12 +- .../roc_audio/builtin_resampler.h | 2 +- .../roc_audio/freq_estimator.cpp | 24 +++ .../roc_audio/freq_estimator.h | 21 ++ .../roc_audio/latency_config.cpp | 50 +++++ .../roc_audio/latency_config.h | 62 ++++++ .../roc_audio/latency_monitor.cpp | 24 +-- .../roc_audio/latency_monitor.h | 62 +----- .../roc_audio/resampler_backend.cpp | 33 ---- .../roc_audio/resampler_backend.h | 46 ----- .../roc_audio/resampler_config.cpp | 69 +++++++ .../roc_audio/resampler_config.h | 80 ++++++++ .../roc_audio/resampler_map.cpp | 15 +- .../roc_audio/resampler_map.h | 8 +- .../roc_audio/resampler_profile.h | 33 ---- .../roc_audio/speex_resampler.cpp | 5 +- .../roc_audio/speex_resampler.h | 2 +- src/internal_modules/roc_audio/watchdog.cpp | 15 ++ src/internal_modules/roc_audio/watchdog.h | 17 +- src/internal_modules/roc_pipeline/config.cpp | 72 +++++++ src/internal_modules/roc_pipeline/config.h | 180 +++++------------- .../roc_pipeline/pipeline_loop.cpp | 2 +- .../roc_pipeline/pipeline_loop.h | 49 ++++- .../roc_pipeline/receiver_loop.cpp | 2 +- .../roc_pipeline/receiver_session.cpp | 14 +- .../roc_pipeline/receiver_session_group.cpp | 2 +- .../roc_pipeline/receiver_source.cpp | 7 +- .../roc_pipeline/sender_loop.cpp | 2 +- .../roc_pipeline/sender_session.cpp | 6 +- .../roc_pipeline/sender_sink.cpp | 4 +- .../roc_pipeline/sender_sink.h | 2 +- .../roc_pipeline/transcoder_sink.cpp | 34 ++-- .../roc_pipeline/transcoder_sink.h | 4 +- .../roc_pipeline/transcoder_source.cpp | 40 ++-- .../roc_pipeline/transcoder_source.h | 4 +- src/public_api/src/adapters.cpp | 73 +++---- src/public_api/src/adapters.h | 4 +- src/tests/roc_audio/test_resampler.cpp | 44 +++-- .../bench_pipeline_loop_contention.cpp | 4 +- .../bench_pipeline_loop_peak_load.cpp | 8 +- .../test_loopback_sink_2_source.cpp | 8 +- src/tests/roc_pipeline/test_pipeline_loop.cpp | 4 +- src/tests/roc_pipeline/test_receiver_loop.cpp | 3 +- .../roc_pipeline/test_receiver_source.cpp | 10 +- src/tests/roc_pipeline/test_sender_loop.cpp | 4 + src/tools/roc_copy/main.cpp | 15 +- src/tools/roc_recv/main.cpp | 55 +++--- src/tools/roc_send/main.cpp | 16 +- 48 files changed, 714 insertions(+), 538 deletions(-) create mode 100644 src/internal_modules/roc_audio/latency_config.cpp create mode 100644 src/internal_modules/roc_audio/latency_config.h delete mode 100644 src/internal_modules/roc_audio/resampler_backend.cpp delete mode 100644 src/internal_modules/roc_audio/resampler_backend.h create mode 100644 src/internal_modules/roc_audio/resampler_config.cpp create mode 100644 src/internal_modules/roc_audio/resampler_config.h delete mode 100644 src/internal_modules/roc_audio/resampler_profile.h create mode 100644 src/internal_modules/roc_pipeline/config.cpp diff --git a/src/internal_modules/roc_audio/builtin_resampler.cpp b/src/internal_modules/roc_audio/builtin_resampler.cpp index 2593ea352..979d97a2f 100644 --- a/src/internal_modules/roc_audio/builtin_resampler.cpp +++ b/src/internal_modules/roc_audio/builtin_resampler.cpp @@ -157,11 +157,13 @@ BuiltinResampler::BuiltinResampler(core::IArena& arena, return; } - roc_log(LogDebug, - "builtin resampler: initializing: " - "window_interp=%lu window_size=%lu frame_size=%lu channels_num=%lu", - (unsigned long)window_interp_, (unsigned long)window_size_, - (unsigned long)frame_size_, (unsigned long)in_spec_.num_channels()); + roc_log( + LogDebug, + "builtin resampler: initializing:" + " profile=%s window_interp=%lu window_size=%lu frame_size=%lu channels_num=%lu", + resampler_profile_to_str(profile), (unsigned long)window_interp_, + (unsigned long)window_size_, (unsigned long)frame_size_, + (unsigned long)in_spec_.num_channels()); valid_ = true; } diff --git a/src/internal_modules/roc_audio/builtin_resampler.h b/src/internal_modules/roc_audio/builtin_resampler.h index f256b71f5..f9212d079 100644 --- a/src/internal_modules/roc_audio/builtin_resampler.h +++ b/src/internal_modules/roc_audio/builtin_resampler.h @@ -15,7 +15,7 @@ #include "roc_audio/frame.h" #include "roc_audio/iframe_reader.h" #include "roc_audio/iresampler.h" -#include "roc_audio/resampler_profile.h" +#include "roc_audio/resampler_config.h" #include "roc_audio/sample.h" #include "roc_audio/sample_spec.h" #include "roc_core/array.h" diff --git a/src/internal_modules/roc_audio/freq_estimator.cpp b/src/internal_modules/roc_audio/freq_estimator.cpp index 8b71573a1..3ee3a30c5 100644 --- a/src/internal_modules/roc_audio/freq_estimator.cpp +++ b/src/internal_modules/roc_audio/freq_estimator.cpp @@ -33,6 +33,9 @@ FreqEstimatorConfig make_config(FreqEstimatorProfile profile) { config.decimation_factor1 = fe_decim_factor_max; config.decimation_factor2 = fe_decim_factor_max; break; + + case FreqEstimatorProfile_Default: + break; } return config; @@ -153,8 +156,29 @@ double FreqEstimator::run_controller_(double current) { return 1 + config_.P * error + config_.I * accum_; } +const char* fe_input_to_str(FreqEstimatorInput input) { + switch (input) { + case FreqEstimatorInput_Disable: + return "disable"; + + case FreqEstimatorInput_Default: + return "default"; + + case FreqEstimatorInput_NiqLatency: + return "niq"; + + case FreqEstimatorInput_E2eLatency: + return "e2e"; + } + + return ""; +} + const char* fe_profile_to_str(FreqEstimatorProfile profile) { switch (profile) { + case FreqEstimatorProfile_Default: + return "default"; + case FreqEstimatorProfile_Responsive: return "responsive"; diff --git a/src/internal_modules/roc_audio/freq_estimator.h b/src/internal_modules/roc_audio/freq_estimator.h index fbfe4a764..5a723e83b 100644 --- a/src/internal_modules/roc_audio/freq_estimator.h +++ b/src/internal_modules/roc_audio/freq_estimator.h @@ -20,8 +20,26 @@ namespace roc { namespace audio { +//! FreqEstimator input value. +enum FreqEstimatorInput { + //! Don't use FreqEstimator. + FreqEstimatorInput_Disable, + + //! Use default input. + FreqEstimatorInput_Default, + + //! Feed FreqEstimator with Network Incoming Queue length. + FreqEstimatorInput_NiqLatency, + + //! Feed FreqEstimator with End-to-end latency. + FreqEstimatorInput_E2eLatency +}; + //! FreqEstimator paremeter preset. enum FreqEstimatorProfile { + //! Use default profile. + FreqEstimatorProfile_Default, + //! Fast and responsive tuning. //! Good for lower network latency and jitter. FreqEstimatorProfile_Responsive, @@ -94,6 +112,9 @@ class FreqEstimator : public core::NonCopyable<> { double coeff_; // Current frequency coefficient value. }; +//! Get string name of FreqEstimator input. +const char* fe_input_to_str(FreqEstimatorInput input); + //! Get string name of FreqEstimator profile. const char* fe_profile_to_str(FreqEstimatorProfile profile); diff --git a/src/internal_modules/roc_audio/latency_config.cpp b/src/internal_modules/roc_audio/latency_config.cpp new file mode 100644 index 000000000..f7a5dc2d9 --- /dev/null +++ b/src/internal_modules/roc_audio/latency_config.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "roc_audio/latency_config.h" + +namespace roc { +namespace audio { + +void LatencyConfig::deduce_defaults(bool is_receiver) { + if (fe_input == audio::FreqEstimatorInput_Default) { + // On receiver, by default adjust clock based on NIQ latency. + // On sender, by default do not adjust clock. + fe_input = is_receiver ? audio::FreqEstimatorInput_NiqLatency + : audio::FreqEstimatorInput_Disable; + } + + if (fe_profile == audio::FreqEstimatorProfile_Default) { + fe_profile = target_latency < 30 * core::Millisecond + // Prefer responsive profile on low latencies, because gradual profile + // won't do it at all. + ? audio::FreqEstimatorProfile_Responsive + // Prefer gradual profile for higher latencies, because it can handle + // higher network jitter. + : audio::FreqEstimatorProfile_Gradual; + } + + if (latency_tolerance < 0) { + // This formula returns target_latency * N, where N starts with larger + // number and approaches 0.5 as target_latency grows. + // Examples: + // target=1ms -> tolerance=8ms (x8) + // target=10ms -> tolerance=20ms (x2) + // target=200ms -> tolerance=200ms (x1) + // target=2000ms -> tolerance=1444ms (x0.722) + const core::nanoseconds_t capped_latency = + std::max(target_latency, core::Millisecond); + + latency_tolerance = core::nanoseconds_t( + capped_latency + * (std::log((200 * core::Millisecond) * 2) / std::log(capped_latency * 2))); + } +} + +} // namespace audio +} // namespace roc diff --git a/src/internal_modules/roc_audio/latency_config.h b/src/internal_modules/roc_audio/latency_config.h new file mode 100644 index 000000000..291679b33 --- /dev/null +++ b/src/internal_modules/roc_audio/latency_config.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +//! @file roc_audio/latency_config.h +//! @brief Latency config. + +#ifndef ROC_AUDIO_LATENCY_CONFIG_H_ +#define ROC_AUDIO_LATENCY_CONFIG_H_ + +#include "roc_audio/freq_estimator.h" +#include "roc_core/time.h" + +namespace roc { +namespace audio { + +//! Parameters for latency and feedback monitors. +struct LatencyConfig { + //! FreqEstimator input. + FreqEstimatorInput fe_input; + + //! FreqEstimator profile. + FreqEstimatorProfile fe_profile; + + //! FreqEstimator update interval, nanoseconds. + //! How often to run FreqEstimator and update Resampler scaling. + core::nanoseconds_t fe_update_interval; + + //! Target latency, nanoseconds. + core::nanoseconds_t target_latency; + + //! Maximum allowed deviation from target latency, nanoseconds. + //! If the latency goes out of bounds, the session is terminated. + core::nanoseconds_t latency_tolerance; + + //! Maximum allowed deviation of freq_coeff from 1.0. + //! If the scaling goes out of bounds, it is trimmed. + //! For example, 0.01 allows freq_coeff values in range [0.99; 1.01]. + float scaling_tolerance; + + //! Initialize. + LatencyConfig(const core::nanoseconds_t default_target_latency) + : fe_input(FreqEstimatorInput_Default) + , fe_profile(FreqEstimatorProfile_Default) + , fe_update_interval(5 * core::Millisecond) + , target_latency(default_target_latency) + , latency_tolerance(-1) + , scaling_tolerance(0.005f) { + } + + //! Automatically fill missing settings. + void deduce_defaults(bool is_receiver); +}; + +} // namespace audio +} // namespace roc + +#endif // ROC_AUDIO_LATENCY_CONFIG_H_ diff --git a/src/internal_modules/roc_audio/latency_monitor.cpp b/src/internal_modules/roc_audio/latency_monitor.cpp index b9f5c4d3f..8b17a04ed 100644 --- a/src/internal_modules/roc_audio/latency_monitor.cpp +++ b/src/internal_modules/roc_audio/latency_monitor.cpp @@ -30,8 +30,7 @@ LatencyMonitor::LatencyMonitor(IFrameReader& frame_reader, const packet::SortedQueue& incoming_queue, const Depacketizer& depacketizer, ResamplerReader* resampler, - const LatencyMonitorConfig& config, - core::nanoseconds_t target_latency, + const LatencyConfig& config, const SampleSpec& input_sample_spec, const SampleSpec& output_sample_spec) : frame_reader_(frame_reader) @@ -52,11 +51,12 @@ LatencyMonitor::LatencyMonitor(IFrameReader& frame_reader, , e2e_latency_(0) , has_niq_latency_(false) , has_e2e_latency_(false) - , target_latency_(input_sample_spec.ns_2_stream_timestamp_delta(target_latency)) + , target_latency_( + input_sample_spec.ns_2_stream_timestamp_delta(config.target_latency)) , min_latency_(input_sample_spec.ns_2_stream_timestamp_delta( - target_latency - config.latency_tolerance)) + config.target_latency - config.latency_tolerance)) , max_latency_(input_sample_spec.ns_2_stream_timestamp_delta( - target_latency + config.latency_tolerance)) + config.target_latency + config.latency_tolerance)) , max_scaling_delta_(config.scaling_tolerance) , input_sample_spec_(input_sample_spec) , output_sample_spec_(output_sample_spec) @@ -67,27 +67,27 @@ LatencyMonitor::LatencyMonitor(IFrameReader& frame_reader, "latency monitor: initializing:" " target=%lu(%.3fms) min=%lu(%.3fms) max=%lu(%.3fms)" " in_rate=%lu out_rate=%lu" - " fe_enable=%d fe_profile=%s fe_interval=%.3fms", + " fe_input=%s fe_profile=%s fe_interval=%.3fms", (unsigned long)target_latency_, timestamp_to_ms(input_sample_spec_, target_latency_), (unsigned long)min_latency_, timestamp_to_ms(input_sample_spec_, min_latency_), (unsigned long)max_latency_, timestamp_to_ms(input_sample_spec_, max_latency_), (unsigned long)input_sample_spec_.sample_rate(), - (unsigned long)output_sample_spec_.sample_rate(), (int)config.fe_enable, - fe_profile_to_str(config.fe_profile), + (unsigned long)output_sample_spec_.sample_rate(), + fe_input_to_str(config.fe_input), fe_profile_to_str(config.fe_profile), timestamp_to_ms(input_sample_spec_, (packet::stream_timestamp_diff_t)update_interval_)); - if (target_latency_ < min_latency_ || target_latency_ > max_latency_ - || target_latency <= 0) { + if (config.target_latency <= 0 || config.latency_tolerance <= 0 + || target_latency_ < min_latency_ || target_latency_ > max_latency_) { roc_log(LogError, "latency monitor: invalid config:" " target_latency=%ldns latency_tolerance=%ldns", - (long)target_latency, (long)config.latency_tolerance); + (long)config.target_latency, (long)config.latency_tolerance); return; } - if (config.fe_enable) { + if (config.fe_input != audio::FreqEstimatorInput_Disable) { if (config.fe_update_interval <= 0) { roc_log(LogError, "latency monitor: invalid config: fe_update_interval=%ld", (long)config.fe_update_interval); diff --git a/src/internal_modules/roc_audio/latency_monitor.h b/src/internal_modules/roc_audio/latency_monitor.h index b600c5b88..8a9839340 100644 --- a/src/internal_modules/roc_audio/latency_monitor.h +++ b/src/internal_modules/roc_audio/latency_monitor.h @@ -15,6 +15,7 @@ #include "roc_audio/depacketizer.h" #include "roc_audio/freq_estimator.h" #include "roc_audio/iframe_reader.h" +#include "roc_audio/latency_config.h" #include "roc_audio/resampler_reader.h" #include "roc_audio/sample_spec.h" #include "roc_core/attributes.h" @@ -27,64 +28,6 @@ namespace roc { namespace audio { -//! Parameters for latency monitor. -struct LatencyMonitorConfig { - //! Enable FreqEstimator. - bool fe_enable; - - //! FreqEstimator profile. - FreqEstimatorProfile fe_profile; - - //! FreqEstimator update interval, nanoseconds. - //! How often to run FreqEstimator and update Resampler scaling. - core::nanoseconds_t fe_update_interval; - - //! Maximum allowed deviation from target latency, nanoseconds. - //! If the latency goes out of bounds, the session is terminated. - core::nanoseconds_t latency_tolerance; - - //! Maximum allowed deviation of freq_coeff from 1.0. - //! If the scaling goes out of bounds, it is trimmed. - //! For example, 0.01 allows freq_coeff values in range [0.99; 1.01]. - float scaling_tolerance; - - LatencyMonitorConfig() - : fe_enable(true) - , fe_profile(FreqEstimatorProfile_Responsive) - , fe_update_interval(5 * core::Millisecond) - , latency_tolerance(0) - , scaling_tolerance(0.005f) { - } - - //! Automatically deduce FreqEstimator profile from target latency. - void deduce_fe_profile(const core::nanoseconds_t target_latency) { - fe_profile = target_latency < 30 * core::Millisecond - // prefer responsive profile on low latencies, because gradual profile - // won't do it at all - ? FreqEstimatorProfile_Responsive - // prefer gradual profile for higher latencies, because it can handle - // higher network jitter - : FreqEstimatorProfile_Gradual; - } - - //! Automatically deduce latency_tolerance from target_latency. - void deduce_latency_tolerance(core::nanoseconds_t target_latency) { - // this formula returns target_latency * N, where N starts with larger - // number and approaches 0.5 as target_latency grows - // examples: - // target=1ms -> tolerance=8ms (x8) - // target=10ms -> tolerance=20ms (x2) - // target=200ms -> tolerance=200ms (x1) - // target=2000ms -> tolerance=1444ms (x0.722) - if (target_latency < core::Millisecond) { - target_latency = core::Millisecond; - } - latency_tolerance = core::nanoseconds_t( - target_latency - * (std::log((200 * core::Millisecond) * 2) / std::log(target_latency * 2))); - } -}; - //! Metrics of latency monitor. struct LatencyMonitorMetrics { //! Estimated NIQ latency. @@ -155,8 +98,7 @@ class LatencyMonitor : public IFrameReader, public core::NonCopyable<> { const packet::SortedQueue& incoming_queue, const Depacketizer& depacketizer, ResamplerReader* resampler, - const LatencyMonitorConfig& config, - core::nanoseconds_t target_latency, + const LatencyConfig& config, const SampleSpec& input_sample_spec, const SampleSpec& output_sample_spec); diff --git a/src/internal_modules/roc_audio/resampler_backend.cpp b/src/internal_modules/roc_audio/resampler_backend.cpp deleted file mode 100644 index 27b188ac7..000000000 --- a/src/internal_modules/roc_audio/resampler_backend.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2020 Roc Streaming authors - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include "roc_audio/resampler_backend.h" - -namespace roc { -namespace audio { - -const char* resampler_backend_to_str(ResamplerBackend backend) { - switch (backend) { - case ResamplerBackend_Builtin: - return "builtin"; - - case ResamplerBackend_Speex: - return "speex"; - - case ResamplerBackend_SpeexDec: - return "speexdec"; - - case ResamplerBackend_Default: - return "default"; - } - - return "invalid"; -} - -} // namespace audio -} // namespace roc diff --git a/src/internal_modules/roc_audio/resampler_backend.h b/src/internal_modules/roc_audio/resampler_backend.h deleted file mode 100644 index 4a5924fa7..000000000 --- a/src/internal_modules/roc_audio/resampler_backend.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020 Roc Streaming authors - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -//! @file roc_audio/resampler_backend.h -//! @brief Resampler backend. - -#ifndef ROC_AUDIO_RESAMPLER_BACKEND_H_ -#define ROC_AUDIO_RESAMPLER_BACKEND_H_ - -namespace roc { -namespace audio { - -//! Resampler backends. -enum ResamplerBackend { - //! Default backend. - //! Resolved to one of other backends, depending on what - //! is enabled at build time. - ResamplerBackend_Default, - - //! Built-in resampler. - //! High precision, high quality, slow. - ResamplerBackend_Builtin, - - //! SpeexDSP resampler. - //! Low precision, high quality, fast. - //! May be disabled at build time. - ResamplerBackend_Speex, - - //! Combined SpeexDSP + decimating resampler. - //! Tolerable precision, tolerable quality, fast. - //! May be disabled at build time. - ResamplerBackend_SpeexDec -}; - -//! Get string name of resampler backend. -const char* resampler_backend_to_str(ResamplerBackend); - -} // namespace audio -} // namespace roc - -#endif // ROC_AUDIO_RESAMPLER_BACKEND_H_ diff --git a/src/internal_modules/roc_audio/resampler_config.cpp b/src/internal_modules/roc_audio/resampler_config.cpp new file mode 100644 index 000000000..c7ed9c377 --- /dev/null +++ b/src/internal_modules/roc_audio/resampler_config.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "roc_audio/resampler_config.h" +#include "roc_audio/resampler_map.h" + +namespace roc { +namespace audio { + +void ResamplerConfig::deduce_defaults(FreqEstimatorInput fe_input, + FreqEstimatorProfile fe_profile) { + if (backend == ResamplerBackend_Default) { + // If responsive profile is set, use builtin backend instead of speex, + // since it has higher scaling precision. + const bool need_builtin_backend = fe_input != FreqEstimatorInput_Disable + && fe_profile == FreqEstimatorProfile_Responsive; + + // If speex backend is not available, fallback to builtin backend. + const bool force_builtin_backend = + !ResamplerMap::instance().is_supported(ResamplerBackend_Speex); + + if (need_builtin_backend || force_builtin_backend) { + backend = ResamplerBackend_Builtin; + } else { + backend = ResamplerBackend_Speex; + } + } +} + +const char* resampler_backend_to_str(ResamplerBackend backend) { + switch (backend) { + case ResamplerBackend_Builtin: + return "builtin"; + + case ResamplerBackend_Speex: + return "speex"; + + case ResamplerBackend_SpeexDec: + return "speexdec"; + + case ResamplerBackend_Default: + return "default"; + } + + return "invalid"; +} + +const char* resampler_profile_to_str(ResamplerProfile profile) { + switch (profile) { + case ResamplerProfile_Low: + return "low"; + + case ResamplerProfile_Medium: + return "medium"; + + case ResamplerProfile_High: + return "high"; + } + + return "invalid"; +} + +} // namespace audio +} // namespace roc diff --git a/src/internal_modules/roc_audio/resampler_config.h b/src/internal_modules/roc_audio/resampler_config.h new file mode 100644 index 000000000..b1f32e1c9 --- /dev/null +++ b/src/internal_modules/roc_audio/resampler_config.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +//! @file roc_audio/resampler_config.h +//! @brief Resampler config. + +#ifndef ROC_AUDIO_RESAMPLER_CONFIG_H_ +#define ROC_AUDIO_RESAMPLER_CONFIG_H_ + +#include "roc_audio/freq_estimator.h" + +namespace roc { +namespace audio { + +//! Resampler backends. +enum ResamplerBackend { + //! Default backend. + //! Resolved to one of other backends, depending on what + //! is enabled at build time. + ResamplerBackend_Default, + + //! Built-in resampler. + //! High precision, high quality, slow. + ResamplerBackend_Builtin, + + //! SpeexDSP resampler. + //! Low precision, high quality, fast. + //! May be disabled at build time. + ResamplerBackend_Speex, + + //! Combined SpeexDSP + decimating resampler. + //! Tolerable precision, tolerable quality, fast. + //! May be disabled at build time. + ResamplerBackend_SpeexDec +}; + +//! Resampler parameters presets. +enum ResamplerProfile { + //! Low quality, fast speed. + ResamplerProfile_Low, + + //! Medium quality, medium speed. + ResamplerProfile_Medium, + + //! Hight quality, low speed. + ResamplerProfile_High +}; + +//! Resampler config. +struct ResamplerConfig { + //! Resampler backend. + ResamplerBackend backend; + + //! Resampler profile. + ResamplerProfile profile; + + ResamplerConfig() + : backend(ResamplerBackend_Default) + , profile(ResamplerProfile_Medium) { + } + + //! Automatically fill missing settings. + void deduce_defaults(FreqEstimatorInput fe_input, FreqEstimatorProfile fe_profile); +}; + +//! Get string name of resampler backend. +const char* resampler_backend_to_str(ResamplerBackend backend); + +//! Get string name of resampler profile. +const char* resampler_profile_to_str(ResamplerProfile profile); + +} // namespace audio +} // namespace roc + +#endif // ROC_AUDIO_RESAMPLER_CONFIG_H_ diff --git a/src/internal_modules/roc_audio/resampler_map.cpp b/src/internal_modules/roc_audio/resampler_map.cpp index a81a0aae4..d2d8f2b07 100644 --- a/src/internal_modules/roc_audio/resampler_map.cpp +++ b/src/internal_modules/roc_audio/resampler_map.cpp @@ -85,21 +85,20 @@ bool ResamplerMap::is_supported(ResamplerBackend backend_id) const { } core::SharedPtr -ResamplerMap::new_resampler(ResamplerBackend backend_id, - core::IArena& arena, +ResamplerMap::new_resampler(core::IArena& arena, core::BufferFactory& buffer_factory, - ResamplerProfile profile, + const ResamplerConfig& config, const audio::SampleSpec& in_spec, const audio::SampleSpec& out_spec) { - const Backend* backend = find_backend_(backend_id); + const Backend* backend = find_backend_(config.backend); if (!backend) { roc_log(LogError, "resampler map: unsupported resampler backend: [%d] %s", - backend_id, resampler_backend_to_str(backend_id)); + config.backend, resampler_backend_to_str(config.backend)); return NULL; } core::SharedPtr resampler = - backend->ctor(arena, buffer_factory, profile, in_spec, out_spec); + backend->ctor(arena, buffer_factory, config.profile, in_spec, out_spec); if (!resampler || !resampler->is_valid()) { return NULL; @@ -115,10 +114,6 @@ void ResamplerMap::add_backend_(const Backend& backend) { const ResamplerMap::Backend* ResamplerMap::find_backend_(ResamplerBackend backend_id) const { - if (backend_id == ResamplerBackend_Default) { - roc_panic_if(n_backends_ == 0); - return &backends_[0]; - } for (size_t n = 0; n < n_backends_; n++) { if (backends_[n].id == backend_id) { return &backends_[n]; diff --git a/src/internal_modules/roc_audio/resampler_map.h b/src/internal_modules/roc_audio/resampler_map.h index 8f22580db..879221e21 100644 --- a/src/internal_modules/roc_audio/resampler_map.h +++ b/src/internal_modules/roc_audio/resampler_map.h @@ -13,8 +13,7 @@ #define ROC_AUDIO_RESAMPLER_MAP_H_ #include "roc_audio/iresampler.h" -#include "roc_audio/resampler_backend.h" -#include "roc_audio/resampler_profile.h" +#include "roc_audio/resampler_config.h" #include "roc_audio/sample_spec.h" #include "roc_core/buffer_factory.h" #include "roc_core/iarena.h" @@ -46,10 +45,9 @@ class ResamplerMap : public core::NonCopyable<> { //! Instantiate IResampler for given backend ID. core::SharedPtr - new_resampler(ResamplerBackend backend_id, - core::IArena& arena, + new_resampler(core::IArena& arena, core::BufferFactory& buffer_factory, - ResamplerProfile profile, + const ResamplerConfig& config, const audio::SampleSpec& in_spec, const audio::SampleSpec& out_spec); diff --git a/src/internal_modules/roc_audio/resampler_profile.h b/src/internal_modules/roc_audio/resampler_profile.h deleted file mode 100644 index 3f5863825..000000000 --- a/src/internal_modules/roc_audio/resampler_profile.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2019 Roc Streaming authors - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -//! @file roc_audio/resampler_profile.h -//! @brief Resampler profile. - -#ifndef ROC_AUDIO_RESAMPLER_PROFILE_H_ -#define ROC_AUDIO_RESAMPLER_PROFILE_H_ - -namespace roc { -namespace audio { - -//! Resampler parameters presets. -enum ResamplerProfile { - //! Low quality, fast speed. - ResamplerProfile_Low, - - //! Medium quality, medium speed. - ResamplerProfile_Medium, - - //! Hight quality, low speed. - ResamplerProfile_High -}; - -} // namespace audio -} // namespace roc - -#endif // ROC_AUDIO_RESAMPLER_PROFILE_H_ diff --git a/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.cpp b/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.cpp index d064e98ae..d515ebe80 100644 --- a/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.cpp +++ b/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.cpp @@ -98,8 +98,9 @@ SpeexResampler::SpeexResampler(core::IArena& arena, roc_log(LogDebug, "speex resampler: initializing:" - " quality=%d frame_size=%lu channels_num=%lu", - quality, (unsigned long)in_frame_size_, (unsigned long)num_ch_); + " profile=%s quality=%d frame_size=%lu channels_num=%lu", + resampler_profile_to_str(profile), quality, (unsigned long)in_frame_size_, + (unsigned long)num_ch_); if (!(in_frame_ = buffer_factory.new_buffer())) { roc_log(LogError, "speex resampler: can't allocate frame buffer"); diff --git a/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.h b/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.h index cd42a9b50..6e3ec1eaf 100644 --- a/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.h +++ b/src/internal_modules/roc_audio/target_speexdsp/roc_audio/speex_resampler.h @@ -15,7 +15,7 @@ #include "roc_audio/frame.h" #include "roc_audio/iframe_reader.h" #include "roc_audio/iresampler.h" -#include "roc_audio/resampler_profile.h" +#include "roc_audio/resampler_config.h" #include "roc_audio/sample.h" #include "roc_audio/sample_spec.h" #include "roc_core/array.h" diff --git a/src/internal_modules/roc_audio/watchdog.cpp b/src/internal_modules/roc_audio/watchdog.cpp index 81c790b0f..36bc61d36 100644 --- a/src/internal_modules/roc_audio/watchdog.cpp +++ b/src/internal_modules/roc_audio/watchdog.cpp @@ -12,6 +12,21 @@ namespace roc { namespace audio { +void WatchdogConfig::deduce_defaults(const core::nanoseconds_t target_latency) { + if (no_playback_timeout < 0) { + no_playback_timeout = target_latency * 4 / 3; + } + + if (choppy_playback_timeout < 0) { + choppy_playback_timeout = 2 * core::Second; + } + + if (choppy_playback_window < 0) { + choppy_playback_window = + std::min(300 * core::Millisecond, choppy_playback_timeout / 4); + } +} + Watchdog::Watchdog(IFrameReader& reader, const audio::SampleSpec& sample_spec, const WatchdogConfig& config, diff --git a/src/internal_modules/roc_audio/watchdog.h b/src/internal_modules/roc_audio/watchdog.h index d238769c8..6098fab64 100644 --- a/src/internal_modules/roc_audio/watchdog.h +++ b/src/internal_modules/roc_audio/watchdog.h @@ -55,21 +55,14 @@ struct WatchdogConfig { //! Initialize config with default values. WatchdogConfig() - : no_playback_timeout(0) - , choppy_playback_timeout(2 * core::Second) - , choppy_playback_window(300 * core::Millisecond) + : no_playback_timeout(-1) + , choppy_playback_timeout(-1) + , choppy_playback_window(-1) , frame_status_window(20) { } - //! Automatically deduce no_playback_timeout from target_latency. - void deduce_no_playback_timeout(core::nanoseconds_t target_latency) { - no_playback_timeout = target_latency * 4 / 3; - } - - //! Automatically deduce choppy_playback_window from choppy_playback_timeout. - void deduce_choppy_playback_window(core::nanoseconds_t timeout) { - choppy_playback_window = std::min(300 * core::Millisecond, timeout / 4); - } + //! Automatically fill missing settings. + void deduce_defaults(const core::nanoseconds_t target_latency); }; //! Watchdog. diff --git a/src/internal_modules/roc_pipeline/config.cpp b/src/internal_modules/roc_pipeline/config.cpp new file mode 100644 index 000000000..e42fb4637 --- /dev/null +++ b/src/internal_modules/roc_pipeline/config.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024 Roc Streaming authors + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "roc_pipeline/config.h" +#include "roc_rtp/headers.h" + +namespace roc { +namespace pipeline { + +SenderConfig::SenderConfig() + : input_sample_spec(DefaultSampleSpec) + , packet_length(DefaultPacketLength) + , payload_type(rtp::PayloadType_L16_Stereo) + , enable_interleaving(false) + , enable_timing(false) + , enable_auto_cts(false) + , enable_profiling(false) { +} + +void SenderConfig::deduce_defaults() { + resampler.deduce_defaults(audio::FreqEstimatorInput_Disable, + audio::FreqEstimatorProfile_Default); +} + +ReceiverSessionConfig::ReceiverSessionConfig() + : payload_type(0) + , latency(DefaultLatency) { +} + +void ReceiverSessionConfig::deduce_defaults() { + latency.deduce_defaults(true); + watchdog.deduce_defaults(latency.target_latency); + resampler.deduce_defaults(latency.fe_input, latency.fe_profile); +} + +ReceiverCommonConfig::ReceiverCommonConfig() + : output_sample_spec(DefaultSampleSpec) + , enable_timing(false) + , enable_auto_reclock(false) + , enable_profiling(false) + , enable_beeping(false) { +} + +void ReceiverCommonConfig::deduce_defaults() { +} + +ReceiverConfig::ReceiverConfig() { +} + +void ReceiverConfig::deduce_defaults() { + default_session.deduce_defaults(); + common.deduce_defaults(); +} + +TranscoderConfig::TranscoderConfig() + : input_sample_spec(DefaultSampleSpec) + , output_sample_spec(DefaultSampleSpec) + , enable_profiling(false) { +} + +void TranscoderConfig::deduce_defaults() { + resampler.deduce_defaults(audio::FreqEstimatorInput_Disable, + audio::FreqEstimatorProfile_Default); +} + +} // namespace pipeline +} // namespace roc diff --git a/src/internal_modules/roc_pipeline/config.h b/src/internal_modules/roc_pipeline/config.h index 78fabc5ec..7869df34a 100644 --- a/src/internal_modules/roc_pipeline/config.h +++ b/src/internal_modules/roc_pipeline/config.h @@ -13,12 +13,9 @@ #define ROC_PIPELINE_CONFIG_H_ #include "roc_address/protocol.h" -#include "roc_audio/freq_estimator.h" -#include "roc_audio/latency_monitor.h" +#include "roc_audio/latency_config.h" #include "roc_audio/profiler.h" -#include "roc_audio/resampler_backend.h" -#include "roc_audio/resampler_map.h" -#include "roc_audio/resampler_profile.h" +#include "roc_audio/resampler_config.h" #include "roc_audio/sample_spec.h" #include "roc_audio/watchdog.h" #include "roc_core/stddefs.h" @@ -27,9 +24,9 @@ #include "roc_fec/reader.h" #include "roc_fec/writer.h" #include "roc_packet/units.h" +#include "roc_pipeline/pipeline_loop.h" #include "roc_rtcp/config.h" #include "roc_rtp/filter.h" -#include "roc_rtp/headers.h" namespace roc { namespace pipeline { @@ -56,60 +53,13 @@ const core::nanoseconds_t DefaultPacketLength = 5 * core::Millisecond; //! networks allow lower latencies, and some networks require higher. const core::nanoseconds_t DefaultLatency = 200 * core::Millisecond; -//! Task processing parameters. -struct TaskConfig { - //! Enable precise task scheduling mode (default). - //! The other settings have effect only when this is set to true. - //! When enabled, pipeline processes tasks in dedicated time intervals between - //! sub-frame and between frames, trying to prevent time collisions between - //! task and frame processing. - bool enable_precise_task_scheduling; - - //! Minimum frame duration between processing tasks. - //! In-frame task processing does not happen until at least given number - //! of samples is processed. - //! Set to zero to allow task processing between frames of any size. - core::nanoseconds_t min_frame_length_between_tasks; - - //! Maximum frame duration between processing tasks. - //! If the frame is larger than this size, it is split into multiple subframes - //! to allow task processing between the sub-frames. - //! Set to zero to disable frame splitting. - core::nanoseconds_t max_frame_length_between_tasks; - - //! Mximum task processing duration happening immediatelly after processing a frame. - //! If this period expires and there are still pending tasks, asynchronous - //! task processing is scheduled. - //! At least one task is always processed after each frame, even if this - //! setting is too small. - core::nanoseconds_t max_inframe_task_processing; - - //! Time interval during which no task processing is allowed. - //! This setting is used to prohibit task processing during the time when - //! next read() or write() call is expected. - //! Since it can not be calculated abolutely precisely, and there is always - //! thread switch overhead, scheduler jitter clock drift, we use a wide interval. - core::nanoseconds_t task_processing_prohibited_interval; - - TaskConfig() - : enable_precise_task_scheduling(true) - , min_frame_length_between_tasks(200 * core::Microsecond) - , max_frame_length_between_tasks(1 * core::Millisecond) - , max_inframe_task_processing(20 * core::Microsecond) - , task_processing_prohibited_interval(200 * core::Microsecond) { - } -}; - //! Sender parameters. struct SenderConfig { //! Task processing parameters. - TaskConfig tasks; + PipelineLoopConfig pipeline_loop; - //! To specify which resampling backend will be used. - audio::ResamplerBackend resampler_backend; - - //! Resampler profile. - audio::ResamplerProfile resampler_profile; + //! Resampler parameters. + audio::ResamplerConfig resampler; //! FEC writer parameters. fec::WriterConfig fec_writer; @@ -139,31 +89,22 @@ struct SenderConfig { bool enable_profiling; //! Profiler configuration. - audio::ProfilerConfig profiler_config; + audio::ProfilerConfig profiler; //! RTCP config. - rtcp::Config rtcp_config; - - SenderConfig() - : resampler_backend(audio::ResamplerBackend_Default) - , resampler_profile(audio::ResamplerProfile_Medium) - , input_sample_spec(DefaultSampleSpec) - , packet_length(DefaultPacketLength) - , payload_type(rtp::PayloadType_L16_Stereo) - , enable_interleaving(false) - , enable_timing(false) - , enable_auto_cts(false) - , enable_profiling(false) { - } + rtcp::Config rtcp; + + //! Initialize config. + SenderConfig(); + + //! Fill unset values with defaults. + void deduce_defaults(); }; //! Receiver session parameters. //! @remarks //! Defines per-session receiver parameters. struct ReceiverSessionConfig { - //! Target latency, nanoseconds. - core::nanoseconds_t target_latency; - //! Packet payload type. unsigned int payload_type; @@ -173,39 +114,20 @@ struct ReceiverSessionConfig { //! FEC decoder parameters. fec::CodecConfig fec_decoder; - //! RTP filter parameters. - rtp::FilterConfig rtp_filter; - //! LatencyMonitor parameters. - audio::LatencyMonitorConfig latency_monitor; + audio::LatencyConfig latency; //! Watchdog parameters. audio::WatchdogConfig watchdog; - //! To specify which resampling backend will be used. - audio::ResamplerBackend resampler_backend; - - //! Resampler profile. - audio::ResamplerProfile resampler_profile; - - ReceiverSessionConfig() - : target_latency(DefaultLatency) - , payload_type(0) - , resampler_backend(audio::ResamplerBackend_Default) - , resampler_profile(audio::ResamplerProfile_Medium) { - latency_monitor.deduce_latency_tolerance(DefaultLatency); - watchdog.deduce_no_playback_timeout(DefaultLatency); - } - - //! Automatically deduce resampler backend from FreqEstimator config. - void deduce_resampler_backend() { - if (latency_monitor.fe_enable - && latency_monitor.fe_profile == audio::FreqEstimatorProfile_Responsive) { - resampler_backend = audio::ResamplerBackend_Builtin; - } else { - resampler_backend = audio::ResamplerBackend_Default; - } - } + //! Resampler parameters. + audio::ResamplerConfig resampler; + + //! Initialize config. + ReceiverSessionConfig(); + + //! Fill unset values with defaults. + void deduce_defaults(); }; //! Receiver common parameters. @@ -225,42 +147,46 @@ struct ReceiverCommonConfig { bool enable_profiling; //! Profiler configuration. - audio::ProfilerConfig profiler_config; + audio::ProfilerConfig profiler; + + //! RTP filter parameters. + rtp::FilterConfig rtp_filter; + + //! RTCP config. + rtcp::Config rtcp; //! Insert weird beeps instead of silence on packet loss. bool enable_beeping; - //! RTCP config. - rtcp::Config rtcp_config; - - ReceiverCommonConfig() - : output_sample_spec(DefaultSampleSpec) - , enable_timing(false) - , enable_auto_reclock(false) - , enable_profiling(false) - , enable_beeping(false) { - } + //! Initialize config. + ReceiverCommonConfig(); + + //! Fill unset values with defaults. + void deduce_defaults(); }; //! Receiver parameters. struct ReceiverConfig { + //! Task processing parameters. + PipelineLoopConfig pipeline_loop; + //! Default parameters for receiver session. ReceiverSessionConfig default_session; //! Parameters common for all sessions. ReceiverCommonConfig common; - //! Task processing parameters. - TaskConfig tasks; + //! Initialize config. + ReceiverConfig(); + + //! Fill unset values with defaults. + void deduce_defaults(); }; //! Converter parameters. struct TranscoderConfig { - //! To specify which resampling backend will be used. - audio::ResamplerBackend resampler_backend; - - //! Resampler profile. - audio::ResamplerProfile resampler_profile; + //! Resampler parameters. + audio::ResamplerConfig resampler; //! Input sample spec audio::SampleSpec input_sample_spec; @@ -272,15 +198,13 @@ struct TranscoderConfig { bool enable_profiling; //! Profiler configuration. - audio::ProfilerConfig profiler_config; - - TranscoderConfig() - : resampler_backend(audio::ResamplerBackend_Default) - , resampler_profile(audio::ResamplerProfile_Medium) - , input_sample_spec(DefaultSampleSpec) - , output_sample_spec(DefaultSampleSpec) - , enable_profiling(false) { - } + audio::ProfilerConfig profiler; + + //! Initialize config. + TranscoderConfig(); + + //! Fill unset values with defaults. + void deduce_defaults(); }; } // namespace pipeline diff --git a/src/internal_modules/roc_pipeline/pipeline_loop.cpp b/src/internal_modules/roc_pipeline/pipeline_loop.cpp index 9068ef9e5..3f3be27ea 100644 --- a/src/internal_modules/roc_pipeline/pipeline_loop.cpp +++ b/src/internal_modules/roc_pipeline/pipeline_loop.cpp @@ -20,7 +20,7 @@ const core::nanoseconds_t StatsReportInterval = core::Minute; } // namespace PipelineLoop::PipelineLoop(IPipelineTaskScheduler& scheduler, - const TaskConfig& config, + const PipelineLoopConfig& config, const audio::SampleSpec& sample_spec) : config_(config) , sample_spec_(sample_spec) diff --git a/src/internal_modules/roc_pipeline/pipeline_loop.h b/src/internal_modules/roc_pipeline/pipeline_loop.h index ee83cfdce..ebbfc5a3e 100644 --- a/src/internal_modules/roc_pipeline/pipeline_loop.h +++ b/src/internal_modules/roc_pipeline/pipeline_loop.h @@ -23,7 +23,6 @@ #include "roc_core/seqlock.h" #include "roc_core/time.h" #include "roc_packet/units.h" -#include "roc_pipeline/config.h" #include "roc_pipeline/ipipeline_task_completer.h" #include "roc_pipeline/ipipeline_task_scheduler.h" #include "roc_pipeline/pipeline_task.h" @@ -31,6 +30,50 @@ namespace roc { namespace pipeline { +//! Pipeline loop task processing parameters. +struct PipelineLoopConfig { + //! Enable precise task scheduling mode (default). + //! The other settings have effect only when this is set to true. + //! When enabled, pipeline processes tasks in dedicated time intervals between + //! sub-frame and between frames, trying to prevent time collisions between + //! task and frame processing. + bool enable_precise_task_scheduling; + + //! Minimum frame duration between processing tasks. + //! In-frame task processing does not happen until at least given number + //! of samples is processed. + //! Set to zero to allow task processing between frames of any size. + core::nanoseconds_t min_frame_length_between_tasks; + + //! Maximum frame duration between processing tasks. + //! If the frame is larger than this size, it is split into multiple subframes + //! to allow task processing between the sub-frames. + //! Set to zero to disable frame splitting. + core::nanoseconds_t max_frame_length_between_tasks; + + //! Mximum task processing duration happening immediatelly after processing a frame. + //! If this period expires and there are still pending tasks, asynchronous + //! task processing is scheduled. + //! At least one task is always processed after each frame, even if this + //! setting is too small. + core::nanoseconds_t max_inframe_task_processing; + + //! Time interval during which no task processing is allowed. + //! This setting is used to prohibit task processing during the time when + //! next read() or write() call is expected. + //! Since it can not be calculated abolutely precisely, and there is always + //! thread switch overhead, scheduler jitter clock drift, we use a wide interval. + core::nanoseconds_t task_processing_prohibited_interval; + + PipelineLoopConfig() + : enable_precise_task_scheduling(true) + , min_frame_length_between_tasks(200 * core::Microsecond) + , max_frame_length_between_tasks(1 * core::Millisecond) + , max_inframe_task_processing(20 * core::Microsecond) + , task_processing_prohibited_interval(200 * core::Microsecond) { + } +}; + //! Base class for task-based pipelines. //! //! Frames, tasks, and threads @@ -235,7 +278,7 @@ class PipelineLoop : public core::NonCopyable<> { //! Initialization. PipelineLoop(IPipelineTaskScheduler& scheduler, - const TaskConfig& config, + const PipelineLoopConfig& config, const audio::SampleSpec& sample_spec); virtual ~PipelineLoop(); @@ -291,7 +334,7 @@ class PipelineLoop : public core::NonCopyable<> { void report_stats_(); // configuration - const TaskConfig config_; + const PipelineLoopConfig config_; const audio::SampleSpec sample_spec_; diff --git a/src/internal_modules/roc_pipeline/receiver_loop.cpp b/src/internal_modules/roc_pipeline/receiver_loop.cpp index 09b0e3ece..25513d2eb 100644 --- a/src/internal_modules/roc_pipeline/receiver_loop.cpp +++ b/src/internal_modules/roc_pipeline/receiver_loop.cpp @@ -89,7 +89,7 @@ ReceiverLoop::ReceiverLoop(IPipelineTaskScheduler& scheduler, core::BufferFactory& byte_buffer_factory, core::BufferFactory& sample_buffer_factory, core::IArena& arena) - : PipelineLoop(scheduler, config.tasks, config.common.output_sample_spec) + : PipelineLoop(scheduler, config.pipeline_loop, config.common.output_sample_spec) , source_(config, encoding_map, packet_factory, diff --git a/src/internal_modules/roc_pipeline/receiver_session.cpp b/src/internal_modules/roc_pipeline/receiver_session.cpp index 44d393b98..0913c5f3a 100644 --- a/src/internal_modules/roc_pipeline/receiver_session.cpp +++ b/src/internal_modules/roc_pipeline/receiver_session.cpp @@ -63,14 +63,14 @@ ReceiverSession::ReceiverSession( } filter_.reset(new (filter_) rtp::Filter( - *preader, *payload_decoder_, session_config.rtp_filter, encoding->sample_spec)); + *preader, *payload_decoder_, common_config.rtp_filter, encoding->sample_spec)); if (!filter_) { return; } preader = filter_.get(); delayed_reader_.reset(new (delayed_reader_) packet::DelayedReader( - *preader, session_config.target_latency, encoding->sample_spec)); + *preader, session_config.latency.target_latency, encoding->sample_spec)); if (!delayed_reader_) { return; } @@ -116,7 +116,7 @@ ReceiverSession::ReceiverSession( preader = fec_reader_.get(); fec_filter_.reset(new (fec_filter_) rtp::Filter(*preader, *payload_decoder_, - session_config.rtp_filter, + common_config.rtp_filter, encoding->sample_spec)); if (!fec_filter_) { return; @@ -168,7 +168,7 @@ ReceiverSession::ReceiverSession( areader = channel_mapper_reader_.get(); } - if (session_config.latency_monitor.fe_enable + if (session_config.latency.fe_input != audio::FreqEstimatorInput_Disable || encoding->sample_spec.sample_rate() != common_config.output_sample_spec.sample_rate()) { resampler_poisoner_.reset(new (resampler_poisoner_) @@ -179,8 +179,7 @@ ReceiverSession::ReceiverSession( areader = resampler_poisoner_.get(); resampler_.reset(audio::ResamplerMap::instance().new_resampler( - session_config.resampler_backend, arena, sample_buffer_factory, - session_config.resampler_profile, + arena, sample_buffer_factory, session_config.resampler, audio::SampleSpec(encoding->sample_spec.sample_rate(), common_config.output_sample_spec.pcm_format(), common_config.output_sample_spec.channel_set()), @@ -211,8 +210,7 @@ ReceiverSession::ReceiverSession( latency_monitor_.reset(new (latency_monitor_) audio::LatencyMonitor( *areader, *source_queue_, *depacketizer_, resampler_reader_.get(), - session_config.latency_monitor, session_config.target_latency, - encoding->sample_spec, common_config.output_sample_spec)); + session_config.latency, encoding->sample_spec, common_config.output_sample_spec)); if (!latency_monitor_ || !latency_monitor_->is_valid()) { return; } diff --git a/src/internal_modules/roc_pipeline/receiver_session_group.cpp b/src/internal_modules/roc_pipeline/receiver_session_group.cpp index 885036c2b..aabb971bb 100644 --- a/src/internal_modules/roc_pipeline/receiver_session_group.cpp +++ b/src/internal_modules/roc_pipeline/receiver_session_group.cpp @@ -60,7 +60,7 @@ bool ReceiverSessionGroup::create_control_pipeline(ReceiverEndpoint* control_end roc_panic_if(rtcp_communicator_); rtcp_communicator_.reset(new (rtcp_communicator_) rtcp::Communicator( - receiver_config_.common.rtcp_config, *this, *control_endpoint->outbound_writer(), + receiver_config_.common.rtcp, *this, *control_endpoint->outbound_writer(), *control_endpoint->outbound_composer(), packet_factory_, byte_buffer_factory_, arena_)); if (!rtcp_communicator_ || !rtcp_communicator_->is_valid()) { diff --git a/src/internal_modules/roc_pipeline/receiver_source.cpp b/src/internal_modules/roc_pipeline/receiver_source.cpp index 1ae8cc92c..ffdc275da 100644 --- a/src/internal_modules/roc_pipeline/receiver_source.cpp +++ b/src/internal_modules/roc_pipeline/receiver_source.cpp @@ -28,6 +28,8 @@ ReceiverSource::ReceiverSource( , frame_reader_(NULL) , config_(config) , valid_(false) { + config_.deduce_defaults(); + mixer_.reset(new (mixer_) audio::Mixer(sample_buffer_factory, true)); if (!mixer_ || !mixer_->is_valid()) { return; @@ -40,10 +42,9 @@ ReceiverSource::ReceiverSource( } areader = poisoner_.get(); - if (config.common.enable_profiling) { + if (config_.common.enable_profiling) { profiler_.reset(new (profiler_) audio::ProfilingReader( - *areader, arena, config.common.output_sample_spec, - config.common.profiler_config)); + *areader, arena, config_.common.output_sample_spec, config_.common.profiler)); if (!profiler_ || !profiler_->is_valid()) { return; } diff --git a/src/internal_modules/roc_pipeline/sender_loop.cpp b/src/internal_modules/roc_pipeline/sender_loop.cpp index 03cb40381..260f8c311 100644 --- a/src/internal_modules/roc_pipeline/sender_loop.cpp +++ b/src/internal_modules/roc_pipeline/sender_loop.cpp @@ -89,7 +89,7 @@ SenderLoop::SenderLoop(IPipelineTaskScheduler& scheduler, core::BufferFactory& byte_buffer_factory, core::BufferFactory& sample_buffer_factory, core::IArena& arena) - : PipelineLoop(scheduler, config.tasks, config.input_sample_spec) + : PipelineLoop(scheduler, config.pipeline_loop, config.input_sample_spec) , sink_(config, encoding_map, packet_factory, diff --git a/src/internal_modules/roc_pipeline/sender_session.cpp b/src/internal_modules/roc_pipeline/sender_session.cpp index 67cb64fc7..cde97f31c 100644 --- a/src/internal_modules/roc_pipeline/sender_session.cpp +++ b/src/internal_modules/roc_pipeline/sender_session.cpp @@ -7,6 +7,7 @@ */ #include "roc_pipeline/sender_session.h" +#include "roc_audio/resampler_map.h" #include "roc_core/log.h" #include "roc_core/panic.h" #include "roc_core/time.h" @@ -144,8 +145,7 @@ bool SenderSession::create_transport_pipeline(SenderEndpoint* source_endpoint, if (encoding->sample_spec.sample_rate() != config_.input_sample_spec.sample_rate()) { resampler_.reset(audio::ResamplerMap::instance().new_resampler( - config_.resampler_backend, arena_, sample_buffer_factory_, - config_.resampler_profile, config_.input_sample_spec, + arena_, sample_buffer_factory_, config_.resampler, config_.input_sample_spec, audio::SampleSpec(encoding->sample_spec.sample_rate(), config_.input_sample_spec.pcm_format(), config_.input_sample_spec.channel_set()))); @@ -180,7 +180,7 @@ bool SenderSession::create_control_pipeline(SenderEndpoint* control_endpoint) { rtcp_address_ = control_endpoint->outbound_address(); rtcp_communicator_.reset(new (rtcp_communicator_) rtcp::Communicator( - config_.rtcp_config, *this, control_endpoint->outbound_writer(), + config_.rtcp, *this, control_endpoint->outbound_writer(), control_endpoint->outbound_composer(), packet_factory_, byte_buffer_factory_, arena_)); if (!rtcp_communicator_ || !rtcp_communicator_->is_valid()) { diff --git a/src/internal_modules/roc_pipeline/sender_sink.cpp b/src/internal_modules/roc_pipeline/sender_sink.cpp index 6bcee5e49..072e12967 100644 --- a/src/internal_modules/roc_pipeline/sender_sink.cpp +++ b/src/internal_modules/roc_pipeline/sender_sink.cpp @@ -28,11 +28,13 @@ SenderSink::SenderSink(const SenderConfig& config, , arena_(arena) , frame_writer_(NULL) , valid_(false) { + config_.deduce_defaults(); + audio::IFrameWriter* awriter = &fanout_; if (config_.enable_profiling) { profiler_.reset(new (profiler_) audio::ProfilingWriter( - *awriter, arena, config_.input_sample_spec, config_.profiler_config)); + *awriter, arena, config_.input_sample_spec, config_.profiler)); if (!profiler_ || !profiler_->is_valid()) { return; } diff --git a/src/internal_modules/roc_pipeline/sender_sink.h b/src/internal_modules/roc_pipeline/sender_sink.h index 2103504a6..4aa358b08 100644 --- a/src/internal_modules/roc_pipeline/sender_sink.h +++ b/src/internal_modules/roc_pipeline/sender_sink.h @@ -101,7 +101,7 @@ class SenderSink : public sndio::ISink, public core::NonCopyable<> { virtual void write(audio::Frame& frame); private: - const SenderConfig config_; + SenderConfig config_; const rtp::EncodingMap& encoding_map_; diff --git a/src/internal_modules/roc_pipeline/transcoder_sink.cpp b/src/internal_modules/roc_pipeline/transcoder_sink.cpp index f4cb18efb..5604b4ddd 100644 --- a/src/internal_modules/roc_pipeline/transcoder_sink.cpp +++ b/src/internal_modules/roc_pipeline/transcoder_sink.cpp @@ -21,41 +21,43 @@ TranscoderSink::TranscoderSink(const TranscoderConfig& config, : frame_writer_(NULL) , config_(config) , valid_(false) { + config_.deduce_defaults(); + audio::IFrameWriter* awriter = output_writer; if (!awriter) { awriter = &null_writer_; } - if (config.input_sample_spec.channel_set() - != config.output_sample_spec.channel_set()) { + if (config_.input_sample_spec.channel_set() + != config_.output_sample_spec.channel_set()) { channel_mapper_writer_.reset( new (channel_mapper_writer_) audio::ChannelMapperWriter( *awriter, buffer_factory, - audio::SampleSpec(config.output_sample_spec.sample_rate(), - config.input_sample_spec.pcm_format(), - config.input_sample_spec.channel_set()), - config.output_sample_spec)); + audio::SampleSpec(config_.output_sample_spec.sample_rate(), + config_.input_sample_spec.pcm_format(), + config_.input_sample_spec.channel_set()), + config_.output_sample_spec)); if (!channel_mapper_writer_ || !channel_mapper_writer_->is_valid()) { return; } awriter = channel_mapper_writer_.get(); } - if (config.input_sample_spec.sample_rate() - != config.output_sample_spec.sample_rate()) { + if (config_.input_sample_spec.sample_rate() + != config_.output_sample_spec.sample_rate()) { resampler_.reset(audio::ResamplerMap::instance().new_resampler( - config.resampler_backend, arena, buffer_factory, config.resampler_profile, - config.input_sample_spec, config.output_sample_spec)); + arena, buffer_factory, config_.resampler, config_.input_sample_spec, + config_.output_sample_spec)); if (!resampler_) { return; } resampler_writer_.reset(new (resampler_writer_) audio::ResamplerWriter( - *awriter, *resampler_, buffer_factory, config.input_sample_spec, - audio::SampleSpec(config.output_sample_spec.sample_rate(), - config.input_sample_spec.pcm_format(), - config.input_sample_spec.channel_set()))); + *awriter, *resampler_, buffer_factory, config_.input_sample_spec, + audio::SampleSpec(config_.output_sample_spec.sample_rate(), + config_.input_sample_spec.pcm_format(), + config_.input_sample_spec.channel_set()))); if (!resampler_writer_ || !resampler_writer_->is_valid()) { return; @@ -63,9 +65,9 @@ TranscoderSink::TranscoderSink(const TranscoderConfig& config, awriter = resampler_writer_.get(); } - if (config.enable_profiling) { + if (config_.enable_profiling) { profiler_.reset(new (profiler_) audio::ProfilingWriter( - *awriter, arena, config.input_sample_spec, config.profiler_config)); + *awriter, arena, config_.input_sample_spec, config_.profiler)); if (!profiler_ || !profiler_->is_valid()) { return; } diff --git a/src/internal_modules/roc_pipeline/transcoder_sink.h b/src/internal_modules/roc_pipeline/transcoder_sink.h index fd75918bb..e86913d64 100644 --- a/src/internal_modules/roc_pipeline/transcoder_sink.h +++ b/src/internal_modules/roc_pipeline/transcoder_sink.h @@ -16,8 +16,6 @@ #include "roc_audio/iresampler.h" #include "roc_audio/null_writer.h" #include "roc_audio/profiling_writer.h" -#include "roc_audio/resampler_map.h" -#include "roc_audio/resampler_profile.h" #include "roc_audio/resampler_writer.h" #include "roc_core/buffer_factory.h" #include "roc_core/optional.h" @@ -85,7 +83,7 @@ class TranscoderSink : public sndio::ISink, public core::NonCopyable<> { audio::IFrameWriter* frame_writer_; - const TranscoderConfig config_; + TranscoderConfig config_; bool valid_; }; diff --git a/src/internal_modules/roc_pipeline/transcoder_source.cpp b/src/internal_modules/roc_pipeline/transcoder_source.cpp index f88bf7f85..f119be6e0 100644 --- a/src/internal_modules/roc_pipeline/transcoder_source.cpp +++ b/src/internal_modules/roc_pipeline/transcoder_source.cpp @@ -22,24 +22,26 @@ TranscoderSource::TranscoderSource(const TranscoderConfig& config, , frame_reader_(NULL) , config_(config) , valid_(false) { + config_.deduce_defaults(); + audio::IFrameReader* areader = &input_source_; - if (config.input_sample_spec.channel_set() - != config.output_sample_spec.channel_set()) { + if (config_.input_sample_spec.channel_set() + != config_.output_sample_spec.channel_set()) { channel_mapper_reader_.reset( new (channel_mapper_reader_) audio::ChannelMapperReader( - *areader, buffer_factory, config.input_sample_spec, - audio::SampleSpec(config.input_sample_spec.sample_rate(), - config.output_sample_spec.pcm_format(), - config.output_sample_spec.channel_set()))); + *areader, buffer_factory, config_.input_sample_spec, + audio::SampleSpec(config_.input_sample_spec.sample_rate(), + config_.output_sample_spec.pcm_format(), + config_.output_sample_spec.channel_set()))); if (!channel_mapper_reader_ || !channel_mapper_reader_->is_valid()) { return; } areader = channel_mapper_reader_.get(); } - if (config.input_sample_spec.sample_rate() - != config.output_sample_spec.sample_rate()) { + if (config_.input_sample_spec.sample_rate() + != config_.output_sample_spec.sample_rate()) { resampler_poisoner_.reset(new (resampler_poisoner_) audio::PoisonReader(*areader)); if (!resampler_poisoner_) { @@ -48,11 +50,11 @@ TranscoderSource::TranscoderSource(const TranscoderConfig& config, areader = resampler_poisoner_.get(); resampler_.reset(audio::ResamplerMap::instance().new_resampler( - config.resampler_backend, arena, buffer_factory, config.resampler_profile, - audio::SampleSpec(config.input_sample_spec.sample_rate(), - config.output_sample_spec.pcm_format(), - config.output_sample_spec.channel_set()), - config.output_sample_spec)); + arena, buffer_factory, config_.resampler, + audio::SampleSpec(config_.input_sample_spec.sample_rate(), + config_.output_sample_spec.pcm_format(), + config_.output_sample_spec.channel_set()), + config_.output_sample_spec)); if (!resampler_) { return; @@ -60,10 +62,10 @@ TranscoderSource::TranscoderSource(const TranscoderConfig& config, resampler_reader_.reset(new (resampler_reader_) audio::ResamplerReader( *areader, *resampler_, - audio::SampleSpec(config.input_sample_spec.sample_rate(), - config.output_sample_spec.pcm_format(), - config.output_sample_spec.channel_set()), - config.output_sample_spec)); + audio::SampleSpec(config_.input_sample_spec.sample_rate(), + config_.output_sample_spec.pcm_format(), + config_.output_sample_spec.channel_set()), + config_.output_sample_spec)); if (!resampler_reader_ || !resampler_reader_->is_valid()) { return; @@ -77,9 +79,9 @@ TranscoderSource::TranscoderSource(const TranscoderConfig& config, } areader = pipeline_poisoner_.get(); - if (config.enable_profiling) { + if (config_.enable_profiling) { profiler_.reset(new (profiler_) audio::ProfilingReader( - *areader, arena, config.output_sample_spec, config.profiler_config)); + *areader, arena, config_.output_sample_spec, config_.profiler)); if (!profiler_ || !profiler_->is_valid()) { return; } diff --git a/src/internal_modules/roc_pipeline/transcoder_source.h b/src/internal_modules/roc_pipeline/transcoder_source.h index 49ebdef14..34a2a41a7 100644 --- a/src/internal_modules/roc_pipeline/transcoder_source.h +++ b/src/internal_modules/roc_pipeline/transcoder_source.h @@ -16,8 +16,6 @@ #include "roc_audio/iresampler.h" #include "roc_audio/poison_reader.h" #include "roc_audio/profiling_reader.h" -#include "roc_audio/resampler_map.h" -#include "roc_audio/resampler_profile.h" #include "roc_audio/resampler_reader.h" #include "roc_core/buffer_factory.h" #include "roc_core/optional.h" @@ -89,7 +87,7 @@ class TranscoderSource : public sndio::ISource, public core::NonCopyable<> { sndio::ISource& input_source_; audio::IFrameReader* frame_reader_; - const TranscoderConfig config_; + TranscoderConfig config_; bool valid_; }; diff --git a/src/public_api/src/adapters.cpp b/src/public_api/src/adapters.cpp index a8345791a..b329dbe31 100644 --- a/src/public_api/src/adapters.cpp +++ b/src/public_api/src/adapters.cpp @@ -12,8 +12,7 @@ #include "roc_audio/channel_defs.h" #include "roc_audio/freq_estimator.h" #include "roc_audio/pcm_format.h" -#include "roc_audio/resampler_backend.h" -#include "roc_audio/resampler_profile.h" +#include "roc_audio/resampler_config.h" #include "roc_core/attributes.h" #include "roc_core/log.h" @@ -119,14 +118,14 @@ bool sender_config_from_user(node::Context& context, return false; } - if (!resampler_backend_from_user(out.resampler_backend, in.resampler_backend)) { + if (!resampler_backend_from_user(out.resampler.backend, in.resampler_backend)) { roc_log(LogError, "bad configuration: invalid roc_sender_config.resampler_backend:" " should be valid enum value"); return false; } - if (!resampler_profile_from_user(out.resampler_profile, in.resampler_profile)) { + if (!resampler_profile_from_user(out.resampler.profile, in.resampler_profile)) { roc_log(LogError, "bad configuration: invalid roc_sender_config.resampler_profile:" " should be valid enum value"); @@ -141,33 +140,25 @@ bool receiver_config_from_user(node::Context&, pipeline::ReceiverConfig& out, const roc_receiver_config& in) { if (in.target_latency != 0) { - out.default_session.target_latency = (core::nanoseconds_t)in.target_latency; + out.default_session.latency.target_latency = + (core::nanoseconds_t)in.target_latency; } if (in.latency_tolerance != 0) { - out.default_session.latency_monitor.latency_tolerance = + out.default_session.latency.latency_tolerance = (core::nanoseconds_t)in.latency_tolerance; - } else { - out.default_session.latency_monitor.deduce_latency_tolerance( - out.default_session.target_latency); } if (in.no_playback_timeout < 0) { out.default_session.watchdog.no_playback_timeout = 0; } else if (in.no_playback_timeout > 0) { out.default_session.watchdog.no_playback_timeout = in.no_playback_timeout; - } else { - out.default_session.watchdog.deduce_no_playback_timeout( - out.default_session.target_latency); } if (in.choppy_playback_timeout < 0) { out.default_session.watchdog.choppy_playback_timeout = 0; } else if (in.choppy_playback_timeout > 0) { out.default_session.watchdog.choppy_playback_timeout = in.choppy_playback_timeout; - - out.default_session.watchdog.deduce_choppy_playback_window( - out.default_session.watchdog.choppy_playback_timeout); } out.common.enable_timing = false; @@ -186,7 +177,7 @@ bool receiver_config_from_user(node::Context&, return false; } - if (!clock_sync_backend_from_user(out.default_session.latency_monitor.fe_enable, + if (!clock_sync_backend_from_user(out.default_session.latency.fe_input, in.clock_sync_backend)) { roc_log(LogError, "bad configuration: invalid roc_receiver_config.clock_sync_backend:" @@ -194,34 +185,23 @@ bool receiver_config_from_user(node::Context&, return false; } - if (in.clock_sync_profile != ROC_CLOCK_SYNC_PROFILE_DEFAULT) { - if (!clock_sync_profile_from_user(out.default_session.latency_monitor.fe_profile, - in.clock_sync_profile)) { - roc_log(LogError, - "bad configuration: invalid roc_receiver_config.clock_sync_profile:" - " should be valid enum value"); - return false; - } - } else { - if (out.default_session.latency_monitor.fe_enable) { - out.default_session.latency_monitor.deduce_fe_profile( - out.default_session.target_latency); - } + if (!clock_sync_profile_from_user(out.default_session.latency.fe_profile, + in.clock_sync_profile)) { + roc_log(LogError, + "bad configuration: invalid roc_receiver_config.clock_sync_profile:" + " should be valid enum value"); + return false; } - if (in.resampler_backend != ROC_RESAMPLER_BACKEND_DEFAULT) { - if (!resampler_backend_from_user(out.default_session.resampler_backend, - in.resampler_backend)) { - roc_log(LogError, - "bad configuration: invalid roc_receiver_config.resampler_backend:" - " should be valid enum value"); - return false; - } - } else { - out.default_session.deduce_resampler_backend(); + if (!resampler_backend_from_user(out.default_session.resampler.backend, + in.resampler_backend)) { + roc_log(LogError, + "bad configuration: invalid roc_receiver_config.resampler_backend:" + " should be valid enum value"); + return false; } - if (!resampler_profile_from_user(out.default_session.resampler_profile, + if (!resampler_profile_from_user(out.default_session.resampler.profile, in.resampler_profile)) { roc_log(LogError, "bad configuration: invalid roc_receiver_config.resampler_profile:" @@ -385,15 +365,19 @@ bool clock_source_from_user(bool& out_timing, roc_clock_source in) { } ROC_ATTR_NO_SANITIZE_UB -bool clock_sync_backend_from_user(bool& out_fe, roc_clock_sync_backend in) { +bool clock_sync_backend_from_user(audio::FreqEstimatorInput& out, + roc_clock_sync_backend in) { switch (enum_from_user(in)) { case ROC_CLOCK_SYNC_BACKEND_DISABLE: - out_fe = false; + out = audio::FreqEstimatorInput_Disable; return true; case ROC_CLOCK_SYNC_BACKEND_DEFAULT: + out = audio::FreqEstimatorInput_Default; + return true; + case ROC_CLOCK_SYNC_BACKEND_NIQ: - out_fe = true; + out = audio::FreqEstimatorInput_NiqLatency; return true; } @@ -405,6 +389,9 @@ bool clock_sync_profile_from_user(audio::FreqEstimatorProfile& out, roc_clock_sync_profile in) { switch (enum_from_user(in)) { case ROC_CLOCK_SYNC_PROFILE_DEFAULT: + out = audio::FreqEstimatorProfile_Default; + return true; + case ROC_CLOCK_SYNC_PROFILE_RESPONSIVE: out = audio::FreqEstimatorProfile_Responsive; return true; diff --git a/src/public_api/src/adapters.h b/src/public_api/src/adapters.h index 4b71b6b26..d8bf3df25 100644 --- a/src/public_api/src/adapters.h +++ b/src/public_api/src/adapters.h @@ -13,6 +13,7 @@ #include "roc/log.h" #include "roc/metrics.h" +#include "roc_audio/freq_estimator.h" #include "roc_node/context.h" #include "roc_node/receiver.h" #include "roc_node/sender.h" @@ -42,7 +43,8 @@ bool channel_set_from_user(audio::ChannelSet& out, bool clock_source_from_user(bool& out_timing, roc_clock_source in); -bool clock_sync_backend_from_user(bool& out_fe, roc_clock_sync_backend in); +bool clock_sync_backend_from_user(audio::FreqEstimatorInput& out, + roc_clock_sync_backend in); bool clock_sync_profile_from_user(audio::FreqEstimatorProfile& out, roc_clock_sync_profile in); diff --git a/src/tests/roc_audio/test_resampler.cpp b/src/tests/roc_audio/test_resampler.cpp index ad3da14c3..9e7bd40ae 100644 --- a/src/tests/roc_audio/test_resampler.cpp +++ b/src/tests/roc_audio/test_resampler.cpp @@ -12,7 +12,6 @@ #include "test_helpers/mock_writer.h" #include "roc_audio/iresampler.h" -#include "roc_audio/resampler_backend.h" #include "roc_audio/resampler_map.h" #include "roc_audio/resampler_reader.h" #include "roc_audio/resampler_writer.h" @@ -284,6 +283,14 @@ void resample_write(IResampler& resampler, } } +ResamplerConfig make_config(ResamplerBackend backend, ResamplerProfile profile) { + ResamplerConfig config; + config.backend = backend; + config.profile = profile; + + return config; +} + void resample(ResamplerBackend backend, ResamplerProfile profile, Direction dir, @@ -293,7 +300,7 @@ void resample(ResamplerBackend backend, const SampleSpec& sample_spec, float scaling) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, profile, sample_spec, sample_spec); + arena, buffer_factory, make_config(backend, profile), sample_spec, sample_spec); CHECK(resampler); CHECK(resampler->is_valid()); @@ -333,8 +340,9 @@ TEST(resampler, supported_scalings) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, - supported_profiles[n_prof], in_spec, out_spec); + arena, buffer_factory, + make_config(backend, supported_profiles[n_prof]), in_spec, + out_spec); CHECK(resampler); CHECK(resampler->is_valid()); @@ -391,8 +399,9 @@ TEST(resampler, invalid_scalings) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, supported_profiles[n_prof], - in_spec, out_spec); + arena, buffer_factory, + make_config(backend, supported_profiles[n_prof]), in_spec, + out_spec); CHECK(resampler); CHECK(resampler->is_valid()); @@ -444,7 +453,8 @@ TEST(resampler, scaling_trend) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, ResamplerProfile_Low, in_spec, + arena, buffer_factory, + make_config(backend, ResamplerProfile_Low), in_spec, out_spec); CHECK(resampler); CHECK(resampler->is_valid()); @@ -668,8 +678,9 @@ TEST(resampler, reader_timestamp_passthrough) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, supported_profiles[n_prof], - in_spec, out_spec); + arena, buffer_factory, + make_config(backend, supported_profiles[n_prof]), in_spec, + out_spec); const core::nanoseconds_t start_ts = 1691499037871419405; core::nanoseconds_t cur_ts = start_ts; @@ -789,8 +800,9 @@ TEST(resampler, writer_timestamp_passthrough) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, supported_profiles[n_prof], - in_spec, out_spec); + arena, buffer_factory, + make_config(backend, supported_profiles[n_prof]), in_spec, + out_spec); const core::nanoseconds_t start_ts = 1691499037871419405; core::nanoseconds_t cur_ts = start_ts; @@ -909,8 +921,9 @@ TEST(resampler, reader_timestamp_zero_or_small) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, supported_profiles[n_prof], - in_spec, out_spec); + arena, buffer_factory, + make_config(backend, supported_profiles[n_prof]), in_spec, + out_spec); test::MockReader input_reader; input_reader.add_zero_samples(); @@ -992,8 +1005,9 @@ TEST(resampler, writer_timestamp_zero_or_small) { core::SharedPtr resampler = ResamplerMap::instance().new_resampler( - backend, arena, buffer_factory, supported_profiles[n_prof], - in_spec, out_spec); + arena, buffer_factory, + make_config(backend, supported_profiles[n_prof]), in_spec, + out_spec); const core::nanoseconds_t epsilon = core::nanoseconds_t(1. / in_spec.sample_rate() * core::Second diff --git a/src/tests/roc_pipeline/bench_pipeline_loop_contention.cpp b/src/tests/roc_pipeline/bench_pipeline_loop_contention.cpp index 176bf425c..e36a43488 100644 --- a/src/tests/roc_pipeline/bench_pipeline_loop_contention.cpp +++ b/src/tests/roc_pipeline/bench_pipeline_loop_contention.cpp @@ -47,7 +47,7 @@ class NoopPipeline : public PipelineLoop, } }; - NoopPipeline(const TaskConfig& config, ctl::ControlTaskQueue& control_queue) + NoopPipeline(const PipelineLoopConfig& config, ctl::ControlTaskQueue& control_queue) : PipelineLoop(*this, config, audio::SampleSpec(SampleRate, @@ -123,7 +123,7 @@ class NoopCompleter : public IPipelineTaskCompleter { struct BM_PipelineContention : benchmark::Fixture { ctl::ControlTaskQueue control_queue; - TaskConfig config; + PipelineLoopConfig config; NoopPipeline pipeline; NoopCompleter completer; diff --git a/src/tests/roc_pipeline/bench_pipeline_loop_peak_load.cpp b/src/tests/roc_pipeline/bench_pipeline_loop_peak_load.cpp index 337c4f57a..4d650adb4 100644 --- a/src/tests/roc_pipeline/bench_pipeline_loop_peak_load.cpp +++ b/src/tests/roc_pipeline/bench_pipeline_loop_peak_load.cpp @@ -267,7 +267,7 @@ class TestPipeline : public PipelineLoop, core::nanoseconds_t start_time_; }; - TestPipeline(const TaskConfig& config, + TestPipeline(const PipelineLoopConfig& config, ctl::ControlTaskQueue& control_queue, DelayStats& stats) : PipelineLoop(*this, @@ -443,7 +443,7 @@ void BM_PipelinePeakLoad_NoTasks(benchmark::State& state) { DelayStats stats; - TaskConfig config; + PipelineLoopConfig config; TestPipeline pipeline(config, control_queue, stats); FrameWriter frame_wr(pipeline, stats, state); @@ -464,7 +464,7 @@ void BM_PipelinePeakLoad_PreciseSchedOff(benchmark::State& state) { DelayStats stats; - TaskConfig config; + PipelineLoopConfig config; config.enable_precise_task_scheduling = false; TestPipeline pipeline(config, control_queue, stats); @@ -494,7 +494,7 @@ void BM_PipelinePeakLoad_PreciseSchedOn(benchmark::State& state) { DelayStats stats; - TaskConfig config; + PipelineLoopConfig config; config.enable_precise_task_scheduling = true; TestPipeline pipeline(config, control_queue, stats); diff --git a/src/tests/roc_pipeline/test_loopback_sink_2_source.cpp b/src/tests/roc_pipeline/test_loopback_sink_2_source.cpp index 76d763a29..e0cc509bc 100644 --- a/src/tests/roc_pipeline/test_loopback_sink_2_source.cpp +++ b/src/tests/roc_pipeline/test_loopback_sink_2_source.cpp @@ -146,7 +146,7 @@ SenderConfig make_sender_config(int flags, config.enable_timing = false; config.enable_profiling = true; - config.rtcp_config.inactivity_timeout = Timeout * core::Second / SampleRate; + config.rtcp.inactivity_timeout = Timeout * core::Second / SampleRate; return config; } @@ -164,10 +164,10 @@ ReceiverConfig make_receiver_config(audio::ChannelMask frame_channels, config.common.enable_timing = false; - config.common.rtcp_config.inactivity_timeout = Timeout * core::Second / SampleRate; + config.common.rtcp.inactivity_timeout = Timeout * core::Second / SampleRate; - config.default_session.latency_monitor.fe_enable = false; - config.default_session.target_latency = Latency * core::Second / SampleRate; + config.default_session.latency.fe_input = audio::FreqEstimatorInput_Disable; + config.default_session.latency.target_latency = Latency * core::Second / SampleRate; config.default_session.watchdog.no_playback_timeout = Timeout * core::Second / SampleRate; diff --git a/src/tests/roc_pipeline/test_pipeline_loop.cpp b/src/tests/roc_pipeline/test_pipeline_loop.cpp index 2a7dbb14e..75727d1ec 100644 --- a/src/tests/roc_pipeline/test_pipeline_loop.cpp +++ b/src/tests/roc_pipeline/test_pipeline_loop.cpp @@ -55,7 +55,7 @@ class TestPipeline : public PipelineLoop, private IPipelineTaskScheduler { } }; - TestPipeline(const TaskConfig& config) + TestPipeline(const PipelineLoopConfig& config) : PipelineLoop(*this, config, SampleSpecs) , blocked_cond_(mutex_) , unblocked_cond_(mutex_) @@ -424,7 +424,7 @@ class AsyncFrameWriter : public core::Thread { TEST_GROUP(pipeline_loop) { audio::sample_t samples[MaxSamples]; - TaskConfig config; + PipelineLoopConfig config; void setup() { config.enable_precise_task_scheduling = true; diff --git a/src/tests/roc_pipeline/test_receiver_loop.cpp b/src/tests/roc_pipeline/test_receiver_loop.cpp index 30f383350..fb4e2d089 100644 --- a/src/tests/roc_pipeline/test_receiver_loop.cpp +++ b/src/tests/roc_pipeline/test_receiver_loop.cpp @@ -105,8 +105,7 @@ TEST_GROUP(receiver_loop) { ReceiverConfig config; void setup() { - config.common.enable_timing = false; - config.default_session.latency_monitor.fe_enable = false; + config.default_session.latency.fe_input = audio::FreqEstimatorInput_Disable; } }; diff --git a/src/tests/roc_pipeline/test_receiver_source.cpp b/src/tests/roc_pipeline/test_receiver_source.cpp index a8180e79e..e61f0c99d 100644 --- a/src/tests/roc_pipeline/test_receiver_source.cpp +++ b/src/tests/roc_pipeline/test_receiver_source.cpp @@ -125,17 +125,17 @@ TEST_GROUP(receiver_source) { config.common.enable_timing = false; config.common.enable_profiling = true; - config.default_session.latency_monitor.fe_enable = false; - config.default_session.target_latency = + config.default_session.latency.fe_input = audio::FreqEstimatorInput_Disable; + config.default_session.latency.target_latency = Latency * core::Second / (int)output_sample_spec.sample_rate(); - config.default_session.latency_monitor.latency_tolerance = + config.default_session.latency.latency_tolerance = Timeout * 10 * core::Second / (int)output_sample_spec.sample_rate(); config.default_session.watchdog.no_playback_timeout = Timeout * core::Second / (int)output_sample_spec.sample_rate(); - config.default_session.rtp_filter.max_sn_jump = MaxSnJump; - config.default_session.rtp_filter.max_ts_jump = + config.common.rtp_filter.max_sn_jump = MaxSnJump; + config.common.rtp_filter.max_ts_jump = MaxTsJump * core::Second / (int)output_sample_spec.sample_rate(); return config; diff --git a/src/tests/roc_pipeline/test_sender_loop.cpp b/src/tests/roc_pipeline/test_sender_loop.cpp index 2b994d18e..fe1876428 100644 --- a/src/tests/roc_pipeline/test_sender_loop.cpp +++ b/src/tests/roc_pipeline/test_sender_loop.cpp @@ -108,6 +108,10 @@ TEST_GROUP(sender_loop) { test::MockScheduler scheduler; SenderConfig config; + + void setup() { + config.latency.fe_input = audio::FreqEstimatorInput_Disable; + } }; TEST(sender_loop, endpoints_sync) { diff --git a/src/tools/roc_copy/main.cpp b/src/tools/roc_copy/main.cpp index d97b9bfc2..d11654be3 100644 --- a/src/tools/roc_copy/main.cpp +++ b/src/tools/roc_copy/main.cpp @@ -7,7 +7,6 @@ */ #include "roc_address/io_uri.h" -#include "roc_audio/resampler_profile.h" #include "roc_core/crash_handler.h" #include "roc_core/heap_arena.h" #include "roc_core/log.h" @@ -136,16 +135,16 @@ int main(int argc, char** argv) { switch (args.resampler_backend_arg) { case resampler_backend_arg_default: - transcoder_config.resampler_backend = audio::ResamplerBackend_Default; + transcoder_config.resampler.backend = audio::ResamplerBackend_Default; break; case resampler_backend_arg_builtin: - transcoder_config.resampler_backend = audio::ResamplerBackend_Builtin; + transcoder_config.resampler.backend = audio::ResamplerBackend_Builtin; break; case resampler_backend_arg_speex: - transcoder_config.resampler_backend = audio::ResamplerBackend_Speex; + transcoder_config.resampler.backend = audio::ResamplerBackend_Speex; break; case resampler_backend_arg_speexdec: - transcoder_config.resampler_backend = audio::ResamplerBackend_SpeexDec; + transcoder_config.resampler.backend = audio::ResamplerBackend_SpeexDec; break; default: break; @@ -153,13 +152,13 @@ int main(int argc, char** argv) { switch (args.resampler_profile_arg) { case resampler_profile_arg_low: - transcoder_config.resampler_profile = audio::ResamplerProfile_Low; + transcoder_config.resampler.profile = audio::ResamplerProfile_Low; break; case resampler_profile_arg_medium: - transcoder_config.resampler_profile = audio::ResamplerProfile_Medium; + transcoder_config.resampler.profile = audio::ResamplerProfile_Medium; break; case resampler_profile_arg_high: - transcoder_config.resampler_profile = audio::ResamplerProfile_High; + transcoder_config.resampler.profile = audio::ResamplerProfile_High; break; default: break; diff --git a/src/tools/roc_recv/main.cpp b/src/tools/roc_recv/main.cpp index 02543f7d7..8ca0ff04a 100644 --- a/src/tools/roc_recv/main.cpp +++ b/src/tools/roc_recv/main.cpp @@ -10,9 +10,6 @@ #include "roc_address/io_uri.h" #include "roc_address/print_supported.h" #include "roc_address/protocol_map.h" -#include "roc_audio/freq_estimator.h" -#include "roc_audio/resampler_profile.h" -#include "roc_core/array.h" #include "roc_core/crash_handler.h" #include "roc_core/heap_arena.h" #include "roc_core/log.h" @@ -108,8 +105,9 @@ int main(int argc, char** argv) { io_config.frame_length, receiver_config.common.output_sample_spec); if (args.sess_latency_given) { - if (!core::parse_duration(args.sess_latency_arg, - receiver_config.default_session.target_latency)) { + if (!core::parse_duration( + args.sess_latency_arg, + receiver_config.default_session.latency.target_latency)) { roc_log(LogError, "invalid --sess-latency"); return 1; } @@ -118,13 +116,10 @@ int main(int argc, char** argv) { if (args.latency_tolerance_given) { if (!core::parse_duration( args.latency_tolerance_arg, - receiver_config.default_session.latency_monitor.latency_tolerance)) { + receiver_config.default_session.latency.latency_tolerance)) { roc_log(LogError, "invalid --latency-tolerance"); return 1; } - } else { - receiver_config.default_session.latency_monitor.deduce_latency_tolerance( - receiver_config.default_session.target_latency); } if (args.no_play_timeout_given) { @@ -134,9 +129,6 @@ int main(int argc, char** argv) { roc_log(LogError, "invalid --no-play-timeout"); return 1; } - } else { - receiver_config.default_session.watchdog.deduce_no_playback_timeout( - receiver_config.default_session.target_latency); } if (args.choppy_play_timeout_given) { @@ -146,16 +138,16 @@ int main(int argc, char** argv) { roc_log(LogError, "invalid --choppy-play-timeout"); return 1; } - receiver_config.default_session.watchdog.deduce_choppy_playback_window( - receiver_config.default_session.watchdog.choppy_playback_timeout); } switch (args.clock_backend_arg) { case clock_backend_arg_disable: - receiver_config.default_session.latency_monitor.fe_enable = false; + receiver_config.default_session.latency.fe_input = + audio::FreqEstimatorInput_Disable; break; case clock_backend_arg_niq: - receiver_config.default_session.latency_monitor.fe_enable = true; + receiver_config.default_session.latency.fe_input = + audio::FreqEstimatorInput_NiqLatency; break; default: break; @@ -163,15 +155,15 @@ int main(int argc, char** argv) { switch (args.clock_profile_arg) { case clock_profile_arg_default: - receiver_config.default_session.latency_monitor.deduce_fe_profile( - receiver_config.default_session.target_latency); + receiver_config.default_session.latency.fe_profile = + audio::FreqEstimatorProfile_Default; break; case clock_profile_arg_responsive: - receiver_config.default_session.latency_monitor.fe_profile = + receiver_config.default_session.latency.fe_profile = audio::FreqEstimatorProfile_Responsive; break; case clock_profile_arg_gradual: - receiver_config.default_session.latency_monitor.fe_profile = + receiver_config.default_session.latency.fe_profile = audio::FreqEstimatorProfile_Gradual; break; default: @@ -180,17 +172,18 @@ int main(int argc, char** argv) { switch (args.resampler_backend_arg) { case resampler_backend_arg_default: - receiver_config.default_session.deduce_resampler_backend(); + receiver_config.default_session.resampler.backend = + audio::ResamplerBackend_Default; break; case resampler_backend_arg_builtin: - receiver_config.default_session.resampler_backend = + receiver_config.default_session.resampler.backend = audio::ResamplerBackend_Builtin; break; case resampler_backend_arg_speex: - receiver_config.default_session.resampler_backend = audio::ResamplerBackend_Speex; + receiver_config.default_session.resampler.backend = audio::ResamplerBackend_Speex; break; case resampler_backend_arg_speexdec: - receiver_config.default_session.resampler_backend = + receiver_config.default_session.resampler.backend = audio::ResamplerBackend_SpeexDec; break; default: @@ -199,14 +192,14 @@ int main(int argc, char** argv) { switch (args.resampler_profile_arg) { case resampler_profile_arg_low: - receiver_config.default_session.resampler_profile = audio::ResamplerProfile_Low; + receiver_config.default_session.resampler.profile = audio::ResamplerProfile_Low; break; case resampler_profile_arg_medium: - receiver_config.default_session.resampler_profile = + receiver_config.default_session.resampler.profile = audio::ResamplerProfile_Medium; break; case resampler_profile_arg_high: - receiver_config.default_session.resampler_profile = audio::ResamplerProfile_High; + receiver_config.default_session.resampler.profile = audio::ResamplerProfile_High; break; default: @@ -356,10 +349,10 @@ int main(int argc, char** argv) { pipeline::TranscoderConfig transcoder_config; - transcoder_config.resampler_backend = - receiver_config.default_session.resampler_backend; - transcoder_config.resampler_profile = - receiver_config.default_session.resampler_profile; + transcoder_config.resampler.backend = + receiver_config.default_session.resampler.backend; + transcoder_config.resampler.profile = + receiver_config.default_session.resampler.profile; transcoder_config.input_sample_spec = audio::SampleSpec(backup_source->sample_spec().sample_rate(), diff --git a/src/tools/roc_send/main.cpp b/src/tools/roc_send/main.cpp index d8dd3de2a..03a732f2a 100644 --- a/src/tools/roc_send/main.cpp +++ b/src/tools/roc_send/main.cpp @@ -10,8 +10,6 @@ #include "roc_address/io_uri.h" #include "roc_address/print_supported.h" #include "roc_address/protocol_map.h" -#include "roc_audio/resampler_profile.h" -#include "roc_core/array.h" #include "roc_core/crash_handler.h" #include "roc_core/heap_arena.h" #include "roc_core/log.h" @@ -150,16 +148,16 @@ int main(int argc, char** argv) { switch (args.resampler_backend_arg) { case resampler_backend_arg_default: - sender_config.resampler_backend = audio::ResamplerBackend_Default; + sender_config.resampler.backend = audio::ResamplerBackend_Default; break; case resampler_backend_arg_builtin: - sender_config.resampler_backend = audio::ResamplerBackend_Builtin; + sender_config.resampler.backend = audio::ResamplerBackend_Builtin; break; case resampler_backend_arg_speex: - sender_config.resampler_backend = audio::ResamplerBackend_Speex; + sender_config.resampler.backend = audio::ResamplerBackend_Speex; break; case resampler_backend_arg_speexdec: - sender_config.resampler_backend = audio::ResamplerBackend_SpeexDec; + sender_config.resampler.backend = audio::ResamplerBackend_SpeexDec; break; default: break; @@ -167,13 +165,13 @@ int main(int argc, char** argv) { switch (args.resampler_profile_arg) { case resampler_profile_arg_low: - sender_config.resampler_profile = audio::ResamplerProfile_Low; + sender_config.resampler.profile = audio::ResamplerProfile_Low; break; case resampler_profile_arg_medium: - sender_config.resampler_profile = audio::ResamplerProfile_Medium; + sender_config.resampler.profile = audio::ResamplerProfile_Medium; break; case resampler_profile_arg_high: - sender_config.resampler_profile = audio::ResamplerProfile_High; + sender_config.resampler.profile = audio::ResamplerProfile_High; break; default: break;