first commit
This commit is contained in:
13
test/makefile
Normal file
13
test/makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
include ../config.mak
|
||||
|
||||
all: default
|
||||
|
||||
PROJECTS=test-input win
|
||||
|
||||
.PHONY: all default clean
|
||||
|
||||
default: $(PROJECTS)
|
||||
@$(foreach PROJECT, $(PROJECTS), $(MAKE) -C $(PROJECT);)
|
||||
|
||||
clean: $(PROJECTS)
|
||||
@$(foreach PROJECT, $(PROJECTS), $(MAKE) clean -C $(PROJECT);)
|
33
test/test-input/makefile
Normal file
33
test/test-input/makefile
Normal file
@@ -0,0 +1,33 @@
|
||||
include ../../config.mak
|
||||
|
||||
.PHONY: all default clean
|
||||
|
||||
all: default
|
||||
|
||||
SRCFILES=test-filter.c test-input.c test-random.c
|
||||
|
||||
SONAME=../../build/test-input.$(SOEXT)
|
||||
|
||||
OBJS += $(SRCFILES:%.c=%.$(OBJ))
|
||||
|
||||
CPPFLAGS += -iquote../../libobs
|
||||
LDFLAGS += -L../../build -lobs
|
||||
|
||||
default: $(SONAME)
|
||||
|
||||
.depend:
|
||||
@rm -f .depend
|
||||
@$(foreach SRC, $(addprefix $(SRCPATH)/, $(SRCFILES)), $(CCDEP) \
|
||||
$(CPPFLAGS) $(SRC) \
|
||||
-MT $(SRC:$(SRCPATH)/%.c=%.$(OBJ)) -MM 1>> .depend;)
|
||||
|
||||
$(SONAME): .depend $(OBJS)
|
||||
$(LD)$@ $(LDFLAGS) $(OBJS)
|
||||
|
||||
depend: .depend
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(SONAME) *.a *.lib *.exp *.pdb .depend
|
68
test/test-input/test-filter.c
Normal file
68
test/test-input/test-filter.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "test-filter.h"
|
||||
|
||||
struct test_filter *test_create(const char *settings, source_t source)
|
||||
{
|
||||
struct test_filter *tf = bmalloc(sizeof(struct test_filter));
|
||||
memset(tf, 0, sizeof(struct test_filter));
|
||||
|
||||
tf->source = source;
|
||||
tf->whatever = gs_create_effect_from_file("test.effect", NULL);
|
||||
if (!tf->whatever) {
|
||||
test_destroy(tf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tf->texrender = texrender_create(GS_RGBA, GS_ZS_NONE);
|
||||
|
||||
return tf;
|
||||
}
|
||||
|
||||
void test_destroy(struct test_filter *tf)
|
||||
{
|
||||
if (tf) {
|
||||
effect_destroy(tf->whatever);
|
||||
texrender_destroy(tf->texrender);
|
||||
bfree(tf);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t test_get_output_flags(struct test_filter *tf)
|
||||
{
|
||||
return SOURCE_VIDEO;
|
||||
}
|
||||
|
||||
void test_video_tick(struct test_filter *tf, float seconds)
|
||||
{
|
||||
texrender_reset(tf->texrender);
|
||||
}
|
||||
|
||||
void test_video_render(struct test_filter *tf)
|
||||
{
|
||||
source_t filter_target = filter_gettarget(tf->source);
|
||||
int cx = source_getwidth(filter_target);
|
||||
int cy = source_getheight(filter_target);
|
||||
float fcx = (float)cx;
|
||||
float fcy = (float)cy;
|
||||
technique_t tech;
|
||||
texture_t tex;
|
||||
|
||||
if (texrender_begin(tf->texrender, cx, cy)) {
|
||||
gs_ortho(0.0f, fcx, 0.0f, fcy, -100.0f, 100.0f);
|
||||
source_video_render(filter_target);
|
||||
texrender_end(tf->texrender);
|
||||
}
|
||||
|
||||
/* --------------------------- */
|
||||
|
||||
tex = texrender_gettexture(tf->texrender);
|
||||
tech = effect_gettechnique(tf->whatever, "Default");
|
||||
effect_settexture(tf->whatever, effect_getparambyidx(tf->whatever, 1),
|
||||
tex);
|
||||
technique_begin(tech);
|
||||
technique_beginpass(tech, 0);
|
||||
|
||||
gs_draw_sprite(tex);
|
||||
|
||||
technique_endpass(tech);
|
||||
technique_end(tech);
|
||||
}
|
27
test/test-input/test-filter.h
Normal file
27
test/test-input/test-filter.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef FILTER_TEST_H
|
||||
#define FILTER_TEST_H
|
||||
|
||||
#include "obs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct test_filter {
|
||||
source_t source;
|
||||
effect_t whatever;
|
||||
texrender_t texrender;
|
||||
};
|
||||
|
||||
EXPORT struct test_filter *test_create(const char *settings, source_t source);
|
||||
EXPORT void test_destroy(struct test_filter *rt);
|
||||
EXPORT uint32_t test_get_output_flags(struct test_filter *rt);
|
||||
|
||||
EXPORT void test_video_tick(struct test_filter *rt, float seconds);
|
||||
EXPORT void test_video_render(struct test_filter *rt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
17
test/test-input/test-input-exports.h
Normal file
17
test/test-input/test-input-exports.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef OBS_CAPTURE_EXPORTS_H
|
||||
#define OBS_CAPTURE_EXPORTS_H
|
||||
|
||||
#include "util/c99defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
EXPORT bool enum_inputs(size_t idx, const char **name);
|
||||
EXPORT bool enum_filters(size_t idx, const char **name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
22
test/test-input/test-input.c
Normal file
22
test/test-input/test-input.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "test-input-exports.h"
|
||||
|
||||
const char *inputs[] = {"random"};
|
||||
const char *filters[] = {"test"};
|
||||
|
||||
bool enum_inputs(size_t idx, const char **name)
|
||||
{
|
||||
if (idx >= (sizeof(inputs)/sizeof(const char*)))
|
||||
return false;
|
||||
|
||||
*name = inputs[idx];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool enum_filters(size_t idx, const char **name)
|
||||
{
|
||||
if (idx >= (sizeof(filters)/sizeof(const char*)))
|
||||
return false;
|
||||
|
||||
*name = filters[idx];
|
||||
return true;
|
||||
}
|
74
test/test-input/test-random.c
Normal file
74
test/test-input/test-random.c
Normal file
@@ -0,0 +1,74 @@
|
||||
#include <stdlib.h>
|
||||
#include "test-random.h"
|
||||
|
||||
struct random_tex *random_create(const char *settings, source_t source)
|
||||
{
|
||||
struct random_tex *rt = bmalloc(sizeof(struct random_tex));
|
||||
uint32_t *pixels = bmalloc(20*20*4);
|
||||
size_t x, y;
|
||||
|
||||
memset(rt, 0, sizeof(struct random_tex));
|
||||
|
||||
for (y = 0; y < 20; y++) {
|
||||
for (x = 0; x < 20; x++) {
|
||||
uint32_t pixel = 0xFF000000;
|
||||
pixel |= (rand()%256);
|
||||
pixel |= (rand()%256) << 8;
|
||||
pixel |= (rand()%256) << 16;
|
||||
pixels[y*20 + x] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
rt->texture = gs_create_texture(20, 20, GS_RGBA, pixels, 0);
|
||||
bfree(pixels);
|
||||
|
||||
if (!rt->texture) {
|
||||
random_destroy(rt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rt->whatever = gs_create_effect_from_file("draw.effect", NULL);
|
||||
if (!rt->whatever) {
|
||||
random_destroy(rt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
void random_destroy(struct random_tex *rt)
|
||||
{
|
||||
if (rt) {
|
||||
effect_destroy(rt->whatever);
|
||||
texture_destroy(rt->texture);
|
||||
bfree(rt);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t random_get_output_flags(struct random_tex *rt)
|
||||
{
|
||||
return SOURCE_VIDEO;
|
||||
}
|
||||
|
||||
void random_video_render(struct random_tex *rt, source_t filter_target)
|
||||
{
|
||||
technique_t tech = effect_gettechnique(rt->whatever, "Default");
|
||||
effect_settexture(rt->whatever, effect_getparambyidx(rt->whatever, 1), rt->texture);
|
||||
technique_begin(tech);
|
||||
technique_beginpass(tech, 0);
|
||||
|
||||
gs_draw_sprite(rt->texture);
|
||||
|
||||
technique_endpass(tech);
|
||||
technique_end(tech);
|
||||
}
|
||||
|
||||
int random_getwidth(struct random_tex *rt)
|
||||
{
|
||||
return texture_getwidth(rt->texture);
|
||||
}
|
||||
|
||||
int random_getheight(struct random_tex *rt)
|
||||
{
|
||||
return texture_getheight(rt->texture);
|
||||
}
|
28
test/test-input/test-random.h
Normal file
28
test/test-input/test-random.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef RANDOM_TEX_H
|
||||
#define RANDOM_TEX_H
|
||||
|
||||
#include "obs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct random_tex {
|
||||
texture_t texture;
|
||||
effect_t whatever;
|
||||
};
|
||||
|
||||
EXPORT struct random_tex *random_create(const char *settings, source_t source);
|
||||
EXPORT void random_destroy(struct random_tex *rt);
|
||||
EXPORT uint32_t random_get_output_flags(struct random_tex *rt);
|
||||
|
||||
EXPORT void random_video_render(struct random_tex *rt, source_t filter_target);
|
||||
|
||||
EXPORT int random_getwidth(struct random_tex *rt);
|
||||
EXPORT int random_getheight(struct random_tex *rt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
35
test/win/makefile
Normal file
35
test/win/makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
include ../../config.mak
|
||||
|
||||
.PHONY: all default clean
|
||||
|
||||
all: default
|
||||
|
||||
SRCFILES=test.cpp
|
||||
|
||||
NAME=../../build/wintest$(EXT)
|
||||
|
||||
OBJS += $(SRCFILES:%.cpp=%.$(OBJ))
|
||||
|
||||
LD=g++ -o
|
||||
LDFLAGS=-L../../build -lobs -Wl,--subsystem,windows
|
||||
|
||||
CPPFLAGS += -I../../libobs -DUNICODE -D_UNICODE
|
||||
|
||||
default: $(NAME)
|
||||
|
||||
.depend:
|
||||
@rm -f .depend
|
||||
@$(foreach SRC, $(addprefix $(SRCPATH)/, $(SRCFILES)), $(CCDEP) \
|
||||
$(CPPFLAGS) $(SRC) \
|
||||
-MT $(SRC:$(SRCPATH)/%.c=%.$(OBJ)) -MM 1>> .depend;)
|
||||
|
||||
$(NAME): .depend $(OBJS)
|
||||
$(LD)$@ $(LDFLAGS) $(OBJS)
|
||||
|
||||
depend: .depend
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(NAME) *.a *.lib *.exp *.pdb .depend
|
201
test/win/test.cpp
Normal file
201
test/win/test.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "util/base.h"
|
||||
#include "obs.h"
|
||||
|
||||
static const int cx = 800;
|
||||
static const int cy = 600;
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
|
||||
class OBSContext {
|
||||
obs_t obs;
|
||||
|
||||
public:
|
||||
inline OBSContext(obs_t obs) : obs(obs) {}
|
||||
inline ~OBSContext() {obs_destroy(obs);}
|
||||
inline operator obs_t() {return obs;}
|
||||
};
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
|
||||
class SourceContext {
|
||||
source_t source;
|
||||
|
||||
public:
|
||||
inline SourceContext(source_t source) : source(source) {}
|
||||
inline ~SourceContext() {source_destroy(source);}
|
||||
inline operator source_t() {return source;}
|
||||
};
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
|
||||
class SceneContext {
|
||||
scene_t scene;
|
||||
|
||||
public:
|
||||
inline SceneContext(scene_t scene) : scene(scene) {}
|
||||
inline ~SceneContext() {scene_destroy(scene);}
|
||||
inline operator scene_t() {return scene;}
|
||||
};
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
|
||||
static LRESULT CALLBACK sceneProc(HWND hwnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
|
||||
case WM_CLOSE:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_log(enum log_type type, const char *msg, va_list args)
|
||||
{
|
||||
char bla[4096];
|
||||
vsnprintf(bla, 4095, msg, args);
|
||||
|
||||
OutputDebugStringA(bla);
|
||||
OutputDebugStringA("\n");
|
||||
}
|
||||
|
||||
static obs_t CreateOBS(HWND hwnd)
|
||||
{
|
||||
struct video_info vi;
|
||||
memset(&vi, 0, sizeof(struct video_info));
|
||||
vi.format = "RGBA";
|
||||
vi.fps_num = 30000;
|
||||
vi.fps_den = 1001;
|
||||
vi.width = cx;
|
||||
vi.height = cy;
|
||||
vi.name = "video";
|
||||
|
||||
struct gs_init_data gsid;
|
||||
memset(&gsid, 0, sizeof(gsid));
|
||||
gsid.hwnd = hwnd;
|
||||
gsid.cx = cx;
|
||||
gsid.cy = cy;
|
||||
gsid.num_backbuffers = 2;
|
||||
gsid.format = GS_RGBA;
|
||||
|
||||
obs_t obs = obs_create("libobs-d3d11.dll", &gsid, &vi, NULL);
|
||||
if (!obs)
|
||||
throw "Couldn't create OBS";
|
||||
|
||||
return obs;
|
||||
}
|
||||
|
||||
static void AddTestItems(scene_t scene, source_t source)
|
||||
{
|
||||
sceneitem_t item = NULL;
|
||||
struct vec2 v2;
|
||||
|
||||
item = scene_add(scene, source);
|
||||
vec2_set(&v2, 100.0f, 200.0f);
|
||||
sceneitem_setpos(item, &v2);
|
||||
sceneitem_setrot(item, 10.0f);
|
||||
vec2_set(&v2, 20.0f, 2.0f);
|
||||
sceneitem_setscale(item, &v2);
|
||||
|
||||
item = scene_add(scene, source);
|
||||
vec2_set(&v2, 200.0f, 100.0f);
|
||||
sceneitem_setpos(item, &v2);
|
||||
sceneitem_setrot(item, -45.0f);
|
||||
vec2_set(&v2, 5.0f, 7.0f);
|
||||
sceneitem_setscale(item, &v2);
|
||||
}
|
||||
|
||||
static HWND CreateTestWindow(HINSTANCE instance)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
base_set_log_handler(do_log);
|
||||
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.lpszClassName = L"bla";
|
||||
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
|
||||
wc.hInstance = instance;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.lpfnWndProc = (WNDPROC)sceneProc;
|
||||
|
||||
if (!RegisterClass(&wc))
|
||||
return 0;
|
||||
|
||||
return CreateWindow(L"bla", L"bla", WS_OVERLAPPEDWINDOW|WS_VISIBLE,
|
||||
1920/2 - cx/2, 1080/2 - cy/2, cx, cy,
|
||||
NULL, NULL, instance, NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------- */
|
||||
|
||||
int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdLine,
|
||||
int numCmd)
|
||||
{
|
||||
HWND hwnd = NULL;
|
||||
|
||||
try {
|
||||
hwnd = CreateTestWindow(instance);
|
||||
if (!hwnd)
|
||||
throw "Couldn't create main window";
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* create OBS */
|
||||
OBSContext obs = CreateOBS(hwnd);
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* load module */
|
||||
if (obs_load_module(obs, "test-input.dll") != 0)
|
||||
throw "Couldn't load module";
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* create source */
|
||||
SourceContext source = source_create(obs, SOURCE_INPUT,
|
||||
"random", NULL);
|
||||
if (!source)
|
||||
throw "Couldn't create random test source";
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* create filter */
|
||||
SourceContext filter = source_create(obs, SOURCE_FILTER,
|
||||
"test", NULL);
|
||||
if (!filter)
|
||||
throw "Couldn't create test filter";
|
||||
source_filter_add(source, filter);
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* create scene and add source to scene (twice) */
|
||||
SceneContext scene = scene_create(obs);
|
||||
if (!scene)
|
||||
throw "Couldn't create scene";
|
||||
|
||||
AddTestItems(scene, source);
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* set the scene as the primary draw source and go */
|
||||
obs_set_primary_source(obs, scene_source(scene));
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
obs_set_primary_source(obs, NULL);
|
||||
|
||||
} catch (char *error) {
|
||||
MessageBoxA(NULL, error, NULL, 0);
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "Number of memory leaks: %u", bnum_allocs());
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user