From 49964e15be0f935cd4391e1341a41df435e1837f Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Tue, 24 Apr 2018 13:48:42 +0200 Subject: [PATCH] gfx-source-texture, source-mirror: Prevent recursion caused by Source Mirror --- source/gfx-source-texture.cpp | 20 ++++++++++++++++---- source/gfx-source-texture.h | 10 ++++++---- source/source-mirror.cpp | 25 +++++++++++++++++++------ source/source-mirror.h | 2 ++ 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/source/gfx-source-texture.cpp b/source/gfx-source-texture.cpp index b6109cd2..54420a39 100644 --- a/source/gfx-source-texture.cpp +++ b/source/gfx-source-texture.cpp @@ -18,6 +18,7 @@ #include "gfx-source-texture.h" gfx::source_texture::~source_texture() { + obs_source_remove_active_child(m_parent, m_source); if (m_source) { obs_source_release(m_source); m_source = nullptr; @@ -25,28 +26,39 @@ gfx::source_texture::~source_texture() { m_rt = nullptr; } -gfx::source_texture::source_texture() { +gfx::source_texture::source_texture(obs_source_t* parent) { m_rt = std::make_shared(GS_RGBA, GS_ZS_NONE); + m_parent = parent; } obs_source_t* gfx::source_texture::get_object() { return m_source; } -gfx::source_texture::source_texture(const char* name) : source_texture() { +obs_source_t* gfx::source_texture::get_parent() { + return m_parent; +} + +gfx::source_texture::source_texture(const char* name, obs_source_t* parent) : source_texture(parent) { m_source = obs_get_source_by_name(name); if (!m_source) { throw std::invalid_argument("No such source."); } + if (!obs_source_add_active_child(m_parent, m_source)) { + throw std::runtime_error("Recursion is not allowed."); + } } -gfx::source_texture::source_texture(std::string name) : source_texture(name.c_str()) {} +gfx::source_texture::source_texture(std::string name, obs_source_t* parent) : source_texture(name.c_str(), parent) {} -gfx::source_texture::source_texture(obs_source_t* src) : source_texture() { +gfx::source_texture::source_texture(obs_source_t* src, obs_source_t* parent) : source_texture(parent) { m_source = src; if (!m_source) { throw std::invalid_argument("No such source."); } + if (!obs_source_add_active_child(m_parent, m_source)) { + throw std::runtime_error("Recursion is not allowed."); + } } std::shared_ptr gfx::source_texture::render(size_t width, size_t height) { diff --git a/source/gfx-source-texture.h b/source/gfx-source-texture.h index 2511500c..bfdfcb8f 100644 --- a/source/gfx-source-texture.h +++ b/source/gfx-source-texture.h @@ -25,16 +25,18 @@ namespace gfx { class source_texture { obs_source_t* m_source; + obs_source_t* m_parent; std::shared_ptr m_rt; - source_texture(); + source_texture(obs_source_t* parent); public: ~source_texture(); - source_texture(const char* name); - source_texture(std::string name); - source_texture(obs_source_t* src); + source_texture(const char* name, obs_source_t* parent); + source_texture(std::string name, obs_source_t* parent); + source_texture(obs_source_t* src, obs_source_t* parent); obs_source_t* get_object(); + obs_source_t* get_parent(); std::shared_ptr render(size_t width, size_t height); }; diff --git a/source/source-mirror.cpp b/source/source-mirror.cpp index ce29a2f3..294fc97a 100644 --- a/source/source-mirror.cpp +++ b/source/source-mirror.cpp @@ -73,6 +73,7 @@ Source::MirrorAddon::MirrorAddon() { osi.deactivate = deactivate; osi.video_tick = video_tick; osi.video_render = video_render; + osi.enum_active_sources = enum_active_sources; obs_register_source(&osi); } @@ -197,6 +198,10 @@ void Source::MirrorAddon::video_render(void *p, gs_effect_t *ef) { static_cast(p)->video_render(ef); } +void Source::MirrorAddon::enum_active_sources(void *p, obs_source_enum_proc_t enum_callback, void *param) { + static_cast(p)->enum_active_sources(enum_callback, param); +} + Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src) { m_active = true; m_source = src; @@ -213,17 +218,19 @@ Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src) { Source::Mirror::~Mirror() {} uint32_t Source::Mirror::get_width() { - if (m_rescale && m_width > 0 && !m_keepOriginalSize) + if (m_rescale && m_width > 0 && !m_keepOriginalSize) { return m_width; - if (m_mirrorSource) + } + if (m_mirrorSource && (m_mirrorSource->get_object() != m_source)) { return obs_source_get_width(m_mirrorSource->get_object()); + } return 1; } uint32_t Source::Mirror::get_height() { if (m_rescale && m_height > 0 && !m_keepOriginalSize) return m_height; - if (m_mirrorSource) + if (m_mirrorSource && (m_mirrorSource->get_object() != m_source)) return obs_source_get_height(m_mirrorSource->get_object()); return 1; } @@ -233,7 +240,7 @@ void Source::Mirror::update(obs_data_t* data) { const char* sourceName = obs_data_get_string(data, P_SOURCE); if (sourceName != m_mirrorName) { try { - m_mirrorSource = std::make_unique(sourceName); + m_mirrorSource = std::make_unique(sourceName, m_source); m_mirrorName = sourceName; } catch (...) { } @@ -312,8 +319,8 @@ void Source::Mirror::video_tick(float) { m_mirrorName = obs_source_get_name(m_mirrorSource->get_object()); } -void Source::Mirror::video_render(gs_effect_t* ) { - if ((m_width == 0) || (m_height == 0) || !m_mirrorSource) { +void Source::Mirror::video_render(gs_effect_t*) { + if ((m_width == 0) || (m_height == 0) || !m_mirrorSource || (m_mirrorSource->get_object() == m_source)) { return; } @@ -367,3 +374,9 @@ void Source::Mirror::video_render(gs_effect_t* ) { obs_source_video_render(m_mirrorSource->get_object()); } } + +void Source::Mirror::enum_active_sources(obs_source_enum_proc_t enum_callback, void *param) { + if (m_mirrorSource) { + enum_callback(m_source, m_mirrorSource->get_object(), param); + } +} diff --git a/source/source-mirror.h b/source/source-mirror.h index 98a8305b..3421be51 100644 --- a/source/source-mirror.h +++ b/source/source-mirror.h @@ -48,6 +48,7 @@ namespace Source { static void deactivate(void *); static void video_tick(void *, float); static void video_render(void *, gs_effect_t *); + static void enum_active_sources(void *data, obs_source_enum_proc_t enum_callback, void *param); }; class Mirror { @@ -77,5 +78,6 @@ namespace Source { void deactivate(); void video_tick(float); void video_render(gs_effect_t*); + void enum_active_sources(obs_source_enum_proc_t enum_callback, void *param); }; };