added linux test module with first implementation of a screengrabber using the xshm extension for x11
This commit is contained in:
parent
3aedfdfb73
commit
12e1855ebc
@ -8,3 +8,7 @@ endif()
|
||||
if(APPLE AND UNIX)
|
||||
add_subdirectory(osx)
|
||||
endif()
|
||||
|
||||
if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||
add_subdirectory(linux)
|
||||
endif()
|
29
test/linux/CMakeLists.txt
Normal file
29
test/linux/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
project(linux)
|
||||
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
|
||||
#include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs-opengl")
|
||||
|
||||
set(linux_SOURCES
|
||||
linux.c
|
||||
xshm-input.c
|
||||
)
|
||||
set(linux_HEADERS
|
||||
linux.h
|
||||
xshm-input.h
|
||||
)
|
||||
|
||||
add_library(linux MODULE
|
||||
${linux_SOURCES}
|
||||
${linux_HEADERS}
|
||||
)
|
||||
target_link_libraries(linux
|
||||
libobs
|
||||
${X11_LIBRARIES}
|
||||
${X11_XShm_LIB}
|
||||
)
|
||||
|
||||
install_obs_plugin(linux)
|
||||
|
||||
#obs_fixup_install_target(xshm-input PATH ${Libx264_LIBRARIES})
|
25
test/linux/linux.c
Normal file
25
test/linux/linux.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <obs.h>
|
||||
#include "linux.h"
|
||||
|
||||
const char *inputs[] = {
|
||||
"xshm_input"
|
||||
};
|
||||
|
||||
uint32_t module_version(uint32_t in_version)
|
||||
{
|
||||
return LIBOBS_API_VER;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return false;
|
||||
}
|
15
test/linux/linux.h
Normal file
15
test/linux/linux.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <util/c99defs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
EXPORT uint32_t module_version(uint32_t in_version);
|
||||
EXPORT bool enum_inputs(size_t idx, const char **name);
|
||||
EXPORT bool enum_filters(size_t idx, const char **name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
173
test/linux/xshm-input.c
Normal file
173
test/linux/xshm-input.c
Normal file
@ -0,0 +1,173 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
#include "xshm-input.h"
|
||||
|
||||
struct xshm_data {
|
||||
Display *dpy;
|
||||
Screen *screen;
|
||||
Window root_window;
|
||||
Visual *visual;
|
||||
int depth;
|
||||
uint32_t width, height;
|
||||
int shm_attached;
|
||||
XShmSegmentInfo shm_info;
|
||||
XImage *image;
|
||||
texture_t texture;
|
||||
};
|
||||
|
||||
const char* xshm_input_getname(const char* locale)
|
||||
{
|
||||
return "X11 Shared Memory Screen Input";
|
||||
}
|
||||
|
||||
struct xshm_data *xshm_input_create(const char *settings, obs_source_t source)
|
||||
{
|
||||
// create data structure
|
||||
struct xshm_data *data = bmalloc(sizeof(struct xshm_data));
|
||||
memset(data, 0, sizeof(struct xshm_data));
|
||||
|
||||
// try to open display and all the good stuff
|
||||
data->dpy = XOpenDisplay(NULL);
|
||||
if (!data->dpy)
|
||||
goto fail;
|
||||
|
||||
data->screen = XDefaultScreenOfDisplay(data->dpy);
|
||||
data->width = WidthOfScreen(data->screen);
|
||||
data->height = HeightOfScreen(data->screen);
|
||||
data->root_window = XRootWindowOfScreen(data->screen);
|
||||
data->visual = DefaultVisualOfScreen(data->screen);
|
||||
data->depth = DefaultDepthOfScreen(data->screen);
|
||||
|
||||
// query for shm extension
|
||||
if (!XShmQueryExtension(data->dpy))
|
||||
goto fail;
|
||||
|
||||
// create xshm image
|
||||
data->image = XShmCreateImage(data->dpy, data->visual, data->depth,
|
||||
ZPixmap, NULL, &data->shm_info,
|
||||
data->width, data->height);
|
||||
if (!data->image)
|
||||
goto fail;
|
||||
|
||||
printf("Image size: %dx%d\n", data->image->width, data->image->height);
|
||||
|
||||
// create shared memory
|
||||
data->shm_info.shmid = shmget(IPC_PRIVATE, data->image->bytes_per_line *
|
||||
data->image->height, IPC_CREAT | 0700);
|
||||
if (data->shm_info.shmid < 0) {
|
||||
printf("Failed to create shared memory !\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// attach shared memory
|
||||
data->shm_info.shmaddr = data->image->data
|
||||
= (char *) shmat(data->shm_info.shmid, 0, 0);
|
||||
if (data->shm_info.shmaddr == (char *) -1) {
|
||||
printf("Failed to attach shared memory !\n");
|
||||
goto fail;
|
||||
}
|
||||
// set shared memory as read only
|
||||
data->shm_info.readOnly = False;
|
||||
|
||||
// attach shm
|
||||
if (!XShmAttach(data->dpy, &data->shm_info)) {
|
||||
printf("Failed to attach to XShm !\n");
|
||||
goto fail;
|
||||
}
|
||||
data->shm_attached = 1;
|
||||
|
||||
// get image
|
||||
if (!XShmGetImage(data->dpy, data->root_window, data->image,
|
||||
0, 0, AllPlanes)) {
|
||||
printf("Failed to get image data !\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// create obs texture
|
||||
gs_entercontext(obs_graphics());
|
||||
data->texture = gs_create_texture(data->width, data->height, GS_BGRA, 1,
|
||||
(const void**) &data->image->data,
|
||||
GS_DYNAMIC);
|
||||
gs_leavecontext();
|
||||
|
||||
if (!data->texture)
|
||||
goto fail;
|
||||
|
||||
return data;
|
||||
|
||||
fail:
|
||||
// clean up and return null
|
||||
xshm_input_destroy(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void xshm_input_destroy(struct xshm_data *data)
|
||||
{
|
||||
if (data) {
|
||||
gs_entercontext(obs_graphics());
|
||||
|
||||
texture_destroy(data->texture);
|
||||
|
||||
gs_leavecontext();
|
||||
|
||||
// detach xshm
|
||||
if (data->shm_attached)
|
||||
XShmDetach(data->dpy, &data->shm_info);
|
||||
|
||||
// detach shared memory
|
||||
if (data->shm_info.shmaddr != (char *) -1) {
|
||||
shmdt(data->shm_info.shmaddr);
|
||||
data->shm_info.shmaddr = (char *) -1;
|
||||
}
|
||||
|
||||
// remove shared memory
|
||||
if (data->shm_info.shmid != -1)
|
||||
shmctl(data->shm_info.shmid, IPC_RMID, NULL);
|
||||
|
||||
// destroy image
|
||||
if (data->image)
|
||||
XDestroyImage(data->image);
|
||||
|
||||
// close display
|
||||
if (data->dpy)
|
||||
XCloseDisplay(data->dpy);
|
||||
|
||||
bfree(data);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t xshm_input_get_output_flags(struct xshm_data *data)
|
||||
{
|
||||
return SOURCE_VIDEO | SOURCE_DEFAULT_EFFECT;
|
||||
}
|
||||
|
||||
void xshm_input_video_render(struct xshm_data *data, obs_source_t filter_target)
|
||||
{
|
||||
// update texture
|
||||
if (!XShmGetImage(data->dpy, data->root_window, data->image,
|
||||
0, 0, AllPlanes)) {
|
||||
printf("Failed to get image !\n");
|
||||
}
|
||||
texture_setimage(data->texture, (void *) data->image->data,
|
||||
data->width * 4, False);
|
||||
|
||||
//effect_t effect = gs_geteffect();
|
||||
//eparam_t diffuse = effect_getparambyname(effect, "diffuse");
|
||||
|
||||
//effect_settexture(effect, diffuse, data->texture);
|
||||
gs_draw_sprite(data->texture, 0, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t xshm_input_getwidth(struct xshm_data *data)
|
||||
{
|
||||
return texture_getwidth(data->texture);
|
||||
}
|
||||
|
||||
uint32_t xshm_input_getheight(struct xshm_data *data)
|
||||
{
|
||||
return texture_getheight(data->texture);
|
||||
}
|
27
test/linux/xshm-input.h
Normal file
27
test/linux/xshm-input.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <obs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// forward declare struct, so we don't have to include X11 headers here
|
||||
struct xshm_data;
|
||||
|
||||
EXPORT const char *xshm_input_getname(const char *locale);
|
||||
|
||||
EXPORT struct xshm_data *xshm_input_create(const char *settings,
|
||||
obs_source_t source);
|
||||
EXPORT void xshm_input_destroy(struct xshm_data *data);
|
||||
EXPORT uint32_t xshm_input_get_output_flags(struct xshm_data *data);
|
||||
|
||||
EXPORT void xshm_input_video_render(struct xshm_data *data,
|
||||
obs_source_t filter_target);
|
||||
|
||||
EXPORT uint32_t xshm_input_getwidth(struct xshm_data *data);
|
||||
EXPORT uint32_t xshm_input_getheight(struct xshm_data *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user