project: Formatting

This commit is contained in:
Michael Fabian 'Xaymar' Dirks 2018-11-07 15:24:25 +01:00
parent 16f55ca583
commit b87ca70796
32 changed files with 982 additions and 922 deletions

View file

@ -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();

View file

@ -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

View file

@ -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();
}
}

View file

@ -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

View file

@ -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());

View file

@ -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

View file

@ -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));

View file

@ -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);

View file

@ -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;

View file

@ -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)
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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};
}

View file

@ -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);

View file

@ -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

View file

@ -18,4 +18,3 @@
*/
#include "utility.h"

View file

@ -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; \
};