diff --git a/source/filter-blur.cpp b/source/filter-blur.cpp index 829f96c7..953dc3d2 100644 --- a/source/filter-blur.cpp +++ b/source/filter-blur.cpp @@ -74,13 +74,6 @@ #define P_MASK_MULTIPLIER "Filter.Blur.Mask.Multiplier" #define P_COLORFORMAT "Filter.Blur.ColorFormat" -// Initializer & Finalizer -INITIALIZER(filterBlurFactoryInitializer) -{ - initializerFunctions.push_back([] { filter::blur::blur_factory::initialize(); }); - finalizerFunctions.push_back([] { filter::blur::blur_factory::finalize(); }); -} - enum ColorFormat : uint64_t { // ToDo: Refactor into full class. RGB, YUV, // 701 @@ -88,7 +81,344 @@ enum ColorFormat : uint64_t { // ToDo: Refactor into full class. static uint8_t const max_kernel_size = 25; -bool filter::blur::blur_instance::apply_shared_param(gs_texture_t* input, float texelX, float texelY) +// Initializer & Finalizer +INITIALIZER(filterBlurFactoryInitializer) +{ + initializerFunctions.push_back([] { filter::blur::factory::initialize(); }); + finalizerFunctions.push_back([] { filter::blur::factory::finalize(); }); +} + +static std::shared_ptr factory_instance = nullptr; + +void filter::blur::factory::initialize() +{ + factory_instance = std::make_shared(); +} + +void filter::blur::factory::finalize() +{ + factory_instance.reset(); +} + +std::shared_ptr filter::blur::factory::get() +{ + return factory_instance; +} + +filter::blur::factory::factory() +{ + memset(&source_info, 0, sizeof(obs_source_info)); + source_info.id = "obs-stream-effects-filter-blur"; + source_info.type = OBS_SOURCE_TYPE_FILTER; + source_info.output_flags = OBS_SOURCE_VIDEO; + source_info.get_name = get_name; + source_info.get_defaults = get_defaults; + source_info.get_properties = get_properties; + + source_info.create = create; + source_info.destroy = destroy; + source_info.update = update; + source_info.activate = activate; + source_info.deactivate = deactivate; + source_info.video_tick = video_tick; + source_info.video_render = video_render; + + obs_register_source(&source_info); + + auto osi = obs_get_signal_handler(); + signal_handler_connect(osi, "source_create", scene_create_handler, this); + signal_handler_connect(osi, "source_destroy", scene_destroy_handler, this); +} + +filter::blur::factory::~factory() +{ + auto osi = obs_get_signal_handler(); + signal_handler_disconnect(osi, "source_create", scene_create_handler, this); + signal_handler_disconnect(osi, "source_destroy", scene_destroy_handler, this); +} + +void filter::blur::factory::on_list_fill() +{ + obs_enter_graphics(); + + { + char* file = obs_module_file("effects/blur.effect"); + try { + blur_effect = std::make_shared(file); + } catch (std::runtime_error ex) { + P_LOG_ERROR(" Loading effect '%s' failed with error(s): %s", file, ex.what()); + } + bfree(file); + } + { + char* file = obs_module_file("effects/color-conversion.effect"); + try { + color_converter_effect = std::make_shared(file); + } catch (std::runtime_error ex) { + P_LOG_ERROR(" Loading effect '%s' failed with error(s): %s", file, ex.what()); + } + bfree(file); + } + { + char* file = obs_module_file("effects/mask.effect"); + try { + mask_effect = std::make_shared(file); + } catch (std::runtime_error ex) { + P_LOG_ERROR(" Loading effect '%s' failed with error(s): %s", file, ex.what()); + } + bfree(file); + } + + generate_kernel_textures(); + obs_leave_graphics(); +} + +void filter::blur::factory::on_list_empty() +{ + obs_enter_graphics(); + blur_effect.reset(); + kernels.clear(); + color_converter_effect.reset(); + mask_effect.reset(); + obs_leave_graphics(); +} + +void filter::blur::factory::generate_gaussian_kernels() +{ + // 2D texture, horizontal is value, vertical is kernel size. + size_t size_power_of_two = size_t(pow(2, util::math::get_power_of_two_exponent_ceil(max_kernel_size))); + + std::vector texture_data(size_power_of_two * size_power_of_two); + std::vector math_data(size_power_of_two); + std::shared_ptr> kernel_data; + + for (size_t width = 1; width <= max_kernel_size; width++) { + size_t v = (width - 1) * size_power_of_two; + kernel_data = std::make_shared>(size_power_of_two); + + // Calculate and normalize + float_t sum = 0; + for (size_t p = 0; p <= width; p++) { + math_data[p] = float_t(Gaussian1D(double_t(p), double_t(width))); + sum += math_data[p] * (p > 0 ? 2 : 1); + } + + // Normalize to Texture Buffer + double_t inverse_sum = 1.0 / sum; + for (size_t p = 0; p <= width; p++) { + texture_data[v + p] = float_t(math_data[p] * inverse_sum); + kernel_data->at(p) = texture_data[v + p]; + } + + gaussian_kernels.insert({uint8_t(width), kernel_data}); + } + + // Create Texture + try { + auto texture_buffer = reinterpret_cast(texture_data.data()); + auto unsafe_buffer = const_cast(&texture_buffer); + + kernels.insert_or_assign(filter::blur::type::Gaussian, + std::make_shared(uint32_t(size_power_of_two), uint32_t(size_power_of_two), + GS_R32F, 1, unsafe_buffer, gs::texture::flags::None)); + } catch (std::runtime_error ex) { + P_LOG_ERROR(" Failed to create gaussian kernel texture."); + } +} + +void filter::blur::factory::generate_kernel_textures() +{ + generate_gaussian_kernels(); +} + +void* filter::blur::factory::create(obs_data_t* data, obs_source_t* parent) +{ + if (get()->sources.empty()) { + get()->on_list_fill(); + } + filter::blur::instance* ptr = new filter::blur::instance(data, parent); + get()->sources.push_back(ptr); + return ptr; +} + +void filter::blur::factory::destroy(void* inptr) +{ + filter::blur::instance* ptr = reinterpret_cast(inptr); + get()->sources.remove(ptr); + if (get()->sources.empty()) { + get()->on_list_empty(); + } + delete ptr; +} + +void filter::blur::factory::get_defaults(obs_data_t* data) +{ + obs_data_set_default_int(data, P_TYPE, filter::blur::type::Box); + obs_data_set_default_int(data, P_SIZE, 5); + + // Bilateral Only + obs_data_set_default_double(data, P_BILATERAL_SMOOTHING, 50.0); + obs_data_set_default_double(data, P_BILATERAL_SHARPNESS, 90.0); + + // Masking + obs_data_set_default_bool(data, P_MASK, false); + obs_data_set_default_int(data, P_MASK_TYPE, mask_type::Region); + obs_data_set_default_double(data, P_MASK_REGION_LEFT, 0.0); + obs_data_set_default_double(data, P_MASK_REGION_RIGHT, 0.0); + obs_data_set_default_double(data, P_MASK_REGION_TOP, 0.0); + obs_data_set_default_double(data, P_MASK_REGION_BOTTOM, 0.0); + obs_data_set_default_double(data, P_MASK_REGION_FEATHER, 0.0); + obs_data_set_default_double(data, P_MASK_REGION_FEATHER_SHIFT, 0.0); + obs_data_set_default_bool(data, P_MASK_REGION_INVERT, false); + char* default_file = obs_module_file("white.png"); + obs_data_set_default_string(data, P_MASK_IMAGE, default_file); + bfree(default_file); + obs_data_set_default_string(data, P_MASK_SOURCE, ""); + obs_data_set_default_int(data, P_MASK_COLOR, 0xFFFFFFFFull); + obs_data_set_default_double(data, P_MASK_MULTIPLIER, 1.0); + + // Directional Blur + obs_data_set_default_bool(data, P_DIRECTIONAL, false); + obs_data_set_default_double(data, P_DIRECTIONAL_ANGLE, 0.0); + + // Scaling + obs_data_set_default_bool(data, P_STEPSCALE, false); + obs_data_set_default_double(data, P_STEPSCALE_X, 100.0); + obs_data_set_default_double(data, P_STEPSCALE_Y, 100.0); + + // Advanced + obs_data_set_default_bool(data, S_ADVANCED, false); + obs_data_set_default_int(data, P_COLORFORMAT, ColorFormat::RGB); +} + +obs_properties_t* filter::blur::factory::get_properties(void* inptr) +{ + return reinterpret_cast(inptr)->get_properties(); +} + +void filter::blur::factory::update(void* inptr, obs_data_t* settings) +{ + reinterpret_cast(inptr)->update(settings); +} + +const char* filter::blur::factory::get_name(void*) +{ + return P_TRANSLATE(SOURCE_NAME); +} + +uint32_t filter::blur::factory::get_width(void* inptr) +{ + return reinterpret_cast(inptr)->get_width(); +} + +uint32_t filter::blur::factory::get_height(void* inptr) +{ + return reinterpret_cast(inptr)->get_height(); +} + +void filter::blur::factory::activate(void* inptr) +{ + reinterpret_cast(inptr)->activate(); +} + +void filter::blur::factory::deactivate(void* inptr) +{ + reinterpret_cast(inptr)->deactivate(); +} + +void filter::blur::factory::video_tick(void* inptr, float delta) +{ + reinterpret_cast(inptr)->video_tick(delta); +} + +void filter::blur::factory::video_render(void* inptr, gs_effect_t* effect) +{ + reinterpret_cast(inptr)->video_render(effect); +} + +void filter::blur::factory::scene_create_handler(void* ptr, calldata_t* data) +{ + filter::blur::factory* self = reinterpret_cast(ptr); + obs_source_t* source = nullptr; + calldata_get_ptr(data, "source", &source); + obs_scene_t* scene = obs_scene_from_source(source); + if (scene) { + self->scenes.insert_or_assign(std::string(obs_source_get_name(source)), scene); + } +} + +void filter::blur::factory::scene_destroy_handler(void* ptr, calldata_t* data) +{ + filter::blur::factory* self = reinterpret_cast(ptr); + obs_source_t* source = nullptr; + calldata_get_ptr(data, "source", &source); + obs_scene_t* scene = obs_scene_from_source(source); + if (scene) { + self->scenes.erase(std::string(obs_source_get_name(source))); + } +} + +std::shared_ptr filter::blur::factory::get_effect(filter::blur::type) +{ + return blur_effect; +} + +std::string filter::blur::factory::get_technique(filter::blur::type type) +{ + switch (type) { + case type::Box: + return "Box"; + case type::Gaussian: + return "Gaussian"; + case type::Bilateral: + return "Bilateral"; + case type::BoxLinear: + return "BoxLinear"; + case type::GaussianLinear: + return "GaussianLinear"; + } + return ""; +} + +std::shared_ptr filter::blur::factory::get_color_converter_effect() +{ + return color_converter_effect; +} + +std::shared_ptr filter::blur::factory::get_mask_effect() +{ + return mask_effect; +} + +std::shared_ptr filter::blur::factory::get_kernel(filter::blur::type type) +{ + return kernels.at(type); +} + +std::shared_ptr> filter::blur::factory::get_gaussian_kernel(uint8_t size) +{ + return gaussian_kernels.at(size); +} + +obs_scene_t* filter::blur::factory::get_scene(std::string name) +{ + auto kv = scenes.find(name); + if (kv != scenes.end()) { + return kv->second; + } + return nullptr; +} + +void filter::blur::factory::enum_scenes(std::function fnc) +{ + for (auto kv : scenes) { + if (!fnc(kv.second)) { + break; + } + } +} + +bool filter::blur::instance::apply_shared_param(gs_texture_t* input, float texelX, float texelY) { bool result = true; @@ -113,7 +443,7 @@ bool filter::blur::blur_instance::apply_shared_param(gs_texture_t* input, float return result; } -bool filter::blur::blur_instance::apply_bilateral_param() +bool filter::blur::instance::apply_bilateral_param() { if (type != type::Bilateral) return false; @@ -129,9 +459,9 @@ bool filter::blur::blur_instance::apply_bilateral_param() return true; } -bool filter::blur::blur_instance::apply_gaussian_param(uint8_t width) +bool filter::blur::instance::apply_gaussian_param(uint8_t width) { - auto kernel = filter::blur::blur_factory::get()->get_gaussian_kernel(width); + auto kernel = filter::blur::factory::get()->get_gaussian_kernel(width); if (blur_effect->has_parameter("kernel")) { blur_effect->get_parameter("kernel").set_float_array(&(kernel->front()), kernel->size()); @@ -140,7 +470,7 @@ bool filter::blur::blur_instance::apply_gaussian_param(uint8_t width) return true; } -bool filter::blur::blur_instance::apply_mask_parameters(std::shared_ptr effect, +bool filter::blur::instance::apply_mask_parameters(std::shared_ptr effect, gs_texture_t* original_texture, gs_texture_t* blurred_texture) { if (effect->has_parameter("image_orig")) { @@ -205,7 +535,7 @@ bool filter::blur::blur_instance::apply_mask_parameters(std::shared_ptr(delta) > std::chrono::milliseconds(200); } -filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* parent) +filter::blur::instance::instance(obs_data_t* settings, obs_source_t* parent) { m_source = parent; @@ -273,18 +603,18 @@ filter::blur::blur_instance::blur_instance(obs_data_t* settings, obs_source_t* p } // Get initial Blur effect. - blur_effect = filter::blur::blur_factory::get()->get_effect(filter::blur::type::Box); + blur_effect = filter::blur::factory::get()->get_effect(filter::blur::type::Box); update(settings); } -filter::blur::blur_instance::~blur_instance() +filter::blur::instance::~instance() { this->rt_primary.reset(); this->rt_secondary.reset(); } -obs_properties_t* filter::blur::blur_instance::get_properties() +obs_properties_t* filter::blur::instance::get_properties() { obs_properties_t* pr = obs_properties_create(); obs_property_t* p = NULL; @@ -352,9 +682,9 @@ obs_properties_t* filter::blur::blur_instance::get_properties() return true; }, p); - blur_factory::get()->enum_scenes([this, p](obs_scene_t* scene) { + factory::get()->enum_scenes([this, p](obs_scene_t* scene) { struct data { - blur_instance* self; + instance* self; obs_property_t* prop; std::string parent_name; }; @@ -404,11 +734,11 @@ obs_properties_t* filter::blur::blur_instance::get_properties() return pr; } -void filter::blur::blur_instance::update(obs_data_t* settings) +void filter::blur::instance::update(obs_data_t* settings) { type = (blur::type)obs_data_get_int(settings, P_TYPE); - blur_effect = blur_factory::get()->get_effect(type); - blur_technique = blur_factory::get()->get_technique(type); + blur_effect = factory::get()->get_effect(type); + blur_technique = factory::get()->get_technique(type); size = (uint64_t)obs_data_get_int(settings, P_SIZE); // bilateral blur @@ -463,21 +793,21 @@ void filter::blur::blur_instance::update(obs_data_t* settings) } } -uint32_t filter::blur::blur_instance::get_width() +uint32_t filter::blur::instance::get_width() { return uint32_t(0); } -uint32_t filter::blur::blur_instance::get_height() +uint32_t filter::blur::instance::get_height() { return uint32_t(0); } -void filter::blur::blur_instance::activate() {} +void filter::blur::instance::activate() {} -void filter::blur::blur_instance::deactivate() {} +void filter::blur::instance::deactivate() {} -void filter::blur::blur_instance::video_tick(float) +void filter::blur::instance::video_tick(float) { if (mask.type == mask_type::Image) { if (mask.image.path_old != mask.image.path) { @@ -503,7 +833,7 @@ void filter::blur::blur_instance::video_tick(float) } } -void filter::blur::blur_instance::video_render(gs_effect_t* effect) +void filter::blur::instance::video_render(gs_effect_t* effect) { obs_source_t* parent = obs_filter_get_parent(this->m_source); obs_source_t* target = obs_filter_get_target(this->m_source); @@ -514,7 +844,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect) bool failed = false; - std::shared_ptr colorConversionEffect = blur_factory::get()->get_color_converter_effect(); + std::shared_ptr colorConversionEffect = factory::get()->get_color_converter_effect(); // Verify that we can actually run first. if (!target || !parent || !this->m_source) { @@ -802,7 +1132,7 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect) this->mask.source.texture = this->mask.source.source_texture->render(source_width, source_height); } - std::shared_ptr mask_effect = blur_factory::get()->get_mask_effect(); + std::shared_ptr mask_effect = factory::get()->get_mask_effect(); apply_mask_parameters(mask_effect, tex_source->get_object(), tex_intermediate->get_object()); try { @@ -874,333 +1204,3 @@ void filter::blur::blur_instance::video_render(gs_effect_t* effect) return; } } - -filter::blur::blur_factory::blur_factory() -{ - memset(&source_info, 0, sizeof(obs_source_info)); - source_info.id = "obs-stream-effects-filter-blur"; - source_info.type = OBS_SOURCE_TYPE_FILTER; - source_info.output_flags = OBS_SOURCE_VIDEO; - source_info.get_name = get_name; - source_info.get_defaults = get_defaults; - source_info.get_properties = get_properties; - - source_info.create = create; - source_info.destroy = destroy; - source_info.update = update; - source_info.activate = activate; - source_info.deactivate = deactivate; - source_info.video_tick = video_tick; - source_info.video_render = video_render; - - obs_register_source(&source_info); - - auto osi = obs_get_signal_handler(); - signal_handler_connect(osi, "source_create", scene_create_handler, this); - signal_handler_connect(osi, "source_destroy", scene_destroy_handler, this); -} - -filter::blur::blur_factory::~blur_factory() -{ - auto osi = obs_get_signal_handler(); - signal_handler_disconnect(osi, "source_create", scene_create_handler, this); - signal_handler_disconnect(osi, "source_destroy", scene_destroy_handler, this); -} - -void filter::blur::blur_factory::on_list_fill() -{ - obs_enter_graphics(); - - { - char* file = obs_module_file("effects/blur.effect"); - try { - blur_effect = std::make_shared(file); - } catch (std::runtime_error ex) { - P_LOG_ERROR(" Loading effect '%s' failed with error(s): %s", file, ex.what()); - } - bfree(file); - } - { - char* file = obs_module_file("effects/color-conversion.effect"); - try { - color_converter_effect = std::make_shared(file); - } catch (std::runtime_error ex) { - P_LOG_ERROR(" Loading effect '%s' failed with error(s): %s", file, ex.what()); - } - bfree(file); - } - { - char* file = obs_module_file("effects/mask.effect"); - try { - mask_effect = std::make_shared(file); - } catch (std::runtime_error ex) { - P_LOG_ERROR(" Loading effect '%s' failed with error(s): %s", file, ex.what()); - } - bfree(file); - } - - generate_kernel_textures(); - obs_leave_graphics(); -} - -void filter::blur::blur_factory::on_list_empty() -{ - obs_enter_graphics(); - blur_effect.reset(); - kernels.clear(); - color_converter_effect.reset(); - mask_effect.reset(); - obs_leave_graphics(); -} - -void filter::blur::blur_factory::generate_gaussian_kernels() -{ - // 2D texture, horizontal is value, vertical is kernel size. - size_t size_power_of_two = size_t(pow(2, util::math::get_power_of_two_exponent_ceil(max_kernel_size))); - - std::vector texture_data(size_power_of_two * size_power_of_two); - std::vector math_data(size_power_of_two); - std::shared_ptr> kernel_data; - - for (size_t width = 1; width <= max_kernel_size; width++) { - size_t v = (width - 1) * size_power_of_two; - kernel_data = std::make_shared>(size_power_of_two); - - // Calculate and normalize - float_t sum = 0; - for (size_t p = 0; p <= width; p++) { - math_data[p] = float_t(Gaussian1D(double_t(p), double_t(width))); - sum += math_data[p] * (p > 0 ? 2 : 1); - } - - // Normalize to Texture Buffer - double_t inverse_sum = 1.0 / sum; - for (size_t p = 0; p <= width; p++) { - texture_data[v + p] = float_t(math_data[p] * inverse_sum); - kernel_data->at(p) = texture_data[v + p]; - } - - gaussian_kernels.insert({uint8_t(width), kernel_data}); - } - - // Create Texture - try { - auto texture_buffer = reinterpret_cast(texture_data.data()); - auto unsafe_buffer = const_cast(&texture_buffer); - - kernels.insert_or_assign(filter::blur::type::Gaussian, - std::make_shared(uint32_t(size_power_of_two), uint32_t(size_power_of_two), - GS_R32F, 1, unsafe_buffer, gs::texture::flags::None)); - } catch (std::runtime_error ex) { - P_LOG_ERROR(" Failed to create gaussian kernel texture."); - } -} - -void filter::blur::blur_factory::generate_kernel_textures() -{ - generate_gaussian_kernels(); -} - -void* filter::blur::blur_factory::create(obs_data_t* data, obs_source_t* parent) -{ - if (get()->sources.empty()) { - get()->on_list_fill(); - } - filter::blur::blur_instance* ptr = new filter::blur::blur_instance(data, parent); - get()->sources.push_back(ptr); - return ptr; -} - -void filter::blur::blur_factory::destroy(void* inptr) -{ - filter::blur::blur_instance* ptr = reinterpret_cast(inptr); - get()->sources.remove(ptr); - if (get()->sources.empty()) { - get()->on_list_empty(); - } - delete ptr; -} - -void filter::blur::blur_factory::get_defaults(obs_data_t* data) -{ - obs_data_set_default_int(data, P_TYPE, filter::blur::type::Box); - obs_data_set_default_int(data, P_SIZE, 5); - - // Bilateral Only - obs_data_set_default_double(data, P_BILATERAL_SMOOTHING, 50.0); - obs_data_set_default_double(data, P_BILATERAL_SHARPNESS, 90.0); - - // Masking - obs_data_set_default_bool(data, P_MASK, false); - obs_data_set_default_int(data, P_MASK_TYPE, mask_type::Region); - obs_data_set_default_double(data, P_MASK_REGION_LEFT, 0.0); - obs_data_set_default_double(data, P_MASK_REGION_RIGHT, 0.0); - obs_data_set_default_double(data, P_MASK_REGION_TOP, 0.0); - obs_data_set_default_double(data, P_MASK_REGION_BOTTOM, 0.0); - obs_data_set_default_double(data, P_MASK_REGION_FEATHER, 0.0); - obs_data_set_default_double(data, P_MASK_REGION_FEATHER_SHIFT, 0.0); - obs_data_set_default_bool(data, P_MASK_REGION_INVERT, false); - char* default_file = obs_module_file("white.png"); - obs_data_set_default_string(data, P_MASK_IMAGE, default_file); - bfree(default_file); - obs_data_set_default_string(data, P_MASK_SOURCE, ""); - obs_data_set_default_int(data, P_MASK_COLOR, 0xFFFFFFFFull); - obs_data_set_default_double(data, P_MASK_MULTIPLIER, 1.0); - - // Directional Blur - obs_data_set_default_bool(data, P_DIRECTIONAL, false); - obs_data_set_default_double(data, P_DIRECTIONAL_ANGLE, 0.0); - - // Scaling - obs_data_set_default_bool(data, P_STEPSCALE, false); - obs_data_set_default_double(data, P_STEPSCALE_X, 100.0); - obs_data_set_default_double(data, P_STEPSCALE_Y, 100.0); - - // Advanced - obs_data_set_default_bool(data, S_ADVANCED, false); - obs_data_set_default_int(data, P_COLORFORMAT, ColorFormat::RGB); -} - -obs_properties_t* filter::blur::blur_factory::get_properties(void* inptr) -{ - return reinterpret_cast(inptr)->get_properties(); -} - -void filter::blur::blur_factory::update(void* inptr, obs_data_t* settings) -{ - reinterpret_cast(inptr)->update(settings); -} - -const char* filter::blur::blur_factory::get_name(void*) -{ - return P_TRANSLATE(SOURCE_NAME); -} - -uint32_t filter::blur::blur_factory::get_width(void* inptr) -{ - return reinterpret_cast(inptr)->get_width(); -} - -uint32_t filter::blur::blur_factory::get_height(void* inptr) -{ - return reinterpret_cast(inptr)->get_height(); -} - -void filter::blur::blur_factory::activate(void* inptr) -{ - reinterpret_cast(inptr)->activate(); -} - -void filter::blur::blur_factory::deactivate(void* inptr) -{ - reinterpret_cast(inptr)->deactivate(); -} - -void filter::blur::blur_factory::video_tick(void* inptr, float delta) -{ - reinterpret_cast(inptr)->video_tick(delta); -} - -void filter::blur::blur_factory::video_render(void* inptr, gs_effect_t* effect) -{ - reinterpret_cast(inptr)->video_render(effect); -} - -void filter::blur::blur_factory::scene_create_handler(void* ptr, calldata_t* data) -{ - filter::blur::blur_factory* self = reinterpret_cast(ptr); - obs_source_t* source = nullptr; - calldata_get_ptr(data, "source", &source); - obs_scene_t* scene = obs_scene_from_source(source); - if (scene) { - self->scenes.insert_or_assign(std::string(obs_source_get_name(source)), scene); - } -} - -void filter::blur::blur_factory::scene_destroy_handler(void* ptr, calldata_t* data) -{ - filter::blur::blur_factory* self = reinterpret_cast(ptr); - obs_source_t* source = nullptr; - calldata_get_ptr(data, "source", &source); - obs_scene_t* scene = obs_scene_from_source(source); - if (scene) { - self->scenes.erase(std::string(obs_source_get_name(source))); - } -} - -std::shared_ptr filter::blur::blur_factory::get_effect(filter::blur::type) -{ - return blur_effect; -} - -std::string filter::blur::blur_factory::get_technique(filter::blur::type type) -{ - switch (type) { - case type::Box: - return "Box"; - case type::Gaussian: - return "Gaussian"; - case type::Bilateral: - return "Bilateral"; - case type::BoxLinear: - return "BoxLinear"; - case type::GaussianLinear: - return "GaussianLinear"; - } - return ""; -} - -std::shared_ptr filter::blur::blur_factory::get_color_converter_effect() -{ - return color_converter_effect; -} - -std::shared_ptr filter::blur::blur_factory::get_mask_effect() -{ - return mask_effect; -} - -std::shared_ptr filter::blur::blur_factory::get_kernel(filter::blur::type type) -{ - return kernels.at(type); -} - -std::shared_ptr> filter::blur::blur_factory::get_gaussian_kernel(uint8_t size) -{ - return gaussian_kernels.at(size); -} - -obs_scene_t* filter::blur::blur_factory::get_scene(std::string name) -{ - auto kv = scenes.find(name); - if (kv != scenes.end()) { - return kv->second; - } - return nullptr; -} - -void filter::blur::blur_factory::enum_scenes(std::function fnc) -{ - for (auto kv : scenes) { - if (!fnc(kv.second)) { - break; - } - } -} - -static filter::blur::blur_factory* factory_instance = nullptr; - -void filter::blur::blur_factory::initialize() -{ - factory_instance = new filter::blur::blur_factory(); -} - -void filter::blur::blur_factory::finalize() -{ - delete factory_instance; -} - -filter::blur::blur_factory* filter::blur::blur_factory::get() -{ - return factory_instance; -} diff --git a/source/filter-blur.hpp b/source/filter-blur.hpp index f39364a3..6612af52 100644 --- a/source/filter-blur.hpp +++ b/source/filter-blur.hpp @@ -17,10 +17,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef OBS_STREAM_EFFECTS_FILTER_BLUR_HPP -#define OBS_STREAM_EFFECTS_FILTER_BLUR_HPP #pragma once - #include #include #include @@ -29,8 +26,8 @@ #include "gfx-source-texture.hpp" #include "gs-effect.hpp" #include "gs-helper.hpp" -#include "gs-texture.hpp" #include "gs-rendertarget.hpp" +#include "gs-texture.hpp" #include "plugin.hpp" // OBS @@ -45,6 +42,8 @@ namespace filter { namespace blur { + class instance; + enum type : int64_t { Box, Gaussian, @@ -59,9 +58,76 @@ namespace filter { Source, }; - class blur_instance { - obs_source_t* m_source; - std::shared_ptr rt_source; + class factory { + friend class std::_Ptr_base; + + obs_source_info source_info; + std::list sources; + std::shared_ptr color_converter_effect; + std::shared_ptr mask_effect; + + std::shared_ptr blur_effect; + std::map> kernels; + std::map>> gaussian_kernels; + + std::map scenes; + + public: // Singleton + static void initialize(); + static void finalize(); + static std::shared_ptr get(); + + public: + factory(); + ~factory(); + + void on_list_fill(); + void on_list_empty(); + + void generate_gaussian_kernels(); + void generate_kernel_textures(); + + static void* create(obs_data_t* settings, obs_source_t* self); + static void destroy(void* source); + + static void get_defaults(obs_data_t* settings); + static obs_properties_t* get_properties(void* source); + static void update(void* source, obs_data_t* settings); + + static const char* get_name(void* source); + static uint32_t get_width(void* source); + static uint32_t get_height(void* source); + + static void activate(void* source); + static void deactivate(void* source); + + static void video_tick(void* source, float delta); + static void video_render(void* source, gs_effect_t* effect); + + static void scene_create_handler(void* ptr, calldata_t* data); + static void scene_destroy_handler(void* ptr, calldata_t* data); + + public: + std::shared_ptr get_effect(filter::blur::type type); + + std::string get_technique(filter::blur::type type); + + std::shared_ptr get_color_converter_effect(); + + std::shared_ptr get_mask_effect(); + + std::shared_ptr get_kernel(filter::blur::type type); + + std::shared_ptr> get_gaussian_kernel(uint8_t size); + + obs_scene_t* get_scene(std::string name); + + void enum_scenes(std::function fnc); + }; + + class instance { + obs_source_t* m_source; + std::shared_ptr rt_source; std::shared_ptr rt_primary; std::shared_ptr rt_secondary; @@ -110,11 +176,11 @@ namespace filter { } mask; // Directional - bool directional; + bool directional; double_t angle; // Scale - bool scaling; + bool scaling; std::pair scale; // advanced @@ -131,11 +197,11 @@ namespace filter { // Logging std::chrono::high_resolution_clock::time_point last_log; - bool can_log(); + bool can_log(); public: - blur_instance(obs_data_t* settings, obs_source_t* self); - ~blur_instance(); + instance(obs_data_t* settings, obs_source_t* self); + ~instance(); obs_properties_t* get_properties(); void update(obs_data_t*); @@ -149,75 +215,5 @@ namespace filter { void video_tick(float); void video_render(gs_effect_t*); }; - - class blur_factory { - obs_source_info source_info; - std::list sources; - std::shared_ptr color_converter_effect; - std::shared_ptr mask_effect; - - std::shared_ptr blur_effect; - std::map> kernels; - std::map>> gaussian_kernels; - - std::map scenes; - - private: - blur_factory(); - ~blur_factory(); - - void on_list_fill(); - void on_list_empty(); - - void generate_gaussian_kernels(); - void generate_kernel_textures(); - - protected: - static void* create(obs_data_t* settings, obs_source_t* self); - static void destroy(void* source); - - static void get_defaults(obs_data_t* settings); - static obs_properties_t* get_properties(void* source); - static void update(void* source, obs_data_t* settings); - - static const char* get_name(void* source); - static uint32_t get_width(void* source); - static uint32_t get_height(void* source); - - static void activate(void* source); - static void deactivate(void* source); - - static void video_tick(void* source, float delta); - static void video_render(void* source, gs_effect_t* effect); - - static void scene_create_handler(void* ptr, calldata_t* data); - static void scene_destroy_handler(void* ptr, calldata_t* data); - - public: - std::shared_ptr get_effect(filter::blur::type type); - - std::string get_technique(filter::blur::type type); - - std::shared_ptr get_color_converter_effect(); - - std::shared_ptr get_mask_effect(); - - std::shared_ptr get_kernel(filter::blur::type type); - - std::shared_ptr> get_gaussian_kernel(uint8_t size); - - obs_scene_t* get_scene(std::string name); - - void enum_scenes(std::function fnc); - - public: // Singleton - static void initialize(); - static void finalize(); - static blur_factory* get(); - }; - } // namespace blur - } // namespace filter - -#endif diff --git a/source/filter-displacement.cpp b/source/filter-displacement.cpp index db343855..ae94f6b9 100644 --- a/source/filter-displacement.cpp +++ b/source/filter-displacement.cpp @@ -22,14 +22,30 @@ #include "strings.hpp" // Initializer & Finalizer -static filter::displacement_factory* filterDisplacementInstance; INITIALIZER(FilterDisplacementInit) { - initializerFunctions.push_back([] { filterDisplacementInstance = new filter::displacement_factory(); }); - finalizerFunctions.push_back([] { delete filterDisplacementInstance; }); + initializerFunctions.push_back([] { filter::displacement::factory::initialize(); }); + finalizerFunctions.push_back([] { filter::displacement::factory::finalize(); }); } -filter::displacement_factory::displacement_factory() +static std::shared_ptr factory_instance = nullptr; + +void filter::displacement::factory::initialize() +{ + factory_instance = std::make_shared(); +} + +void filter::displacement::factory::finalize() +{ + factory_instance.reset(); +} + +std::shared_ptr filter::displacement::factory::get() +{ + return factory_instance; +} + +filter::displacement::factory::factory() { memset(&sourceInfo, 0, sizeof(obs_source_info)); sourceInfo.id = "obs-stream-effects-filter-displacement"; @@ -52,34 +68,34 @@ filter::displacement_factory::displacement_factory() obs_register_source(&sourceInfo); } -filter::displacement_factory::~displacement_factory() {} +filter::displacement::factory::~factory() {} -const char* filter::displacement_factory::get_name(void*) +const char* filter::displacement::factory::get_name(void*) { return P_TRANSLATE(S_FILTER_DISPLACEMENT); } -void* filter::displacement_factory::create(obs_data_t* data, obs_source_t* source) +void* filter::displacement::factory::create(obs_data_t* data, obs_source_t* source) { - return new displacement(data, source); + return new instance(data, source); } -void filter::displacement_factory::destroy(void* ptr) +void filter::displacement::factory::destroy(void* ptr) { - delete reinterpret_cast(ptr); + delete reinterpret_cast(ptr); } -uint32_t filter::displacement_factory::get_width(void* ptr) +uint32_t filter::displacement::factory::get_width(void* ptr) { - return reinterpret_cast(ptr)->get_width(); + return reinterpret_cast(ptr)->get_width(); } -uint32_t filter::displacement_factory::get_height(void* ptr) +uint32_t filter::displacement::factory::get_height(void* ptr) { - return reinterpret_cast(ptr)->get_height(); + return reinterpret_cast(ptr)->get_height(); } -void filter::displacement_factory::get_defaults(obs_data_t* data) +void filter::displacement::factory::get_defaults(obs_data_t* data) { char* disp = obs_module_file("filter-displacement/neutral.png"); obs_data_set_default_string(data, S_FILTER_DISPLACEMENT_FILE, disp); @@ -88,13 +104,13 @@ void filter::displacement_factory::get_defaults(obs_data_t* data) bfree(disp); } -obs_properties_t* filter::displacement_factory::get_properties(void* ptr) +obs_properties_t* filter::displacement::factory::get_properties(void* ptr) { obs_properties_t* pr = obs_properties_create(); std::string path = ""; if (ptr) - path = reinterpret_cast(ptr)->get_file(); + path = reinterpret_cast(ptr)->get_file(); obs_properties_add_path(pr, S_FILTER_DISPLACEMENT_FILE, P_TRANSLATE(S_FILTER_DISPLACEMENT_FILE), obs_path_type::OBS_PATH_FILE, P_TRANSLATE(S_FILTER_DISPLACEMENT_FILE_TYPES), path.c_str()); @@ -105,42 +121,42 @@ obs_properties_t* filter::displacement_factory::get_properties(void* ptr) return pr; } -void filter::displacement_factory::update(void* ptr, obs_data_t* data) +void filter::displacement::factory::update(void* ptr, obs_data_t* data) { - reinterpret_cast(ptr)->update(data); + reinterpret_cast(ptr)->update(data); } -void filter::displacement_factory::activate(void* ptr) +void filter::displacement::factory::activate(void* ptr) { - reinterpret_cast(ptr)->activate(); + reinterpret_cast(ptr)->activate(); } -void filter::displacement_factory::deactivate(void* ptr) +void filter::displacement::factory::deactivate(void* ptr) { - reinterpret_cast(ptr)->deactivate(); + reinterpret_cast(ptr)->deactivate(); } -void filter::displacement_factory::show(void* ptr) +void filter::displacement::factory::show(void* ptr) { - reinterpret_cast(ptr)->show(); + reinterpret_cast(ptr)->show(); } -void filter::displacement_factory::hide(void* ptr) +void filter::displacement::factory::hide(void* ptr) { - reinterpret_cast(ptr)->hide(); + reinterpret_cast(ptr)->hide(); } -void filter::displacement_factory::video_tick(void* ptr, float time) +void filter::displacement::factory::video_tick(void* ptr, float time) { - reinterpret_cast(ptr)->video_tick(time); + reinterpret_cast(ptr)->video_tick(time); } -void filter::displacement_factory::video_render(void* ptr, gs_effect_t* effect) +void filter::displacement::factory::video_render(void* ptr, gs_effect_t* effect) { - reinterpret_cast(ptr)->video_render(effect); + reinterpret_cast(ptr)->video_render(effect); } -void filter::displacement::validate_file_texture(std::string file) +void filter::displacement::instance::validate_file_texture(std::string file) { bool do_update = false; @@ -168,7 +184,7 @@ void filter::displacement::validate_file_texture(std::string file) } } -filter::displacement::displacement(obs_data_t* data, obs_source_t* context) +filter::displacement::instance::instance(obs_data_t* data, obs_source_t* context) : m_self(context), m_active(true), m_timer(0), m_effect(nullptr), m_distance(0), m_file_create_time(0), m_file_modified_time(0), m_file_size(0) { @@ -183,13 +199,13 @@ filter::displacement::displacement(obs_data_t* data, obs_source_t* context) update(data); } -filter::displacement::~displacement() +filter::displacement::instance::~instance() { m_effect.reset(); m_file_texture.reset(); } -void filter::displacement::update(obs_data_t* data) +void filter::displacement::instance::update(obs_data_t* data) { validate_file_texture(obs_data_get_string(data, S_FILTER_DISPLACEMENT_FILE)); @@ -198,25 +214,25 @@ void filter::displacement::update(obs_data_t* data) float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_SCALE))); } -uint32_t filter::displacement::get_width() +uint32_t filter::displacement::instance::get_width() { return 0; } -uint32_t filter::displacement::get_height() +uint32_t filter::displacement::instance::get_height() { return 0; } -void filter::displacement::activate() {} +void filter::displacement::instance::activate() {} -void filter::displacement::deactivate() {} +void filter::displacement::instance::deactivate() {} -void filter::displacement::show() {} +void filter::displacement::instance::show() {} -void filter::displacement::hide() {} +void filter::displacement::instance::hide() {} -void filter::displacement::video_tick(float time) +void filter::displacement::instance::video_tick(float time) { m_timer += time; if (m_timer >= 1.0) { @@ -230,7 +246,7 @@ float interp(float a, float b, float v) return (a * (1.0f - v)) + (b * v); } -void filter::displacement::video_render(gs_effect_t*) +void filter::displacement::instance::video_render(gs_effect_t*) { obs_source_t* parent = obs_filter_get_parent(m_self); obs_source_t* target = obs_filter_get_target(m_self); @@ -261,7 +277,7 @@ void filter::displacement::video_render(gs_effect_t*) obs_source_process_filter_end(m_self, m_effect->get_object(), baseW, baseH); } -std::string filter::displacement::get_file() +std::string filter::displacement::instance::get_file() { return m_file_name; } diff --git a/source/filter-displacement.hpp b/source/filter-displacement.hpp index 39307b36..74079f72 100644 --- a/source/filter-displacement.hpp +++ b/source/filter-displacement.hpp @@ -41,63 +41,72 @@ #define S_FILTER_DISPLACEMENT_SCALE "Filter.Displacement.Scale" namespace filter { - class displacement_factory { - obs_source_info sourceInfo; + namespace displacement { + class factory { + friend class std::_Ptr_base; - public: - displacement_factory(); - ~displacement_factory(); + obs_source_info sourceInfo; - static const char* get_name(void*); + public: // Singleton + static void initialize(); + static void finalize(); + static std::shared_ptr get(); - static void* create(obs_data_t*, obs_source_t*); - static void destroy(void*); - static uint32_t get_width(void*); - static uint32_t get_height(void*); - static void get_defaults(obs_data_t*); - static obs_properties_t* get_properties(void*); - static void update(void*, obs_data_t*); - static void activate(void*); - static void deactivate(void*); - static void show(void*); - static void hide(void*); - static void video_tick(void*, float); - static void video_render(void*, gs_effect_t*); - }; + public: + factory(); + ~factory(); - class displacement { - obs_source_t* m_self; - bool m_active; - float_t m_timer; + static const char* get_name(void*); - // Rendering - std::shared_ptr m_effect; - float_t m_distance; - vec2 m_displacement_scale; + static void* create(obs_data_t*, obs_source_t*); + static void destroy(void*); + static uint32_t get_width(void*); + static uint32_t get_height(void*); + static void get_defaults(obs_data_t*); + static obs_properties_t* get_properties(void*); + static void update(void*, obs_data_t*); + static void activate(void*); + static void deactivate(void*); + static void show(void*); + static void hide(void*); + static void video_tick(void*, float); + static void video_render(void*, gs_effect_t*); + }; - // Displacement Map - std::string m_file_name; - std::shared_ptr m_file_texture; - time_t m_file_create_time; - time_t m_file_modified_time; - size_t m_file_size; + class instance { + obs_source_t* m_self; + bool m_active; + float_t m_timer; - void validate_file_texture(std::string file); + // Rendering + std::shared_ptr m_effect; + float_t m_distance; + vec2 m_displacement_scale; - public: - displacement(obs_data_t*, obs_source_t*); - ~displacement(); + // Displacement Map + std::string m_file_name; + std::shared_ptr m_file_texture; + time_t m_file_create_time; + time_t m_file_modified_time; + size_t m_file_size; - void update(obs_data_t*); - uint32_t get_width(); - uint32_t get_height(); - void activate(); - void deactivate(); - void show(); - void hide(); - void video_tick(float); - void video_render(gs_effect_t*); + void validate_file_texture(std::string file); - std::string get_file(); - }; + public: + instance(obs_data_t*, obs_source_t*); + ~instance(); + + void update(obs_data_t*); + uint32_t get_width(); + uint32_t get_height(); + void activate(); + void deactivate(); + void show(); + void hide(); + void video_tick(float); + void video_render(gs_effect_t*); + + std::string get_file(); + }; + } // namespace displacement } // namespace filter diff --git a/source/filter-shadow-sdf.cpp b/source/filter-shadow-sdf.cpp index 801a7842..668f682c 100644 --- a/source/filter-shadow-sdf.cpp +++ b/source/filter-shadow-sdf.cpp @@ -41,11 +41,28 @@ // Initializer & Finalizer INITIALIZER(filterShadowFactoryInitializer) { - initializerFunctions.push_back([] { filter::shadow_sdf_factory::initialize(); }); - finalizerFunctions.push_back([] { filter::shadow_sdf_factory::finalize(); }); + initializerFunctions.push_back([] { filter::shadow_sdf::factory::initialize(); }); + finalizerFunctions.push_back([] { filter::shadow_sdf::factory::finalize(); }); } -bool filter::shadow_sdf::cb_modified_inside(void*, obs_properties_t* props, obs_property*, +static std::shared_ptr factory_instance = nullptr; + +void filter::shadow_sdf::factory::initialize() +{ + factory_instance = std::make_shared(); +} + +void filter::shadow_sdf::factory::finalize() +{ + factory_instance.reset(); +} + +std::shared_ptr filter::shadow_sdf::factory::get() +{ + return factory_instance; +} + +bool filter::shadow_sdf::instance::cb_modified_inside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) { bool v = obs_data_get_bool(settings, P_INNER); @@ -58,7 +75,7 @@ bool filter::shadow_sdf::cb_modified_inside(void*, obs_properties_t* props, obs_ return true; } -bool filter::shadow_sdf::cb_modified_outside(void*, obs_properties_t* props, obs_property*, +bool filter::shadow_sdf::instance::cb_modified_outside(void*, obs_properties_t* props, obs_property*, obs_data_t* settings) { bool v = obs_data_get_bool(settings, P_OUTER); @@ -71,7 +88,7 @@ bool filter::shadow_sdf::cb_modified_outside(void*, obs_properties_t* props, obs return true; } -filter::shadow_sdf::shadow_sdf(obs_data_t* settings, obs_source_t* self) +filter::shadow_sdf::instance::instance(obs_data_t* settings, obs_source_t* self) : m_self(self), m_source_rendered(false) { this->m_source_rt = std::make_shared(GS_RGBA, GS_ZS_NONE); @@ -86,9 +103,9 @@ filter::shadow_sdf::shadow_sdf(obs_data_t* settings, obs_source_t* self) this->update(settings); } -filter::shadow_sdf::~shadow_sdf() {} +filter::shadow_sdf::instance::~instance() {} -obs_properties_t* filter::shadow_sdf::get_properties() +obs_properties_t* filter::shadow_sdf::instance::get_properties() { obs_properties_t* props = obs_properties_create(); obs_property_t* p = nullptr; @@ -144,7 +161,7 @@ obs_properties_t* filter::shadow_sdf::get_properties() return props; } -void filter::shadow_sdf::update(obs_data_t* data) +void filter::shadow_sdf::instance::update(obs_data_t* data) { this->m_inner_shadow = obs_data_get_bool(data, P_INNER); this->m_inner_range_min = float_t(obs_data_get_double(data, P_INNER_RANGE_MINIMUM)); @@ -169,27 +186,27 @@ void filter::shadow_sdf::update(obs_data_t* data) | (int32_t(obs_data_get_double(data, P_OUTER_ALPHA) * 2.55) << 24); } -uint32_t filter::shadow_sdf::get_width() +uint32_t filter::shadow_sdf::instance::get_width() { return uint32_t(0); } -uint32_t filter::shadow_sdf::get_height() +uint32_t filter::shadow_sdf::instance::get_height() { return uint32_t(0); } -void filter::shadow_sdf::activate() {} +void filter::shadow_sdf::instance::activate() {} -void filter::shadow_sdf::deactivate() {} +void filter::shadow_sdf::instance::deactivate() {} -void filter::shadow_sdf::video_tick(float time) +void filter::shadow_sdf::instance::video_tick(float time) { this->m_tick += time; m_source_rendered = false; } -void filter::shadow_sdf::video_render(gs_effect_t*) +void filter::shadow_sdf::instance::video_render(gs_effect_t*) { obs_source_t* parent = obs_filter_get_parent(this->m_self); obs_source_t* target = obs_filter_get_target(this->m_self); @@ -239,7 +256,7 @@ void filter::shadow_sdf::video_render(gs_effect_t*) } std::shared_ptr sdf_effect = - filter::shadow_sdf_factory::get()->get_sdf_generator_effect(); + filter::shadow_sdf::factory::get()->get_sdf_generator_effect(); if (!sdf_effect) { throw std::runtime_error("SDF Effect no loaded"); } @@ -275,7 +292,7 @@ void filter::shadow_sdf::video_render(gs_effect_t*) { std::shared_ptr shadow_effect = - filter::shadow_sdf_factory::get()->get_sdf_shadow_effect(); + filter::shadow_sdf::factory::get()->get_sdf_shadow_effect(); if (!shadow_effect) { throw std::runtime_error("Shadow Effect no loaded"); } @@ -339,7 +356,7 @@ void filter::shadow_sdf::video_render(gs_effect_t*) gs_enable_depth_test(false); } -filter::shadow_sdf_factory::shadow_sdf_factory() +filter::shadow_sdf::factory::factory() { memset(&source_info, 0, sizeof(obs_source_info)); source_info.id = "obs-stream-effects-filter-shadow-sdf"; @@ -360,9 +377,9 @@ filter::shadow_sdf_factory::shadow_sdf_factory() obs_register_source(&source_info); } -filter::shadow_sdf_factory::~shadow_sdf_factory() {} +filter::shadow_sdf::factory::~factory() {} -void filter::shadow_sdf_factory::on_list_fill() +void filter::shadow_sdf::factory::on_list_fill() { { char* file = obs_module_file("effects/sdf-generator.effect"); @@ -384,25 +401,25 @@ void filter::shadow_sdf_factory::on_list_fill() } } -void filter::shadow_sdf_factory::on_list_empty() +void filter::shadow_sdf::factory::on_list_empty() { sdf_generator_effect.reset(); sdf_shadow_effect.reset(); } -void* filter::shadow_sdf_factory::create(obs_data_t* data, obs_source_t* parent) +void* filter::shadow_sdf::factory::create(obs_data_t* data, obs_source_t* parent) { if (get()->sources.empty()) { get()->on_list_fill(); } - filter::shadow_sdf* ptr = new filter::shadow_sdf(data, parent); + filter::shadow_sdf::instance* ptr = new filter::shadow_sdf::instance(data, parent); get()->sources.push_back(ptr); return ptr; } -void filter::shadow_sdf_factory::destroy(void* inptr) +void filter::shadow_sdf::factory::destroy(void* inptr) { - filter::shadow_sdf* ptr = reinterpret_cast(inptr); + filter::shadow_sdf::instance* ptr = reinterpret_cast(inptr); get()->sources.remove(ptr); if (get()->sources.empty()) { get()->on_list_empty(); @@ -410,7 +427,7 @@ void filter::shadow_sdf_factory::destroy(void* inptr) delete ptr; } -void filter::shadow_sdf_factory::get_defaults(obs_data_t* data) +void filter::shadow_sdf::factory::get_defaults(obs_data_t* data) { obs_data_set_bool(data, P_INNER, false); obs_data_set_double(data, P_INNER_RANGE_MINIMUM, 0.0); @@ -429,74 +446,57 @@ void filter::shadow_sdf_factory::get_defaults(obs_data_t* data) obs_data_set_double(data, P_OUTER_ALPHA, 100.0); } -obs_properties_t* filter::shadow_sdf_factory::get_properties(void* inptr) +obs_properties_t* filter::shadow_sdf::factory::get_properties(void* inptr) { - return reinterpret_cast(inptr)->get_properties(); + return reinterpret_cast(inptr)->get_properties(); } -void filter::shadow_sdf_factory::update(void* inptr, obs_data_t* settings) +void filter::shadow_sdf::factory::update(void* inptr, obs_data_t* settings) { - reinterpret_cast(inptr)->update(settings); + reinterpret_cast(inptr)->update(settings); } -const char* filter::shadow_sdf_factory::get_name(void*) +const char* filter::shadow_sdf::factory::get_name(void*) { return P_TRANSLATE(SOURCE_NAME); } -uint32_t filter::shadow_sdf_factory::get_width(void* inptr) +uint32_t filter::shadow_sdf::factory::get_width(void* inptr) { - return reinterpret_cast(inptr)->get_width(); + return reinterpret_cast(inptr)->get_width(); } -uint32_t filter::shadow_sdf_factory::get_height(void* inptr) +uint32_t filter::shadow_sdf::factory::get_height(void* inptr) { - return reinterpret_cast(inptr)->get_height(); + return reinterpret_cast(inptr)->get_height(); } -void filter::shadow_sdf_factory::activate(void* inptr) +void filter::shadow_sdf::factory::activate(void* inptr) { - reinterpret_cast(inptr)->activate(); + reinterpret_cast(inptr)->activate(); } -void filter::shadow_sdf_factory::deactivate(void* inptr) +void filter::shadow_sdf::factory::deactivate(void* inptr) { - reinterpret_cast(inptr)->deactivate(); + reinterpret_cast(inptr)->deactivate(); } -void filter::shadow_sdf_factory::video_tick(void* inptr, float delta) +void filter::shadow_sdf::factory::video_tick(void* inptr, float delta) { - reinterpret_cast(inptr)->video_tick(delta); + reinterpret_cast(inptr)->video_tick(delta); } -void filter::shadow_sdf_factory::video_render(void* inptr, gs_effect_t* effect) +void filter::shadow_sdf::factory::video_render(void* inptr, gs_effect_t* effect) { - reinterpret_cast(inptr)->video_render(effect); + reinterpret_cast(inptr)->video_render(effect); } -std::shared_ptr filter::shadow_sdf_factory::get_sdf_generator_effect() +std::shared_ptr filter::shadow_sdf::factory::get_sdf_generator_effect() { return sdf_generator_effect; } -std::shared_ptr filter::shadow_sdf_factory::get_sdf_shadow_effect() +std::shared_ptr filter::shadow_sdf::factory::get_sdf_shadow_effect() { return sdf_shadow_effect; } - -static filter::shadow_sdf_factory* factory_instance = nullptr; - -void filter::shadow_sdf_factory::initialize() -{ - factory_instance = new filter::shadow_sdf_factory(); -} - -void filter::shadow_sdf_factory::finalize() -{ - delete factory_instance; -} - -filter::shadow_sdf_factory* filter::shadow_sdf_factory::get() -{ - return factory_instance; -} diff --git a/source/filter-shadow-sdf.hpp b/source/filter-shadow-sdf.hpp index 403ba584..92a16756 100644 --- a/source/filter-shadow-sdf.hpp +++ b/source/filter-shadow-sdf.hpp @@ -40,95 +40,102 @@ #endif namespace filter { - class shadow_sdf { - obs_source_t* m_self; + namespace shadow_sdf { + class instance; - // Input - std::shared_ptr m_source_rt; - std::shared_ptr m_source_texture; - bool m_source_rendered; + class factory { + friend class std::_Ptr_base; - // Distance Field - std::shared_ptr m_sdf_write, m_sdf_read; - std::shared_ptr m_sdf_texture; + obs_source_info source_info; + std::list sources; - float_t m_tick = 0.; + std::shared_ptr sdf_generator_effect; + std::shared_ptr sdf_shadow_effect; - bool m_inner_shadow; - float_t m_inner_range_min; - float_t m_inner_range_max; - float_t m_inner_offset_x; - float_t m_inner_offset_y; - uint32_t m_inner_color; - bool m_outer_shadow; - float_t m_outer_range_min; - float_t m_outer_range_max; - float_t m_outer_offset_x; - float_t m_outer_offset_y; - uint32_t m_outer_color; + public: // Singleton + static void initialize(); + static void finalize(); + static std::shared_ptr get(); - static bool cb_modified_inside(void* ptr, obs_properties_t* props, obs_property* prop, obs_data_t* settings); + public: + factory(); + ~factory(); - static bool cb_modified_outside(void* ptr, obs_properties_t* props, obs_property* prop, obs_data_t* settings); + void on_list_fill(); + void on_list_empty(); - public: - shadow_sdf(obs_data_t* settings, obs_source_t* self); - ~shadow_sdf(); + static void* create(obs_data_t* settings, obs_source_t* self); + static void destroy(void* source); - obs_properties_t* get_properties(); - void update(obs_data_t*); + static void get_defaults(obs_data_t* settings); + static obs_properties_t* get_properties(void* source); + static void update(void* source, obs_data_t* settings); - uint32_t get_width(); - uint32_t get_height(); + static const char* get_name(void* source); + static uint32_t get_width(void* source); + static uint32_t get_height(void* source); - void activate(); - void deactivate(); + static void activate(void* source); + static void deactivate(void* source); - void video_tick(float); - void video_render(gs_effect_t*); - }; + static void video_tick(void* source, float delta); + static void video_render(void* source, gs_effect_t* effect); - class shadow_sdf_factory { - obs_source_info source_info; - std::list sources; + public: + std::shared_ptr get_sdf_generator_effect(); + std::shared_ptr get_sdf_shadow_effect(); + }; - std::shared_ptr sdf_generator_effect; - std::shared_ptr sdf_shadow_effect; + class instance { + obs_source_t* m_self; - private: - shadow_sdf_factory(); - ~shadow_sdf_factory(); + // Input + std::shared_ptr m_source_rt; + std::shared_ptr m_source_texture; + bool m_source_rendered; - void on_list_fill(); - void on_list_empty(); + // Distance Field + std::shared_ptr m_sdf_write, m_sdf_read; + std::shared_ptr m_sdf_texture; - protected: - static void* create(obs_data_t* settings, obs_source_t* self); - static void destroy(void* source); + float_t m_tick = 0.; - static void get_defaults(obs_data_t* settings); - static obs_properties_t* get_properties(void* source); - static void update(void* source, obs_data_t* settings); + bool m_inner_shadow; + float_t m_inner_range_min; + float_t m_inner_range_max; + float_t m_inner_offset_x; + float_t m_inner_offset_y; + uint32_t m_inner_color; + bool m_outer_shadow; + float_t m_outer_range_min; + float_t m_outer_range_max; + float_t m_outer_offset_x; + float_t m_outer_offset_y; + uint32_t m_outer_color; - static const char* get_name(void* source); - static uint32_t get_width(void* source); - static uint32_t get_height(void* source); + static bool cb_modified_inside(void* ptr, obs_properties_t* props, obs_property* prop, + obs_data_t* settings); - static void activate(void* source); - static void deactivate(void* source); + static bool cb_modified_outside(void* ptr, obs_properties_t* props, obs_property* prop, + obs_data_t* settings); - static void video_tick(void* source, float delta); - static void video_render(void* source, gs_effect_t* effect); + public: + instance(obs_data_t* settings, obs_source_t* self); + ~instance(); - public: - std::shared_ptr get_sdf_generator_effect(); - std::shared_ptr get_sdf_shadow_effect(); + obs_properties_t* get_properties(); + void update(obs_data_t*); - public: // Singleton - static void initialize(); - static void finalize(); - static shadow_sdf_factory* get(); - }; + uint32_t get_width(); + uint32_t get_height(); + + void activate(); + void deactivate(); + + void video_tick(float); + void video_render(gs_effect_t*); + }; + } // namespace shadow_sdf } // namespace filter #endif diff --git a/source/filter-transform.cpp b/source/filter-transform.cpp index f177820f..8b6e72f6 100644 --- a/source/filter-transform.cpp +++ b/source/filter-transform.cpp @@ -33,14 +33,6 @@ #pragma warning(pop) #endif -// Initializer & Finalizer -static filter::transform_factory* filterTransformInstance; -INITIALIZER(FilterTransformInit) -{ - initializerFunctions.push_back([] { filterTransformInstance = new filter::transform_factory(); }); - finalizerFunctions.push_back([] { delete filterTransformInstance; }); -} - #define ST "Filter.Transform" #define ST_CAMERA "Filter.Transform.Camera" #define ST_CAMERA_ORTHOGRAPHIC "Filter.Transform.Camera.Orthographic" @@ -83,7 +75,31 @@ enum RotationOrder : int64_t { ZYX, }; -filter::transform_factory::transform_factory() +// Initializer & Finalizer +INITIALIZER(FilterTransformInit) +{ + initializerFunctions.push_back([] { filter::transform::factory::initialize(); }); + finalizerFunctions.push_back([] { filter::transform::factory::finalize(); }); +} + +static std::shared_ptr factory_instance = nullptr; + +void filter::transform::factory::initialize() +{ + factory_instance = std::make_shared(); +} + +void filter::transform::factory::finalize() +{ + factory_instance.reset(); +} + +std::shared_ptr filter::transform::factory::get() +{ + return factory_instance; +} + +filter::transform::factory::factory() { memset(&sourceInfo, 0, sizeof(obs_source_info)); sourceInfo.id = "obs-stream-effects-filter-transform"; @@ -104,14 +120,14 @@ filter::transform_factory::transform_factory() obs_register_source(&sourceInfo); } -filter::transform_factory::~transform_factory() {} +filter::transform::factory::~factory() {} -const char* filter::transform_factory::get_name(void*) +const char* filter::transform::factory::get_name(void*) { return P_TRANSLATE(ST); } -void filter::transform_factory::get_defaults(obs_data_t* data) +void filter::transform::factory::get_defaults(obs_data_t* data) { obs_data_set_default_int(data, ST_CAMERA, (int64_t)CameraMode::Orthographic); obs_data_set_default_double(data, ST_CAMERA_FIELDOFVIEW, 90.0); @@ -129,7 +145,7 @@ void filter::transform_factory::get_defaults(obs_data_t* data) obs_data_set_default_int(data, ST_ROTATION_ORDER, RotationOrder::ZXY); } -obs_properties_t* filter::transform_factory::get_properties(void*) +obs_properties_t* filter::transform::factory::get_properties(void*) { obs_properties_t* pr = obs_properties_create(); obs_property_t* p = NULL; @@ -211,30 +227,25 @@ obs_properties_t* filter::transform_factory::get_properties(void*) obs_property_set_modified_callback(p, modified_properties); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(ST_MIPMAPPING))); - p = obs_properties_add_list(pr, S_MIPGENERATOR, P_TRANSLATE(S_MIPGENERATOR), - OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); + p = obs_properties_add_list(pr, S_MIPGENERATOR, P_TRANSLATE(S_MIPGENERATOR), OBS_COMBO_TYPE_LIST, + OBS_COMBO_FORMAT_INT); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_MIPGENERATOR))); obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), (long long)gs::mipmapper::generator::Point); - obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), - (long long)gs::mipmapper::generator::Linear); - obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), - (long long)gs::mipmapper::generator::Sharpen); - obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), - (long long)gs::mipmapper::generator::Smoothen); - obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), - (long long)gs::mipmapper::generator::Bicubic); - obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), - (long long)gs::mipmapper::generator::Lanczos); + obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), (long long)gs::mipmapper::generator::Linear); + obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), (long long)gs::mipmapper::generator::Sharpen); + obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), (long long)gs::mipmapper::generator::Smoothen); + obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), (long long)gs::mipmapper::generator::Bicubic); + obs_property_list_add_int(p, P_TRANSLATE(S_MIPGENERATOR_POINT), (long long)gs::mipmapper::generator::Lanczos); - p = obs_properties_add_float_slider(pr, S_MIPGENERATOR_STRENGTH, P_TRANSLATE(S_MIPGENERATOR_STRENGTH), 0.0, - 1000.0, 0.01); + p = obs_properties_add_float_slider(pr, S_MIPGENERATOR_STRENGTH, P_TRANSLATE(S_MIPGENERATOR_STRENGTH), 0.0, 1000.0, + 0.01); obs_property_set_long_description(p, P_TRANSLATE(P_DESC(S_MIPGENERATOR_STRENGTH))); return pr; } -bool filter::transform_factory::modified_properties(obs_properties_t* pr, obs_property_t*, obs_data_t* d) +bool filter::transform::factory::modified_properties(obs_properties_t* pr, obs_property_t*, obs_data_t* d) { switch ((CameraMode)obs_data_get_int(d, ST_CAMERA)) { case CameraMode::Orthographic: @@ -258,52 +269,52 @@ bool filter::transform_factory::modified_properties(obs_properties_t* pr, obs_pr return true; } -void* filter::transform_factory::create(obs_data_t* data, obs_source_t* source) +void* filter::transform::factory::create(obs_data_t* data, obs_source_t* source) { - return new transform(data, source); + return new instance(data, source); } -void filter::transform_factory::destroy(void* ptr) +void filter::transform::factory::destroy(void* ptr) { - delete reinterpret_cast(ptr); + delete reinterpret_cast(ptr); } -uint32_t filter::transform_factory::get_width(void* ptr) +uint32_t filter::transform::factory::get_width(void* ptr) { - return reinterpret_cast(ptr)->get_width(); + return reinterpret_cast(ptr)->get_width(); } -uint32_t filter::transform_factory::get_height(void* ptr) +uint32_t filter::transform::factory::get_height(void* ptr) { - return reinterpret_cast(ptr)->get_height(); + return reinterpret_cast(ptr)->get_height(); } -void filter::transform_factory::update(void* ptr, obs_data_t* data) +void filter::transform::factory::update(void* ptr, obs_data_t* data) { - reinterpret_cast(ptr)->update(data); + reinterpret_cast(ptr)->update(data); } -void filter::transform_factory::activate(void* ptr) +void filter::transform::factory::activate(void* ptr) { - reinterpret_cast(ptr)->activate(); + reinterpret_cast(ptr)->activate(); } -void filter::transform_factory::deactivate(void* ptr) +void filter::transform::factory::deactivate(void* ptr) { - reinterpret_cast(ptr)->deactivate(); + reinterpret_cast(ptr)->deactivate(); } -void filter::transform_factory::video_tick(void* ptr, float time) +void filter::transform::factory::video_tick(void* ptr, float time) { - reinterpret_cast(ptr)->video_tick(time); + reinterpret_cast(ptr)->video_tick(time); } -void filter::transform_factory::video_render(void* ptr, gs_effect_t* effect) +void filter::transform::factory::video_render(void* ptr, gs_effect_t* effect) { - reinterpret_cast(ptr)->video_render(effect); + reinterpret_cast(ptr)->video_render(effect); } -filter::transform::~transform() +filter::transform::instance::~instance() { m_shear.reset(); m_scale.reset(); @@ -316,7 +327,7 @@ filter::transform::~transform() m_source_rendertarget.reset(); } -filter::transform::transform(obs_data_t* data, obs_source_t* context) +filter::transform::instance::instance(obs_data_t* data, obs_source_t* context) : m_active(true), m_self(context), m_source_rendered(false), m_mipmap_enabled(false), m_mipmap_strength(50.0), m_mipmap_generator(gs::mipmapper::generator::Linear), m_update_mesh(false), m_rotation_order(RotationOrder::ZXY), m_camera_orthographic(true), m_camera_fov(90.0) @@ -337,17 +348,17 @@ filter::transform::transform(obs_data_t* data, obs_source_t* context) update(data); } -uint32_t filter::transform::get_width() +uint32_t filter::transform::instance::get_width() { return 0; } -uint32_t filter::transform::get_height() +uint32_t filter::transform::instance::get_height() { return 0; } -void filter::transform::update(obs_data_t* data) +void filter::transform::instance::update(obs_data_t* data) { // Camera m_camera_orthographic = obs_data_get_int(data, ST_CAMERA) == 0; @@ -376,17 +387,17 @@ void filter::transform::update(obs_data_t* data) m_update_mesh = true; } -void filter::transform::activate() +void filter::transform::instance::activate() { m_active = true; } -void filter::transform::deactivate() +void filter::transform::instance::deactivate() { m_active = false; } -void filter::transform::video_tick(float) +void filter::transform::instance::video_tick(float) { // Update Mesh if (m_update_mesh) { @@ -490,7 +501,7 @@ void filter::transform::video_tick(float) this->m_source_rendered = false; } -void filter::transform::video_render(gs_effect_t* paramEffect) +void filter::transform::instance::video_render(gs_effect_t* paramEffect) { if (!m_active) { obs_source_skip_video_filter(m_self); diff --git a/source/filter-transform.hpp b/source/filter-transform.hpp index 3e01d2d7..86973408 100644 --- a/source/filter-transform.hpp +++ b/source/filter-transform.hpp @@ -27,74 +27,83 @@ #include "plugin.hpp" namespace filter { - class transform_factory { - obs_source_info sourceInfo; + namespace transform { + class factory { + friend class std::_Ptr_base; - public: - transform_factory(); - ~transform_factory(); + obs_source_info sourceInfo; - static const char* get_name(void*); - static void get_defaults(obs_data_t*); - static obs_properties_t* get_properties(void*); - static bool modified_properties(obs_properties_t*, obs_property_t*, obs_data_t*); + public: // Singleton + static void initialize(); + static void finalize(); + static std::shared_ptr get(); - static void* create(obs_data_t*, obs_source_t*); - static void destroy(void*); - static uint32_t get_width(void*); - static uint32_t get_height(void*); - static void update(void*, obs_data_t*); - static void activate(void*); - static void deactivate(void*); - static void show(void*); - static void hide(void*); - static void video_tick(void*, float); - static void video_render(void*, gs_effect_t*); - }; + public: + factory(); + ~factory(); - class transform { - bool m_active; - obs_source_t* m_self; + static const char* get_name(void*); + static void get_defaults(obs_data_t*); + static obs_properties_t* get_properties(void*); + static bool modified_properties(obs_properties_t*, obs_property_t*, obs_data_t*); - // Input - std::shared_ptr m_source_rendertarget; - std::shared_ptr m_source_texture; - bool m_source_rendered; + static void* create(obs_data_t*, obs_source_t*); + static void destroy(void*); + static uint32_t get_width(void*); + static uint32_t get_height(void*); + static void update(void*, obs_data_t*); + static void activate(void*); + static void deactivate(void*); + static void show(void*); + static void hide(void*); + static void video_tick(void*, float); + static void video_render(void*, gs_effect_t*); + }; - // Mipmapping - bool m_mipmap_enabled; - double_t m_mipmap_strength; - gs::mipmapper::generator m_mipmap_generator; - gs::mipmapper m_mipmapper; + class instance { + bool m_active; + obs_source_t* m_self; - // Rendering - std::shared_ptr m_shape_rendertarget; - std::shared_ptr m_shape_texture; + // Input + std::shared_ptr m_source_rendertarget; + std::shared_ptr m_source_texture; + bool m_source_rendered; - // Mesh - bool m_update_mesh; - std::shared_ptr m_vertex_buffer; - uint32_t m_rotation_order; - std::unique_ptr m_position; - std::unique_ptr m_rotation; - std::unique_ptr m_scale; - std::unique_ptr m_shear; + // Mipmapping + bool m_mipmap_enabled; + double_t m_mipmap_strength; + gs::mipmapper::generator m_mipmap_generator; + gs::mipmapper m_mipmapper; - // Camera - bool m_camera_orthographic; - float_t m_camera_fov; + // Rendering + std::shared_ptr m_shape_rendertarget; + std::shared_ptr m_shape_texture; - public: - ~transform(); - transform(obs_data_t*, obs_source_t*); + // Mesh + bool m_update_mesh; + std::shared_ptr m_vertex_buffer; + uint32_t m_rotation_order; + std::unique_ptr m_position; + std::unique_ptr m_rotation; + std::unique_ptr m_scale; + std::unique_ptr m_shear; - uint32_t get_width(); - uint32_t get_height(); + // Camera + bool m_camera_orthographic; + float_t m_camera_fov; - void update(obs_data_t*); - void activate(); - void deactivate(); - void video_tick(float); - void video_render(gs_effect_t*); - }; + public: + ~instance(); + instance(obs_data_t*, obs_source_t*); + + uint32_t get_width(); + uint32_t get_height(); + + void update(obs_data_t*); + void activate(); + void deactivate(); + void video_tick(float); + void video_render(gs_effect_t*); + }; + } // namespace transform } // namespace filter diff --git a/source/source-mirror.cpp b/source/source-mirror.cpp index 11b28114..6ee2848a 100644 --- a/source/source-mirror.cpp +++ b/source/source-mirror.cpp @@ -57,14 +57,30 @@ #define P_SCALING_BOUNDS_FILLHEIGHT "Source.Mirror.Scaling.Bounds.FillHeight" // Initializer & Finalizer -Source::mirror_factory* sourceMirrorInstance; INITIALIZER(SourceMirrorInit) { - initializerFunctions.push_back([] { sourceMirrorInstance = new Source::mirror_factory(); }); - finalizerFunctions.push_back([] { delete sourceMirrorInstance; }); + initializerFunctions.push_back([] { source::mirror::factory::initialize(); }); + finalizerFunctions.push_back([] { source::mirror::factory::finalize(); }); } -Source::mirror_factory::mirror_factory() +static std::shared_ptr factory_instance = nullptr; + +void source::mirror::factory::initialize() +{ + factory_instance = std::make_shared(); +} + +void source::mirror::factory::finalize() +{ + factory_instance.reset(); +} + +std::shared_ptr source::mirror::factory::get() +{ + return factory_instance; +} + +source::mirror::factory::factory() { memset(&osi, 0, sizeof(obs_source_info)); osi.id = "obs-stream-effects-source-mirror"; @@ -90,14 +106,14 @@ Source::mirror_factory::mirror_factory() obs_register_source(&osi); } -Source::mirror_factory::~mirror_factory() {} +source::mirror::factory::~factory() {} -const char* Source::mirror_factory::get_name(void*) +const char* source::mirror::factory::get_name(void*) { return P_TRANSLATE(S_SOURCE_MIRROR); } -void Source::mirror_factory::get_defaults(obs_data_t* data) +void source::mirror::factory::get_defaults(obs_data_t* data) { obs_data_set_default_string(data, P_SOURCE, ""); obs_data_set_default_bool(data, P_SOURCE_AUDIO, false); @@ -108,7 +124,7 @@ void Source::mirror_factory::get_defaults(obs_data_t* data) obs_data_set_default_int(data, P_SCALING_BOUNDS, (int64_t)obs_bounds_type::OBS_BOUNDS_STRETCH); } -bool Source::mirror_factory::modified_properties(obs_properties_t* pr, obs_property_t* p, obs_data_t* data) +bool source::mirror::factory::modified_properties(obs_properties_t* pr, obs_property_t* p, obs_data_t* data) { if (obs_properties_get(pr, P_SOURCE) == p) { obs_source_t* target = obs_get_source_by_name(obs_data_get_string(data, P_SOURCE)); @@ -151,7 +167,7 @@ static void UpdateSourceList(obs_property_t* p) #endif } -obs_properties_t* Source::mirror_factory::get_properties(void*) +obs_properties_t* source::mirror::factory::get_properties(void*) { obs_properties_t* pr = obs_properties_create(); obs_property_t* p = nullptr; @@ -200,91 +216,91 @@ obs_properties_t* Source::mirror_factory::get_properties(void*) return pr; } -void* Source::mirror_factory::create(obs_data_t* data, obs_source_t* source) +void* source::mirror::factory::create(obs_data_t* data, obs_source_t* source) { - return new Source::mirror(data, source); + return new source::mirror::instance(data, source); } -void Source::mirror_factory::destroy(void* p) +void source::mirror::factory::destroy(void* p) { if (p) { - delete static_cast(p); + delete static_cast(p); } } -uint32_t Source::mirror_factory::get_width(void* p) +uint32_t source::mirror::factory::get_width(void* p) { if (p) { - return static_cast(p)->get_width(); + return static_cast(p)->get_width(); } return 0; } -uint32_t Source::mirror_factory::get_height(void* p) +uint32_t source::mirror::factory::get_height(void* p) { if (p) { - return static_cast(p)->get_height(); + return static_cast(p)->get_height(); } return 0; } -void Source::mirror_factory::update(void* p, obs_data_t* data) +void source::mirror::factory::update(void* p, obs_data_t* data) { if (p) { - static_cast(p)->update(data); + static_cast(p)->update(data); } } -void Source::mirror_factory::activate(void* p) +void source::mirror::factory::activate(void* p) { if (p) { - static_cast(p)->activate(); + static_cast(p)->activate(); } } -void Source::mirror_factory::deactivate(void* p) +void source::mirror::factory::deactivate(void* p) { if (p) { - static_cast(p)->deactivate(); + static_cast(p)->deactivate(); } } -void Source::mirror_factory::video_tick(void* p, float t) +void source::mirror::factory::video_tick(void* p, float t) { if (p) { - static_cast(p)->video_tick(t); + static_cast(p)->video_tick(t); } } -void Source::mirror_factory::video_render(void* p, gs_effect_t* ef) +void source::mirror::factory::video_render(void* p, gs_effect_t* ef) { if (p) { - static_cast(p)->video_render(ef); + static_cast(p)->video_render(ef); } } -void Source::mirror_factory::enum_active_sources(void* p, obs_source_enum_proc_t enum_callback, void* param) +void source::mirror::factory::enum_active_sources(void* p, obs_source_enum_proc_t enum_callback, void* param) { if (p) { - static_cast(p)->enum_active_sources(enum_callback, param); + static_cast(p)->enum_active_sources(enum_callback, param); } } -void Source::mirror_factory::load(void* p, obs_data_t* d) +void source::mirror::factory::load(void* p, obs_data_t* d) { if (p) { - static_cast(p)->load(d); + static_cast(p)->load(d); } } -void Source::mirror_factory::save(void* p, obs_data_t* d) +void source::mirror::factory::save(void* p, obs_data_t* d) { if (p) { - static_cast(p)->save(d); + static_cast(p)->save(d); } } -void Source::mirror::release_input() +void source::mirror::instance::release_input() { // Clear any references to the previous source. if (this->m_source_item) { @@ -298,7 +314,7 @@ void Source::mirror::release_input() this->m_source.reset(); } -void Source::mirror::acquire_input(std::string source_name) +void source::mirror::instance::acquire_input(std::string source_name) { // Acquire new reference to current source. obs_source_t* ref_source = obs_get_source_by_name(source_name.c_str()); @@ -333,12 +349,12 @@ void Source::mirror::acquire_input(std::string source_name) // If everything worked fine, we now set everything up. this->m_source = std::move(new_source); - this->m_source->events.rename += std::bind(&Source::mirror::on_source_rename, this, std::placeholders::_1, + this->m_source->events.rename += std::bind(&source::mirror::instance::on_source_rename, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); try { // Audio this->m_source_audio = std::make_shared(this->m_source); - this->m_source_audio->on.data += std::bind(&Source::mirror::audio_capture_cb, this, std::placeholders::_1, + this->m_source_audio->on.data += std::bind(&source::mirror::instance::audio_capture_cb, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); } catch (...) { P_LOG_ERROR(" Unexpected error during registering audio callback for '%s'.", @@ -346,7 +362,7 @@ void Source::mirror::acquire_input(std::string source_name) } } -Source::mirror::mirror(obs_data_t* data, obs_source_t* src) +source::mirror::instance::instance(obs_data_t* data, obs_source_t* src) : m_self(src), m_active(true), m_tick(0), m_scene_rendered(false), m_rescale_enabled(false), m_rescale_keep_orig_size(false), m_rescale_width(1), m_rescale_height(1), m_rescale_type(obs_scale_type::OBS_SCALE_BICUBIC), m_rescale_bounds(obs_bounds_type::OBS_BOUNDS_STRETCH), @@ -363,10 +379,10 @@ Source::mirror::mirror(obs_data_t* data, obs_source_t* src) for (size_t idx = 0; idx < this->m_audio_data.size(); idx++) { this->m_audio_data[idx].resize(AUDIO_OUTPUT_FRAMES); } - this->m_audio_thread = std::thread(std::bind(&Source::mirror::audio_output_cb, this)); + this->m_audio_thread = std::thread(std::bind(&source::mirror::instance::audio_output_cb, this)); } -Source::mirror::~mirror() +source::mirror::instance::~instance() { release_input(); @@ -382,7 +398,7 @@ Source::mirror::~mirror() this->m_scene.reset(); } -uint32_t Source::mirror::get_width() +uint32_t source::mirror::instance::get_width() { if (this->m_rescale_enabled && this->m_rescale_width > 0 && !this->m_rescale_keep_orig_size) { return this->m_rescale_width; @@ -394,7 +410,7 @@ uint32_t Source::mirror::get_width() return 1; } -uint32_t Source::mirror::get_height() +uint32_t source::mirror::instance::get_height() { if (this->m_rescale_enabled && this->m_rescale_height > 0 && !this->m_rescale_keep_orig_size) return this->m_rescale_height; @@ -405,7 +421,7 @@ uint32_t Source::mirror::get_height() return 1; } -void Source::mirror::update(obs_data_t* data) +void source::mirror::instance::update(obs_data_t* data) { { // User changed the source we are tracking. release_input(); @@ -455,7 +471,7 @@ void Source::mirror::update(obs_data_t* data) } } -void Source::mirror::activate() +void source::mirror::instance::activate() { this->m_active = true; @@ -465,7 +481,7 @@ void Source::mirror::activate() } } -void Source::mirror::deactivate() +void source::mirror::instance::deactivate() { this->m_active = false; } @@ -480,7 +496,7 @@ static inline void mix_audio(float* p_out, float* p_in, size_t pos, size_t count *(out++) += *(in++); } -void Source::mirror::video_tick(float time) +void source::mirror::instance::video_tick(float time) { this->m_tick += time; if (this->m_tick > 0.1f) { @@ -521,7 +537,7 @@ void Source::mirror::video_tick(float time) m_scene_rendered = false; } -void Source::mirror::video_render(gs_effect_t* effect) +void source::mirror::instance::video_render(gs_effect_t* effect) { if ((this->m_rescale_width == 0) || (this->m_rescale_height == 0) || !this->m_source_item || !this->m_scene_texture_renderer) { @@ -554,7 +570,7 @@ void Source::mirror::video_render(gs_effect_t* effect) } } -void Source::mirror::audio_capture_cb(std::shared_ptr source, audio_data const* const audio, bool) +void source::mirror::instance::audio_capture_cb(std::shared_ptr source, audio_data const* const audio, bool) { std::unique_lock ulock(this->m_audio_lock); if (!this->m_audio_enabled) { @@ -592,7 +608,7 @@ void Source::mirror::audio_capture_cb(std::shared_ptr source, audio this->m_audio_notify.notify_all(); } -void Source::mirror::audio_output_cb() +void source::mirror::instance::audio_output_cb() { std::unique_lock ulock(this->m_audio_lock); @@ -606,26 +622,26 @@ void Source::mirror::audio_output_cb() } } -void Source::mirror::enum_active_sources(obs_source_enum_proc_t enum_callback, void* param) +void source::mirror::instance::enum_active_sources(obs_source_enum_proc_t enum_callback, void* param) { if (this->m_scene) { enum_callback(this->m_self, this->m_scene->get(), param); } } -void Source::mirror::load(obs_data_t* data) +void source::mirror::instance::load(obs_data_t* data) { this->update(data); } -void Source::mirror::save(obs_data_t* data) +void source::mirror::instance::save(obs_data_t* data) { if (this->m_source_item) { obs_data_set_string(data, P_SOURCE, obs_source_get_name(m_source->get())); } } -void Source::mirror::on_source_rename(obs::source* source, std::string, std::string) +void source::mirror::instance::on_source_rename(obs::source* source, std::string, std::string) { obs_data_t* ref = obs_source_get_settings(this->m_self); obs_data_set_string(ref, P_SOURCE, obs_source_get_name(source->get())); diff --git a/source/source-mirror.hpp b/source/source-mirror.hpp index 043527a7..0b360ec6 100644 --- a/source/source-mirror.hpp +++ b/source/source-mirror.hpp @@ -40,92 +40,101 @@ #pragma warning(pop) #endif -namespace Source { - class mirror_factory { - obs_source_info osi; +namespace source { + namespace mirror { + class factory { + friend class std::_Ptr_base; - public: - mirror_factory(); - ~mirror_factory(); + obs_source_info osi; - static const char* get_name(void*); - static void get_defaults(obs_data_t*); - static bool modified_properties(obs_properties_t*, obs_property_t*, obs_data_t*); - static obs_properties_t* get_properties(void*); + public: // Singleton + static void initialize(); + static void finalize(); + static std::shared_ptr get(); - static void* create(obs_data_t*, obs_source_t*); - static void destroy(void*); + public: + factory(); + ~factory(); - static uint32_t get_width(void*); - static uint32_t get_height(void*); + static const char* get_name(void*); + static void get_defaults(obs_data_t*); + static bool modified_properties(obs_properties_t*, obs_property_t*, obs_data_t*); + static obs_properties_t* get_properties(void*); - static void update(void*, obs_data_t*); - static void activate(void*); - static void deactivate(void*); - static void video_tick(void*, float); - static void video_render(void*, gs_effect_t*); - static void enum_active_sources(void*, obs_source_enum_proc_t, void*); - static void load(void*, obs_data_t*); - static void save(void*, obs_data_t*); - }; + static void* create(obs_data_t*, obs_source_t*); + static void destroy(void*); - class mirror { - bool m_active; - obs_source_t* m_self; - float_t m_tick; + static uint32_t get_width(void*); + static uint32_t get_height(void*); - // Video Rendering - std::shared_ptr m_scene; - std::shared_ptr m_scene_texture_renderer; - std::shared_ptr m_scene_texture; - bool m_scene_rendered; + static void update(void*, obs_data_t*); + static void activate(void*); + static void deactivate(void*); + static void video_tick(void*, float); + static void video_render(void*, gs_effect_t*); + static void enum_active_sources(void*, obs_source_enum_proc_t, void*); + static void load(void*, obs_data_t*); + static void save(void*, obs_data_t*); + }; - // Rescaling - bool m_rescale_enabled; - uint32_t m_rescale_width; - uint32_t m_rescale_height; - bool m_rescale_keep_orig_size; - obs_scale_type m_rescale_type; - obs_bounds_type m_rescale_bounds; + class instance { + bool m_active; + obs_source_t* m_self; + float_t m_tick; - // Audio Rendering - bool m_audio_enabled; - std::mutex m_audio_lock; - std::condition_variable m_audio_notify; - obs_source_audio m_audio_output; - std::vector> m_audio_data; - std::thread m_audio_thread; - bool m_audio_kill_thread; - bool m_audio_have_output; + // Video Rendering + std::shared_ptr m_scene; + std::shared_ptr m_scene_texture_renderer; + std::shared_ptr m_scene_texture; + bool m_scene_rendered; - // Input - std::shared_ptr m_source; - obs_sceneitem_t* m_source_item; - std::string m_source_name; - std::shared_ptr m_source_audio; + // Rescaling + bool m_rescale_enabled; + uint32_t m_rescale_width; + uint32_t m_rescale_height; + bool m_rescale_keep_orig_size; + obs_scale_type m_rescale_type; + obs_bounds_type m_rescale_bounds; - private: - void release_input(); - void acquire_input(std::string source_name); + // Audio Rendering + bool m_audio_enabled; + std::mutex m_audio_lock; + std::condition_variable m_audio_notify; + obs_source_audio m_audio_output; + std::vector> m_audio_data; + std::thread m_audio_thread; + bool m_audio_kill_thread; + bool m_audio_have_output; - public: - mirror(obs_data_t*, obs_source_t*); - ~mirror(); + // Input + std::shared_ptr m_source; + obs_sceneitem_t* m_source_item; + std::string m_source_name; + std::shared_ptr m_source_audio; - uint32_t get_width(); - uint32_t get_height(); + private: + void release_input(); + void acquire_input(std::string source_name); - void update(obs_data_t*); - void activate(); - void deactivate(); - void video_tick(float); - void video_render(gs_effect_t*); - void audio_capture_cb(std::shared_ptr source, audio_data const* const audio, bool muted); - void audio_output_cb(); - void enum_active_sources(obs_source_enum_proc_t, void*); - void load(obs_data_t*); - void save(obs_data_t*); + public: + instance(obs_data_t*, obs_source_t*); + ~instance(); - void on_source_rename(obs::source* source, std::string new_name, std::string old_name); - }; -}; // namespace Source + uint32_t get_width(); + uint32_t get_height(); + + void update(obs_data_t*); + void activate(); + void deactivate(); + void video_tick(float); + void video_render(gs_effect_t*); + void audio_capture_cb(std::shared_ptr source, audio_data const* const audio, bool muted); + void audio_output_cb(); + void enum_active_sources(obs_source_enum_proc_t, void*); + void load(obs_data_t*); + void save(obs_data_t*); + + void on_source_rename(obs::source* source, std::string new_name, std::string old_name); + }; + } // namespace mirror +}; // namespace source