mirror of
https://github.com/Xaymar/obs-StreamFX
synced 2024-12-29 11:01:23 +00:00
project: Formatting
This commit is contained in:
parent
16f55ca583
commit
b87ca70796
32 changed files with 982 additions and 922 deletions
|
@ -18,21 +18,21 @@
|
|||
*/
|
||||
|
||||
#include "filter-custom-shader.h"
|
||||
#include "strings.h"
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <fstream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include "strings.h"
|
||||
|
||||
extern "C" {
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4201)
|
||||
#include "util/platform.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include "graphics/graphics.h"
|
||||
#include "graphics/matrix4.h"
|
||||
#pragma warning (pop)
|
||||
#include "util/platform.h"
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
#define S "Filter.CustomShader"
|
||||
#define S "Filter.CustomShader"
|
||||
|
||||
/** Shader Definitions
|
||||
* - Only one technique, any number of passes.
|
||||
|
@ -53,36 +53,31 @@ extern "C" {
|
|||
* - $(name)_Texel: Texture Texel Size (1/Texture Size) (float2).
|
||||
**/
|
||||
|
||||
enum class ShaderType : int64_t {
|
||||
Text,
|
||||
File
|
||||
};
|
||||
enum class ShaderType : int64_t { Text, File };
|
||||
|
||||
static filter::CustomShader* handler;
|
||||
INITIALIZER(HandlerInit) {
|
||||
initializerFunctions.push_back([] {
|
||||
handler = new filter::CustomShader();
|
||||
});
|
||||
finalizerFunctions.push_back([] {
|
||||
delete handler;
|
||||
});
|
||||
INITIALIZER(HandlerInit)
|
||||
{
|
||||
initializerFunctions.push_back([] { handler = new filter::CustomShader(); });
|
||||
finalizerFunctions.push_back([] { delete handler; });
|
||||
}
|
||||
|
||||
filter::CustomShader::CustomShader() {
|
||||
filter::CustomShader::CustomShader()
|
||||
{
|
||||
memset(&sourceInfo, 0, sizeof(obs_source_info));
|
||||
sourceInfo.id = "obs-stream-effects-filter-custom-shader";
|
||||
sourceInfo.type = OBS_SOURCE_TYPE_FILTER;
|
||||
sourceInfo.output_flags = OBS_SOURCE_VIDEO;
|
||||
sourceInfo.get_name = get_name;
|
||||
sourceInfo.get_defaults = get_defaults;
|
||||
sourceInfo.id = "obs-stream-effects-filter-custom-shader";
|
||||
sourceInfo.type = OBS_SOURCE_TYPE_FILTER;
|
||||
sourceInfo.output_flags = OBS_SOURCE_VIDEO;
|
||||
sourceInfo.get_name = get_name;
|
||||
sourceInfo.get_defaults = get_defaults;
|
||||
sourceInfo.get_properties = get_properties;
|
||||
|
||||
sourceInfo.create = create;
|
||||
sourceInfo.destroy = destroy;
|
||||
sourceInfo.update = update;
|
||||
sourceInfo.activate = activate;
|
||||
sourceInfo.deactivate = deactivate;
|
||||
sourceInfo.video_tick = video_tick;
|
||||
sourceInfo.create = create;
|
||||
sourceInfo.destroy = destroy;
|
||||
sourceInfo.update = update;
|
||||
sourceInfo.activate = activate;
|
||||
sourceInfo.deactivate = deactivate;
|
||||
sourceInfo.video_tick = video_tick;
|
||||
sourceInfo.video_render = video_render;
|
||||
|
||||
obs_register_source(&sourceInfo);
|
||||
|
@ -90,59 +85,72 @@ filter::CustomShader::CustomShader() {
|
|||
|
||||
filter::CustomShader::~CustomShader() {}
|
||||
|
||||
const char * filter::CustomShader::get_name(void *) {
|
||||
const char* filter::CustomShader::get_name(void*)
|
||||
{
|
||||
return P_TRANSLATE(S);
|
||||
}
|
||||
|
||||
void filter::CustomShader::get_defaults(obs_data_t *data) {
|
||||
void filter::CustomShader::get_defaults(obs_data_t* data)
|
||||
{
|
||||
gfx::effect_source::get_defaults(data);
|
||||
}
|
||||
|
||||
obs_properties_t * filter::CustomShader::get_properties(void *ptr) {
|
||||
obs_properties_t *pr = obs_properties_create_param(ptr, nullptr);
|
||||
obs_properties_t* filter::CustomShader::get_properties(void* ptr)
|
||||
{
|
||||
obs_properties_t* pr = obs_properties_create_param(ptr, nullptr);
|
||||
reinterpret_cast<Instance*>(ptr)->get_properties(pr);
|
||||
return pr;
|
||||
}
|
||||
|
||||
void * filter::CustomShader::create(obs_data_t *data, obs_source_t *src) {
|
||||
void* filter::CustomShader::create(obs_data_t* data, obs_source_t* src)
|
||||
{
|
||||
return new Instance(data, src);
|
||||
}
|
||||
|
||||
void filter::CustomShader::destroy(void *ptr) {
|
||||
void filter::CustomShader::destroy(void* ptr)
|
||||
{
|
||||
delete reinterpret_cast<Instance*>(ptr);
|
||||
}
|
||||
|
||||
uint32_t filter::CustomShader::get_width(void *ptr) {
|
||||
uint32_t filter::CustomShader::get_width(void* ptr)
|
||||
{
|
||||
return reinterpret_cast<Instance*>(ptr)->get_width();
|
||||
}
|
||||
|
||||
uint32_t filter::CustomShader::get_height(void *ptr) {
|
||||
uint32_t filter::CustomShader::get_height(void* ptr)
|
||||
{
|
||||
return reinterpret_cast<Instance*>(ptr)->get_height();
|
||||
}
|
||||
|
||||
void filter::CustomShader::update(void *ptr, obs_data_t *data) {
|
||||
void filter::CustomShader::update(void* ptr, obs_data_t* data)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->update(data);
|
||||
}
|
||||
|
||||
void filter::CustomShader::activate(void *ptr) {
|
||||
void filter::CustomShader::activate(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->activate();
|
||||
}
|
||||
|
||||
void filter::CustomShader::deactivate(void *ptr) {
|
||||
void filter::CustomShader::deactivate(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->deactivate();
|
||||
}
|
||||
|
||||
void filter::CustomShader::video_tick(void *ptr, float time) {
|
||||
void filter::CustomShader::video_tick(void* ptr, float time)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->video_tick(time);
|
||||
}
|
||||
|
||||
void filter::CustomShader::video_render(void *ptr, gs_effect_t *effect) {
|
||||
void filter::CustomShader::video_render(void* ptr, gs_effect_t* effect)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->video_render(effect);
|
||||
}
|
||||
|
||||
filter::CustomShader::Instance::Instance(obs_data_t *data, obs_source_t *source) : gfx::effect_source(data, source) {
|
||||
filter::CustomShader::Instance::Instance(obs_data_t* data, obs_source_t* source) : gfx::effect_source(data, source)
|
||||
{
|
||||
m_defaultShaderPath = "shaders/filter/example.effect";
|
||||
m_renderTarget = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
m_renderTarget = std::make_shared<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
update(data);
|
||||
}
|
||||
|
||||
|
@ -299,28 +307,27 @@ filter::CustomShader::Instance::~Instance() {}
|
|||
// }
|
||||
//}
|
||||
|
||||
uint32_t filter::CustomShader::Instance::get_width() {
|
||||
uint32_t filter::CustomShader::Instance::get_width()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t filter::CustomShader::Instance::get_height() {
|
||||
uint32_t filter::CustomShader::Instance::get_height()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool filter::CustomShader::Instance::is_special_parameter(std::string name, gs::effect_parameter::type type) {
|
||||
bool filter::CustomShader::Instance::is_special_parameter(std::string name, gs::effect_parameter::type type)
|
||||
{
|
||||
std::pair<std::string, gs::effect_parameter::type> reservedParameters[] = {
|
||||
{ "ViewProj", gs::effect_parameter::type::Matrix },
|
||||
{ "ViewSize", gs::effect_parameter::type::Float2 },
|
||||
{ "ViewSizeI", gs::effect_parameter::type::Integer2 },
|
||||
{ "Time", gs::effect_parameter::type::Float },
|
||||
{ "TimeActive", gs::effect_parameter::type::Float },
|
||||
{ "Image", gs::effect_parameter::type::Texture },
|
||||
{"ViewProj", gs::effect_parameter::type::Matrix}, {"ViewSize", gs::effect_parameter::type::Float2},
|
||||
{"ViewSizeI", gs::effect_parameter::type::Integer2}, {"Time", gs::effect_parameter::type::Float},
|
||||
{"TimeActive", gs::effect_parameter::type::Float}, {"Image", gs::effect_parameter::type::Texture},
|
||||
};
|
||||
std::pair<std::string, gs::effect_parameter::type> textureParameters[] = {
|
||||
{ "Size", gs::effect_parameter::type::Float2 },
|
||||
{ "SizeI", gs::effect_parameter::type::Integer2 },
|
||||
{ "Texel", gs::effect_parameter::type::Float2 }
|
||||
};
|
||||
{"Size", gs::effect_parameter::type::Float2},
|
||||
{"SizeI", gs::effect_parameter::type::Integer2},
|
||||
{"Texel", gs::effect_parameter::type::Float2}};
|
||||
|
||||
for (auto& kv : reservedParameters) {
|
||||
if ((name == kv.first) && (type == kv.second))
|
||||
|
@ -331,7 +338,7 @@ bool filter::CustomShader::Instance::is_special_parameter(std::string name, gs::
|
|||
size_t posUnderscore = name.find_last_of('_');
|
||||
if (posUnderscore != std::string::npos) {
|
||||
std::string firstPart, secondPart;
|
||||
firstPart = name.substr(0, posUnderscore);
|
||||
firstPart = name.substr(0, posUnderscore);
|
||||
secondPart = name.substr(posUnderscore + 1);
|
||||
|
||||
try {
|
||||
|
@ -350,7 +357,8 @@ bool filter::CustomShader::Instance::is_special_parameter(std::string name, gs::
|
|||
return false;
|
||||
}
|
||||
|
||||
bool filter::CustomShader::Instance::apply_special_parameters(uint32_t viewW, uint32_t viewH) {
|
||||
bool filter::CustomShader::Instance::apply_special_parameters(uint32_t viewW, uint32_t viewH)
|
||||
{
|
||||
std::unique_ptr<gs::texture> imageTexture;
|
||||
m_renderTarget->get_texture(imageTexture);
|
||||
|
||||
|
@ -360,38 +368,37 @@ bool filter::CustomShader::Instance::apply_special_parameters(uint32_t viewW, ui
|
|||
return false;
|
||||
}
|
||||
if (m_shader.effect->has_parameter("Image_Size", gs::effect_parameter::type::Float2)) {
|
||||
m_shader.effect->get_parameter("Image_Size").set_float2(
|
||||
float_t(imageTexture->get_width()),
|
||||
float_t(imageTexture->get_height()));
|
||||
m_shader.effect->get_parameter("Image_Size")
|
||||
.set_float2(float_t(imageTexture->get_width()), float_t(imageTexture->get_height()));
|
||||
}
|
||||
if (m_shader.effect->has_parameter("Image_SizeI"/*, gs::effect_parameter::type::Integer2*/)) {
|
||||
m_shader.effect->get_parameter("Image_SizeI").set_int2(
|
||||
imageTexture->get_width(),
|
||||
imageTexture->get_height());
|
||||
if (m_shader.effect->has_parameter("Image_SizeI" /*, gs::effect_parameter::type::Integer2*/)) {
|
||||
m_shader.effect->get_parameter("Image_SizeI").set_int2(imageTexture->get_width(), imageTexture->get_height());
|
||||
}
|
||||
if (m_shader.effect->has_parameter("Image_Texel", gs::effect_parameter::type::Float2)) {
|
||||
m_shader.effect->get_parameter("Image_Texel").set_float2(
|
||||
float_t(1.0 / imageTexture->get_width()),
|
||||
float_t(1.0 / imageTexture->get_height()));
|
||||
m_shader.effect->get_parameter("Image_Texel")
|
||||
.set_float2(float_t(1.0 / imageTexture->get_width()), float_t(1.0 / imageTexture->get_height()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool filter::CustomShader::Instance::video_tick_impl(float_t time) {
|
||||
bool filter::CustomShader::Instance::video_tick_impl(float_t time)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool filter::CustomShader::Instance::video_render_impl(gs_effect_t* parent_effect, uint32_t viewW, uint32_t viewH) {
|
||||
bool filter::CustomShader::Instance::video_render_impl(gs_effect_t* parent_effect, uint32_t viewW, uint32_t viewH)
|
||||
{
|
||||
// Render original source to render target.
|
||||
{
|
||||
auto op = m_renderTarget->render(viewW, viewH);
|
||||
vec4 black; vec4_zero(&black);
|
||||
vec4 black;
|
||||
vec4_zero(&black);
|
||||
gs_ortho(0, (float_t)viewW, 0, (float_t)viewH, 0, 1);
|
||||
gs_clear(GS_CLEAR_COLOR, &black, 0, 0);
|
||||
if (obs_source_process_filter_begin(m_source, GS_RGBA, OBS_NO_DIRECT_RENDERING)) {
|
||||
obs_source_process_filter_end(m_source,
|
||||
parent_effect ? parent_effect : obs_get_base_effect(OBS_EFFECT_DEFAULT), viewW, viewH);
|
||||
obs_source_process_filter_end(
|
||||
m_source, parent_effect ? parent_effect : obs_get_base_effect(OBS_EFFECT_DEFAULT), viewW, viewH);
|
||||
}
|
||||
}
|
||||
gs_texture_t* sourceTexture = m_renderTarget->get_object();
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "plugin.h"
|
||||
#include "gs-effect.h"
|
||||
#include "gs-rendertarget.h"
|
||||
#include <inttypes.h>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <inttypes.h>
|
||||
#include "gfx-effect-source.h"
|
||||
#include "gs-effect.h"
|
||||
#include "gs-rendertarget.h"
|
||||
#include "plugin.h"
|
||||
|
||||
namespace filter {
|
||||
class CustomShader {
|
||||
|
@ -32,19 +32,19 @@ namespace filter {
|
|||
CustomShader();
|
||||
~CustomShader();
|
||||
|
||||
static const char *get_name(void *);
|
||||
static void get_defaults(obs_data_t *);
|
||||
static obs_properties_t *get_properties(void *);
|
||||
static const char* get_name(void*);
|
||||
static void get_defaults(obs_data_t*);
|
||||
static obs_properties_t* get_properties(void*);
|
||||
|
||||
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 video_tick(void *, float);
|
||||
static void video_render(void *, gs_effect_t *);
|
||||
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 video_tick(void*, float);
|
||||
static void video_render(void*, gs_effect_t*);
|
||||
|
||||
private:
|
||||
obs_source_info sourceInfo;
|
||||
|
@ -56,7 +56,7 @@ namespace filter {
|
|||
std::shared_ptr<gs::rendertarget> m_renderTarget;
|
||||
|
||||
protected:
|
||||
bool apply_special_parameters(uint32_t viewW, uint32_t viewH);
|
||||
bool apply_special_parameters(uint32_t viewW, uint32_t viewH);
|
||||
virtual bool is_special_parameter(std::string name, gs::effect_parameter::type type) override;
|
||||
virtual bool video_tick_impl(float_t time) override;
|
||||
virtual bool video_render_impl(gs_effect_t* parent_effect, uint32_t viewW, uint32_t viewH) override;
|
||||
|
@ -64,9 +64,9 @@ namespace filter {
|
|||
public:
|
||||
Instance(obs_data_t*, obs_source_t*);
|
||||
~Instance();
|
||||
|
||||
|
||||
uint32_t get_width();
|
||||
uint32_t get_height();
|
||||
uint32_t get_height();
|
||||
};
|
||||
};
|
||||
}
|
||||
} // namespace filter
|
||||
|
|
|
@ -22,62 +22,64 @@
|
|||
|
||||
// Initializer & Finalizer
|
||||
static filter::Displacement* filterDisplacementInstance;
|
||||
INITIALIZER(FilterDisplacementInit) {
|
||||
initializerFunctions.push_back([] {
|
||||
filterDisplacementInstance = new filter::Displacement();
|
||||
});
|
||||
finalizerFunctions.push_back([] {
|
||||
delete filterDisplacementInstance;
|
||||
});
|
||||
INITIALIZER(FilterDisplacementInit)
|
||||
{
|
||||
initializerFunctions.push_back([] { filterDisplacementInstance = new filter::Displacement(); });
|
||||
finalizerFunctions.push_back([] { delete filterDisplacementInstance; });
|
||||
}
|
||||
|
||||
filter::Displacement::Displacement() {
|
||||
filter::Displacement::Displacement()
|
||||
{
|
||||
memset(&sourceInfo, 0, sizeof(obs_source_info));
|
||||
sourceInfo.id = "obs-stream-effects-filter-displacement";
|
||||
sourceInfo.type = OBS_SOURCE_TYPE_FILTER;
|
||||
sourceInfo.output_flags = OBS_SOURCE_VIDEO;
|
||||
sourceInfo.get_name = get_name;
|
||||
sourceInfo.get_defaults = get_defaults;
|
||||
sourceInfo.id = "obs-stream-effects-filter-displacement";
|
||||
sourceInfo.type = OBS_SOURCE_TYPE_FILTER;
|
||||
sourceInfo.output_flags = OBS_SOURCE_VIDEO;
|
||||
sourceInfo.get_name = get_name;
|
||||
sourceInfo.get_defaults = get_defaults;
|
||||
sourceInfo.get_properties = get_properties;
|
||||
|
||||
sourceInfo.create = create;
|
||||
sourceInfo.destroy = destroy;
|
||||
sourceInfo.update = update;
|
||||
sourceInfo.activate = activate;
|
||||
sourceInfo.deactivate = deactivate;
|
||||
sourceInfo.show = show;
|
||||
sourceInfo.hide = hide;
|
||||
sourceInfo.video_tick = video_tick;
|
||||
sourceInfo.create = create;
|
||||
sourceInfo.destroy = destroy;
|
||||
sourceInfo.update = update;
|
||||
sourceInfo.activate = activate;
|
||||
sourceInfo.deactivate = deactivate;
|
||||
sourceInfo.show = show;
|
||||
sourceInfo.hide = hide;
|
||||
sourceInfo.video_tick = video_tick;
|
||||
sourceInfo.video_render = video_render;
|
||||
|
||||
obs_register_source(&sourceInfo);
|
||||
}
|
||||
|
||||
filter::Displacement::~Displacement() {
|
||||
filter::Displacement::~Displacement() {}
|
||||
|
||||
}
|
||||
|
||||
const char * filter::Displacement::get_name(void *) {
|
||||
const char* filter::Displacement::get_name(void*)
|
||||
{
|
||||
return P_TRANSLATE(S_FILTER_DISPLACEMENT);
|
||||
}
|
||||
|
||||
void * filter::Displacement::create(obs_data_t *data, obs_source_t *source) {
|
||||
void* filter::Displacement::create(obs_data_t* data, obs_source_t* source)
|
||||
{
|
||||
return new Instance(data, source);
|
||||
}
|
||||
|
||||
void filter::Displacement::destroy(void *ptr) {
|
||||
void filter::Displacement::destroy(void* ptr)
|
||||
{
|
||||
delete reinterpret_cast<Instance*>(ptr);
|
||||
}
|
||||
|
||||
uint32_t filter::Displacement::get_width(void *ptr) {
|
||||
uint32_t filter::Displacement::get_width(void* ptr)
|
||||
{
|
||||
return reinterpret_cast<Instance*>(ptr)->get_width();
|
||||
}
|
||||
|
||||
uint32_t filter::Displacement::get_height(void *ptr) {
|
||||
uint32_t filter::Displacement::get_height(void* ptr)
|
||||
{
|
||||
return reinterpret_cast<Instance*>(ptr)->get_height();
|
||||
}
|
||||
|
||||
void filter::Displacement::get_defaults(obs_data_t *data) {
|
||||
void filter::Displacement::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);
|
||||
obs_data_set_default_double(data, S_FILTER_DISPLACEMENT_RATIO, 0);
|
||||
|
@ -85,66 +87,71 @@ void filter::Displacement::get_defaults(obs_data_t *data) {
|
|||
bfree(disp);
|
||||
}
|
||||
|
||||
obs_properties_t * filter::Displacement::get_properties(void *ptr) {
|
||||
obs_properties_t *pr = obs_properties_create();
|
||||
obs_properties_t* filter::Displacement::get_properties(void* ptr)
|
||||
{
|
||||
obs_properties_t* pr = obs_properties_create();
|
||||
|
||||
std::string path = "";
|
||||
if (ptr)
|
||||
path = reinterpret_cast<Instance*>(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());
|
||||
obs_properties_add_float_slider(pr, S_FILTER_DISPLACEMENT_RATIO,
|
||||
P_TRANSLATE(S_FILTER_DISPLACEMENT_RATIO), 0, 1, 0.01);
|
||||
obs_properties_add_float_slider(pr, S_FILTER_DISPLACEMENT_SCALE,
|
||||
P_TRANSLATE(S_FILTER_DISPLACEMENT_SCALE), -1000, 1000, 0.01);
|
||||
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());
|
||||
obs_properties_add_float_slider(pr, S_FILTER_DISPLACEMENT_RATIO, P_TRANSLATE(S_FILTER_DISPLACEMENT_RATIO), 0, 1,
|
||||
0.01);
|
||||
obs_properties_add_float_slider(pr, S_FILTER_DISPLACEMENT_SCALE, P_TRANSLATE(S_FILTER_DISPLACEMENT_SCALE), -1000,
|
||||
1000, 0.01);
|
||||
return pr;
|
||||
}
|
||||
|
||||
void filter::Displacement::update(void *ptr, obs_data_t *data) {
|
||||
void filter::Displacement::update(void* ptr, obs_data_t* data)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->update(data);
|
||||
}
|
||||
|
||||
void filter::Displacement::activate(void *ptr) {
|
||||
void filter::Displacement::activate(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->activate();
|
||||
}
|
||||
|
||||
void filter::Displacement::deactivate(void *ptr) {
|
||||
void filter::Displacement::deactivate(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->deactivate();
|
||||
}
|
||||
|
||||
void filter::Displacement::show(void *ptr) {
|
||||
void filter::Displacement::show(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->show();
|
||||
}
|
||||
|
||||
void filter::Displacement::hide(void *ptr) {
|
||||
void filter::Displacement::hide(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->hide();
|
||||
}
|
||||
|
||||
void filter::Displacement::video_tick(void *ptr, float time) {
|
||||
void filter::Displacement::video_tick(void* ptr, float time)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->video_tick(time);
|
||||
}
|
||||
|
||||
void filter::Displacement::video_render(void *ptr, gs_effect_t *effect) {
|
||||
void filter::Displacement::video_render(void* ptr, gs_effect_t* effect)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->video_render(effect);
|
||||
}
|
||||
|
||||
filter::Displacement::Instance::Instance(obs_data_t *data,
|
||||
obs_source_t *context) {
|
||||
this->dispmap.texture = nullptr;
|
||||
this->dispmap.createTime = 0;
|
||||
filter::Displacement::Instance::Instance(obs_data_t* data, obs_source_t* context)
|
||||
{
|
||||
this->dispmap.texture = nullptr;
|
||||
this->dispmap.createTime = 0;
|
||||
this->dispmap.modifiedTime = 0;
|
||||
this->dispmap.size = 0;
|
||||
this->timer = 0;
|
||||
this->context = context;
|
||||
this->dispmap.size = 0;
|
||||
this->timer = 0;
|
||||
this->context = context;
|
||||
|
||||
obs_enter_graphics();
|
||||
char* effectFile = obs_module_file("effects/displace.effect");
|
||||
char* effectFile = obs_module_file("effects/displace.effect");
|
||||
char* errorMessage = nullptr;
|
||||
this->customEffect = gs_effect_create_from_file(effectFile,
|
||||
&errorMessage);
|
||||
this->customEffect = gs_effect_create_from_file(effectFile, &errorMessage);
|
||||
bfree(effectFile);
|
||||
if (errorMessage != nullptr) {
|
||||
P_LOG_ERROR("%s", errorMessage);
|
||||
|
@ -155,30 +162,30 @@ filter::Displacement::Instance::Instance(obs_data_t *data,
|
|||
update(data);
|
||||
}
|
||||
|
||||
filter::Displacement::Instance::~Instance() {
|
||||
filter::Displacement::Instance::~Instance()
|
||||
{
|
||||
obs_enter_graphics();
|
||||
gs_effect_destroy(customEffect);
|
||||
gs_texture_destroy(dispmap.texture);
|
||||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
void filter::Displacement::Instance::update(obs_data_t *data) {
|
||||
updateDisplacementMap(obs_data_get_string(data,
|
||||
S_FILTER_DISPLACEMENT_FILE));
|
||||
void filter::Displacement::Instance::update(obs_data_t* data)
|
||||
{
|
||||
updateDisplacementMap(obs_data_get_string(data, S_FILTER_DISPLACEMENT_FILE));
|
||||
|
||||
distance = float_t(obs_data_get_double(data,
|
||||
S_FILTER_DISPLACEMENT_RATIO));
|
||||
vec2_set(&displacementScale,
|
||||
float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_SCALE)),
|
||||
float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_SCALE))
|
||||
);
|
||||
distance = float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_RATIO));
|
||||
vec2_set(&displacementScale, float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_SCALE)),
|
||||
float_t(obs_data_get_double(data, S_FILTER_DISPLACEMENT_SCALE)));
|
||||
}
|
||||
|
||||
uint32_t filter::Displacement::Instance::get_width() {
|
||||
uint32_t filter::Displacement::Instance::get_width()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t filter::Displacement::Instance::get_height() {
|
||||
uint32_t filter::Displacement::Instance::get_height()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -190,7 +197,8 @@ void filter::Displacement::Instance::show() {}
|
|||
|
||||
void filter::Displacement::Instance::hide() {}
|
||||
|
||||
void filter::Displacement::Instance::video_tick(float time) {
|
||||
void filter::Displacement::Instance::video_tick(float time)
|
||||
{
|
||||
timer += time;
|
||||
if (timer >= 1.0) {
|
||||
timer -= 1.0;
|
||||
|
@ -198,34 +206,30 @@ void filter::Displacement::Instance::video_tick(float time) {
|
|||
}
|
||||
}
|
||||
|
||||
float interp(float a, float b, float v) {
|
||||
float interp(float a, float b, float v)
|
||||
{
|
||||
return (a * (1.0f - v)) + (b * v);
|
||||
}
|
||||
|
||||
void filter::Displacement::Instance::video_render(gs_effect_t *) {
|
||||
obs_source_t *parent = obs_filter_get_parent(context);
|
||||
obs_source_t *target = obs_filter_get_target(context);
|
||||
uint32_t
|
||||
baseW = obs_source_get_base_width(target),
|
||||
baseH = obs_source_get_base_height(target);
|
||||
void filter::Displacement::Instance::video_render(gs_effect_t*)
|
||||
{
|
||||
obs_source_t* parent = obs_filter_get_parent(context);
|
||||
obs_source_t* target = obs_filter_get_target(context);
|
||||
uint32_t baseW = obs_source_get_base_width(target), baseH = obs_source_get_base_height(target);
|
||||
|
||||
// Skip rendering if our target, parent or context is not valid.
|
||||
if (!target || !parent || !context || !dispmap.texture
|
||||
|| !baseW || !baseH) {
|
||||
if (!target || !parent || !context || !dispmap.texture || !baseW || !baseH) {
|
||||
obs_source_skip_video_filter(context);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obs_source_process_filter_begin(context, GS_RGBA,
|
||||
OBS_ALLOW_DIRECT_RENDERING))
|
||||
if (!obs_source_process_filter_begin(context, GS_RGBA, OBS_ALLOW_DIRECT_RENDERING))
|
||||
return;
|
||||
|
||||
gs_eparam_t *param;
|
||||
gs_eparam_t* param;
|
||||
|
||||
vec2 texelScale;
|
||||
vec2_set(&texelScale,
|
||||
interp((1.0f / baseW), 1.0f, distance),
|
||||
interp((1.0f / baseH), 1.0f, distance));
|
||||
vec2_set(&texelScale, interp((1.0f / baseW), 1.0f, distance), interp((1.0f / baseH), 1.0f, distance));
|
||||
param = gs_effect_get_param_by_name(customEffect, "texelScale");
|
||||
if (param)
|
||||
gs_effect_set_vec2(param, &texelScale);
|
||||
|
@ -247,24 +251,25 @@ void filter::Displacement::Instance::video_render(gs_effect_t *) {
|
|||
obs_source_process_filter_end(context, customEffect, baseW, baseH);
|
||||
}
|
||||
|
||||
std::string filter::Displacement::Instance::get_file() {
|
||||
std::string filter::Displacement::Instance::get_file()
|
||||
{
|
||||
return dispmap.file;
|
||||
}
|
||||
|
||||
void filter::Displacement::Instance::updateDisplacementMap(std::string file) {
|
||||
void filter::Displacement::Instance::updateDisplacementMap(std::string file)
|
||||
{
|
||||
bool shouldUpdateTexture = false;
|
||||
|
||||
// Different File
|
||||
if (file != dispmap.file) {
|
||||
dispmap.file = file;
|
||||
dispmap.file = file;
|
||||
shouldUpdateTexture = true;
|
||||
} else { // Different Timestamps
|
||||
struct stat stats;
|
||||
if (os_stat(dispmap.file.c_str(), &stats) != 0) {
|
||||
shouldUpdateTexture = shouldUpdateTexture ||
|
||||
(dispmap.createTime != stats.st_ctime) ||
|
||||
(dispmap.modifiedTime != stats.st_mtime);
|
||||
dispmap.createTime = stats.st_ctime;
|
||||
shouldUpdateTexture = shouldUpdateTexture || (dispmap.createTime != stats.st_ctime)
|
||||
|| (dispmap.modifiedTime != stats.st_mtime);
|
||||
dispmap.createTime = stats.st_ctime;
|
||||
dispmap.modifiedTime = stats.st_mtime;
|
||||
}
|
||||
}
|
||||
|
@ -276,8 +281,7 @@ void filter::Displacement::Instance::updateDisplacementMap(std::string file) {
|
|||
dispmap.texture = nullptr;
|
||||
}
|
||||
if (os_file_exists(file.c_str()))
|
||||
dispmap.texture =
|
||||
gs_texture_create_from_file(dispmap.file.c_str());
|
||||
dispmap.texture = gs_texture_create_from_file(dispmap.file.c_str());
|
||||
obs_leave_graphics();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,20 +21,20 @@
|
|||
#include "plugin.h"
|
||||
|
||||
extern "C" {
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4201)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include <obs-source.h>
|
||||
#include <util/platform.h>
|
||||
#pragma warning (pop)
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
#include <string>
|
||||
|
||||
#define S_FILTER_DISPLACEMENT "Filter.Displacement"
|
||||
#define S_FILTER_DISPLACEMENT_FILE "Filter.Displacement.File"
|
||||
#define S_FILTER_DISPLACEMENT_FILE_TYPES "Filter.Displacement.File.Types"
|
||||
#define S_FILTER_DISPLACEMENT_RATIO "Filter.Displacement.Ratio"
|
||||
#define S_FILTER_DISPLACEMENT_SCALE "Filter.Displacement.Scale"
|
||||
#define S_FILTER_DISPLACEMENT "Filter.Displacement"
|
||||
#define S_FILTER_DISPLACEMENT_FILE "Filter.Displacement.File"
|
||||
#define S_FILTER_DISPLACEMENT_FILE_TYPES "Filter.Displacement.File.Types"
|
||||
#define S_FILTER_DISPLACEMENT_RATIO "Filter.Displacement.Ratio"
|
||||
#define S_FILTER_DISPLACEMENT_SCALE "Filter.Displacement.Scale"
|
||||
|
||||
namespace filter {
|
||||
class Displacement {
|
||||
|
@ -42,21 +42,21 @@ namespace filter {
|
|||
Displacement();
|
||||
~Displacement();
|
||||
|
||||
static const char *get_name(void *);
|
||||
static const char* get_name(void*);
|
||||
|
||||
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 *);
|
||||
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*);
|
||||
|
||||
private:
|
||||
obs_source_info sourceInfo;
|
||||
|
@ -67,35 +67,34 @@ namespace filter {
|
|||
Instance(obs_data_t*, obs_source_t*);
|
||||
~Instance();
|
||||
|
||||
void update(obs_data_t*);
|
||||
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 activate();
|
||||
void deactivate();
|
||||
void show();
|
||||
void hide();
|
||||
void video_tick(float);
|
||||
void video_render(gs_effect_t*);
|
||||
|
||||
std::string get_file();
|
||||
|
||||
private:
|
||||
void updateDisplacementMap(std::string file);
|
||||
|
||||
obs_source_t *context;
|
||||
gs_effect_t *customEffect;
|
||||
float_t distance;
|
||||
vec2 displacementScale;
|
||||
obs_source_t* context;
|
||||
gs_effect_t* customEffect;
|
||||
float_t distance;
|
||||
vec2 displacementScale;
|
||||
struct {
|
||||
std::string file;
|
||||
|
||||
gs_texture_t* texture;
|
||||
time_t createTime,
|
||||
modifiedTime;
|
||||
size_t size;
|
||||
time_t createTime, modifiedTime;
|
||||
size_t size;
|
||||
} dispmap;
|
||||
|
||||
float_t timer;
|
||||
};
|
||||
};
|
||||
}
|
||||
} // namespace filter
|
||||
|
|
|
@ -18,81 +18,70 @@
|
|||
*/
|
||||
|
||||
#include "filter-shape.h"
|
||||
#include "strings.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "strings.h"
|
||||
|
||||
extern "C" {
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4201)
|
||||
#include "util/platform.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include "graphics/graphics.h"
|
||||
#include "graphics/matrix4.h"
|
||||
#pragma warning (pop)
|
||||
#include "util/platform.h"
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
// Initializer & Finalizer
|
||||
static filter::Shape* filterShapeInstance;
|
||||
INITIALIZER(FilterShapeInit) {
|
||||
initializerFunctions.push_back([] {
|
||||
filterShapeInstance = new filter::Shape();
|
||||
});
|
||||
finalizerFunctions.push_back([] {
|
||||
delete filterShapeInstance;
|
||||
});
|
||||
INITIALIZER(FilterShapeInit)
|
||||
{
|
||||
initializerFunctions.push_back([] { filterShapeInstance = new filter::Shape(); });
|
||||
finalizerFunctions.push_back([] { delete filterShapeInstance; });
|
||||
}
|
||||
|
||||
typedef std::pair<uint32_t, std::string> cacheKey;
|
||||
typedef std::pair<uint32_t, std::string> cacheKey;
|
||||
typedef std::pair<std::string, std::string> cacheValue;
|
||||
static std::map<cacheKey, cacheValue> cache;
|
||||
static const uint32_t minimumPoints = 3;
|
||||
static const uint32_t maximumPoints = 16;
|
||||
static std::map<cacheKey, cacheValue> cache;
|
||||
static const uint32_t minimumPoints = 3;
|
||||
static const uint32_t maximumPoints = 16;
|
||||
|
||||
static void initialize() {
|
||||
static void initialize()
|
||||
{
|
||||
if (cache.size() != 0)
|
||||
return;
|
||||
for (uint32_t point = 0; point < maximumPoints; point++) {
|
||||
std::vector<char> handle(1024), name(1024);
|
||||
const char* vals[] = {
|
||||
P_SHAPE_POINT_X,
|
||||
P_SHAPE_POINT_Y,
|
||||
P_SHAPE_POINT_U,
|
||||
P_SHAPE_POINT_V
|
||||
};
|
||||
const char* vals[] = {P_SHAPE_POINT_X, P_SHAPE_POINT_Y, P_SHAPE_POINT_U, P_SHAPE_POINT_V};
|
||||
for (const char* v : vals) {
|
||||
snprintf(handle.data(), handle.size(), "%s.%" PRIu32, v,
|
||||
point);
|
||||
snprintf(name.data(), name.size(), P_TRANSLATE(v),
|
||||
point);
|
||||
cacheValue x = std::make_pair(
|
||||
std::string(handle.data()),
|
||||
std::string(name.data()));
|
||||
cache.insert(std::make_pair(std::make_pair(point, v),
|
||||
x));
|
||||
snprintf(handle.data(), handle.size(), "%s.%" PRIu32, v, point);
|
||||
snprintf(name.data(), name.size(), P_TRANSLATE(v), point);
|
||||
cacheValue x = std::make_pair(std::string(handle.data()), std::string(name.data()));
|
||||
cache.insert(std::make_pair(std::make_pair(point, v), x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filter::Shape::Shape() {
|
||||
filter::Shape::Shape()
|
||||
{
|
||||
return; // Disabled for the time being. 3D Transform is better for this.
|
||||
memset(&sourceInfo, 0, sizeof(obs_source_info));
|
||||
sourceInfo.id = "obs-stream-effects-filter-shape";
|
||||
sourceInfo.type = OBS_SOURCE_TYPE_FILTER;
|
||||
sourceInfo.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_DEPRECATED;
|
||||
sourceInfo.get_name = get_name;
|
||||
sourceInfo.get_defaults = get_defaults;
|
||||
sourceInfo.id = "obs-stream-effects-filter-shape";
|
||||
sourceInfo.type = OBS_SOURCE_TYPE_FILTER;
|
||||
sourceInfo.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_DEPRECATED;
|
||||
sourceInfo.get_name = get_name;
|
||||
sourceInfo.get_defaults = get_defaults;
|
||||
sourceInfo.get_properties = get_properties;
|
||||
|
||||
sourceInfo.create = create;
|
||||
sourceInfo.destroy = destroy;
|
||||
sourceInfo.update = update;
|
||||
sourceInfo.activate = activate;
|
||||
sourceInfo.deactivate = deactivate;
|
||||
sourceInfo.show = show;
|
||||
sourceInfo.hide = hide;
|
||||
sourceInfo.video_tick = video_tick;
|
||||
sourceInfo.create = create;
|
||||
sourceInfo.destroy = destroy;
|
||||
sourceInfo.update = update;
|
||||
sourceInfo.activate = activate;
|
||||
sourceInfo.deactivate = deactivate;
|
||||
sourceInfo.show = show;
|
||||
sourceInfo.hide = hide;
|
||||
sourceInfo.video_tick = video_tick;
|
||||
sourceInfo.video_render = video_render;
|
||||
|
||||
obs_register_source(&sourceInfo);
|
||||
|
@ -100,83 +89,57 @@ filter::Shape::Shape() {
|
|||
initialize();
|
||||
}
|
||||
|
||||
filter::Shape::~Shape() {
|
||||
filter::Shape::~Shape() {}
|
||||
|
||||
}
|
||||
|
||||
const char * filter::Shape::get_name(void *) {
|
||||
const char* filter::Shape::get_name(void*)
|
||||
{
|
||||
return "Shape";
|
||||
}
|
||||
|
||||
void filter::Shape::get_defaults(obs_data_t *data) {
|
||||
void filter::Shape::get_defaults(obs_data_t* data)
|
||||
{
|
||||
obs_data_set_default_bool(data, P_SHAPE_LOOP, true);
|
||||
obs_data_set_default_int(data, P_SHAPE_POINTS, minimumPoints);
|
||||
|
||||
for (uint32_t point = 0; point < maximumPoints; point++) {
|
||||
const char* vals[] = {
|
||||
P_SHAPE_POINT_X,
|
||||
P_SHAPE_POINT_Y,
|
||||
P_SHAPE_POINT_U,
|
||||
P_SHAPE_POINT_V
|
||||
};
|
||||
const char* vals[] = {P_SHAPE_POINT_X, P_SHAPE_POINT_Y, P_SHAPE_POINT_U, P_SHAPE_POINT_V};
|
||||
for (const char* v : vals) {
|
||||
auto strings = cache.find(std::make_pair(point, v));
|
||||
if (strings != cache.end()) {
|
||||
obs_data_set_default_double(data,
|
||||
strings->second.first.c_str(), 0);
|
||||
obs_data_set_default_double(data, strings->second.first.c_str(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obs_properties_t * filter::Shape::get_properties(void *) {
|
||||
obs_properties_t *pr = obs_properties_create();
|
||||
obs_property_t* p = NULL;
|
||||
obs_properties_t* filter::Shape::get_properties(void*)
|
||||
{
|
||||
obs_properties_t* pr = obs_properties_create();
|
||||
obs_property_t* p = NULL;
|
||||
|
||||
p = obs_properties_add_bool(pr, P_SHAPE_LOOP,
|
||||
P_TRANSLATE(P_SHAPE_LOOP));
|
||||
p = obs_properties_add_bool(pr, P_SHAPE_LOOP, P_TRANSLATE(P_SHAPE_LOOP));
|
||||
obs_property_set_long_description(p, P_DESC(P_SHAPE_LOOP));
|
||||
|
||||
p = obs_properties_add_list(pr, P_SHAPE_MODE, P_TRANSLATE(P_SHAPE_MODE),
|
||||
obs_combo_type::OBS_COMBO_TYPE_LIST,
|
||||
obs_combo_format::OBS_COMBO_FORMAT_INT);
|
||||
p = obs_properties_add_list(pr, P_SHAPE_MODE, P_TRANSLATE(P_SHAPE_MODE), obs_combo_type::OBS_COMBO_TYPE_LIST,
|
||||
obs_combo_format::OBS_COMBO_FORMAT_INT);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SHAPE_MODE)));
|
||||
obs_property_list_add_int(p, P_TRANSLATE(P_SHAPE_MODE_TRIS), GS_TRIS);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(P_SHAPE_MODE_TRISTRIP),
|
||||
GS_TRISTRIP);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(P_SHAPE_MODE_TRISTRIP), GS_TRISTRIP);
|
||||
|
||||
p = obs_properties_add_int_slider(pr, P_SHAPE_POINTS,
|
||||
P_TRANSLATE(P_SHAPE_POINTS), minimumPoints, maximumPoints, 1);
|
||||
p = obs_properties_add_int_slider(pr, P_SHAPE_POINTS, P_TRANSLATE(P_SHAPE_POINTS), minimumPoints, maximumPoints, 1);
|
||||
obs_property_set_long_description(p, P_DESC(P_SHAPE_POINTS));
|
||||
obs_property_set_modified_callback(p, modified_properties);
|
||||
|
||||
for (uint32_t point = 0; point < maximumPoints; point++) {
|
||||
std::pair<const char*, const char*> vals[] = {
|
||||
{
|
||||
P_SHAPE_POINT_X,
|
||||
P_TRANSLATE(P_DESC(P_SHAPE_POINT_X))
|
||||
},
|
||||
{
|
||||
P_SHAPE_POINT_Y,
|
||||
P_TRANSLATE(P_DESC(P_SHAPE_POINT_Y))
|
||||
},
|
||||
{
|
||||
P_SHAPE_POINT_U,
|
||||
P_TRANSLATE(P_DESC(P_SHAPE_POINT_U))
|
||||
},
|
||||
{
|
||||
P_SHAPE_POINT_V,
|
||||
P_TRANSLATE(P_DESC(P_SHAPE_POINT_V))
|
||||
}
|
||||
};
|
||||
std::pair<const char*, const char*> vals[] = {{P_SHAPE_POINT_X, P_TRANSLATE(P_DESC(P_SHAPE_POINT_X))},
|
||||
{P_SHAPE_POINT_Y, P_TRANSLATE(P_DESC(P_SHAPE_POINT_Y))},
|
||||
{P_SHAPE_POINT_U, P_TRANSLATE(P_DESC(P_SHAPE_POINT_U))},
|
||||
{P_SHAPE_POINT_V, P_TRANSLATE(P_DESC(P_SHAPE_POINT_V))}};
|
||||
for (std::pair<const char*, const char*> v : vals) {
|
||||
auto strings = cache.find(
|
||||
std::make_pair(point, v.first));
|
||||
auto strings = cache.find(std::make_pair(point, v.first));
|
||||
if (strings != cache.end()) {
|
||||
p = obs_properties_add_float_slider(pr,
|
||||
strings->second.first.c_str(),
|
||||
strings->second.second.c_str(),
|
||||
0, 100.0, 0.01);
|
||||
p = obs_properties_add_float_slider(pr, strings->second.first.c_str(), strings->second.second.c_str(),
|
||||
0, 100.0, 0.01);
|
||||
obs_property_set_long_description(p, v.second);
|
||||
}
|
||||
}
|
||||
|
@ -185,75 +148,79 @@ obs_properties_t * filter::Shape::get_properties(void *) {
|
|||
return pr;
|
||||
}
|
||||
|
||||
bool filter::Shape::modified_properties(obs_properties_t *pr, obs_property_t *,
|
||||
obs_data_t *data) {
|
||||
bool filter::Shape::modified_properties(obs_properties_t* pr, obs_property_t*, obs_data_t* data)
|
||||
{
|
||||
uint32_t points = (uint32_t)obs_data_get_int(data, P_SHAPE_POINTS);
|
||||
for (uint32_t point = 0; point < maximumPoints; point++) {
|
||||
bool visible = point < points ? true : false;
|
||||
const char* vals[] = {
|
||||
P_SHAPE_POINT_X,
|
||||
P_SHAPE_POINT_Y,
|
||||
P_SHAPE_POINT_U,
|
||||
P_SHAPE_POINT_V
|
||||
};
|
||||
bool visible = point < points ? true : false;
|
||||
const char* vals[] = {P_SHAPE_POINT_X, P_SHAPE_POINT_Y, P_SHAPE_POINT_U, P_SHAPE_POINT_V};
|
||||
for (const char* v : vals) {
|
||||
auto strings = cache.find(std::make_pair(point, v));
|
||||
if (strings != cache.end()) {
|
||||
obs_property_set_visible(obs_properties_get(pr,
|
||||
strings->second.first.c_str()), visible
|
||||
);
|
||||
obs_property_set_visible(obs_properties_get(pr, strings->second.first.c_str()), visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void * filter::Shape::create(obs_data_t *data, obs_source_t *source) {
|
||||
void* filter::Shape::create(obs_data_t* data, obs_source_t* source)
|
||||
{
|
||||
return new Instance(data, source);
|
||||
}
|
||||
|
||||
void filter::Shape::destroy(void *ptr) {
|
||||
void filter::Shape::destroy(void* ptr)
|
||||
{
|
||||
delete reinterpret_cast<Instance*>(ptr);
|
||||
}
|
||||
|
||||
uint32_t filter::Shape::get_width(void *ptr) {
|
||||
uint32_t filter::Shape::get_width(void* ptr)
|
||||
{
|
||||
return reinterpret_cast<Instance*>(ptr)->get_width();
|
||||
}
|
||||
|
||||
uint32_t filter::Shape::get_height(void *ptr) {
|
||||
uint32_t filter::Shape::get_height(void* ptr)
|
||||
{
|
||||
return reinterpret_cast<Instance*>(ptr)->get_height();
|
||||
}
|
||||
|
||||
void filter::Shape::update(void *ptr, obs_data_t *data) {
|
||||
void filter::Shape::update(void* ptr, obs_data_t* data)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->update(data);
|
||||
}
|
||||
|
||||
void filter::Shape::activate(void *ptr) {
|
||||
void filter::Shape::activate(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->activate();
|
||||
}
|
||||
|
||||
void filter::Shape::deactivate(void *ptr) {
|
||||
void filter::Shape::deactivate(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->deactivate();
|
||||
}
|
||||
|
||||
void filter::Shape::show(void *ptr) {
|
||||
void filter::Shape::show(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->show();
|
||||
}
|
||||
|
||||
void filter::Shape::hide(void *ptr) {
|
||||
void filter::Shape::hide(void* ptr)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->hide();
|
||||
}
|
||||
|
||||
void filter::Shape::video_tick(void *ptr, float time) {
|
||||
void filter::Shape::video_tick(void* ptr, float time)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->video_tick(time);
|
||||
}
|
||||
|
||||
void filter::Shape::video_render(void *ptr, gs_effect_t *effect) {
|
||||
void filter::Shape::video_render(void* ptr, gs_effect_t* effect)
|
||||
{
|
||||
reinterpret_cast<Instance*>(ptr)->video_render(effect);
|
||||
}
|
||||
|
||||
filter::Shape::Instance::Instance(obs_data_t *data, obs_source_t *context)
|
||||
: context(context) {
|
||||
filter::Shape::Instance::Instance(obs_data_t* data, obs_source_t* context) : context(context)
|
||||
{
|
||||
obs_enter_graphics();
|
||||
m_vertexHelper = new gs::vertex_buffer(maximumPoints);
|
||||
m_vertexHelper->set_uv_layers(1);
|
||||
|
@ -263,50 +230,44 @@ filter::Shape::Instance::Instance(obs_data_t *data, obs_source_t *context)
|
|||
update(data);
|
||||
}
|
||||
|
||||
filter::Shape::Instance::~Instance() {
|
||||
filter::Shape::Instance::~Instance()
|
||||
{
|
||||
obs_enter_graphics();
|
||||
delete m_vertexHelper;
|
||||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
void filter::Shape::Instance::update(obs_data_t *data) {
|
||||
void filter::Shape::Instance::update(obs_data_t* data)
|
||||
{
|
||||
uint32_t points = (uint32_t)obs_data_get_int(data, P_SHAPE_POINTS);
|
||||
m_vertexHelper->resize(points);
|
||||
for (uint32_t point = 0; point < points; point++) {
|
||||
gs::vertex v = m_vertexHelper->at(point);
|
||||
{
|
||||
auto strings = cache.find(std::make_pair(point,
|
||||
P_SHAPE_POINT_X));
|
||||
auto strings = cache.find(std::make_pair(point, P_SHAPE_POINT_X));
|
||||
if (strings != cache.end()) {
|
||||
v.position->x = (float)(obs_data_get_double(data,
|
||||
strings->second.first.c_str()) / 100.0);
|
||||
v.position->x = (float)(obs_data_get_double(data, strings->second.first.c_str()) / 100.0);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto strings = cache.find(std::make_pair(point,
|
||||
P_SHAPE_POINT_Y));
|
||||
auto strings = cache.find(std::make_pair(point, P_SHAPE_POINT_Y));
|
||||
if (strings != cache.end()) {
|
||||
v.position->y = (float)(obs_data_get_double(data,
|
||||
strings->second.first.c_str()) / 100.0);
|
||||
v.position->y = (float)(obs_data_get_double(data, strings->second.first.c_str()) / 100.0);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto strings = cache.find(std::make_pair(point,
|
||||
P_SHAPE_POINT_U));
|
||||
auto strings = cache.find(std::make_pair(point, P_SHAPE_POINT_U));
|
||||
if (strings != cache.end()) {
|
||||
v.uv[0]->x = (float)(obs_data_get_double(data,
|
||||
strings->second.first.c_str()) / 100.0);
|
||||
v.uv[0]->x = (float)(obs_data_get_double(data, strings->second.first.c_str()) / 100.0);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto strings = cache.find(std::make_pair(point,
|
||||
P_SHAPE_POINT_V));
|
||||
auto strings = cache.find(std::make_pair(point, P_SHAPE_POINT_V));
|
||||
if (strings != cache.end()) {
|
||||
v.uv[0]->y = (float)(obs_data_get_double(data,
|
||||
strings->second.first.c_str()) / 100.0);
|
||||
v.uv[0]->y = (float)(obs_data_get_double(data, strings->second.first.c_str()) / 100.0);
|
||||
}
|
||||
}
|
||||
*v.color = 0xFFFFFFFF;
|
||||
*v.color = 0xFFFFFFFF;
|
||||
v.position->z = 0.0f;
|
||||
}
|
||||
drawmode = (gs_draw_mode)obs_data_get_int(data, P_SHAPE_MODE);
|
||||
|
@ -315,11 +276,13 @@ void filter::Shape::Instance::update(obs_data_t *data) {
|
|||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
uint32_t filter::Shape::Instance::get_width() {
|
||||
uint32_t filter::Shape::Instance::get_width()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t filter::Shape::Instance::get_height() {
|
||||
uint32_t filter::Shape::Instance::get_height()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -333,16 +296,14 @@ void filter::Shape::Instance::hide() {}
|
|||
|
||||
void filter::Shape::Instance::video_tick(float) {}
|
||||
|
||||
void filter::Shape::Instance::video_render(gs_effect_t *effect) {
|
||||
obs_source_t *parent = obs_filter_get_parent(context);
|
||||
obs_source_t *target = obs_filter_get_target(context);
|
||||
uint32_t
|
||||
baseW = obs_source_get_base_width(target),
|
||||
baseH = obs_source_get_base_height(target);
|
||||
void filter::Shape::Instance::video_render(gs_effect_t* effect)
|
||||
{
|
||||
obs_source_t* parent = obs_filter_get_parent(context);
|
||||
obs_source_t* target = obs_filter_get_target(context);
|
||||
uint32_t baseW = obs_source_get_base_width(target), baseH = obs_source_get_base_height(target);
|
||||
|
||||
// Skip rendering if our target, parent or context is not valid.
|
||||
if (!target || !parent || !context || !m_vertexBuffer
|
||||
|| !m_texRender || !baseW || !baseH) {
|
||||
if (!target || !parent || !context || !m_vertexBuffer || !m_texRender || !baseW || !baseH) {
|
||||
obs_source_skip_video_filter(context);
|
||||
return;
|
||||
}
|
||||
|
@ -352,13 +313,10 @@ void filter::Shape::Instance::video_render(gs_effect_t *effect) {
|
|||
obs_source_skip_video_filter(context);
|
||||
return;
|
||||
}
|
||||
if (!obs_source_process_filter_begin(context, GS_RGBA,
|
||||
OBS_NO_DIRECT_RENDERING)) {
|
||||
if (!obs_source_process_filter_begin(context, GS_RGBA, OBS_NO_DIRECT_RENDERING)) {
|
||||
obs_source_skip_video_filter(context);
|
||||
} else {
|
||||
obs_source_process_filter_end(context,
|
||||
effect ? effect : obs_get_base_effect(OBS_EFFECT_OPAQUE),
|
||||
baseW, baseH);
|
||||
obs_source_process_filter_end(context, effect ? effect : obs_get_base_effect(OBS_EFFECT_OPAQUE), baseW, baseH);
|
||||
}
|
||||
gs_texrender_end(m_texRender);
|
||||
gs_texture* tex = gs_texrender_get_texture(m_texRender);
|
||||
|
@ -382,8 +340,7 @@ void filter::Shape::Instance::video_render(gs_effect_t *effect) {
|
|||
|
||||
gs_effect_t* eff = obs_get_base_effect(OBS_EFFECT_OPAQUE);
|
||||
while (gs_effect_loop(eff, "Draw")) {
|
||||
gs_effect_set_texture(gs_effect_get_param_by_name(eff, "image"),
|
||||
tex);
|
||||
gs_effect_set_texture(gs_effect_get_param_by_name(eff, "image"), tex);
|
||||
gs_load_vertexbuffer(m_vertexBuffer);
|
||||
gs_load_indexbuffer(nullptr);
|
||||
gs_draw(drawmode, 0, (uint32_t)m_vertexHelper->size());
|
||||
|
|
|
@ -18,20 +18,20 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "plugin.h"
|
||||
#include "gs-vertexbuffer.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#define P_SHAPE "Shape"
|
||||
#define P_SHAPE_LOOP "Shape.Loop"
|
||||
#define P_SHAPE_MODE "Shape.Mode"
|
||||
#define P_SHAPE_MODE_TRIS "Shape.Mode.Tris"
|
||||
#define P_SHAPE_MODE_TRISTRIP "Shape.Mode.TriStrip"
|
||||
#define P_SHAPE_MODE "Shape.Mode"
|
||||
#define P_SHAPE_POINTS "Shape.Points"
|
||||
#define P_SHAPE_POINT_X "Shape.Point.X"
|
||||
#define P_SHAPE_POINT_Y "Shape.Point.Y"
|
||||
#define P_SHAPE_POINT_U "Shape.Point.U"
|
||||
#define P_SHAPE_POINT_V "Shape.Point.V"
|
||||
#define P_SHAPE "Shape"
|
||||
#define P_SHAPE_LOOP "Shape.Loop"
|
||||
#define P_SHAPE_MODE "Shape.Mode"
|
||||
#define P_SHAPE_MODE_TRIS "Shape.Mode.Tris"
|
||||
#define P_SHAPE_MODE_TRISTRIP "Shape.Mode.TriStrip"
|
||||
#define P_SHAPE_MODE "Shape.Mode"
|
||||
#define P_SHAPE_POINTS "Shape.Points"
|
||||
#define P_SHAPE_POINT_X "Shape.Point.X"
|
||||
#define P_SHAPE_POINT_Y "Shape.Point.Y"
|
||||
#define P_SHAPE_POINT_U "Shape.Point.U"
|
||||
#define P_SHAPE_POINT_V "Shape.Point.V"
|
||||
|
||||
namespace filter {
|
||||
class Shape {
|
||||
|
@ -39,22 +39,22 @@ namespace filter {
|
|||
Shape();
|
||||
~Shape();
|
||||
|
||||
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 *);
|
||||
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*);
|
||||
|
||||
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 *);
|
||||
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*);
|
||||
|
||||
private:
|
||||
obs_source_info sourceInfo;
|
||||
|
@ -65,23 +65,23 @@ namespace filter {
|
|||
Instance(obs_data_t*, obs_source_t*);
|
||||
~Instance();
|
||||
|
||||
void update(obs_data_t*);
|
||||
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 activate();
|
||||
void deactivate();
|
||||
void show();
|
||||
void hide();
|
||||
void video_tick(float);
|
||||
void video_render(gs_effect_t*);
|
||||
|
||||
private:
|
||||
obs_source_t *context;
|
||||
gs_effect_t *customEffect;
|
||||
gs::vertex_buffer *m_vertexHelper;
|
||||
gs_vertbuffer_t *m_vertexBuffer;
|
||||
gs_draw_mode drawmode;
|
||||
gs_texrender_t *m_texRender;
|
||||
obs_source_t* context;
|
||||
gs_effect_t* customEffect;
|
||||
gs::vertex_buffer* m_vertexHelper;
|
||||
gs_vertbuffer_t* m_vertexBuffer;
|
||||
gs_draw_mode drawmode;
|
||||
gs_texrender_t* m_texRender;
|
||||
};
|
||||
};
|
||||
}
|
||||
} // namespace filter
|
||||
|
|
|
@ -204,13 +204,11 @@ obs_properties_t* filter::Transform::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, strings::MipGenerator::Name,
|
||||
P_TRANSLATE(strings::MipGenerator::Name), OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
p = obs_properties_add_list(pr, strings::MipGenerator::Name, P_TRANSLATE(strings::MipGenerator::Name),
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(strings::MipGenerator::Description));
|
||||
|
||||
obs_property_list_add_int(p, P_TRANSLATE(strings::MipGenerator::Point),
|
||||
(long long)gs::mipmapper::generator::Point);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(strings::MipGenerator::Point), (long long)gs::mipmapper::generator::Point);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(strings::MipGenerator::Linear),
|
||||
(long long)gs::mipmapper::generator::Linear);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(strings::MipGenerator::Sharpen),
|
||||
|
@ -222,8 +220,8 @@ obs_properties_t* filter::Transform::get_properties(void*)
|
|||
obs_property_list_add_int(p, P_TRANSLATE(strings::MipGenerator::Lanczos),
|
||||
(long long)gs::mipmapper::generator::Lanczos);
|
||||
|
||||
p = obs_properties_add_float(pr, strings::MipGenerator::Strength,
|
||||
P_TRANSLATE(strings::MipGenerator::Strength), 0.0, 100.0, 0.01);
|
||||
p = obs_properties_add_float(pr, strings::MipGenerator::Strength, P_TRANSLATE(strings::MipGenerator::Strength), 0.0,
|
||||
100.0, 0.01);
|
||||
|
||||
return pr;
|
||||
}
|
||||
|
@ -310,8 +308,8 @@ filter::Transform::Instance::Instance(obs_data_t* data, obs_source_t* context)
|
|||
vec3_set(rotation.get(), 0, 0, 0);
|
||||
vec3_set(scale.get(), 1, 1, 1);
|
||||
|
||||
enable_mipmapping = false;
|
||||
generator = gs::mipmapper::generator::Linear;
|
||||
enable_mipmapping = false;
|
||||
generator = gs::mipmapper::generator::Linear;
|
||||
generator_strength = 50.0;
|
||||
|
||||
obs_enter_graphics();
|
||||
|
@ -354,7 +352,7 @@ void filter::Transform::Instance::update(obs_data_t* data)
|
|||
shear->z = 0.0f;
|
||||
|
||||
// Mipmapping
|
||||
enable_mipmapping = obs_data_get_bool(data, ST_MIPMAPPING);
|
||||
enable_mipmapping = obs_data_get_bool(data, ST_MIPMAPPING);
|
||||
generator_strength = obs_data_get_double(data, strings::MipGenerator::Strength);
|
||||
generator = (gs::mipmapper::generator)obs_data_get_int(data, strings::MipGenerator::Name);
|
||||
|
||||
|
@ -391,9 +389,9 @@ void filter::Transform::Instance::video_render(gs_effect_t* paramEffect)
|
|||
obs_source_t* parent = obs_filter_get_parent(source_context);
|
||||
obs_source_t* target = obs_filter_get_target(source_context);
|
||||
|
||||
uint32_t width = obs_source_get_base_width(target);
|
||||
uint32_t height = obs_source_get_base_height(target);
|
||||
uint32_t real_width = width;
|
||||
uint32_t width = obs_source_get_base_width(target);
|
||||
uint32_t height = obs_source_get_base_height(target);
|
||||
uint32_t real_width = width;
|
||||
uint32_t real_height = height;
|
||||
|
||||
gs_effect_t* default_effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||
|
@ -493,7 +491,7 @@ void filter::Transform::Instance::video_render(gs_effect_t* paramEffect)
|
|||
// Most GPUs cap out here, so let's not go higher.
|
||||
double_t aspect = double_t(width) / double_t(height);
|
||||
if (aspect > 1.0) { // height < width
|
||||
real_width = 8192;
|
||||
real_width = 8192;
|
||||
real_height = uint32_t(real_width / aspect);
|
||||
} else if (aspect < 1.0) { // width > height
|
||||
real_height = 8192;
|
||||
|
@ -546,8 +544,8 @@ void filter::Transform::Instance::video_render(gs_effect_t* paramEffect)
|
|||
}
|
||||
}
|
||||
|
||||
source_texture = std::make_shared<gs::texture>(real_width, real_height, GS_RGBA, uint32_t(1u + mip_levels), nullptr,
|
||||
gs::texture::flags::BuildMipMaps);
|
||||
source_texture = std::make_shared<gs::texture>(real_width, real_height, GS_RGBA, uint32_t(1u + mip_levels),
|
||||
nullptr, gs::texture::flags::BuildMipMaps);
|
||||
}
|
||||
|
||||
mipmapper.rebuild(source_tex, source_texture, generator, float_t(generator_strength));
|
||||
|
|
|
@ -77,7 +77,7 @@ bool gfx::effect_source::property_texture_type_modified(void* priv, obs_properti
|
|||
obs_property_set_visible(obs_properties_get(props, tpm->ui.names[2]), false);
|
||||
} else { // Source
|
||||
obs_property_set_visible(obs_properties_get(props, tpm->ui.names[1]), false);
|
||||
obs_property_set_visible(obs_properties_get(props, tpm->ui.names[2]), true);
|
||||
obs_property_set_visible(obs_properties_get(props, tpm->ui.names[2]), true);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -427,7 +427,7 @@ bool gfx::effect_source::test_for_updates(const char* text, const char* path)
|
|||
for (size_t i = 0; i <= 2; i++) {
|
||||
bufsize += ui_name[i].size() + ui_desc[i].size() + 2;
|
||||
}
|
||||
|
||||
|
||||
nparam->ui.names.resize(3);
|
||||
nparam->ui.descs.resize(3);
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ namespace gfx {
|
|||
static bool property_texture_type_modified(void* priv, obs_properties_t* props, obs_property_t* prop,
|
||||
obs_data_t* sett);
|
||||
static bool property_texture_input_modified(void* priv, obs_properties_t* props, obs_property_t* prop,
|
||||
obs_data_t* sett);
|
||||
obs_data_t* sett);
|
||||
|
||||
virtual bool is_special_parameter(std::string name, gs::effect_parameter::type type) = 0;
|
||||
|
||||
|
|
|
@ -30,9 +30,9 @@ extern "C" {
|
|||
#pragma warning(disable : 4201)
|
||||
#include <graphics/graphics.h>
|
||||
#include <graphics/matrix4.h>
|
||||
#include <graphics/vec4.h>
|
||||
#include <graphics/vec3.h>
|
||||
#include <graphics/vec2.h>
|
||||
#include <graphics/vec3.h>
|
||||
#include <graphics/vec4.h>
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,76 +19,94 @@
|
|||
|
||||
#include "gs-helper.h"
|
||||
|
||||
gs_effect_param* gs_effect_get_param(gs_effect_t* effect, const char* name) {
|
||||
gs_effect_param* gs_effect_get_param(gs_effect_t* effect, const char* name)
|
||||
{
|
||||
gs_effect_param* p = gs_effect_get_param_by_name(effect, name);
|
||||
if (!p)
|
||||
P_LOG_ERROR("Failed to find parameter %s in effect.", name);
|
||||
return p;
|
||||
}
|
||||
|
||||
bool gs_set_param_int(gs_effect_t* effect, const char* name, int value) {
|
||||
bool gs_set_param_int(gs_effect_t* effect, const char* name, int value)
|
||||
{
|
||||
gs_effect_param* p = nullptr;
|
||||
if (nullptr != (p = gs_effect_get_param(effect, name))) {
|
||||
gs_effect_set_int(p, value);
|
||||
return true;
|
||||
}
|
||||
P_LOG_ERROR("Failed to set value %d for parameter %s in"
|
||||
" effect.", value, name);
|
||||
P_LOG_ERROR(
|
||||
"Failed to set value %d for parameter %s in"
|
||||
" effect.",
|
||||
value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gs_set_param_float(gs_effect_t* effect, const char* name, float value) {
|
||||
bool gs_set_param_float(gs_effect_t* effect, const char* name, float value)
|
||||
{
|
||||
gs_effect_param* p = nullptr;
|
||||
if (nullptr != (p = gs_effect_get_param(effect, name))) {
|
||||
gs_effect_set_float(p, value);
|
||||
return true;
|
||||
}
|
||||
P_LOG_ERROR("Failed to set value %f for parameter %s in"
|
||||
" effect.", value, name);
|
||||
P_LOG_ERROR(
|
||||
"Failed to set value %f for parameter %s in"
|
||||
" effect.",
|
||||
value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gs_set_param_float2(gs_effect_t* effect, const char* name, vec2* value) {
|
||||
bool gs_set_param_float2(gs_effect_t* effect, const char* name, vec2* value)
|
||||
{
|
||||
gs_effect_param* p = nullptr;
|
||||
if (nullptr != (p = gs_effect_get_param(effect, name))) {
|
||||
gs_effect_set_vec2(p, value);
|
||||
return true;
|
||||
}
|
||||
P_LOG_ERROR("Failed to set value {%f,%f} for parameter %s"
|
||||
" in effect.", value->x, value->y, name);
|
||||
P_LOG_ERROR(
|
||||
"Failed to set value {%f,%f} for parameter %s"
|
||||
" in effect.",
|
||||
value->x, value->y, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gs_set_param_float3(gs_effect_t* effect, const char* name, vec3* value) {
|
||||
bool gs_set_param_float3(gs_effect_t* effect, const char* name, vec3* value)
|
||||
{
|
||||
gs_effect_param* p = nullptr;
|
||||
if (nullptr != (p = gs_effect_get_param(effect, name))) {
|
||||
gs_effect_set_vec3(p, value);
|
||||
return true;
|
||||
}
|
||||
P_LOG_ERROR("Failed to set value {%f,%f,%f} for parameter"
|
||||
"%s in effect.", value->x, value->y, value->z, name);
|
||||
P_LOG_ERROR(
|
||||
"Failed to set value {%f,%f,%f} for parameter"
|
||||
"%s in effect.",
|
||||
value->x, value->y, value->z, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gs_set_param_float4(gs_effect_t* effect, const char* name, vec4* value) {
|
||||
bool gs_set_param_float4(gs_effect_t* effect, const char* name, vec4* value)
|
||||
{
|
||||
gs_effect_param* p = nullptr;
|
||||
if (nullptr != (p = gs_effect_get_param(effect, name))) {
|
||||
gs_effect_set_vec4(p, value);
|
||||
return true;
|
||||
}
|
||||
P_LOG_ERROR("Failed to set value {%f,%f,%f,%f} for"
|
||||
" parameter %s in effect.", value->x, value->y, value->z,
|
||||
value->w, name);
|
||||
P_LOG_ERROR(
|
||||
"Failed to set value {%f,%f,%f,%f} for"
|
||||
" parameter %s in effect.",
|
||||
value->x, value->y, value->z, value->w, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gs_set_param_texture(gs_effect_t* effect, const char* name, gs_texture_t* value) {
|
||||
bool gs_set_param_texture(gs_effect_t* effect, const char* name, gs_texture_t* value)
|
||||
{
|
||||
gs_effect_param* p = nullptr;
|
||||
if (nullptr != (p = gs_effect_get_param(effect, name))) {
|
||||
gs_effect_set_texture(p, value);
|
||||
return true;
|
||||
}
|
||||
P_LOG_ERROR("Failed to set texture for"
|
||||
" parameter %s in effect.", name);
|
||||
P_LOG_ERROR(
|
||||
"Failed to set texture for"
|
||||
" parameter %s in effect.",
|
||||
name);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -18,19 +18,19 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "plugin.h"
|
||||
#include <vector>
|
||||
#include "plugin.h"
|
||||
extern "C" {
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4201)
|
||||
#include "graphics/graphics.h"
|
||||
#pragma warning (pop)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include "graphics/graphics.h"
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
gs_effect_param* gs_effect_get_param(gs_effect_t* effect, const char* name);
|
||||
bool gs_set_param_int(gs_effect_t* effect, const char* name, int value);
|
||||
bool gs_set_param_float(gs_effect_t* effect, const char* name, float value);
|
||||
bool gs_set_param_float2(gs_effect_t* effect, const char* name, vec2* value);
|
||||
bool gs_set_param_float3(gs_effect_t* effect, const char* name, vec3* value);
|
||||
bool gs_set_param_float4(gs_effect_t* effect, const char* name, vec4* value);
|
||||
bool gs_set_param_texture(gs_effect_t* effect, const char* name, gs_texture_t* value);
|
||||
bool gs_set_param_int(gs_effect_t* effect, const char* name, int value);
|
||||
bool gs_set_param_float(gs_effect_t* effect, const char* name, float value);
|
||||
bool gs_set_param_float2(gs_effect_t* effect, const char* name, vec2* value);
|
||||
bool gs_set_param_float3(gs_effect_t* effect, const char* name, vec3* value);
|
||||
bool gs_set_param_float4(gs_effect_t* effect, const char* name, vec4* value);
|
||||
bool gs_set_param_texture(gs_effect_t* effect, const char* name, gs_texture_t* value);
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
#include "gs-indexbuffer.h"
|
||||
#include "gs-limits.h"
|
||||
extern "C" {
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable: 4201 )
|
||||
#include <obs.h>
|
||||
#pragma warning( pop )
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include <obs.h>
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
gs::index_buffer::index_buffer(uint32_t maximumVertices) {
|
||||
gs::index_buffer::index_buffer(uint32_t maximumVertices)
|
||||
{
|
||||
this->reserve(maximumVertices);
|
||||
|
||||
obs_enter_graphics();
|
||||
|
@ -36,25 +37,30 @@ gs::index_buffer::index_buffer(uint32_t maximumVertices) {
|
|||
|
||||
gs::index_buffer::index_buffer() : index_buffer(MAXIMUM_VERTICES) {}
|
||||
|
||||
gs::index_buffer::index_buffer(index_buffer& other) : index_buffer((uint32_t)other.size()) {
|
||||
gs::index_buffer::index_buffer(index_buffer& other) : index_buffer((uint32_t)other.size())
|
||||
{
|
||||
std::copy(other.begin(), other.end(), this->end());
|
||||
}
|
||||
|
||||
gs::index_buffer::index_buffer(std::vector<uint32_t>& other) : index_buffer((uint32_t)other.size()) {
|
||||
gs::index_buffer::index_buffer(std::vector<uint32_t>& other) : index_buffer((uint32_t)other.size())
|
||||
{
|
||||
std::copy(other.begin(), other.end(), this->end());
|
||||
}
|
||||
|
||||
gs::index_buffer::~index_buffer() {
|
||||
gs::index_buffer::~index_buffer()
|
||||
{
|
||||
obs_enter_graphics();
|
||||
gs_indexbuffer_destroy(m_indexBuffer);
|
||||
obs_leave_graphics();
|
||||
}
|
||||
|
||||
gs_indexbuffer_t* gs::index_buffer::get() {
|
||||
gs_indexbuffer_t* gs::index_buffer::get()
|
||||
{
|
||||
return get(true);
|
||||
}
|
||||
|
||||
gs_indexbuffer_t* gs::index_buffer::get(bool refreshGPU) {
|
||||
gs_indexbuffer_t* gs::index_buffer::get(bool refreshGPU)
|
||||
{
|
||||
if (refreshGPU) {
|
||||
obs_enter_graphics();
|
||||
gs_indexbuffer_flush(m_indexBuffer);
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
#include <inttypes.h>
|
||||
#include <vector>
|
||||
extern "C" {
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable: 4201 )
|
||||
#include <graphics/graphics.h>
|
||||
#pragma warning( pop )
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include <graphics/graphics.h>
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
namespace gs {
|
||||
|
@ -43,4 +43,4 @@ namespace gs {
|
|||
protected:
|
||||
gs_indexbuffer_t* m_indexBuffer;
|
||||
};
|
||||
}
|
||||
} // namespace gs
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
namespace gs {
|
||||
static const uint32_t MAXIMUM_VERTICES = 0xFFFFFFu;
|
||||
static const uint32_t MAXIMUM_VERTICES = 0xFFFFFFu;
|
||||
static const uint32_t MAXIMUM_UVW_LAYERS = 8u;
|
||||
}
|
||||
} // namespace gs
|
||||
|
|
|
@ -216,7 +216,7 @@ void gs::mipmapper::rebuild(std::shared_ptr<gs::texture> source, std::shared_ptr
|
|||
texture_height = 1;
|
||||
}
|
||||
|
||||
texel_width = 1.0 / texture_width;
|
||||
texel_width = 1.0 / texture_width;
|
||||
texel_height = 1.0 / texture_height;
|
||||
|
||||
// Draw mipmap layer
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace gs {
|
|||
gs_texrender_t* render_target;
|
||||
bool is_being_rendered;
|
||||
|
||||
gs_color_format color_format;
|
||||
gs_color_format color_format;
|
||||
gs_zstencil_format zstencil_format;
|
||||
|
||||
public:
|
||||
|
|
|
@ -19,77 +19,93 @@
|
|||
|
||||
#include "gs-sampler.h"
|
||||
|
||||
gs::sampler::sampler() {
|
||||
m_dirty = true;
|
||||
m_samplerInfo = { GS_FILTER_LINEAR, GS_ADDRESS_WRAP, GS_ADDRESS_WRAP, GS_ADDRESS_WRAP, 1, 0 };
|
||||
gs::sampler::sampler()
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo = {GS_FILTER_LINEAR, GS_ADDRESS_WRAP, GS_ADDRESS_WRAP, GS_ADDRESS_WRAP, 1, 0};
|
||||
m_samplerState = nullptr;
|
||||
}
|
||||
|
||||
gs::sampler::~sampler() {
|
||||
gs::sampler::~sampler()
|
||||
{
|
||||
if (m_samplerState)
|
||||
gs_samplerstate_destroy(m_samplerState);
|
||||
}
|
||||
|
||||
void gs::sampler::set_filter(gs_sample_filter v) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_filter(gs_sample_filter v)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.filter = v;
|
||||
}
|
||||
|
||||
gs_sample_filter gs::sampler::get_filter() {
|
||||
gs_sample_filter gs::sampler::get_filter()
|
||||
{
|
||||
return m_samplerInfo.filter;
|
||||
}
|
||||
|
||||
void gs::sampler::set_address_mode_u(gs_address_mode v) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_address_mode_u(gs_address_mode v)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.address_u = v;
|
||||
}
|
||||
|
||||
gs_address_mode gs::sampler::get_address_mode_u() {
|
||||
gs_address_mode gs::sampler::get_address_mode_u()
|
||||
{
|
||||
return m_samplerInfo.address_u;
|
||||
}
|
||||
|
||||
void gs::sampler::set_address_mode_v(gs_address_mode v) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_address_mode_v(gs_address_mode v)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.address_v = v;
|
||||
}
|
||||
|
||||
gs_address_mode gs::sampler::get_address_mode_v() {
|
||||
gs_address_mode gs::sampler::get_address_mode_v()
|
||||
{
|
||||
return m_samplerInfo.address_v;
|
||||
}
|
||||
|
||||
void gs::sampler::set_address_mode_w(gs_address_mode v) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_address_mode_w(gs_address_mode v)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.address_w = v;
|
||||
}
|
||||
|
||||
gs_address_mode gs::sampler::get_address_mode_w() {
|
||||
gs_address_mode gs::sampler::get_address_mode_w()
|
||||
{
|
||||
return m_samplerInfo.address_w;
|
||||
}
|
||||
|
||||
void gs::sampler::set_max_anisotropy(int v) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_max_anisotropy(int v)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.max_anisotropy = v;
|
||||
}
|
||||
|
||||
int gs::sampler::get_max_anisotropy() {
|
||||
int gs::sampler::get_max_anisotropy()
|
||||
{
|
||||
return m_samplerInfo.max_anisotropy;
|
||||
}
|
||||
|
||||
void gs::sampler::set_border_color(uint32_t v) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_border_color(uint32_t v)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.border_color = v;
|
||||
}
|
||||
|
||||
void gs::sampler::set_border_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
m_dirty = true;
|
||||
void gs::sampler::set_border_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
m_dirty = true;
|
||||
m_samplerInfo.border_color = a << 24 | r << 16 | g << 8 | b;
|
||||
}
|
||||
|
||||
uint32_t gs::sampler::get_border_color() {
|
||||
uint32_t gs::sampler::get_border_color()
|
||||
{
|
||||
return m_samplerInfo.border_color;
|
||||
}
|
||||
|
||||
uint8_t gs::sampler::get_border_color(bool r, bool g, bool b, bool a) {
|
||||
uint8_t gs::sampler::get_border_color(bool r, bool g, bool b, bool a)
|
||||
{
|
||||
if (a)
|
||||
return (m_samplerInfo.border_color >> 24) & 0xFF;
|
||||
if (r)
|
||||
|
@ -101,14 +117,16 @@ uint8_t gs::sampler::get_border_color(bool r, bool g, bool b, bool a) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
gs_sampler_state* gs::sampler::refresh() {
|
||||
gs_sampler_state* gs::sampler::refresh()
|
||||
{
|
||||
gs_samplerstate_destroy(m_samplerState);
|
||||
m_samplerState = gs_samplerstate_create(&m_samplerInfo);
|
||||
m_dirty = false;
|
||||
m_dirty = false;
|
||||
return m_samplerState;
|
||||
}
|
||||
|
||||
gs_sampler_state* gs::sampler::get_object() {
|
||||
gs_sampler_state* gs::sampler::get_object()
|
||||
{
|
||||
if (m_dirty)
|
||||
return refresh();
|
||||
return m_samplerState;
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
extern "C" {
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable: 4201 )
|
||||
#include <graphics/graphics.h>
|
||||
#pragma warning( pop )
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include <graphics/graphics.h>
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
namespace gs {
|
||||
|
@ -32,33 +32,33 @@ namespace gs {
|
|||
sampler();
|
||||
~sampler();
|
||||
|
||||
void set_filter(gs_sample_filter v);
|
||||
void set_filter(gs_sample_filter v);
|
||||
gs_sample_filter get_filter();
|
||||
|
||||
void set_address_mode_u(gs_address_mode v);
|
||||
void set_address_mode_u(gs_address_mode v);
|
||||
gs_address_mode get_address_mode_u();
|
||||
|
||||
void set_address_mode_v(gs_address_mode v);
|
||||
void set_address_mode_v(gs_address_mode v);
|
||||
gs_address_mode get_address_mode_v();
|
||||
|
||||
void set_address_mode_w(gs_address_mode v);
|
||||
void set_address_mode_w(gs_address_mode v);
|
||||
gs_address_mode get_address_mode_w();
|
||||
|
||||
void set_max_anisotropy(int v);
|
||||
int get_max_anisotropy();
|
||||
int get_max_anisotropy();
|
||||
|
||||
void set_border_color(uint32_t v);
|
||||
void set_border_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
void set_border_color(uint32_t v);
|
||||
void set_border_color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||
uint32_t get_border_color();
|
||||
uint8_t get_border_color(bool r, bool g, bool b, bool a);
|
||||
uint8_t get_border_color(bool r, bool g, bool b, bool a);
|
||||
|
||||
gs_sampler_state* refresh();
|
||||
|
||||
gs_sampler_state* get_object();
|
||||
|
||||
private:
|
||||
bool m_dirty;
|
||||
gs_sampler_info m_samplerInfo;
|
||||
bool m_dirty;
|
||||
gs_sampler_info m_samplerInfo;
|
||||
gs_sampler_state* m_samplerState;
|
||||
};
|
||||
}
|
||||
} // namespace gs
|
||||
|
|
|
@ -19,26 +19,31 @@
|
|||
|
||||
#include "obs-audio-capture.h"
|
||||
|
||||
void obs::audio_capture::audio_capture_cb(void* data, obs_source_t*, const struct audio_data* audio, bool muted) {
|
||||
void obs::audio_capture::audio_capture_cb(void* data, obs_source_t*, const struct audio_data* audio, bool muted)
|
||||
{
|
||||
auto self = reinterpret_cast<obs::audio_capture*>(data);
|
||||
self->cb(self->cb_data, audio, muted);
|
||||
}
|
||||
|
||||
obs::audio_capture::audio_capture(obs_source_t* source) {
|
||||
obs::audio_capture::audio_capture(obs_source_t* source)
|
||||
{
|
||||
this->source = source;
|
||||
obs_source_add_audio_capture_callback(this->source, audio_capture_cb, this);
|
||||
}
|
||||
|
||||
obs::audio_capture::~audio_capture() {
|
||||
obs::audio_capture::~audio_capture()
|
||||
{
|
||||
obs_source_remove_audio_capture_callback(this->source, audio_capture_cb, this);
|
||||
}
|
||||
|
||||
void obs::audio_capture::set_callback(audio_capture_callback_t cb, void* data) {
|
||||
this->cb = cb;
|
||||
void obs::audio_capture::set_callback(audio_capture_callback_t cb, void* data)
|
||||
{
|
||||
this->cb = cb;
|
||||
this->cb_data = data;
|
||||
}
|
||||
|
||||
void obs::audio_capture::set_callback(audio_capture_callback_t cb) {
|
||||
this->cb = cb;
|
||||
void obs::audio_capture::set_callback(audio_capture_callback_t cb)
|
||||
{
|
||||
this->cb = cb;
|
||||
this->cb_data = nullptr;
|
||||
}
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <obs.h>
|
||||
#include <functional>
|
||||
#include <obs.h>
|
||||
|
||||
namespace obs {
|
||||
typedef std::function<void(void* data, struct audio_data const *audio, bool muted)> audio_capture_callback_t;
|
||||
typedef std::function<void(void* data, struct audio_data const* audio, bool muted)> audio_capture_callback_t;
|
||||
|
||||
class audio_capture {
|
||||
obs_source_t* source;
|
||||
obs_source_t* source;
|
||||
audio_capture_callback_t cb;
|
||||
void* cb_data;
|
||||
void* cb_data;
|
||||
|
||||
static void audio_capture_cb(void*, obs_source_t*, struct audio_data const *, bool);
|
||||
static void audio_capture_cb(void*, obs_source_t*, struct audio_data const*, bool);
|
||||
|
||||
public:
|
||||
audio_capture(obs_source_t* source);
|
||||
|
@ -38,4 +38,4 @@ namespace obs {
|
|||
void set_callback(audio_capture_callback_t cb, void* data);
|
||||
void set_callback(audio_capture_callback_t cb);
|
||||
};
|
||||
}
|
||||
} // namespace obs
|
||||
|
|
|
@ -29,7 +29,7 @@ obs::source::~source()
|
|||
|
||||
obs::source::source(std::string name, bool track_ownership, bool add_reference)
|
||||
{
|
||||
this->self = obs_get_source_by_name(name.c_str());
|
||||
this->self = obs_get_source_by_name(name.c_str());
|
||||
this->track_ownership = track_ownership;
|
||||
if (!add_reference) {
|
||||
obs_source_release(this->self);
|
||||
|
@ -86,7 +86,8 @@ uint32_t obs::source::height()
|
|||
return obs_source_get_height(self);
|
||||
}
|
||||
|
||||
void obs::source::clear() {
|
||||
void obs::source::clear()
|
||||
{
|
||||
self = nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include <map>
|
||||
|
||||
struct scs_searchdata {
|
||||
obs_source_t* source;
|
||||
bool found = false;
|
||||
obs_source_t* source;
|
||||
bool found = false;
|
||||
std::map<obs_source_t*, bool> visited;
|
||||
};
|
||||
|
||||
|
|
|
@ -27,37 +27,39 @@ OBS_DECLARE_MODULE();
|
|||
OBS_MODULE_AUTHOR("Michael Fabian Dirks");
|
||||
OBS_MODULE_USE_DEFAULT_LOCALE("obs-stream-effects", "en-US");
|
||||
|
||||
filter::Displacement *filterDisplacement;
|
||||
filter::Shape *filterShape;
|
||||
filter::Transform *filterTransform;
|
||||
filter::Displacement* filterDisplacement;
|
||||
filter::Shape* filterShape;
|
||||
filter::Transform* filterTransform;
|
||||
|
||||
std::list<std::function<void()>> initializerFunctions;
|
||||
std::list<std::function<void()>> finalizerFunctions;
|
||||
|
||||
MODULE_EXPORT bool obs_module_load(void) {
|
||||
P_LOG_INFO("[" PLUGIN_NAME "] Loading Version %u.%u.%u (Build %u)",
|
||||
PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH,
|
||||
PROJECT_VERSION_TWEAK);
|
||||
MODULE_EXPORT bool obs_module_load(void)
|
||||
{
|
||||
P_LOG_INFO("[" PLUGIN_NAME "] Loading Version %u.%u.%u (Build %u)", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR,
|
||||
PROJECT_VERSION_PATCH, PROJECT_VERSION_TWEAK);
|
||||
for (auto func : initializerFunctions) {
|
||||
func();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MODULE_EXPORT void obs_module_unload(void) {
|
||||
P_LOG_INFO("[" PLUGIN_NAME "] Unloading Version %u.%u.%u (Build %u)",
|
||||
PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR, PROJECT_VERSION_PATCH,
|
||||
PROJECT_VERSION_TWEAK);
|
||||
MODULE_EXPORT void obs_module_unload(void)
|
||||
{
|
||||
P_LOG_INFO("[" PLUGIN_NAME "] Unloading Version %u.%u.%u (Build %u)", PROJECT_VERSION_MAJOR, PROJECT_VERSION_MINOR,
|
||||
PROJECT_VERSION_PATCH, PROJECT_VERSION_TWEAK);
|
||||
for (auto func : finalizerFunctions) {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_EXPORT const char* obs_module_name() {
|
||||
MODULE_EXPORT const char* obs_module_name()
|
||||
{
|
||||
return PLUGIN_NAME;
|
||||
}
|
||||
|
||||
MODULE_EXPORT const char* obs_module_description() {
|
||||
MODULE_EXPORT const char* obs_module_description()
|
||||
{
|
||||
return PLUGIN_NAME;
|
||||
}
|
||||
|
||||
|
@ -67,8 +69,8 @@ MODULE_EXPORT const char* obs_module_description() {
|
|||
|
||||
#include <windows.h>
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID) {
|
||||
BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -18,71 +18,76 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <inttypes.h>
|
||||
#include <list>
|
||||
#include <functional>
|
||||
|
||||
extern "C" {
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4201)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
#include "obs-module.h"
|
||||
#include "util/platform.h"
|
||||
#pragma warning (pop)
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
// Plugin
|
||||
#define PLUGIN_NAME "Stream Effects"
|
||||
#define PLUGIN_NAME "Stream Effects"
|
||||
#include "version.h"
|
||||
|
||||
#define P_LOG(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__);
|
||||
#define P_LOG_ERROR(...) P_LOG(LOG_ERROR, __VA_ARGS__)
|
||||
#define P_LOG_WARNING(...) P_LOG(LOG_WARNING, __VA_ARGS__)
|
||||
#define P_LOG_INFO(...) P_LOG(LOG_INFO, __VA_ARGS__)
|
||||
#define P_LOG_DEBUG(...) P_LOG(LOG_DEBUG, __VA_ARGS__)
|
||||
#define P_LOG(level, ...) blog(level, "[" PLUGIN_NAME "] " __VA_ARGS__);
|
||||
#define P_LOG_ERROR(...) P_LOG(LOG_ERROR, __VA_ARGS__)
|
||||
#define P_LOG_WARNING(...) P_LOG(LOG_WARNING, __VA_ARGS__)
|
||||
#define P_LOG_INFO(...) P_LOG(LOG_INFO, __VA_ARGS__)
|
||||
#define P_LOG_DEBUG(...) P_LOG(LOG_DEBUG, __VA_ARGS__)
|
||||
|
||||
// Utility
|
||||
#define vstr(s) dstr(s)
|
||||
#define dstr(s) #s
|
||||
|
||||
#define clamp(val,low,high) (val > high ? high : (val < low ? low : val))
|
||||
#define clamp(val, low, high) (val > high ? high : (val < low ? low : val))
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(val,high) (val > high ? val : high)
|
||||
#define max(val, high) (val > high ? val : high)
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(val,low ) (val < low ? val : low)
|
||||
#define min(val, low) (val < low ? val : low)
|
||||
|
||||
#ifndef __FUNCTION_NAME__
|
||||
#if defined(_WIN32) || defined(_WIN64) //WINDOWS
|
||||
#define __FUNCTION_NAME__ __FUNCTION__
|
||||
#else //*NIX
|
||||
#define __FUNCTION_NAME__ __func__
|
||||
#if defined(_WIN32) || defined(_WIN64) //WINDOWS
|
||||
#define __FUNCTION_NAME__ __FUNCTION__
|
||||
#else //*NIX
|
||||
#define __FUNCTION_NAME__ __func__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void); \
|
||||
struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
|
||||
static void f(void)
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void); \
|
||||
struct f##_t_ { \
|
||||
f##_t_(void) \
|
||||
{ \
|
||||
f(); \
|
||||
} \
|
||||
}; \
|
||||
static f##_t_ f##_; \
|
||||
static void f(void)
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma section(".CRT$XCU",read)
|
||||
#define INITIALIZER2_(f,p) \
|
||||
static void f(void); \
|
||||
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||
__pragma(comment(linker,"/include:" p #f "_")) \
|
||||
static void f(void)
|
||||
#pragma section(".CRT$XCU", read)
|
||||
#define INITIALIZER2_(f, p) \
|
||||
static void f(void); \
|
||||
__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
|
||||
__pragma(comment(linker, "/include:" p #f "_")) static void f(void)
|
||||
#ifdef _WIN64
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"")
|
||||
#define INITIALIZER(f) INITIALIZER2_(f, "")
|
||||
#else
|
||||
#define INITIALIZER(f) INITIALIZER2_(f,"_")
|
||||
#define INITIALIZER(f) INITIALIZER2_(f, "_")
|
||||
#endif
|
||||
#else
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void) __attribute__((constructor)); \
|
||||
static void f(void)
|
||||
#define INITIALIZER(f) \
|
||||
static void f(void) __attribute__((constructor)); \
|
||||
static void f(void)
|
||||
#endif
|
||||
|
||||
// Initializer & Finalizer
|
||||
|
|
|
@ -18,28 +18,28 @@
|
|||
*/
|
||||
|
||||
#include "source-mirror.h"
|
||||
#include "strings.h"
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <bitset>
|
||||
#include <media-io/audio-io.h>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <media-io/audio-io.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "obs-tools.hpp"
|
||||
#include "strings.h"
|
||||
|
||||
#define S_SOURCE_MIRROR "Source.Mirror"
|
||||
#define P_SOURCE "Source.Mirror.Source"
|
||||
#define P_SOURCE_SIZE "Source.Mirror.Source.Size"
|
||||
#define P_SOURCE_AUDIO "Source.Mirror.Source.Audio"
|
||||
#define P_SCALING "Source.Mirror.Scaling"
|
||||
#define P_SCALING_METHOD "Source.Mirror.Scaling.Method"
|
||||
#define P_SCALING_METHOD_POINT "Source.Mirror.Scaling.Method.Point"
|
||||
#define P_SCALING_METHOD_BILINEAR "Source.Mirror.Scaling.Method.Bilinear"
|
||||
#define P_SCALING_METHOD_BILINEARLOWRES "Source.Mirror.Scaling.Method.BilinearLowRes"
|
||||
#define P_SCALING_METHOD_BICUBIC "Source.Mirror.Scaling.Method.Bicubic"
|
||||
#define P_SCALING_METHOD_LANCZOS "Source.Mirror.Scaling.Method.Lanczos"
|
||||
#define P_SCALING_SIZE "Source.Mirror.Scaling.Size"
|
||||
#define P_SCALING_TRANSFORMKEEPORIGINAL "Source.Mirror.Scaling.TransformKeepOriginal"
|
||||
#define S_SOURCE_MIRROR "Source.Mirror"
|
||||
#define P_SOURCE "Source.Mirror.Source"
|
||||
#define P_SOURCE_SIZE "Source.Mirror.Source.Size"
|
||||
#define P_SOURCE_AUDIO "Source.Mirror.Source.Audio"
|
||||
#define P_SCALING "Source.Mirror.Scaling"
|
||||
#define P_SCALING_METHOD "Source.Mirror.Scaling.Method"
|
||||
#define P_SCALING_METHOD_POINT "Source.Mirror.Scaling.Method.Point"
|
||||
#define P_SCALING_METHOD_BILINEAR "Source.Mirror.Scaling.Method.Bilinear"
|
||||
#define P_SCALING_METHOD_BILINEARLOWRES "Source.Mirror.Scaling.Method.BilinearLowRes"
|
||||
#define P_SCALING_METHOD_BICUBIC "Source.Mirror.Scaling.Method.Bicubic"
|
||||
#define P_SCALING_METHOD_LANCZOS "Source.Mirror.Scaling.Method.Lanczos"
|
||||
#define P_SCALING_SIZE "Source.Mirror.Scaling.Size"
|
||||
#define P_SCALING_TRANSFORMKEEPORIGINAL "Source.Mirror.Scaling.TransformKeepOriginal"
|
||||
|
||||
enum class ScalingMethod : int64_t {
|
||||
Point,
|
||||
|
@ -51,33 +51,31 @@ enum class ScalingMethod : int64_t {
|
|||
|
||||
// Initializer & Finalizer
|
||||
Source::MirrorAddon* sourceMirrorInstance;
|
||||
INITIALIZER(SourceMirrorInit) {
|
||||
initializerFunctions.push_back([] {
|
||||
sourceMirrorInstance = new Source::MirrorAddon();
|
||||
});
|
||||
finalizerFunctions.push_back([] {
|
||||
delete sourceMirrorInstance;
|
||||
});
|
||||
INITIALIZER(SourceMirrorInit)
|
||||
{
|
||||
initializerFunctions.push_back([] { sourceMirrorInstance = new Source::MirrorAddon(); });
|
||||
finalizerFunctions.push_back([] { delete sourceMirrorInstance; });
|
||||
}
|
||||
|
||||
Source::MirrorAddon::MirrorAddon() {
|
||||
Source::MirrorAddon::MirrorAddon()
|
||||
{
|
||||
memset(&osi, 0, sizeof(obs_source_info));
|
||||
osi.id = "obs-stream-effects-source-mirror";
|
||||
osi.type = OBS_SOURCE_TYPE_INPUT;
|
||||
osi.id = "obs-stream-effects-source-mirror";
|
||||
osi.type = OBS_SOURCE_TYPE_INPUT;
|
||||
osi.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_AUDIO | OBS_SOURCE_CUSTOM_DRAW;
|
||||
|
||||
osi.get_name = get_name;
|
||||
osi.get_defaults = get_defaults;
|
||||
osi.get_properties = get_properties;
|
||||
osi.get_width = get_width;
|
||||
osi.get_height = get_height;
|
||||
osi.create = create;
|
||||
osi.destroy = destroy;
|
||||
osi.update = update;
|
||||
osi.activate = activate;
|
||||
osi.deactivate = deactivate;
|
||||
osi.video_tick = video_tick;
|
||||
osi.video_render = video_render;
|
||||
osi.get_name = get_name;
|
||||
osi.get_defaults = get_defaults;
|
||||
osi.get_properties = get_properties;
|
||||
osi.get_width = get_width;
|
||||
osi.get_height = get_height;
|
||||
osi.create = create;
|
||||
osi.destroy = destroy;
|
||||
osi.update = update;
|
||||
osi.activate = activate;
|
||||
osi.deactivate = deactivate;
|
||||
osi.video_tick = video_tick;
|
||||
osi.video_render = video_render;
|
||||
osi.enum_active_sources = enum_active_sources;
|
||||
|
||||
obs_register_source(&osi);
|
||||
|
@ -85,11 +83,13 @@ Source::MirrorAddon::MirrorAddon() {
|
|||
|
||||
Source::MirrorAddon::~MirrorAddon() {}
|
||||
|
||||
const char * Source::MirrorAddon::get_name(void *) {
|
||||
const char* Source::MirrorAddon::get_name(void*)
|
||||
{
|
||||
return P_TRANSLATE(S_SOURCE_MIRROR);
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::get_defaults(obs_data_t *data) {
|
||||
void Source::MirrorAddon::get_defaults(obs_data_t* data)
|
||||
{
|
||||
obs_data_set_default_string(data, P_SOURCE, "");
|
||||
obs_data_set_default_bool(data, P_SOURCE_AUDIO, false);
|
||||
obs_data_set_default_bool(data, P_SCALING, false);
|
||||
|
@ -97,13 +97,13 @@ void Source::MirrorAddon::get_defaults(obs_data_t *data) {
|
|||
obs_data_set_default_int(data, P_SCALING_METHOD, (int64_t)ScalingMethod::Bilinear);
|
||||
}
|
||||
|
||||
bool Source::MirrorAddon::modified_properties(obs_properties_t *pr, obs_property_t *p, obs_data_t *data) {
|
||||
bool Source::MirrorAddon::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));
|
||||
if (target) {
|
||||
std::vector<char> buf(256);
|
||||
sprintf_s(buf.data(), buf.size(), "%ldx%ld\0",
|
||||
obs_source_get_width(target), obs_source_get_height(target));
|
||||
sprintf_s(buf.data(), buf.size(), "%ldx%ld\0", obs_source_get_width(target), obs_source_get_height(target));
|
||||
obs_data_set_string(data, P_SOURCE_SIZE, buf.data());
|
||||
} else {
|
||||
obs_data_set_string(data, P_SOURCE_SIZE, "0x0");
|
||||
|
@ -120,24 +120,26 @@ bool Source::MirrorAddon::modified_properties(obs_properties_t *pr, obs_property
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool UpdateSourceListCB(void *ptr, obs_source_t* src) {
|
||||
static bool UpdateSourceListCB(void* ptr, obs_source_t* src)
|
||||
{
|
||||
obs_property_t* p = (obs_property_t*)ptr;
|
||||
obs_property_list_add_string(p, obs_source_get_name(src), obs_source_get_name(src));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void UpdateSourceList(obs_property_t* p) {
|
||||
static void UpdateSourceList(obs_property_t* p)
|
||||
{
|
||||
obs_property_list_clear(p);
|
||||
obs_enum_sources(UpdateSourceListCB, p);
|
||||
obs_enum_scenes(UpdateSourceListCB, p);
|
||||
}
|
||||
|
||||
obs_properties_t * Source::MirrorAddon::get_properties(void *) {
|
||||
obs_properties_t* Source::MirrorAddon::get_properties(void*)
|
||||
{
|
||||
obs_properties_t* pr = obs_properties_create();
|
||||
obs_property_t* p = nullptr;
|
||||
obs_property_t* p = nullptr;
|
||||
|
||||
p = obs_properties_add_list(pr, P_SOURCE, P_TRANSLATE(P_SOURCE),
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
p = obs_properties_add_list(pr, P_SOURCE, P_TRANSLATE(P_SOURCE), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SOURCE)));
|
||||
obs_property_set_modified_callback(p, modified_properties);
|
||||
UpdateSourceList(p);
|
||||
|
@ -153,8 +155,8 @@ obs_properties_t * Source::MirrorAddon::get_properties(void *) {
|
|||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SCALING)));
|
||||
obs_property_set_modified_callback(p, modified_properties);
|
||||
|
||||
p = obs_properties_add_list(pr, P_SCALING_METHOD, P_TRANSLATE(P_SCALING_METHOD),
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
p = obs_properties_add_list(pr, P_SCALING_METHOD, P_TRANSLATE(P_SCALING_METHOD), OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_INT);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SCALING_METHOD)));
|
||||
obs_property_list_add_int(p, P_TRANSLATE(P_SCALING_METHOD_POINT), (int64_t)ScalingMethod::Point);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(P_SCALING_METHOD_BILINEAR), (int64_t)ScalingMethod::Bilinear);
|
||||
|
@ -162,8 +164,7 @@ obs_properties_t * Source::MirrorAddon::get_properties(void *) {
|
|||
obs_property_list_add_int(p, P_TRANSLATE(P_SCALING_METHOD_BICUBIC), (int64_t)ScalingMethod::Bicubic);
|
||||
obs_property_list_add_int(p, P_TRANSLATE(P_SCALING_METHOD_LANCZOS), (int64_t)ScalingMethod::Lanczos);
|
||||
|
||||
p = obs_properties_add_text(pr, P_SCALING_SIZE, P_TRANSLATE(P_SCALING_SIZE),
|
||||
OBS_TEXT_DEFAULT);
|
||||
p = obs_properties_add_text(pr, P_SCALING_SIZE, P_TRANSLATE(P_SCALING_SIZE), OBS_TEXT_DEFAULT);
|
||||
obs_property_set_long_description(p, P_TRANSLATE(P_DESC(P_SCALING_SIZE)));
|
||||
|
||||
p = obs_properties_add_bool(pr, P_SCALING_TRANSFORMKEEPORIGINAL, P_TRANSLATE(P_SCALING_TRANSFORMKEEPORIGINAL));
|
||||
|
@ -172,166 +173,181 @@ obs_properties_t * Source::MirrorAddon::get_properties(void *) {
|
|||
return pr;
|
||||
}
|
||||
|
||||
void * Source::MirrorAddon::create(obs_data_t *data, obs_source_t *source) {
|
||||
void* Source::MirrorAddon::create(obs_data_t* data, obs_source_t* source)
|
||||
{
|
||||
return new Source::Mirror(data, source);
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::destroy(void *p) {
|
||||
void Source::MirrorAddon::destroy(void* p)
|
||||
{
|
||||
if (p) {
|
||||
delete static_cast<Source::Mirror*>(p);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Source::MirrorAddon::get_width(void *p) {
|
||||
uint32_t Source::MirrorAddon::get_width(void* p)
|
||||
{
|
||||
if (p) {
|
||||
return static_cast<Source::Mirror*>(p)->get_width();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Source::MirrorAddon::get_height(void *p) {
|
||||
uint32_t Source::MirrorAddon::get_height(void* p)
|
||||
{
|
||||
if (p) {
|
||||
return static_cast<Source::Mirror*>(p)->get_height();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::update(void *p, obs_data_t *data) {
|
||||
void Source::MirrorAddon::update(void* p, obs_data_t* data)
|
||||
{
|
||||
if (p) {
|
||||
static_cast<Source::Mirror*>(p)->update(data);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::activate(void *p) {
|
||||
void Source::MirrorAddon::activate(void* p)
|
||||
{
|
||||
if (p) {
|
||||
static_cast<Source::Mirror*>(p)->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::deactivate(void *p) {
|
||||
void Source::MirrorAddon::deactivate(void* p)
|
||||
{
|
||||
if (p) {
|
||||
static_cast<Source::Mirror*>(p)->deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::video_tick(void *p, float t) {
|
||||
void Source::MirrorAddon::video_tick(void* p, float t)
|
||||
{
|
||||
if (p) {
|
||||
static_cast<Source::Mirror*>(p)->video_tick(t);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::MirrorAddon::video_render(void *p, gs_effect_t *ef) {
|
||||
void Source::MirrorAddon::video_render(void* p, gs_effect_t* ef)
|
||||
{
|
||||
if (p) {
|
||||
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) {
|
||||
void Source::MirrorAddon::enum_active_sources(void* p, obs_source_enum_proc_t enum_callback, void* param)
|
||||
{
|
||||
if (p) {
|
||||
static_cast<Source::Mirror*>(p)->enum_active_sources(enum_callback, param);
|
||||
}
|
||||
}
|
||||
|
||||
Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src) {
|
||||
m_source = src;
|
||||
Source::Mirror::Mirror(obs_data_t* data, obs_source_t* src)
|
||||
{
|
||||
this->m_source = src;
|
||||
this->m_rescale = false;
|
||||
this->m_width = 1;
|
||||
this->m_height = this->m_width;
|
||||
this->m_render_target_scale = std::make_unique<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
this->m_sampler = std::make_shared<gs::sampler>();
|
||||
this->m_scaling_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
|
||||
m_rescale = false;
|
||||
m_width = m_height = 1;
|
||||
m_renderTargetScale = std::make_unique<gs::rendertarget>(GS_RGBA, GS_ZS_NONE);
|
||||
m_sampler = std::make_shared<gs::sampler>();
|
||||
m_scalingEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
|
||||
m_audioData.resize(MAX_AUDIO_CHANNELS);
|
||||
for (size_t idx = 0; idx < m_audioData.size(); idx++) {
|
||||
m_audioData[idx].resize(AUDIO_OUTPUT_FRAMES);
|
||||
this->m_audio_data.resize(MAX_AUDIO_CHANNELS);
|
||||
for (size_t idx = 0; idx < this->m_audio_data.size(); idx++) {
|
||||
this->m_audio_data[idx].resize(AUDIO_OUTPUT_FRAMES);
|
||||
}
|
||||
m_audioThread = std::thread(std::bind(&Source::Mirror::audio_output_cb, this));
|
||||
this->m_audio_thread = std::thread(std::bind(&Source::Mirror::audio_output_cb, this));
|
||||
|
||||
update(data);
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
Source::Mirror::~Mirror() {
|
||||
if (m_audioCapture) {
|
||||
m_audioCapture.reset();
|
||||
Source::Mirror::~Mirror()
|
||||
{
|
||||
if (this->m_audio_capture) {
|
||||
this->m_audio_capture.reset();
|
||||
}
|
||||
if (m_source_texture) {
|
||||
m_source_texture.reset();
|
||||
if (this->m_source_texture) {
|
||||
this->m_source_texture.reset();
|
||||
}
|
||||
if (m_scene) {
|
||||
obs_scene_release(m_scene);
|
||||
if (this->m_scene) {
|
||||
obs_scene_release(this->m_scene);
|
||||
}
|
||||
|
||||
m_killAudioThread = true;
|
||||
m_audioNotify.notify_all();
|
||||
if (m_audioThread.joinable())
|
||||
m_audioThread.join();
|
||||
this->m_kill_audio_thread = true;
|
||||
this->m_audio_notify.notify_all();
|
||||
if (this->m_audio_thread.joinable()) {
|
||||
this->m_audio_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Source::Mirror::get_width() {
|
||||
if (m_rescale && m_width > 0 && !m_keepOriginalSize) {
|
||||
return m_width;
|
||||
uint32_t Source::Mirror::get_width()
|
||||
{
|
||||
if (this->m_rescale && this->m_width > 0 && !this->m_keep_original_size) {
|
||||
return this->m_width;
|
||||
}
|
||||
obs_source_t* source = obs_sceneitem_get_source(m_sceneitem);
|
||||
obs_source_t* source = obs_sceneitem_get_source(this->m_sceneitem);
|
||||
if (source) {
|
||||
return obs_source_get_width(source);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t Source::Mirror::get_height() {
|
||||
if (m_rescale && m_height > 0 && !m_keepOriginalSize)
|
||||
return m_height;
|
||||
obs_source_t* source = obs_sceneitem_get_source(m_sceneitem);
|
||||
uint32_t Source::Mirror::get_height()
|
||||
{
|
||||
if (this->m_rescale && this->m_height > 0 && !this->m_keep_original_size)
|
||||
return this->m_height;
|
||||
obs_source_t* source = obs_sceneitem_get_source(this->m_sceneitem);
|
||||
if (source) {
|
||||
return obs_source_get_height(source);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Source::Mirror::update(obs_data_t* data) {
|
||||
if (!this->m_scene && m_active) {
|
||||
m_scene = obs_scene_create_private("localscene");
|
||||
m_scene_source = std::make_shared<obs::source>(obs_scene_get_source(m_scene), false, false);
|
||||
m_source_texture = std::make_unique<gfx::source_texture>(m_scene_source, m_source);
|
||||
void Source::Mirror::update(obs_data_t* data)
|
||||
{
|
||||
if (!this->m_scene && this->m_active) {
|
||||
this->m_scene = obs_scene_create_private("localscene");
|
||||
this->m_scene_source = std::make_shared<obs::source>(obs_scene_get_source(this->m_scene), false, false);
|
||||
this->m_source_texture = std::make_unique<gfx::source_texture>(this->m_scene_source, this->m_source);
|
||||
}
|
||||
|
||||
// Update selected source.
|
||||
const char* sourceName = obs_data_get_string(data, P_SOURCE);
|
||||
if (sourceName != m_mirrorName) {
|
||||
const char* new_source_name = obs_data_get_string(data, P_SOURCE);
|
||||
if (new_source_name != m_source_name) {
|
||||
if (m_scene) {
|
||||
if (m_sceneitem) {
|
||||
obs_sceneitem_remove(m_sceneitem);
|
||||
m_sceneitem = nullptr;
|
||||
if (this->m_sceneitem) {
|
||||
obs_sceneitem_remove(this->m_sceneitem);
|
||||
this->m_sceneitem = nullptr;
|
||||
}
|
||||
obs_source_t* source = obs_get_source_by_name(sourceName);
|
||||
obs_source_t* source = obs_get_source_by_name(new_source_name);
|
||||
if (source) {
|
||||
bool allow = true;
|
||||
bool allow = true;
|
||||
if (strcmp(obs_source_get_id(source), "scene") == 0) {
|
||||
if (obs::tools::scene_contains_source(obs_scene_from_source(source), m_source)) {
|
||||
if (obs::tools::scene_contains_source(obs_scene_from_source(source), this->m_source)) {
|
||||
allow = false;
|
||||
}
|
||||
}
|
||||
if (allow) {
|
||||
m_sceneitem = obs_scene_add(m_scene, source);
|
||||
if (allow) {
|
||||
this->m_sceneitem = obs_scene_add(m_scene, source);
|
||||
try {
|
||||
m_audioCapture = std::make_unique<obs::audio_capture>(source);
|
||||
m_audioCapture->set_callback(std::bind(&Source::Mirror::audio_capture_cb, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
} catch(...) {
|
||||
this->m_audio_capture = std::make_unique<obs::audio_capture>(source);
|
||||
this->m_audio_capture->set_callback(std::bind(&Source::Mirror::audio_capture_cb, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
obs_source_release(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_enableAudio = obs_data_get_bool(data, P_SOURCE_AUDIO);
|
||||
this->m_enable_audio = obs_data_get_bool(data, P_SOURCE_AUDIO);
|
||||
|
||||
// Rescaling
|
||||
m_rescale = obs_data_get_bool(data, P_SCALING);
|
||||
if (m_rescale) { // Parse rescaling settings.
|
||||
this->m_rescale = obs_data_get_bool(data, P_SCALING);
|
||||
if (this->m_rescale) { // Parse rescaling settings.
|
||||
uint32_t width, height;
|
||||
|
||||
// Read value.
|
||||
|
@ -341,101 +357,105 @@ void Source::Mirror::update(obs_data_t* data) {
|
|||
// Width
|
||||
width = strtoul(size, nullptr, 10);
|
||||
if (errno == ERANGE || width == 0) {
|
||||
m_rescale = false;
|
||||
m_width = 1;
|
||||
this->m_rescale = false;
|
||||
this->m_width = 1;
|
||||
} else {
|
||||
m_width = width;
|
||||
this->m_width = width;
|
||||
}
|
||||
|
||||
height = strtoul(xpos + 1, nullptr, 10);
|
||||
if (errno == ERANGE || height == 0) {
|
||||
m_rescale = false;
|
||||
m_height = 1;
|
||||
this->m_rescale = false;
|
||||
this->m_height = 1;
|
||||
} else {
|
||||
m_height = height;
|
||||
this->m_height = height;
|
||||
}
|
||||
} else {
|
||||
m_rescale = false;
|
||||
m_width = 1;
|
||||
m_height = 1;
|
||||
this->m_rescale = false;
|
||||
this->m_width = 1;
|
||||
this->m_height = 1;
|
||||
}
|
||||
|
||||
ScalingMethod scaler = (ScalingMethod)obs_data_get_int(data, P_SCALING_METHOD);
|
||||
switch (scaler) {
|
||||
case ScalingMethod::Point:
|
||||
default:
|
||||
m_scalingEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
m_sampler->set_filter(GS_FILTER_POINT);
|
||||
break;
|
||||
case ScalingMethod::Bilinear:
|
||||
m_scalingEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::BilinearLowRes:
|
||||
m_scalingEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_BILINEAR_LOWRES);
|
||||
m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::Bicubic:
|
||||
m_scalingEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_BICUBIC);
|
||||
m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::Lanczos:
|
||||
m_scalingEffect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_LANCZOS);
|
||||
m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::Point:
|
||||
default:
|
||||
this->m_scaling_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
this->m_sampler->set_filter(GS_FILTER_POINT);
|
||||
break;
|
||||
case ScalingMethod::Bilinear:
|
||||
this->m_scaling_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_DEFAULT);
|
||||
this->m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::BilinearLowRes:
|
||||
this->m_scaling_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_BILINEAR_LOWRES);
|
||||
this->m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::Bicubic:
|
||||
this->m_scaling_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_BICUBIC);
|
||||
this->m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
case ScalingMethod::Lanczos:
|
||||
this->m_scaling_effect = obs_get_base_effect(obs_base_effect::OBS_EFFECT_LANCZOS);
|
||||
this->m_sampler->set_filter(GS_FILTER_LINEAR);
|
||||
break;
|
||||
}
|
||||
|
||||
m_keepOriginalSize = obs_data_get_bool(data, P_SCALING_TRANSFORMKEEPORIGINAL);
|
||||
this->m_keep_original_size = obs_data_get_bool(data, P_SCALING_TRANSFORMKEEPORIGINAL);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::Mirror::activate() {
|
||||
m_active = true;
|
||||
if (!m_sceneitem) {
|
||||
obs_data_t* ref = obs_source_get_settings(m_source);
|
||||
void Source::Mirror::activate()
|
||||
{
|
||||
this->m_active = true;
|
||||
if (!this->m_sceneitem) {
|
||||
obs_data_t* ref = obs_source_get_settings(this->m_source);
|
||||
update(ref);
|
||||
obs_data_release(ref);
|
||||
}
|
||||
}
|
||||
|
||||
void Source::Mirror::deactivate() {
|
||||
m_active = false;
|
||||
void Source::Mirror::deactivate()
|
||||
{
|
||||
this->m_active = false;
|
||||
}
|
||||
|
||||
static inline void mix_audio(float *p_out, float *p_in,
|
||||
size_t pos, size_t count) {
|
||||
register float *out = p_out;
|
||||
register float *in = p_in + pos;
|
||||
register float *end = in + count;
|
||||
static inline void mix_audio(float* p_out, float* p_in, size_t pos, size_t count)
|
||||
{
|
||||
register float* out = p_out;
|
||||
register float* in = p_in + pos;
|
||||
register float* end = in + count;
|
||||
|
||||
while (in < end)
|
||||
*(out++) += *(in++);
|
||||
}
|
||||
|
||||
void Source::Mirror::video_tick(float time) {
|
||||
m_tick += time;
|
||||
void Source::Mirror::video_tick(float time)
|
||||
{
|
||||
this->m_tick += time;
|
||||
|
||||
if (m_sceneitem) {
|
||||
m_mirrorName = obs_source_get_name(obs_sceneitem_get_source(m_sceneitem));
|
||||
if (this->m_sceneitem) {
|
||||
this->m_source_name = obs_source_get_name(obs_sceneitem_get_source(this->m_sceneitem));
|
||||
} else {
|
||||
if (m_tick > 0.1f) {
|
||||
obs_data_t* ref = obs_source_get_settings(m_source);
|
||||
if (this->m_tick > 0.1f) {
|
||||
obs_data_t* ref = obs_source_get_settings(this->m_source);
|
||||
update(ref);
|
||||
obs_data_release(ref);
|
||||
m_tick -= 0.1f;
|
||||
this->m_tick -= 0.1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Source::Mirror::video_render(gs_effect_t*) {
|
||||
if ((m_width == 0) || (m_height == 0) || !m_source_texture || (m_source_texture->get_object() == m_source)
|
||||
|| !m_scene || !m_sceneitem) {
|
||||
void Source::Mirror::video_render(gs_effect_t*)
|
||||
{
|
||||
if ((this->m_width == 0) || (this->m_height == 0) || !this->m_source_texture || !this->m_scene
|
||||
|| !this->m_sceneitem) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_rescale && m_width > 0 && m_height > 0 && m_scalingEffect) {
|
||||
if (this->m_rescale && this->m_width > 0 && this->m_height > 0 && this->m_scaling_effect) {
|
||||
// Get Size of source.
|
||||
obs_source_t* source = obs_sceneitem_get_source(m_sceneitem);
|
||||
obs_source_t* source = obs_sceneitem_get_source(this->m_sceneitem);
|
||||
|
||||
uint32_t sw, sh;
|
||||
sw = obs_source_get_width(source);
|
||||
|
@ -444,57 +464,56 @@ void Source::Mirror::video_render(gs_effect_t*) {
|
|||
vec2 bounds;
|
||||
bounds.x = sw;
|
||||
bounds.y = sh;
|
||||
obs_sceneitem_set_bounds(m_sceneitem, &bounds);
|
||||
obs_sceneitem_set_bounds(this->m_sceneitem, &bounds);
|
||||
|
||||
// Store original Source Texture
|
||||
std::shared_ptr<gs::texture> tex;
|
||||
try {
|
||||
tex = m_source_texture->render(sw, sh);
|
||||
tex = this->m_source_texture->render(sw, sh);
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
|
||||
gs_eparam_t *scale_param = gs_effect_get_param_by_name(m_scalingEffect, "base_dimension_i");
|
||||
gs_eparam_t* scale_param = gs_effect_get_param_by_name(this->m_scaling_effect, "base_dimension_i");
|
||||
if (scale_param) {
|
||||
struct vec2 base_res_i = {
|
||||
1.0f / (float)sw,
|
||||
1.0f / (float)sh
|
||||
};
|
||||
struct vec2 base_res_i = {1.0f / float_t(sw), 1.0f / float_t(sh)};
|
||||
gs_effect_set_vec2(scale_param, &base_res_i);
|
||||
}
|
||||
|
||||
if (m_keepOriginalSize) {
|
||||
if (this->m_keep_original_size) {
|
||||
{
|
||||
vec4 black; vec4_zero(&black);
|
||||
auto op = m_renderTargetScale->render(m_width, m_height);
|
||||
gs_ortho(0, (float_t)m_width, 0, (float_t)m_height, 0, 1);
|
||||
vec4 black;
|
||||
vec4_zero(&black);
|
||||
auto op = m_render_target_scale->render(this->m_width, this->m_height);
|
||||
gs_ortho(0, float_t(this->m_width), 0, float_t(this->m_height), 0, 1);
|
||||
gs_clear(GS_CLEAR_COLOR, &black, 0, 0);
|
||||
while (gs_effect_loop(m_scalingEffect, "Draw")) {
|
||||
gs_eparam_t* image = gs_effect_get_param_by_name(m_scalingEffect, "image");
|
||||
gs_effect_set_next_sampler(image, m_sampler->get_object());
|
||||
obs_source_draw(tex->get_object(), 0, 0, m_width, m_height, false);
|
||||
while (gs_effect_loop(this->m_scaling_effect, "Draw")) {
|
||||
gs_eparam_t* image = gs_effect_get_param_by_name(this->m_scaling_effect, "image");
|
||||
gs_effect_set_next_sampler(image, this->m_sampler->get_object());
|
||||
obs_source_draw(tex->get_object(), 0, 0, this->m_width, this->m_height, false);
|
||||
}
|
||||
}
|
||||
while (gs_effect_loop(obs_get_base_effect(OBS_EFFECT_DEFAULT), "Draw")) {
|
||||
gs_eparam_t* image = gs_effect_get_param_by_name(obs_get_base_effect(OBS_EFFECT_DEFAULT), "image");
|
||||
gs_effect_set_next_sampler(image, m_sampler->get_object());
|
||||
obs_source_draw(m_renderTargetScale->get_object(), 0, 0, sw, sh, false);
|
||||
gs_effect_set_next_sampler(image, this->m_sampler->get_object());
|
||||
obs_source_draw(this->m_render_target_scale->get_object(), 0, 0, sw, sh, false);
|
||||
}
|
||||
} else {
|
||||
while (gs_effect_loop(m_scalingEffect, "Draw")) {
|
||||
gs_eparam_t* image = gs_effect_get_param_by_name(m_scalingEffect, "image");
|
||||
gs_effect_set_next_sampler(image, m_sampler->get_object());
|
||||
obs_source_draw(tex->get_object(), 0, 0, m_width, m_height, false);
|
||||
while (gs_effect_loop(this->m_scaling_effect, "Draw")) {
|
||||
gs_eparam_t* image = gs_effect_get_param_by_name(this->m_scaling_effect, "image");
|
||||
gs_effect_set_next_sampler(image, this->m_sampler->get_object());
|
||||
obs_source_draw(tex->get_object(), 0, 0, this->m_width, this->m_height, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
obs_source_video_render(m_source_texture->get_object());
|
||||
obs_source_video_render(this->m_source_texture->get_object());
|
||||
}
|
||||
}
|
||||
|
||||
void Source::Mirror::audio_capture_cb(void*, const audio_data* audio, bool) {
|
||||
std::unique_lock<std::mutex> ulock(m_audioLock);
|
||||
if (!m_enableAudio) {
|
||||
void Source::Mirror::audio_capture_cb(void*, const audio_data* audio, bool)
|
||||
{
|
||||
std::unique_lock<std::mutex> ulock(this->m_audio_lock);
|
||||
if (!this->m_enable_audio) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -509,40 +528,42 @@ void Source::Mirror::audio_capture_cb(void*, const audio_data* audio, bool) {
|
|||
|
||||
std::bitset<8> layout;
|
||||
for (size_t plane = 0; plane < MAX_AV_PLANES; plane++) {
|
||||
float *samples = (float*)audio->data[plane];
|
||||
float* samples = (float*)audio->data[plane];
|
||||
if (!samples) {
|
||||
m_audioOutput.data[plane] = nullptr;
|
||||
this->m_audio_output.data[plane] = nullptr;
|
||||
continue;
|
||||
}
|
||||
layout.set(plane);
|
||||
|
||||
memcpy(m_audioData[plane].data(), audio->data[plane], audio->frames * sizeof(float_t));
|
||||
m_audioOutput.data[plane] = (uint8_t*)m_audioData[plane].data();
|
||||
memcpy(this->m_audio_data[plane].data(), audio->data[plane], audio->frames * sizeof(float_t));
|
||||
this->m_audio_output.data[plane] = reinterpret_cast<uint8_t*>(this->m_audio_data[plane].data());
|
||||
}
|
||||
m_audioOutput.format = aoi->format;
|
||||
m_audioOutput.frames = audio->frames;
|
||||
m_audioOutput.timestamp = audio->timestamp;
|
||||
m_audioOutput.samples_per_sec = aoi->samples_per_sec;
|
||||
m_audioOutput.speakers = aoi->speakers;
|
||||
this->m_audio_output.format = aoi->format;
|
||||
this->m_audio_output.frames = audio->frames;
|
||||
this->m_audio_output.timestamp = audio->timestamp;
|
||||
this->m_audio_output.samples_per_sec = aoi->samples_per_sec;
|
||||
this->m_audio_output.speakers = aoi->speakers;
|
||||
|
||||
m_haveAudioOutput = true;
|
||||
m_audioNotify.notify_all();
|
||||
this->m_have_audio_output = true;
|
||||
this->m_audio_notify.notify_all();
|
||||
}
|
||||
|
||||
void Source::Mirror::audio_output_cb() {
|
||||
std::unique_lock<std::mutex> ulock(m_audioLock);
|
||||
void Source::Mirror::audio_output_cb()
|
||||
{
|
||||
std::unique_lock<std::mutex> ulock(this->m_audio_lock);
|
||||
|
||||
while (!m_killAudioThread) {
|
||||
if (m_haveAudioOutput) {
|
||||
obs_source_output_audio(m_source, &m_audioOutput);
|
||||
m_haveAudioOutput = false;
|
||||
while (!this->m_kill_audio_thread) {
|
||||
if (this->m_have_audio_output) {
|
||||
obs_source_output_audio(this->m_source, &this->m_audio_output);
|
||||
this->m_have_audio_output = false;
|
||||
}
|
||||
m_audioNotify.wait(ulock, [this]() { return m_haveAudioOutput || m_killAudioThread; });
|
||||
this->m_audio_notify.wait(ulock, [this]() { return this->m_have_audio_output || this->m_kill_audio_thread; });
|
||||
}
|
||||
}
|
||||
|
||||
void Source::Mirror::enum_active_sources(obs_source_enum_proc_t enum_callback, void *param) {
|
||||
if (m_sceneitem) {
|
||||
enum_callback(m_source, obs_sceneitem_get_source(m_sceneitem), param);
|
||||
void Source::Mirror::enum_active_sources(obs_source_enum_proc_t enum_callback, void* param)
|
||||
{
|
||||
if (this->m_sceneitem) {
|
||||
enum_callback(this->m_source, obs_sceneitem_get_source(this->m_sceneitem), param);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,57 +42,58 @@ namespace Source {
|
|||
MirrorAddon();
|
||||
~MirrorAddon();
|
||||
|
||||
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 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 *create(obs_data_t *, obs_source_t *);
|
||||
static void destroy(void *);
|
||||
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 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 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 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*);
|
||||
};
|
||||
|
||||
class Mirror {
|
||||
bool m_active = false;
|
||||
bool m_active = false;
|
||||
obs_source_t* m_source = nullptr;
|
||||
float_t m_tick = 0;
|
||||
float_t m_tick = 0;
|
||||
|
||||
// Input
|
||||
obs_scene_t* m_scene = nullptr;
|
||||
std::shared_ptr<obs::source> m_scene_source;
|
||||
obs_scene_t* m_scene = nullptr;
|
||||
std::shared_ptr<obs::source> m_scene_source;
|
||||
std::unique_ptr<gfx::source_texture> m_source_texture;
|
||||
|
||||
// Input Source
|
||||
obs_sceneitem_t* m_sceneitem = nullptr;
|
||||
std::string m_mirrorName;
|
||||
std::string m_source_name;
|
||||
|
||||
// Scaling
|
||||
bool m_rescale = false;
|
||||
uint32_t m_width, m_height;
|
||||
gs_effect_t* m_scalingEffect = nullptr;
|
||||
bool m_keepOriginalSize = false;
|
||||
std::unique_ptr<gs::rendertarget> m_renderTargetScale;
|
||||
std::shared_ptr<gs::sampler> m_sampler;
|
||||
bool m_rescale = false;
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
gs_effect_t* m_scaling_effect = nullptr;
|
||||
bool m_keep_original_size = false;
|
||||
std::unique_ptr<gs::rendertarget> m_render_target_scale;
|
||||
std::shared_ptr<gs::sampler> m_sampler;
|
||||
|
||||
// Audio
|
||||
bool m_enableAudio = false;
|
||||
std::unique_ptr<obs::audio_capture> m_audioCapture;
|
||||
std::mutex m_audioLock;
|
||||
std::condition_variable m_audioNotify;
|
||||
obs_source_audio m_audioOutput;
|
||||
std::vector<std::vector<float_t>> m_audioData;
|
||||
std::thread m_audioThread;
|
||||
bool m_killAudioThread = false;
|
||||
bool m_haveAudioOutput = false;
|
||||
bool m_enable_audio = false;
|
||||
std::unique_ptr<obs::audio_capture> m_audio_capture;
|
||||
std::mutex m_audio_lock;
|
||||
std::condition_variable m_audio_notify;
|
||||
obs_source_audio m_audio_output;
|
||||
std::vector<std::vector<float_t>> m_audio_data;
|
||||
std::thread m_audio_thread;
|
||||
bool m_kill_audio_thread = false;
|
||||
bool m_have_audio_output = false;
|
||||
|
||||
public:
|
||||
Mirror(obs_data_t*, obs_source_t*);
|
||||
|
@ -108,6 +109,6 @@ namespace Source {
|
|||
void video_render(gs_effect_t*);
|
||||
void audio_capture_cb(void* data, const audio_data* audio, bool muted);
|
||||
void audio_output_cb();
|
||||
void enum_active_sources(obs_source_enum_proc_t, void *);
|
||||
void enum_active_sources(obs_source_enum_proc_t, void*);
|
||||
};
|
||||
};
|
||||
}; // namespace Source
|
||||
|
|
|
@ -18,53 +18,62 @@
|
|||
*/
|
||||
|
||||
#include "util-math.h"
|
||||
#include "util-memory.h"
|
||||
#include <cctype>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <cctype>
|
||||
#include "util-memory.h"
|
||||
|
||||
void* util::vec3a::operator new(size_t count) {
|
||||
void* util::vec3a::operator new(size_t count)
|
||||
{
|
||||
return _aligned_malloc(count, 16);
|
||||
}
|
||||
|
||||
void* util::vec3a::operator new[](size_t count) {
|
||||
void* util::vec3a::operator new[](size_t count)
|
||||
{
|
||||
return _aligned_malloc(count, 16);
|
||||
}
|
||||
|
||||
void util::vec3a::operator delete(void* p) {
|
||||
void util::vec3a::operator delete(void* p)
|
||||
{
|
||||
_aligned_free(p);
|
||||
}
|
||||
|
||||
void util::vec3a::operator delete[](void* p) {
|
||||
void util::vec3a::operator delete[](void* p)
|
||||
{
|
||||
_aligned_free(p);
|
||||
}
|
||||
|
||||
void* util::vec4a::operator new(size_t count) {
|
||||
void* util::vec4a::operator new(size_t count)
|
||||
{
|
||||
return _aligned_malloc(count, 16);
|
||||
}
|
||||
|
||||
void* util::vec4a::operator new[](size_t count) {
|
||||
void* util::vec4a::operator new[](size_t count)
|
||||
{
|
||||
return _aligned_malloc(count, 16);
|
||||
}
|
||||
|
||||
void util::vec4a::operator delete(void* p) {
|
||||
void util::vec4a::operator delete(void* p)
|
||||
{
|
||||
_aligned_free(p);
|
||||
}
|
||||
|
||||
void util::vec4a::operator delete[](void* p) {
|
||||
void util::vec4a::operator delete[](void* p)
|
||||
{
|
||||
_aligned_free(p);
|
||||
}
|
||||
|
||||
std::pair<int64_t, int64_t> util::SizeFromString(std::string text, bool allowSquare) {
|
||||
std::pair<int64_t, int64_t> util::SizeFromString(std::string text, bool allowSquare)
|
||||
{
|
||||
int64_t width, height;
|
||||
|
||||
const char* begin = text.c_str();
|
||||
const char* end = text.c_str() + text.size() + 1;
|
||||
char* here = const_cast<char*>(end);
|
||||
const char* end = text.c_str() + text.size() + 1;
|
||||
char* here = const_cast<char*>(end);
|
||||
|
||||
long long res = strtoll(begin, &here, 0);
|
||||
if (errno == ERANGE) {
|
||||
return { 0, 0 };
|
||||
return {0, 0};
|
||||
}
|
||||
width = res;
|
||||
|
||||
|
@ -78,18 +87,18 @@ std::pair<int64_t, int64_t> util::SizeFromString(std::string text, bool allowSqu
|
|||
// Are we allowed to return a square?
|
||||
if (allowSquare) {
|
||||
// Yes: Return width,width.
|
||||
return { width, width };
|
||||
return {width, width};
|
||||
} else {
|
||||
// No: Return width,0.
|
||||
return { width, 0 };
|
||||
return {width, 0};
|
||||
}
|
||||
}
|
||||
|
||||
res = strtoll(here, nullptr, 0);
|
||||
if (errno == ERANGE) {
|
||||
return { width, 0 };
|
||||
return {width, 0};
|
||||
}
|
||||
height = res;
|
||||
|
||||
return { width, height };
|
||||
return {width, height};
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
#include <cstdlib>
|
||||
#define USE_STD_ALLOC_FREE
|
||||
|
||||
void* util::malloc_aligned(size_t align, size_t size) {
|
||||
void* util::malloc_aligned(size_t align, size_t size)
|
||||
{
|
||||
#ifdef USE_STD_ALLOC_FREE
|
||||
#if defined(_MSC_VER)
|
||||
return _aligned_malloc(size, align);
|
||||
|
@ -46,7 +47,8 @@ void* util::malloc_aligned(size_t align, size_t size) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void util::free_aligned(void* mem) {
|
||||
void util::free_aligned(void* mem)
|
||||
{
|
||||
#ifdef USE_STD_ALLOC_FREE
|
||||
#if defined(_MSC_VER)
|
||||
_aligned_free(mem);
|
||||
|
|
|
@ -18,81 +18,91 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace util {
|
||||
inline size_t aligned_offset(size_t align, size_t pos) {
|
||||
inline size_t aligned_offset(size_t align, size_t pos)
|
||||
{
|
||||
return ((pos / align) + 1) * align;
|
||||
}
|
||||
void* malloc_aligned(size_t align, size_t size);
|
||||
void free_aligned(void* mem);
|
||||
void free_aligned(void* mem);
|
||||
|
||||
template <typename T, size_t N = 16>
|
||||
template<typename T, size_t N = 16>
|
||||
class AlignmentAllocator {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef size_t size_type;
|
||||
typedef T value_type;
|
||||
typedef size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
typedef T & reference;
|
||||
typedef const T & const_reference;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
|
||||
public:
|
||||
inline AlignmentAllocator() throw () {}
|
||||
inline AlignmentAllocator() throw() {}
|
||||
|
||||
template <typename T2>
|
||||
inline AlignmentAllocator(const AlignmentAllocator<T2, N> &) throw () {}
|
||||
template<typename T2>
|
||||
inline AlignmentAllocator(const AlignmentAllocator<T2, N>&) throw()
|
||||
{}
|
||||
|
||||
inline ~AlignmentAllocator() throw () {}
|
||||
inline ~AlignmentAllocator() throw() {}
|
||||
|
||||
inline pointer adress(reference r) {
|
||||
inline pointer adress(reference r)
|
||||
{
|
||||
return &r;
|
||||
}
|
||||
|
||||
inline const_pointer adress(const_reference r) const {
|
||||
inline const_pointer adress(const_reference r) const
|
||||
{
|
||||
return &r;
|
||||
}
|
||||
|
||||
inline pointer allocate(size_type n) {
|
||||
return (pointer)malloc_aligned(n*sizeof(value_type), N);
|
||||
inline pointer allocate(size_type n)
|
||||
{
|
||||
return (pointer)malloc_aligned(n * sizeof(value_type), N);
|
||||
}
|
||||
|
||||
inline void deallocate(pointer p, size_type) {
|
||||
inline void deallocate(pointer p, size_type)
|
||||
{
|
||||
free_aligned(p);
|
||||
}
|
||||
|
||||
inline void construct(pointer p, const value_type & wert) {
|
||||
new (p)value_type(wert);
|
||||
inline void construct(pointer p, const value_type& wert)
|
||||
{
|
||||
new (p) value_type(wert);
|
||||
}
|
||||
|
||||
inline void destroy(pointer p) {
|
||||
inline void destroy(pointer p)
|
||||
{
|
||||
p->~value_type();
|
||||
p;
|
||||
}
|
||||
|
||||
inline size_type max_size() const throw () {
|
||||
inline size_type max_size() const throw()
|
||||
{
|
||||
return size_type(-1) / sizeof(value_type);
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
template<typename T2>
|
||||
struct rebind {
|
||||
typedef AlignmentAllocator<T2, N> other;
|
||||
};
|
||||
|
||||
bool operator!=(const AlignmentAllocator<T, N>& other) const {
|
||||
bool operator!=(const AlignmentAllocator<T, N>& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// Returns true if and only if storage allocated from *this
|
||||
// can be deallocated from other, and vice versa.
|
||||
// Always returns true for stateless allocators.
|
||||
bool operator==(const AlignmentAllocator<T, N>& other) const {
|
||||
bool operator==(const AlignmentAllocator<T, N>& other) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}; // namespace util
|
||||
|
|
|
@ -18,4 +18,3 @@
|
|||
*/
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
|
|
|
@ -26,23 +26,21 @@ struct enable_bitmask_operators {
|
|||
};
|
||||
|
||||
template<typename Enum>
|
||||
typename std::enable_if<enable_bitmask_operators<Enum>::enable, Enum>::type
|
||||
operator |(Enum lhs, Enum rhs) {
|
||||
typename std::enable_if<enable_bitmask_operators<Enum>::enable, Enum>::type operator|(Enum lhs, Enum rhs)
|
||||
{
|
||||
using underlying = typename std::underlying_type<Enum>::type;
|
||||
return static_cast<Enum> (
|
||||
static_cast<underlying>(lhs) |
|
||||
static_cast<underlying>(rhs)
|
||||
);
|
||||
return static_cast<Enum>(static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
typename std::enable_if<enable_bitmask_operators<Enum>::enable, Enum>::type
|
||||
operator &(Enum lhs, Enum rhs) {
|
||||
typename std::enable_if<enable_bitmask_operators<Enum>::enable, Enum>::type operator&(Enum lhs, Enum rhs)
|
||||
{
|
||||
using underlying = typename std::underlying_type<Enum>::type;
|
||||
return static_cast<Enum> (
|
||||
static_cast<underlying>(lhs) &
|
||||
static_cast<underlying>(rhs)
|
||||
);
|
||||
return static_cast<Enum>(static_cast<underlying>(lhs) & static_cast<underlying>(rhs));
|
||||
}
|
||||
|
||||
#define ENABLE_BITMASK_OPERATORS(x) template<> struct enable_bitmask_operators<x> { static const bool enable = true; };
|
||||
#define ENABLE_BITMASK_OPERATORS(x) \
|
||||
template<> \
|
||||
struct enable_bitmask_operators<x> { \
|
||||
static const bool enable = true; \
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue