From 8fb7d193f51aaf2b1cd526ef2b8501a4f8cfe0dd Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Tue, 2 Apr 2019 19:12:44 +0200 Subject: [PATCH] obs-source: Add audio capture and selectively listen to events Audio capture previously needed an additional class, however there is no need for this if this can be done together with the actual obs::source object. So obs::source now has a new audio_data event that can be listened to, which handles capturing audio data if requested. Additionally all other events are now selectively listened to, instead of permanently listening to them. This should drastically reduce the overhead of using obs::source. --- source/obs/obs-source.cpp | 142 +++++++++++++++++++------------------- source/obs/obs-source.hpp | 37 ++++++---- 2 files changed, 94 insertions(+), 85 deletions(-) diff --git a/source/obs/obs-source.cpp b/source/obs/obs-source.cpp index e0aeb8d9..1a76680e 100644 --- a/source/obs/obs-source.cpp +++ b/source/obs/obs-source.cpp @@ -286,6 +286,16 @@ void obs::source::handle_audio_mixers(void* p, calldata_t* calldata) calldata_set_int(calldata, "mixers", mixers); } +void obs::source::handle_audio_data(void* p, obs_source_t* source, const audio_data* audio, bool muted) +{ + obs::source* self = reinterpret_cast(p); + if (!self->events.audio_data) { + return; + } + + self->events.audio_data(self, audio, muted); +} + void obs::source::handle_filter_add(void* p, calldata_t* calldata) { obs::source* self = reinterpret_cast(p); @@ -352,83 +362,73 @@ void obs::source::handle_transition_stop(void* p, calldata_t*) self->events.transition_stop(self); } -void obs::source::connect_signals() -{ - auto sh = obs_source_get_signal_handler(this->self); - if (sh) { -#define auto_signal_c(SIGNAL) signal_handler_connect(sh, "" #SIGNAL, obs::source::handle_##SIGNAL, this); - auto_signal_c(destroy); - auto_signal_c(remove); - auto_signal_c(save); - auto_signal_c(load); - auto_signal_c(activate); - auto_signal_c(deactivate); - auto_signal_c(show); - auto_signal_c(hide); - auto_signal_c(mute); - auto_signal_c(push_to_mute_changed); - auto_signal_c(push_to_mute_delay); - auto_signal_c(push_to_talk_changed); - auto_signal_c(push_to_talk_delay); - auto_signal_c(enable); - auto_signal_c(rename); - auto_signal_c(volume); - auto_signal_c(update_properties); - auto_signal_c(update_flags); - auto_signal_c(audio_sync); - auto_signal_c(audio_mixers); - auto_signal_c(filter_add); - auto_signal_c(filter_remove); - auto_signal_c(reorder_filters); - auto_signal_c(transition_start); - auto_signal_c(transition_video_stop); - auto_signal_c(transition_stop); -#undef auto_signal_c - } -} - obs::source::~source() { - if (this->self) { - auto sh = obs_source_get_signal_handler(this->self); - if (sh) { -#define auto_signal_dc(SIGNAL) signal_handler_disconnect(sh, "" #SIGNAL, obs::source::handle_##SIGNAL, this); - auto_signal_dc(destroy); - auto_signal_dc(remove); - auto_signal_dc(save); - auto_signal_dc(load); - auto_signal_dc(activate); - auto_signal_dc(deactivate); - auto_signal_dc(show); - auto_signal_dc(hide); - auto_signal_dc(mute); - auto_signal_dc(push_to_mute_changed); - auto_signal_dc(push_to_mute_delay); - auto_signal_dc(push_to_talk_changed); - auto_signal_dc(push_to_talk_delay); - auto_signal_dc(enable); - auto_signal_dc(rename); - auto_signal_dc(volume); - auto_signal_dc(update_properties); - auto_signal_dc(update_flags); - auto_signal_dc(audio_sync); - auto_signal_dc(audio_mixers); - auto_signal_dc(filter_add); - auto_signal_dc(filter_remove); - auto_signal_dc(reorder_filters); - auto_signal_dc(transition_start); - auto_signal_dc(transition_video_stop); - auto_signal_dc(transition_stop); -#undef auto_signal_dc - } - } if (this->track_ownership && this->self) { obs_source_release(this->self); } this->self = nullptr; } -obs::source::source(std::string name, bool track_ownership, bool add_reference) +obs::source::source() +{ +#ifdef auto_signal_c +#undef auto_signal_c +#endif +#define auto_signal_c(SIGNAL) \ + { \ + this->events.##SIGNAL.set_listen_callback([this] { \ + auto sh = obs_source_get_signal_handler(this->self); \ + if (sh) { \ + signal_handler_connect(sh, "" #SIGNAL, obs::source::handle_##SIGNAL, this); \ + } \ + }); \ + this->events.##SIGNAL.set_silence_callback([this] { \ + auto sh = obs_source_get_signal_handler(this->self); \ + if (sh) { \ + signal_handler_disconnect(sh, "" #SIGNAL, obs::source::handle_##SIGNAL, this); \ + } \ + }); \ + } + auto_signal_c(destroy); + auto_signal_c(remove); + auto_signal_c(save); + auto_signal_c(load); + auto_signal_c(activate); + auto_signal_c(deactivate); + auto_signal_c(show); + auto_signal_c(hide); + auto_signal_c(mute); + auto_signal_c(push_to_mute_changed); + auto_signal_c(push_to_mute_delay); + auto_signal_c(push_to_talk_changed); + auto_signal_c(push_to_talk_delay); + auto_signal_c(enable); + auto_signal_c(rename); + auto_signal_c(volume); + auto_signal_c(update_properties); + auto_signal_c(update_flags); + auto_signal_c(audio_sync); + auto_signal_c(audio_mixers); + auto_signal_c(filter_add); + auto_signal_c(filter_remove); + auto_signal_c(reorder_filters); + auto_signal_c(transition_start); + auto_signal_c(transition_video_stop); + auto_signal_c(transition_stop); +#undef auto_signal_c + + // libOBS unfortunately does not use the event system for audio data callbacks, which is kind of odd as most other + // things do. So instead we'll have to manually deal with it for now. + { + this->events.audio_data.set_listen_callback( + [this] { obs_source_add_audio_capture_callback(this->self, obs::source::handle_audio_data, this); }); + this->events.audio_data.set_silence_callback( + [this] { obs_source_remove_audio_capture_callback(this->self, obs::source::handle_audio_data, this); }); + } +} + +obs::source::source(std::string name, bool track_ownership, bool add_reference) : source() { this->self = obs_get_source_by_name(name.c_str()); if (!this->self) { @@ -439,10 +439,9 @@ obs::source::source(std::string name, bool track_ownership, bool add_reference) if (!add_reference) { obs_source_release(this->self); } - connect_signals(); } -obs::source::source(obs_source_t* source, bool track_ownership, bool add_reference) +obs::source::source(obs_source_t* source, bool track_ownership, bool add_reference) : source() { this->self = source; if (!this->self) { @@ -453,7 +452,6 @@ obs::source::source(obs_source_t* source, bool track_ownership, bool add_referen if (add_reference) { obs_source_addref(this->self); } - connect_signals(); } obs::source::source(source const& other) diff --git a/source/obs/obs-source.hpp b/source/obs/obs-source.hpp index cb1f4e02..db57a5de 100644 --- a/source/obs/obs-source.hpp +++ b/source/obs/obs-source.hpp @@ -60,6 +60,7 @@ namespace obs { static void handle_volume(void* p, calldata_t* calldata); static void handle_audio_sync(void* p, calldata_t* calldata); static void handle_audio_mixers(void* p, calldata_t* calldata); + static void handle_audio_data(void* p, obs_source_t* source, const audio_data* audio, bool muted); static void handle_filter_add(void* p, calldata_t* calldata); static void handle_filter_remove(void* p, calldata_t* calldata); static void handle_reorder_filters(void* p, calldata_t* calldata); @@ -67,12 +68,11 @@ namespace obs { static void handle_transition_video_stop(void* p, calldata_t* calldata); static void handle_transition_stop(void* p, calldata_t* calldata); - private: - void connect_signals(); - public: virtual ~source(); + source(); + source(std::string name, bool track_ownership = true, bool add_reference = true); source(obs_source_t* source, bool track_ownership = true, bool add_reference = false); @@ -102,36 +102,47 @@ namespace obs { public: // Events struct { + // Destroy and Remove util::event destroy; util::event remove; + + // Saving, Loading and Update util::event save; util::event load; + util::event update_properties; + + // Activate, Deactivate util::event activate; util::event deactivate; + + // Show Hide util::event show; util::event hide; - util::event enable; + // Other + util::event enable; + util::event rename; + util::event update_flags; + // Hotkeys (PtM, PtT) util::event push_to_mute_changed; util::event push_to_mute_delay; util::event push_to_talk_changed; util::event push_to_talk_delay; - util::event rename; - - util::event update_properties; - util::event update_flags; - - util::event mute; - util::event volume; - util::event audio_sync; - util::event audio_mixers; + // Audio + util::event mute; + util::event volume; + util::event audio_sync; + util::event audio_mixers; + util::event audio_data; + // Filters util::event filter_add; util::event filter_remove; util::event reorder_filters; + // Transition util::event transition_start; util::event transition_video_stop; util::event transition_stop;