From d6c903a3bda4373a9e12080b0c6b197779ff8c91 Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Fri, 20 Mar 2020 23:59:42 +0100 Subject: [PATCH] source-mirror: Fix out-of-order playback of audio On highly parallel systems (> 4 Threads) audio had a chance of being played back out of order, causing it to jitter. This queue should help eliminate the issue entirely. Fixes #111 --- source/sources/source-mirror.cpp | 27 +++++++++++++++++---------- source/sources/source-mirror.hpp | 6 ++++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/source/sources/source-mirror.cpp b/source/sources/source-mirror.cpp index 71571ff3..b44128d7 100644 --- a/source/sources/source-mirror.cpp +++ b/source/sources/source-mirror.cpp @@ -55,18 +55,18 @@ source::mirror::mirror_audio_data::mirror_audio_data(const audio_data* audio, sp // Build a clone of a packet. audio_t* oad = obs_get_audio(); const audio_output_info* aoi = audio_output_get_info(oad); - osa.frames = audio->frames; - osa.timestamp = audio->timestamp; - osa.speakers = layout; - osa.format = aoi->format; - osa.samples_per_sec = aoi->samples_per_sec; + osa.frames = audio->frames; + osa.timestamp = audio->timestamp; + osa.speakers = layout; + osa.format = aoi->format; + osa.samples_per_sec = aoi->samples_per_sec; data.resize(MAX_AV_PLANES); for (size_t idx = 0; idx < MAX_AV_PLANES; idx++) { if (!audio->data[idx]) { osa.data[idx] = nullptr; continue; } - + data[idx].resize(audio->frames * get_audio_bytes_per_channel(osa.format)); memcpy(data[idx].data(), audio->data[idx], data[idx].size()); osa.data[idx] = data[idx].data(); @@ -249,16 +249,23 @@ void source::mirror::mirror_instance::on_audio(std::shared_ptr, co } } + { + std::unique_lock ul(_audio_queue_lock); + _audio_queue.emplace(audio, detected_layout); + } + // Create a clone of the audio data and push it to the thread pool. get_global_threadpool()->push( - std::bind(&source::mirror::mirror_instance::audio_output, this, std::placeholders::_1), - std::make_shared(audio, detected_layout)); + std::bind(&source::mirror::mirror_instance::audio_output, this, std::placeholders::_1), nullptr); } void source::mirror::mirror_instance::audio_output(std::shared_ptr data) { - std::shared_ptr mad = std::static_pointer_cast(data); - obs_source_output_audio(_self, &mad->osa); + std::unique_lock ul(_audio_queue_lock); + while (_audio_queue.size() > 0) { + obs_source_output_audio(_self, &((_audio_queue.front()).osa)); + _audio_queue.pop(); + } } std::shared_ptr mirror::mirror_factory::factory_instance; diff --git a/source/sources/source-mirror.hpp b/source/sources/source-mirror.hpp index 9adf06d4..af2c9d34 100644 --- a/source/sources/source-mirror.hpp +++ b/source/sources/source-mirror.hpp @@ -59,8 +59,10 @@ namespace source::mirror { std::shared_ptr _signal_audio; // Audio - bool _audio_enabled; - speaker_layout _audio_layout; + bool _audio_enabled; + speaker_layout _audio_layout; + std::mutex _audio_queue_lock; + std::queue _audio_queue; public: mirror_instance(obs_data_t* settings, obs_source_t* self);