Browse Source

Add example monitor capture for OSX (need to clean up (CMake) files)

Palana 11 years ago
parent
commit
4fd4b12c84

+ 2 - 2
CMakeLists.txt

@@ -47,6 +47,6 @@ endif()
 
 set(LIBRARY_OUTPUT_PATH ${obs_BINARY_DIR}/plugins)
 set(RUNTIME_OUTPUT_PATH ${obs_BINARY_DIR}/plugins)
-add_subdirectory(obs)
-
 add_subdirectory(test)
+
+add_subdirectory(obs)

+ 35 - 0
build/data/obs-plugins/test-input/draw_rect.effect

@@ -0,0 +1,35 @@
+uniform float4x4 ViewProj;
+uniform texture_rect diffuse;
+
+sampler_state texSampler {
+	AddressU  = Clamp;
+	AddressV  = Clamp;
+	Filter    = Linear;
+};
+
+struct VertexInOut {
+	float4 pos : POSITION;
+	float2 uv  : TEXCOORD0;
+};
+
+VertexInOut VShader(VertexInOut vert_in)
+{
+	VertexInOut vert_out;
+	vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
+	vert_out.uv = vert_in.uv;
+	return vert_out;
+}
+
+float4 PShader(VertexInOut fragment_in) : TARGET
+{
+	return diffuse.Sample(texSampler, fragment_in.uv);
+}
+
+technique Default
+{
+	pass
+	{
+		vertex_shader = VShader(vert_in);
+		pixel_shader  = PShader(fragment_in);
+	}
+}

+ 13 - 2
test/test-input/CMakeLists.txt

@@ -1,16 +1,27 @@
 include_directories(SYSTEM ${obs_SOURCE_DIR}/libobs)
 
 add_library(test-input MODULE
+	test-desktop.m
 	test-filter.c
 	test-input.c
 	test-sinewave.c
 	test-random.c)
 
+set_source_files_properties(test-desktop.m
+	PROPERTIES LANGUAGE C
+		COMPILE_FLAGS "-fobjc-arc")
+
+find_library(IOSURF IOSurface)
+
+
 target_link_libraries(test-input
-	libobs)
+	libobs
+	${IOSURF})
 
 obs_add_plugin(test-input)
 
 obs_add_data_source(/data/obs-plugins/test-input/
+	${obs_SOURCE_DIR}/build/data/obs-plugins/test-input/draw_rect.effect
 	${obs_SOURCE_DIR}/build/data/obs-plugins/test-input/draw.effect
-	${obs_SOURCE_DIR}/build/data/obs-plugins/test-input/test.effect)
+	${obs_SOURCE_DIR}/build/data/obs-plugins/test-input/test.effect
+	)

+ 34 - 0
test/test-input/test-desktop.h

@@ -0,0 +1,34 @@
+#pragma once
+
+#include "obs.h"
+#import <CoreGraphics/CGDisplayStream.h>
+
+#include <util/darray.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct desktop_tex {
+	samplerstate_t sampler;
+	effect_t whatever;
+	CGDisplayStreamRef disp;
+	uint32_t width, height;
+};
+
+EXPORT const char *desktop_getname(const char *locale);
+
+EXPORT struct desktop_tex *desktop_create(const char *settings, obs_source_t source);
+EXPORT void desktop_destroy(struct desktop_tex *rt);
+EXPORT uint32_t desktop_get_output_flags(struct desktop_tex *rt);
+EXPORT void desktop_video_tick(struct desktop_tex *rt, float dt);
+
+EXPORT void desktop_video_render(struct desktop_tex *rt, obs_source_t filter_target);
+
+EXPORT uint32_t desktop_getwidth(struct desktop_tex *rt);
+EXPORT uint32_t desktop_getheight(struct desktop_tex *rt);
+
+#ifdef __cplusplus
+}
+#endif

+ 174 - 0
test/test-input/test-desktop.m

