gfx-source-texture, source-mirror: Prevent recursion caused by Source Mirror

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2018-04-24 13:48:42 +02:00
parent 31342239bc
commit 49964e15be
4 changed files with 43 additions and 14 deletions

View file

@ -18,6 +18,7 @@
#include "gfx-source-texture.h" #include "gfx-source-texture.h"
gfx::source_texture::~source_texture() { gfx::source_texture::~source_texture() {
obs_source_remove_active_child(m_parent, m_source);
if (m_source) { if (m_source) {
obs_source_release(m_source); obs_source_release(m_source);
m_source = nullptr; m_source = nullptr;
@ -25,28 +26,39 @@ gfx::source_texture::~source_texture() {
m_rt = nullptr; m_rt = nullptr;
} }
gfx::source_texture::source_texture() { gfx::source_texture::source_texture(obs_source_t* parent) {
m_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE); m_rt = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
m_parent = parent;
} }
obs_source_t* gfx::source_texture::get_object() { obs_source_t* gfx::source_texture::get_object() {
return m_source; 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); m_source = obs_get_source_by_name(name);
if (!m_source) { if (!m_source) {
throw std::invalid_argument("No such 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; m_source = src;
if (!m_source) { if (!m_source) {
throw std::invalid_argument("No such 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<gs::texture> gfx::source_texture::render(size_t width, size_t height) { std::shared_ptr<gs::texture> gfx::source_texture::render(size_t width, size_t height) {

View file

@ -25,16 +25,18 @@
namespace gfx { namespace gfx {
class source_texture { class source_texture {
obs_source_t* m_source; obs_source_t* m_source;
obs_source_t* m_parent;
std::shared_ptr<gs::rendertarget> m_rt; std::shared_ptr<gs::rendertarget> m_rt;
source_texture(); source_texture(obs_source_t* parent);
public: public:
~source_texture(); ~source_texture();
source_texture(const char* name); source_texture(const char* name, obs_source_t* parent);
source_texture(std::string name); source_texture(std::string name, obs_source_t* parent);
source_texture(obs_source_t* src); source_texture(obs_source_t* src, obs_source_t* parent);
obs_source_t* get_object(); obs_source_t* get_object();
obs_source_t* get_parent();
std::shared_ptr<gs::texture> render(size_t width, size_t height); std::shared_ptr<gs::texture> render(size_t width, size_t height);
}; };

View file

@ -73,6 +73,7 @@ Source::MirrorAddon::MirrorAddon() {
osi.deactivate = deactivate; osi.deactivate = deactivate;
osi.video_tick = video_tick; osi.video_tick = video_tick;
osi.video_render = video_render; osi.video_render = video_render;
osi.enum_active_sources = enum_active_sources;
obs_register_source(&osi); obs_register_source(&osi);
} }
@ -197,6 +198,10 @@ void Source::MirrorAddon::video_render(void *p, gs_effect_t *ef) {
static_cast<Source::Mirror*>(p)->video_render(ef); static_cast<Source::Mirror*>(p)->video_render(ef);
} }
void Source::MirrorAddon::enum_active_sources(void *p, obs_source_enum_proc_t enum_callback, void *param) {
static_cast<Source::Mirror*>(p)->enum_active_sources(enum_callback, param);
}
Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src) { Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src) {
m_active = true; m_active = true;
m_source = src; m_source = src;
@ -213,17 +218,19 @@ Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src) {
Source::Mirror::~Mirror() {} Source::Mirror::~Mirror() {}
uint32_t Source::Mirror::get_width() { 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; 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 obs_source_get_width(m_mirrorSource->get_object());
}
return 1; return 1;
} }
uint32_t Source::Mirror::get_height() { uint32_t Source::Mirror::get_height() {
if (m_rescale && m_height > 0 && !m_keepOriginalSize) if (m_rescale && m_height > 0 && !m_keepOriginalSize)
return m_height; 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 obs_source_get_height(m_mirrorSource->get_object());
return 1; return 1;
} }
@ -233,7 +240,7 @@ void Source::Mirror::update(obs_data_t* data) {
const char* sourceName = obs_data_get_string(data, P_SOURCE); const char* sourceName = obs_data_get_string(data, P_SOURCE);
if (sourceName != m_mirrorName) { if (sourceName != m_mirrorName) {
try { try {
m_mirrorSource = std::make_unique<gfx::source_texture>(sourceName); m_mirrorSource = std::make_unique<gfx::source_texture>(sourceName, m_source);
m_mirrorName = sourceName; m_mirrorName = sourceName;
} catch (...) { } catch (...) {
} }
@ -312,8 +319,8 @@ void Source::Mirror::video_tick(float) {
m_mirrorName = obs_source_get_name(m_mirrorSource->get_object()); m_mirrorName = obs_source_get_name(m_mirrorSource->get_object());
} }
void Source::Mirror::video_render(gs_effect_t* ) { void Source::Mirror::video_render(gs_effect_t*) {
if ((m_width == 0) || (m_height == 0) || !m_mirrorSource) { if ((m_width == 0) || (m_height == 0) || !m_mirrorSource || (m_mirrorSource->get_object() == m_source)) {
return; return;
} }
@ -367,3 +374,9 @@ void Source::Mirror::video_render(gs_effect_t* ) {
obs_source_video_render(m_mirrorSource->get_object()); 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);
}
}

View file

@ -48,6 +48,7 @@ namespace Source {
static void deactivate(void *); static void deactivate(void *);
static void video_tick(void *, float); static void video_tick(void *, float);
static void video_render(void *, gs_effect_t *); 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 { class Mirror {
@ -77,5 +78,6 @@ namespace Source {
void deactivate(); void deactivate();
void video_tick(float); void video_tick(float);
void video_render(gs_effect_t*); void video_render(gs_effect_t*);
void enum_active_sources(obs_source_enum_proc_t enum_callback, void *param);
}; };
}; };