Improve default buffer sizes in PipeWireOut, and allow user to configure them via advanced prefs

This commit is contained in:
casey langen 2022-10-23 16:57:47 -07:00
parent 2e8ec50bb0
commit ebf54a6c96
3 changed files with 26 additions and 10 deletions

View File

@ -4,6 +4,8 @@
* fixed PulseAudio compile issue. * fixed PulseAudio compile issue.
* fixed `musikdroid` app notification on Android 13 devices. * fixed `musikdroid` app notification on Android 13 devices.
* fixed ancient metadata indexer crash when trimming whitespace from strings. * fixed ancient metadata indexer crash when trimming whitespace from strings.
* fixed `pipewireout` to have more sensible default buffer sizes, and add the
ability for the user to configure them.
* updated `musikdroid` dependencies and tooling, fixed a few warnings. * updated `musikdroid` dependencies and tooling, fixed a few warnings.
* merged latest upstream `PDCurses` code for Windows builds. * merged latest upstream `PDCurses` code for Windows builds.
* sending `musikcubed` a SIGUSR1 will trigger a library rescan. * sending `musikcubed` a SIGUSR1 will trigger a library rescan.

View File

@ -48,8 +48,11 @@
constexpr const char* TAG = "PipeWireOut"; constexpr const char* TAG = "PipeWireOut";
constexpr size_t SAMPLES_PER_BUFFER = 2048; constexpr size_t SAMPLES_PER_BUFFER = 2048;
constexpr size_t SAMPLE_SIZE_BYTES = sizeof(float); constexpr size_t SAMPLE_SIZE_BYTES = sizeof(float);
constexpr size_t MAX_BUFFERS = 16;
constexpr const char* PREF_DEVICE_ID = "device_id"; constexpr const char* PREF_DEVICE_ID = "device_id";
constexpr const char* PREF_OUTPUT_BUFFER_SIZE_IN_SAMPLES = "output_buffer_size_in_samples";
constexpr const char* PREF_OUTPUT_BUFFER_COUNT = "output_buffer_count";
constexpr int DEFAULT_OUTPUT_BUFFER_SIZE_IN_SAMPLES = 2048;
constexpr int DEFAULT_OUTPUT_BUFFER_COUNT = 16;
static std::atomic<bool> pipeWireInitialized(false); static std::atomic<bool> pipeWireInitialized(false);
@ -68,6 +71,12 @@ extern "C" void SetPreferences(IPreferences* prefs) {
extern "C" musik::core::sdk::ISchema* GetSchema() { extern "C" musik::core::sdk::ISchema* GetSchema() {
auto schema = new TSchema<>(); auto schema = new TSchema<>();
schema->AddInt(
PREF_OUTPUT_BUFFER_SIZE_IN_SAMPLES,
DEFAULT_OUTPUT_BUFFER_SIZE_IN_SAMPLES,
DEFAULT_OUTPUT_BUFFER_SIZE_IN_SAMPLES / 8,
DEFAULT_OUTPUT_BUFFER_SIZE_IN_SAMPLES * 16);
schema->AddInt(PREF_OUTPUT_BUFFER_COUNT, DEFAULT_OUTPUT_BUFFER_COUNT, 8, 64);
return schema; return schema;
} }
@ -348,7 +357,7 @@ bool PipeWireOut::StartPipeWire(IBuffer* buffer) {
if (this->pwStream) { if (this->pwStream) {
uint8_t builderBuffer[4096]; uint8_t builderBuffer[4096];
spa_pod_builder builder = SPA_POD_BUILDER_INIT(builderBuffer, sizeof(builderBuffer)); spa_pod_builder builder = SPA_POD_BUILDER_INIT(builderBuffer, sizeof(builderBuffer));
const spa_pod *params[1]; const spa_pod *params[2];
this->channelCount = buffer->Channels(); this->channelCount = buffer->Channels();
this->sampleRate = buffer->SampleRate(); this->sampleRate = buffer->SampleRate();
@ -369,12 +378,15 @@ bool PipeWireOut::StartPipeWire(IBuffer* buffer) {
goto cleanup; goto cleanup;
} }
// params[1] = (spa_pod*) spa_pod_builder_add_object( int pwOutputBufferSize = prefs->GetInt(PREF_OUTPUT_BUFFER_SIZE_IN_SAMPLES, DEFAULT_OUTPUT_BUFFER_SIZE_IN_SAMPLES);
// &builder, int pwOutputBufferCount = prefs->GetInt(PREF_OUTPUT_BUFFER_COUNT, DEFAULT_OUTPUT_BUFFER_COUNT);
// SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
// SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(MAX_BUFFERS), params[1] = (spa_pod*) spa_pod_builder_add_object(
// SPA_PARAM_BUFFERS_size, SPA_POD_Int(SAMPLES_PER_BUFFER * SAMPLE_SIZE_BYTES * buffer->Channels()), &builder,
// SPA_PARAM_BUFFERS_stride, SPA_POD_Int(SAMPLE_SIZE_BYTES * audioInfo.channels)); SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(pwOutputBufferCount),
SPA_PARAM_BUFFERS_size, SPA_POD_Int(pwOutputBufferSize * SAMPLE_SIZE_BYTES * buffer->Channels()),
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(SAMPLE_SIZE_BYTES * audioInfo.channels));
pw_stream_flags streamFlags = (pw_stream_flags)( pw_stream_flags streamFlags = (pw_stream_flags)(
PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_AUTOCONNECT |
@ -386,7 +398,7 @@ bool PipeWireOut::StartPipeWire(IBuffer* buffer) {
this->deviceList.ResolveId(getDeviceId()), this->deviceList.ResolveId(getDeviceId()),
streamFlags, streamFlags,
params, params,
1); 2);
if (result == 0) { if (result == 0) {
pw_thread_loop_unlock(this->pwThreadLoop); pw_thread_loop_unlock(this->pwThreadLoop);
@ -417,6 +429,7 @@ cleanup:
OutputState PipeWireOut::Play(IBuffer *buffer, IBufferProvider *provider) { OutputState PipeWireOut::Play(IBuffer *buffer, IBufferProvider *provider) {
if (!this->initialized) { if (!this->initialized) {
std::unique_lock<std::recursive_mutex> lock(this->mutex); std::unique_lock<std::recursive_mutex> lock(this->mutex);
this->maxInternalBuffers = prefs->GetInt(PREF_OUTPUT_BUFFER_COUNT, DEFAULT_OUTPUT_BUFFER_COUNT);
if (!pipeWireInitialized) { if (!pipeWireInitialized) {
pw_init(nullptr, nullptr); pw_init(nullptr, nullptr);
pipeWireInitialized = true; pipeWireInitialized = true;
@ -443,7 +456,7 @@ OutputState PipeWireOut::Play(IBuffer *buffer, IBufferProvider *provider) {
{ {
std::unique_lock<std::recursive_mutex> lock(this->mutex); std::unique_lock<std::recursive_mutex> lock(this->mutex);
if (this->buffers.size() >= MAX_BUFFERS) { if (this->buffers.size() >= maxInternalBuffers) {
return OutputState::BufferFull; return OutputState::BufferFull;
} }
this->buffers.push_back(new InBufferContext(buffer, provider)); this->buffers.push_back(new InBufferContext(buffer, provider));

View File

@ -294,5 +294,6 @@ class PipeWireOut : public IOutput {
OutBufferContext outBufferContext; OutBufferContext outBufferContext;
long channelCount{0}; long channelCount{0};
long sampleRate{0}; long sampleRate{0};
size_t maxInternalBuffers{0};
DeviceList deviceList; DeviceList deviceList;
}; };