@@ -0,0 +1,174 @@
+#include <stdlib.h>
+#include "test-desktop.h"
+
+#import <Cocoa/Cocoa.h>
+#import <AppKit/AppKit.h>
+#import <OpenGL/OpenGL.h>
+#import <OpenGL/CGLIOSurface.h>
+#import <OpenGL/CGLMacro.h>
+#import <CoreGraphics/CGDisplayStream.h>
+#include <pthread.h>
+
+
+const char *desktop_getname(const char *locale)
+{
+	return "OSX Monitor Capture";
+}
+
+static IOSurfaceRef current = NULL,
+		    prev = NULL;
+static texture_t tex = NULL;
+static pthread_mutex_t c_mutex;
+
+struct desktop_tex *desktop_create(const char *settings, obs_source_t source)
+{
+	struct desktop_tex *rt = bmalloc(sizeof(struct desktop_tex));
+	char *effect_file;
+
+	memset(rt, 0, sizeof(struct desktop_tex));
+
+	gs_entercontext(obs_graphics());
+
+	struct gs_sampler_info info = {
+		.filter = GS_FILTER_LINEAR,
+		.address_u = GS_ADDRESS_CLAMP,
+		.address_v = GS_ADDRESS_CLAMP,
+		.address_w = GS_ADDRESS_CLAMP,
+		.max_anisotropy = 1,
+	};
+	rt->sampler = gs_create_samplerstate(&info);
+
+	effect_file = obs_find_plugin_file("test-input/draw_rect.effect");
+	rt->whatever = gs_create_effect_from_file(effect_file, NULL);
+	bfree(effect_file);
+
+	if (!rt->whatever) {
+		desktop_destroy(rt);
+		return NULL;
+	}
+
+	if ([[NSScreen screens] count] < 1) {
+		desktop_destroy(rt);
+		return NULL;
+	}
+
+	NSScreen *screen = [NSScreen screens][0];
+
+	NSRect frame = [screen convertRectToBacking:[screen frame]];
+
+	rt->width = frame.size.width;
+	rt->height = frame.size.height;
+
+	printf("%u %u\n", rt->width, rt->height);
+
+	pthread_mutex_init(&c_mutex, NULL);
+
+	NSDictionary *dict = @{
+		(__bridge NSString*)kCGDisplayStreamSourceRect:
+		(__bridge NSDictionary*)CGRectCreateDictionaryRepresentation(
+				CGRectMake(0, 0, rt->width, rt->height)),
+		(__bridge NSString*)kCGDisplayStreamQueueDepth: @5
+	};
+
+	rt->disp = CGDisplayStreamCreateWithDispatchQueue(CGMainDisplayID(),
+			rt->width, rt->height, 'BGRA',
+			(__bridge CFDictionaryRef)dict,
+			dispatch_queue_create("dispstream", NULL),
+			^(CGDisplayStreamFrameStatus status, uint64_t
+				displayTime, IOSurfaceRef frameSurface,
+				CGDisplayStreamUpdateRef updateRef)
+			{
+				if (!frameSurface ||
+					pthread_mutex_trylock(&c_mutex))
+					return;
+
+				if (current) {
+					IOSurfaceDecrementUseCount(current);
+					CFRelease(current);
+					current = NULL;
+				}
+
+				current = frameSurface;
+				CFRetain(current);
+				IOSurfaceIncrementUseCount(current);
+				pthread_mutex_unlock(&c_mutex);
+			}
+	);
+
+	gs_leavecontext();
+
+	if (CGDisplayStreamStart(rt->disp)) {
+		desktop_destroy(rt);
+		return NULL;
+	}
+
+	return rt;
+}
+
+void desktop_destroy(struct desktop_tex *rt)
+{
+	if (rt) {
+		pthread_mutex_lock(&c_mutex);
+		gs_entercontext(obs_graphics());
+
+		if (current) {
+			IOSurfaceDecrementUseCount(current);
+			CFRelease(current);
+		}
+		if (rt->sampler)
+			samplerstate_destroy(rt->sampler);
+		if (tex)
+			texture_destroy(tex);
+		CGDisplayStreamStop(rt->disp);
+		effect_destroy(rt->whatever);
+		bfree(rt);
+
+		gs_leavecontext();
+		pthread_mutex_unlock(&c_mutex);
+	}
+}
+
+uint32_t desktop_get_output_flags(struct desktop_tex *rt)
+{
+	return SOURCE_VIDEO;
+}
+
+void desktop_video_render(struct desktop_tex *rt, obs_source_t filter_target)
+{
+	pthread_mutex_lock(&c_mutex);
+
+	if (prev != current) {
+		if (tex)
+			texture_rebind_iosurface(tex, current);
+		else
+			tex = gs_create_texture_from_iosurface(current);
+		prev = current;
+	}
+
+	if (!tex) goto fail;
+
+	gs_load_samplerstate(rt->sampler, 0);
+	technique_t tech = effect_gettechnique(rt->whatever, "Default");
+	effect_settexture(rt->whatever, effect_getparambyidx(rt->whatever, 1),
+			tex);
+	technique_begin(tech);
+	technique_beginpass(tech, 0);
+
+	gs_draw_sprite(tex, 0, 0, 0);
+
+	technique_endpass(tech);
+	technique_end(tech);
+
+fail:
+	pthread_mutex_unlock(&c_mutex);
+}
+
+uint32_t desktop_getwidth(struct desktop_tex *rt)
+{
+	return rt->width;
+}
+
+uint32_t desktop_getheight(struct desktop_tex *rt)
+{
+	return rt->height;
+}

+ 1 - 1
test/test-input/test-input.c

@@ -1,7 +1,7 @@
 #include <obs.h>
 #include "test-input-exports.h"
 
-const char *inputs[] = {"random", "sinewave"};
+const char *inputs[] = {"desktop", "random", "sinewave"};
 const char *filters[] = {"test"};
 
 uint32_t module_version(uint32_t in_version)