From c1a5a52bc60a21a7b2e2b2de6613de969d79c166 Mon Sep 17 00:00:00 2001 From: badaix Date: Mon, 23 Nov 2020 13:51:19 +0100 Subject: [PATCH] Make buffer time and fragments configurable --- client/player/alsa_player.cpp | 38 ++++++++++++++++++++++++---------- client/player/alsa_player.hpp | 5 +++++ client/player/pulse_player.cpp | 14 +++++++------ client/player/pulse_player.hpp | 1 + client/snapclient.cpp | 8 ++++++- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/client/player/alsa_player.cpp b/client/player/alsa_player.cpp index d0667737..219bf7f7 100644 --- a/client/player/alsa_player.cpp +++ b/client/player/alsa_player.cpp @@ -22,11 +22,14 @@ #include "common/str_compat.hpp" #include "common/utils/string_utils.hpp" -//#define BUFFER_TIME 120000 -#define PERIOD_TIME 30000 +using namespace std::chrono_literals; +using namespace std; + +static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms; +static constexpr int PERIODS = 4; + #define exp10(x) (exp((x)*log(10))) -using namespace std; static constexpr auto LOG_TAG = "Alsa"; static constexpr auto DEFAULT_MIXER = "PCM"; @@ -61,6 +64,16 @@ AlsaPlayer::AlsaPlayer(boost::asio::io_context& io_context, const ClientSettings LOG(DEBUG, LOG_TAG) << "Mixer: " << mixer_name_ << ", device: " << mixer_device_ << "\n"; } + + buffer_time_ = BUFFER_TIME; + periods_ = PERIODS; + auto params = utils::string::split_pairs(settings.parameter, ',', '='); + if (params.find("buffer_time") != params.end()) + buffer_time_ = std::chrono::milliseconds(std::max(cpt::stoi(params["buffer_time"]), 10)); + if (params.find("fragments") != params.end()) + periods_ = std::max(cpt::stoi(params["fragments"]), 2); + + LOG(INFO, LOG_TAG) << "Using buffer_time: " << buffer_time_.count() / 1000 << " ms, fragments: " << periods_ << "\n"; } @@ -334,15 +347,12 @@ void AlsaPlayer::initAlsa() if ((err = snd_pcm_hw_params_set_rate_near(handle_, params, &rate, nullptr)) < 0) throw SnapException("Can't set rate: " + string(snd_strerror(err))); - unsigned int period_time; - snd_pcm_hw_params_get_period_time_max(params, &period_time, nullptr); - if (period_time > PERIOD_TIME) - period_time = PERIOD_TIME; + unsigned int buffer_time = buffer_time_.count(); + if ((err = snd_pcm_hw_params_set_buffer_time_near(handle_, params, &buffer_time, nullptr)) < 0) + throw SnapException("Can't set buffer time: " + string(snd_strerror(err))); - unsigned int buffer_time = 4 * period_time; - - snd_pcm_hw_params_set_period_time_near(handle_, params, &period_time, nullptr); - snd_pcm_hw_params_set_buffer_time_near(handle_, params, &buffer_time, nullptr); + if ((err = snd_pcm_hw_params_set_periods(handle_, params, periods_, 0)) < 0) + throw SnapException("Can't set periods: " + string(snd_strerror(err))); // long unsigned int periodsize = stream_->format.msRate() * 50;//2*rate/50; // if ((pcm = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, params, &periodsize)) < 0) @@ -365,9 +375,15 @@ void AlsaPlayer::initAlsa() snd_pcm_hw_params_get_period_size(params, &frames_, nullptr); LOG(DEBUG, LOG_TAG) << "frames: " << frames_ << "\n"; + snd_pcm_hw_params_get_buffer_time(params, &tmp, nullptr); + LOG(DEBUG, LOG_TAG) << "buffer time: " << tmp << "\n"; + snd_pcm_hw_params_get_period_time(params, &tmp, nullptr); LOG(DEBUG, LOG_TAG) << "period time: " << tmp << "\n"; + snd_pcm_hw_params_get_periods(params, &tmp, nullptr); + LOG(DEBUG, LOG_TAG) << "periods: " << tmp << "\n"; + snd_pcm_sw_params_t* swparams; snd_pcm_sw_params_alloca(&swparams); snd_pcm_sw_params_current(handle_, swparams); diff --git a/client/player/alsa_player.hpp b/client/player/alsa_player.hpp index 01cb0360..dff20387 100644 --- a/client/player/alsa_player.hpp +++ b/client/player/alsa_player.hpp @@ -20,7 +20,9 @@ #define ALSA_PLAYER_H #include "player.hpp" + #include +#include /// Audio Player @@ -73,6 +75,9 @@ private: std::chrono::time_point last_change_; std::recursive_mutex mutex_; boost::asio::steady_timer timer_; + + std::chrono::microseconds buffer_time_; + unsigned int periods_; }; diff --git a/client/player/pulse_player.cpp b/client/player/pulse_player.cpp index 17da1e3b..d7838903 100644 --- a/client/player/pulse_player.cpp +++ b/client/player/pulse_player.cpp @@ -25,8 +25,11 @@ #include "common/utils/string_utils.hpp" #include "pulse_player.hpp" +using namespace std::chrono_literals; using namespace std; +static constexpr std::chrono::milliseconds BUFFER_TIME = 80ms; + static constexpr auto LOG_TAG = "PulsePlayer"; // Example code: @@ -36,14 +39,13 @@ static constexpr auto LOG_TAG = "PulsePlayer"; PulsePlayer::PulsePlayer(boost::asio::io_context& io_context, const ClientSettings::Player& settings, std::shared_ptr stream) - : Player(io_context, settings, stream), latency_(100ms), pa_ml_(nullptr), pa_ctx_(nullptr), playstream_(nullptr) + : Player(io_context, settings, stream), latency_(BUFFER_TIME), pa_ml_(nullptr), pa_ctx_(nullptr), playstream_(nullptr) { auto params = utils::string::split_pairs(settings.parameter, ',', '='); - if (params.find("latency") != params.end()) - { - latency_ = std::chrono::milliseconds(std::max(cpt::stoi(params["latency"]), 10)); - } - LOG(INFO, LOG_TAG) << "Using latency: " << latency_.count() / 1000 << " ms\n"; + if (params.find("buffer_time") != params.end()) + latency_ = std::chrono::milliseconds(std::max(cpt::stoi(params["buffer_time"]), 10)); + + LOG(INFO, LOG_TAG) << "Using buffer_time: " << latency_.count() / 1000 << " ms\n"; } diff --git a/client/player/pulse_player.hpp b/client/player/pulse_player.hpp index 5948b7e6..030e0857 100644 --- a/client/player/pulse_player.hpp +++ b/client/player/pulse_player.hpp @@ -20,6 +20,7 @@ #define PULSE_PLAYER_HPP #include "player.hpp" + #include #include #include diff --git a/client/snapclient.cpp b/client/snapclient.cpp index 27859454..1bab5c50 100644 --- a/client/snapclient.cpp +++ b/client/snapclient.cpp @@ -335,7 +335,13 @@ int main(int argc, char** argv) else if (settings.player.player_name == "pulse") { cout << "Options are a comma separated list of:\n" - << " \"latency=\" - default 100, min 10\n"; + << " \"buffer_time=\" - default 80, min 10\n"; + } + else if (settings.player.player_name == "alsa") + { + cout << "Options are a comma separated list of:\n" + << " \"buffer_time=\" - default 80, min 10\n" + << " \"fragments=\" - default 4, min 2\n"; } else {