Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
尘离序散
obs-studio
提交
f5e85e16
O
obs-studio
项目概览
尘离序散
/
obs-studio
与 Fork 源项目一致
从无法访问的项目Fork
通知
30
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
obs-studio
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f5e85e16
编写于
5月 15, 2014
作者:
J
Jim
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #74 from BtbN/linux_new_plugins
Add xcomposite capture
上级
4d13e2fb
3280cd1d
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
1032 addition
and
0 deletion
+1032
-0
obs/window-basic-main.cpp
obs/window-basic-main.cpp
+1
-0
plugins/CMakeLists.txt
plugins/CMakeLists.txt
+1
-0
plugins/linux-xcomposite/CMakeLists.txt
plugins/linux-xcomposite/CMakeLists.txt
+28
-0
plugins/linux-xcomposite/plugin-main.cpp
plugins/linux-xcomposite/plugin-main.cpp
+101
-0
plugins/linux-xcomposite/xcompcap-helper.cpp
plugins/linux-xcomposite/xcompcap-helper.cpp
+344
-0
plugins/linux-xcomposite/xcompcap-helper.h
plugins/linux-xcomposite/xcompcap-helper.h
+75
-0
plugins/linux-xcomposite/xcompcap-main.cpp
plugins/linux-xcomposite/xcompcap-main.cpp
+455
-0
plugins/linux-xcomposite/xcompcap-main.h
plugins/linux-xcomposite/xcompcap-main.h
+27
-0
未找到文件。
obs/window-basic-main.cpp
浏览文件 @
f5e85e16
...
...
@@ -444,6 +444,7 @@ void OBSBasic::OBSInit()
obs_load_module
(
"win-capture"
);
#else
obs_load_module
(
"linux-xshm"
);
obs_load_module
(
"linux-xcomposite"
);
obs_load_module
(
"linux-pulseaudio"
);
#endif
...
...
plugins/CMakeLists.txt
浏览文件 @
f5e85e16
...
...
@@ -9,6 +9,7 @@ elseif(APPLE)
add_subdirectory
(
mac-capture
)
elseif
(
"
${
CMAKE_SYSTEM_NAME
}
"
MATCHES
"Linux"
)
add_subdirectory
(
linux-xshm
)
add_subdirectory
(
linux-xcomposite
)
add_subdirectory
(
linux-pulseaudio
)
endif
()
...
...
plugins/linux-xcomposite/CMakeLists.txt
0 → 100644
浏览文件 @
f5e85e16
project
(
linux-xcomposite
)
find_package
(
X11
)
if
(
NOT X11_Xcomposite_FOUND
)
message
(
STATUS
"Xcomposite library not found, Xcomposite plugin disabled"
)
return
()
endif
()
include_directories
(
${
X11_Xcomposite_INCLUDE_PATH
}
${
X11_X11_INCLUDE_PATH
}
)
set
(
linux-xcomposite_SOURCES
plugin-main.cpp
xcompcap-main.cpp
xcompcap-main.h
xcompcap-helper.cpp
xcompcap-helper.h
)
add_library
(
linux-xcomposite MODULE
${
linux-xcomposite_SOURCES
}
)
target_link_libraries
(
linux-xcomposite
libobs
glad
${
X11_X11_LIB
}
${
X11_Xcomposite_LIB
}
)
install_obs_plugin
(
linux-xcomposite
)
plugins/linux-xcomposite/plugin-main.cpp
0 → 100644
浏览文件 @
f5e85e16
#include <obs-module.h>
#include "xcompcap-main.h"
static
void
*
xcompcap_create
(
obs_data_t
settings
,
obs_source_t
source
)
{
return
new
XCompcapMain
(
settings
,
source
);
}
static
void
xcompcap_destroy
(
void
*
data
)
{
XCompcapMain
*
cc
=
(
XCompcapMain
*
)
data
;
delete
cc
;
}
static
void
xcompcap_video_tick
(
void
*
data
,
float
seconds
)
{
XCompcapMain
*
cc
=
(
XCompcapMain
*
)
data
;
cc
->
tick
(
seconds
);
}
static
void
xcompcap_video_render
(
void
*
data
,
effect_t
effect
)
{
XCompcapMain
*
cc
=
(
XCompcapMain
*
)
data
;
cc
->
render
(
effect
);
}
static
uint32_t
xcompcap_getwidth
(
void
*
data
)
{
XCompcapMain
*
cc
=
(
XCompcapMain
*
)
data
;
return
cc
->
width
();
}
static
uint32_t
xcompcap_getheight
(
void
*
data
)
{
XCompcapMain
*
cc
=
(
XCompcapMain
*
)
data
;
return
cc
->
height
();
}
static
obs_properties_t
xcompcap_props
(
const
char
*
locale
)
{
return
XCompcapMain
::
properties
(
locale
);
}
void
xcompcap_defaults
(
obs_data_t
settings
)
{
XCompcapMain
::
defaults
(
settings
);
}
void
xcompcap_update
(
void
*
data
,
obs_data_t
settings
)
{
XCompcapMain
*
cc
=
(
XCompcapMain
*
)
data
;
cc
->
updateSettings
(
settings
);
}
OBS_DECLARE_MODULE
()
static
const
char
*
xcompcap_getname
(
const
char
*
locale
)
{
UNUSED_PARAMETER
(
locale
);
return
"Xcomposite capture"
;
}
bool
obs_module_load
(
uint32_t
libobs_version
)
{
UNUSED_PARAMETER
(
libobs_version
);
if
(
!
XCompcapMain
::
init
())
return
false
;
obs_source_info
sinfo
;
memset
(
&
sinfo
,
0
,
sizeof
(
obs_source_info
));
sinfo
.
id
=
"xcomposite_input"
;
sinfo
.
output_flags
=
OBS_SOURCE_VIDEO
;
sinfo
.
getname
=
xcompcap_getname
;
sinfo
.
create
=
xcompcap_create
;
sinfo
.
destroy
=
xcompcap_destroy
;
sinfo
.
properties
=
xcompcap_props
;
sinfo
.
defaults
=
xcompcap_defaults
;
sinfo
.
update
=
xcompcap_update
;
sinfo
.
video_tick
=
xcompcap_video_tick
;
sinfo
.
video_render
=
xcompcap_video_render
;
sinfo
.
getwidth
=
xcompcap_getwidth
;
sinfo
.
getheight
=
xcompcap_getheight
;
obs_register_source
(
&
sinfo
);
blog
(
LOG_INFO
,
"Xcomposite capture plugin loaded"
);
return
true
;
}
void
obs_module_unload
()
{
XCompcapMain
::
deinit
();
blog
(
LOG_INFO
,
"Xcomposite capture plugin unloaded"
);
}
plugins/linux-xcomposite/xcompcap-helper.cpp
0 → 100644
浏览文件 @
f5e85e16
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <unordered_set>
#include <pthread.h>
#include <obs-module.h>
#include "xcompcap-helper.h"
namespace
XCompcap
{
static
Display
*
xdisplay
=
0
;
Display
*
disp
()
{
if
(
!
xdisplay
)
xdisplay
=
XOpenDisplay
(
NULL
);
return
xdisplay
;
}
void
cleanupDisplay
()
{
if
(
!
xdisplay
)
return
;
XCloseDisplay
(
xdisplay
);
xdisplay
=
0
;
}
static
void
getAllWindows
(
Window
parent
,
std
::
list
<
Window
>&
windows
)
{
UNUSED_PARAMETER
(
parent
);
UNUSED_PARAMETER
(
windows
);
}
std
::
list
<
Window
>
getAllWindows
()
{
std
::
list
<
Window
>
res
;
for
(
int
i
=
0
;
i
<
ScreenCount
(
disp
());
++
i
)
getAllWindows
(
RootWindow
(
disp
(),
i
),
res
);
return
res
;
}
std
::
list
<
Window
>
getTopLevelWindows
()
{
std
::
list
<
Window
>
res
;
Atom
netClList
=
XInternAtom
(
disp
(),
"_NET_CLIENT_LIST"
,
true
);
Atom
actualType
;
int
format
;
unsigned
long
num
,
bytes
;
Window
*
data
=
0
;
for
(
int
i
=
0
;
i
<
ScreenCount
(
disp
());
++
i
)
{
Window
rootWin
=
RootWindow
(
disp
(),
i
);
int
status
=
XGetWindowProperty
(
disp
(),
rootWin
,
netClList
,
0L
,
~
0L
,
false
,
AnyPropertyType
,
&
actualType
,
&
format
,
&
num
,
&
bytes
,
(
uint8_t
**
)
&
data
);
if
(
status
!=
Success
)
{
blog
(
LOG_WARNING
,
"Failed getting root "
"window properties"
);
continue
;
}
for
(
unsigned
long
i
=
0
;
i
<
num
;
++
i
)
res
.
push_back
(
data
[
i
]);
XFree
(
data
);
}
return
res
;
}
int
getRootWindowScreen
(
Window
root
)
{
XWindowAttributes
attr
;
if
(
!
XGetWindowAttributes
(
disp
(),
root
,
&
attr
))
return
DefaultScreen
(
disp
());
return
XScreenNumberOfScreen
(
attr
.
screen
);
}
std
::
string
getWindowName
(
Window
win
)
{
Atom
netWmName
=
XInternAtom
(
disp
(),
"_NET_WM_NAME"
,
false
);
int
n
;
char
**
list
=
0
;
XTextProperty
tp
;
std
::
string
res
=
"unknown"
;
XGetTextProperty
(
disp
(),
win
,
&
tp
,
netWmName
);
if
(
!
tp
.
nitems
)
XGetWMName
(
disp
(),
win
,
&
tp
);
if
(
!
tp
.
nitems
)
return
"error"
;
if
(
tp
.
encoding
==
XA_STRING
)
{
res
=
(
char
*
)
tp
.
value
;
}
else
{
int
ret
=
XmbTextPropertyToTextList
(
disp
(),
&
tp
,
&
list
,
&
n
);
if
(
ret
>=
Success
&&
n
>
0
&&
*
list
)
{
res
=
*
list
;
XFreeStringList
(
list
);
}
}
XFree
(
tp
.
value
);
return
res
;
}
std
::
string
getWindowCommand
(
Window
win
)
{
Atom
xi
=
XInternAtom
(
disp
(),
"WM_COMMAND"
,
false
);
int
n
;
char
**
list
=
0
;
XTextProperty
tp
;
std
::
string
res
=
"error"
;
XGetTextProperty
(
disp
(),
win
,
&
tp
,
xi
);
if
(
!
tp
.
nitems
)
return
std
::
string
();
if
(
tp
.
encoding
==
XA_STRING
)
{
res
=
(
char
*
)
tp
.
value
;
}
else
{
int
ret
=
XmbTextPropertyToTextList
(
disp
(),
&
tp
,
&
list
,
&
n
);
if
(
ret
>=
Success
&&
n
>
0
&&
*
list
)
{
res
=
*
list
;
XFreeStringList
(
list
);
}
}
XFree
(
tp
.
value
);
return
res
;
}
int
getWindowPid
(
Window
win
)
{
UNUSED_PARAMETER
(
win
);
return
1234
;
//TODO
}
static
std
::
unordered_set
<
Window
>
changedWindows
;
static
pthread_mutex_t
changeLock
=
PTHREAD_MUTEX_INITIALIZER
;
void
processEvents
()
{
PLock
lock
(
&
changeLock
);
XLockDisplay
(
disp
());
while
(
XEventsQueued
(
disp
(),
QueuedAfterReading
)
>
0
)
{
XEvent
ev
;
XNextEvent
(
disp
(),
&
ev
);
if
(
ev
.
type
==
ConfigureNotify
)
changedWindows
.
insert
(
ev
.
xconfigure
.
event
);
if
(
ev
.
type
==
MapNotify
)
changedWindows
.
insert
(
ev
.
xmap
.
event
);
if
(
ev
.
type
==
DestroyNotify
)
changedWindows
.
insert
(
ev
.
xdestroywindow
.
event
);
}
XUnlockDisplay
(
disp
());
}
bool
windowWasReconfigured
(
Window
win
)
{
PLock
lock
(
&
changeLock
);
auto
it
=
changedWindows
.
find
(
win
);
if
(
it
!=
changedWindows
.
end
())
{
changedWindows
.
erase
(
it
);
return
true
;
}
return
false
;
}
}
PLock
::
PLock
(
pthread_mutex_t
*
mtx
,
bool
trylock
)
:
m
(
mtx
)
{
if
(
trylock
)
islock
=
mtx
&&
pthread_mutex_trylock
(
mtx
)
==
0
;
else
islock
=
mtx
&&
pthread_mutex_lock
(
mtx
)
==
0
;
}
PLock
::~
PLock
()
{
if
(
islock
)
{
pthread_mutex_unlock
(
m
);
}
}
bool
PLock
::
isLocked
()
{
return
islock
;
}
void
PLock
::
unlock
()
{
if
(
islock
)
{
pthread_mutex_unlock
(
m
);
islock
=
false
;
}
}
void
PLock
::
lock
()
{
if
(
!
islock
)
{
pthread_mutex_lock
(
m
);
islock
=
true
;
}
}
static
bool
*
curErrorTarget
=
0
;
static
char
curErrorText
[
200
];
static
int
xerrorlock_handler
(
Display
*
disp
,
XErrorEvent
*
err
)
{
if
(
curErrorTarget
)
*
curErrorTarget
=
true
;
XGetErrorText
(
disp
,
err
->
error_code
,
curErrorText
,
200
);
return
0
;
}
XErrorLock
::
XErrorLock
()
{
goterr
=
false
;
islock
=
false
;
prevhandler
=
0
;
lock
();
}
XErrorLock
::~
XErrorLock
()
{
unlock
();
}
bool
XErrorLock
::
isLocked
()
{
return
islock
;
}
void
XErrorLock
::
lock
()
{
if
(
!
islock
)
{
XLockDisplay
(
XCompcap
::
disp
());
XSync
(
XCompcap
::
disp
(),
0
);
curErrorTarget
=
&
goterr
;
curErrorText
[
0
]
=
0
;
prevhandler
=
XSetErrorHandler
(
xerrorlock_handler
);
islock
=
true
;
}
}
void
XErrorLock
::
unlock
()
{
if
(
islock
)
{
curErrorTarget
=
0
;
XSetErrorHandler
(
prevhandler
);
prevhandler
=
0
;
XUnlockDisplay
(
XCompcap
::
disp
());
islock
=
false
;
}
}
bool
XErrorLock
::
gotError
()
{
if
(
!
islock
)
return
false
;
XSync
(
XCompcap
::
disp
(),
0
);
bool
res
=
goterr
;
goterr
=
false
;
return
res
;
}
std
::
string
XErrorLock
::
getErrorText
()
{
return
curErrorText
;
}
void
XErrorLock
::
resetError
()
{
if
(
islock
)
XSync
(
XCompcap
::
disp
(),
0
);
goterr
=
false
;
curErrorText
[
0
]
=
0
;
}
ObsGsContextHolder
::
ObsGsContextHolder
()
{
gs_entercontext
(
obs_graphics
());
}
ObsGsContextHolder
::~
ObsGsContextHolder
()
{
gs_leavecontext
();
}
plugins/linux-xcomposite/xcompcap-helper.h
0 → 100644
浏览文件 @
f5e85e16
#pragma once
#include <string>
#include <list>
#define blog(level, msg, ...) blog(level, "xcompcap: " msg, ##__VA_ARGS__)
class
PLock
{
pthread_mutex_t
*
m
;
bool
islock
;
public:
PLock
(
const
PLock
&
)
=
delete
;
PLock
&
operator
=
(
const
PLock
&
)
=
delete
;
PLock
(
pthread_mutex_t
*
mtx
,
bool
trylock
=
false
);
~
PLock
();
bool
isLocked
();
void
unlock
();
void
lock
();
};
class
XErrorLock
{
bool
islock
;
bool
goterr
;
XErrorHandler
prevhandler
;
public:
XErrorLock
(
const
XErrorLock
&
)
=
delete
;
XErrorLock
&
operator
=
(
const
XErrorLock
&
)
=
delete
;
XErrorLock
();
~
XErrorLock
();
bool
isLocked
();
void
unlock
();
void
lock
();
bool
gotError
();
std
::
string
getErrorText
();
void
resetError
();
};
class
ObsGsContextHolder
{
public:
ObsGsContextHolder
(
const
ObsGsContextHolder
&
)
=
delete
;
ObsGsContextHolder
&
operator
=
(
const
ObsGsContextHolder
&
)
=
delete
;
ObsGsContextHolder
();
~
ObsGsContextHolder
();
};
namespace
XCompcap
{
Display
*
disp
();
void
cleanupDisplay
();
std
::
string
getWindowCommand
(
Window
win
);
int
getRootWindowScreen
(
Window
root
);
std
::
string
getWindowName
(
Window
win
);
int
getWindowPid
(
Window
win
);
std
::
list
<
Window
>
getTopLevelWindows
();
std
::
list
<
Window
>
getAllWindows
();
void
processEvents
();
bool
windowWasReconfigured
(
Window
win
);
}
plugins/linux-xcomposite/xcompcap-main.cpp
0 → 100644
浏览文件 @
f5e85e16
#include <glad/glad.h>
#include <glad/glad_glx.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
#include <pthread.h>
#include <vector>
#include <obs-module.h>
#include <graphics/vec4.h>
#include <util/platform.h>
#include "xcompcap-main.h"
#include "xcompcap-helper.h"
#define xdisp (XCompcap::disp())
#define WIN_STRING_DIV "\r\n"
bool
XCompcapMain
::
init
()
{
if
(
!
xdisp
)
{
blog
(
LOG_ERROR
,
"failed opening display"
);
return
false
;
}
int
eventBase
,
errorBase
;
if
(
!
XCompositeQueryExtension
(
xdisp
,
&
eventBase
,
&
errorBase
))
{
blog
(
LOG_ERROR
,
"Xcomposite extension not supported"
);
return
false
;
}
int
major
=
0
,
minor
=
2
;
XCompositeQueryVersion
(
xdisp
,
&
major
,
&
minor
);
if
(
major
==
0
&&
minor
<
2
)
{
blog
(
LOG_ERROR
,
"Xcomposite extension is too old: %d.%d < 0.2"
,
major
,
minor
);
return
false
;
}
return
true
;
}
void
XCompcapMain
::
deinit
()
{
XCompcap
::
cleanupDisplay
();
}
obs_properties_t
XCompcapMain
::
properties
(
const
char
*
locale
)
{
obs_properties_t
props
=
obs_properties_create
(
locale
);
obs_property_t
wins
=
obs_properties_add_list
(
props
,
"capture_window"
,
"Captured Window"
,
OBS_COMBO_TYPE_LIST
,
OBS_COMBO_FORMAT_STRING
);
for
(
Window
win
:
XCompcap
::
getTopLevelWindows
())
{
std
::
string
wname
=
XCompcap
::
getWindowName
(
win
);
std
::
string
progpath
=
XCompcap
::
getWindowCommand
(
win
);
std
::
string
winid
=
std
::
to_string
((
long
long
)
win
);
std
::
string
desc
=
(
winid
+
WIN_STRING_DIV
+
wname
+
WIN_STRING_DIV
+
progpath
);
obs_property_list_add_string
(
wins
,
wname
.
c_str
(),
desc
.
c_str
());
}
obs_properties_add_int
(
props
,
"cut_top"
,
"Cut top pixels"
,
0
,
4096
,
1
);
obs_properties_add_int
(
props
,
"cut_left"
,
"Cut left pixels"
,
0
,
4096
,
1
);
obs_properties_add_int
(
props
,
"cut_right"
,
"Cut right pixels"
,
0
,
4096
,
1
);
obs_properties_add_int
(
props
,
"cut_bot"
,
"Cut bottom pixels"
,
0
,
4096
,
1
);
obs_properties_add_bool
(
props
,
"swap_redblue"
,
"Swap red and blue"
);
obs_properties_add_bool
(
props
,
"lock_x"
,
"Lock X server when "
"capturing"
);
return
props
;
}
void
XCompcapMain
::
defaults
(
obs_data_t
settings
)
{
obs_data_setstring
(
settings
,
"capture_window"
,
""
);
obs_data_setint
(
settings
,
"cut_top"
,
0
);
obs_data_setint
(
settings
,
"cut_left"
,
0
);
obs_data_setint
(
settings
,
"cut_right"
,
0
);
obs_data_setint
(
settings
,
"cut_bot"
,
0
);
obs_data_setbool
(
settings
,
"swap_redblue"
,
false
);
obs_data_setbool
(
settings
,
"lock_x"
,
false
);
}
struct
XCompcapMain_private
{
XCompcapMain_private
()
:
win
(
0
)
,
cut_top
(
0
),
cur_cut_top
(
0
)
,
cut_left
(
0
),
cur_cut_left
(
0
)
,
cut_right
(
0
),
cur_cut_right
(
0
)
,
cut_bot
(
0
),
cur_cut_bot
(
0
)
,
inverted
(
false
)
,
width
(
0
),
height
(
0
)
,
pixmap
(
0
)
,
glxpixmap
(
0
)
,
tex
(
0
)
,
gltex
(
0
)
{
pthread_mutexattr_init
(
&
lockattr
);
pthread_mutexattr_settype
(
&
lockattr
,
PTHREAD_MUTEX_RECURSIVE
);
pthread_mutex_init
(
&
lock
,
&
lockattr
);
}
~
XCompcapMain_private
()
{
pthread_mutex_destroy
(
&
lock
);
pthread_mutexattr_destroy
(
&
lockattr
);
}
obs_source_t
source
;
Window
win
;
int
cut_top
,
cur_cut_top
;
int
cut_left
,
cur_cut_left
;
int
cut_right
,
cur_cut_right
;
int
cut_bot
,
cur_cut_bot
;
bool
inverted
;
bool
swapRedBlue
;
bool
lockX
;
uint32_t
width
;
uint32_t
height
;
Pixmap
pixmap
;
GLXPixmap
glxpixmap
;
texture_t
tex
;
texture_t
gltex
;
pthread_mutex_t
lock
;
pthread_mutexattr_t
lockattr
;
};
XCompcapMain
::
XCompcapMain
(
obs_data_t
settings
,
obs_source_t
source
)
{
p
=
new
XCompcapMain_private
;
p
->
source
=
source
;
updateSettings
(
settings
);
}
static
void
xcc_cleanup
(
XCompcapMain_private
*
p
);
XCompcapMain
::~
XCompcapMain
()
{
ObsGsContextHolder
obsctx
;
if
(
p
->
tex
)
{
texture_destroy
(
p
->
tex
);
p
->
tex
=
0
;
}
xcc_cleanup
(
p
);
delete
p
;
}
static
Window
getWindowFromString
(
std
::
string
wstr
)
{
if
(
wstr
==
""
)
{
return
XCompcap
::
getTopLevelWindows
().
front
();
}
if
(
wstr
.
substr
(
0
,
4
)
==
"root"
)
{
int
i
=
std
::
stoi
(
"0"
+
wstr
.
substr
(
4
));
return
RootWindow
(
xdisp
,
i
);
}
size_t
firstMark
=
wstr
.
find
(
WIN_STRING_DIV
);
if
(
firstMark
==
std
::
string
::
npos
)
return
(
Window
)
std
::
stol
(
wstr
);
std
::
string
widstr
=
wstr
.
substr
(
0
,
firstMark
);
Window
wid
=
(
Window
)
std
::
stol
(
widstr
);
wstr
=
wstr
.
substr
(
firstMark
+
strlen
(
WIN_STRING_DIV
));
size_t
lastMark
=
wstr
.
rfind
(
WIN_STRING_DIV
);
std
::
string
wname
=
wstr
.
substr
(
0
,
lastMark
);
Window
matchedNameWin
=
wid
;
for
(
Window
cwin
:
XCompcap
::
getTopLevelWindows
())
{
std
::
string
cwinname
=
XCompcap
::
getWindowName
(
cwin
);
if
(
cwin
==
wid
&&
wname
==
cwinname
)
return
wid
;
if
(
wname
==
cwinname
)
matchedNameWin
=
cwin
;
}
return
matchedNameWin
;
}
static
void
xcc_cleanup
(
XCompcapMain_private
*
p
)
{
if
(
p
->
gltex
)
{
texture_destroy
(
p
->
gltex
);
p
->
gltex
=
0
;
}
if
(
p
->
glxpixmap
)
{
glXDestroyPixmap
(
xdisp
,
p
->
glxpixmap
);
p
->
glxpixmap
=
0
;
}
if
(
p
->
pixmap
)
{
XFreePixmap
(
xdisp
,
p
->
pixmap
);
p
->
pixmap
=
0
;
}
if
(
p
->
win
)
{
XCompositeUnredirectWindow
(
xdisp
,
p
->
win
,
CompositeRedirectAutomatic
);
XSelectInput
(
xdisp
,
p
->
win
,
0
);
p
->
win
=
0
;
}
}
void
XCompcapMain
::
updateSettings
(
obs_data_t
settings
)
{
PLock
lock
(
&
p
->
lock
);
XErrorLock
xlock
;
ObsGsContextHolder
obsctx
;
blog
(
LOG_DEBUG
,
"Settings updating"
);
Window
prevWin
=
p
->
win
;
xcc_cleanup
(
p
);
if
(
settings
)
{
const
char
*
windowName
=
obs_data_getstring
(
settings
,
"capture_window"
);
p
->
win
=
getWindowFromString
(
windowName
);
p
->
cut_top
=
obs_data_getint
(
settings
,
"cut_top"
);
p
->
cut_left
=
obs_data_getint
(
settings
,
"cut_left"
);
p
->
cut_right
=
obs_data_getint
(
settings
,
"cut_right"
);
p
->
cut_bot
=
obs_data_getint
(
settings
,
"cut_bot"
);
p
->
lockX
=
obs_data_getbool
(
settings
,
"lock_x"
);
p
->
swapRedBlue
=
obs_data_getbool
(
settings
,
"swap_redblue"
);
}
else
{
p
->
win
=
prevWin
;
}
xlock
.
resetError
();
XCompositeRedirectWindow
(
xdisp
,
p
->
win
,
CompositeRedirectAutomatic
);
if
(
xlock
.
gotError
())
{
blog
(
LOG_ERROR
,
"XCompositeRedirectWindow failed: %s"
,
xlock
.
getErrorText
().
c_str
());
return
;
}
XSelectInput
(
xdisp
,
p
->
win
,
StructureNotifyMask
);
XSync
(
xdisp
,
0
);
XWindowAttributes
attr
;
if
(
!
XGetWindowAttributes
(
xdisp
,
p
->
win
,
&
attr
))
{
p
->
win
=
0
;
p
->
width
=
0
;
p
->
height
=
0
;
return
;
}
gs_color_format
cf
=
GS_RGBA
;
p
->
width
=
attr
.
width
;
p
->
height
=
attr
.
height
;
if
(
p
->
cut_top
+
p
->
cut_bot
<
(
int
)
p
->
height
)
{
p
->
cur_cut_top
=
p
->
cut_top
;
p
->
cur_cut_bot
=
p
->
cut_bot
;
}
else
{
p
->
cur_cut_top
=
0
;
p
->
cur_cut_bot
=
0
;
}
if
(
p
->
cut_left
+
p
->
cut_right
<
(
int
)
p
->
width
)
{
p
->
cur_cut_left
=
p
->
cut_left
;
p
->
cur_cut_right
=
p
->
cut_right
;
}
else
{
p
->
cur_cut_left
=
0
;
p
->
cur_cut_right
=
0
;
}
if
(
p
->
tex
)
texture_destroy
(
p
->
tex
);
uint8_t
*
texData
=
new
uint8_t
[
width
()
*
height
()
*
4
];
for
(
unsigned
int
i
=
0
;
i
<
width
()
*
height
()
*
4
;
i
+=
4
)
{
texData
[
i
+
0
]
=
p
->
swapRedBlue
?
0xFF
:
0
;
texData
[
i
+
1
]
=
0
;
texData
[
i
+
2
]
=
p
->
swapRedBlue
?
0
:
0xFF
;
texData
[
i
+
3
]
=
0xFF
;
}
const
uint8_t
*
texDataArr
[]
=
{
texData
,
0
};
p
->
tex
=
gs_create_texture
(
width
(),
height
(),
cf
,
1
,
(
const
void
**
)
texDataArr
,
0
);
delete
[]
texData
;
if
(
!
p
->
swapRedBlue
)
{
GLuint
tex
=
*
(
GLuint
*
)
texture_getobj
(
p
->
tex
);
glBindTexture
(
GL_TEXTURE_2D
,
tex
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_SWIZZLE_B
,
GL_RED
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_SWIZZLE_R
,
GL_BLUE
);
glBindTexture
(
GL_TEXTURE_2D
,
0
);
}
const
int
attrs
[]
=
{
GLX_BIND_TO_TEXTURE_RGBA_EXT
,
GL_TRUE
,
GLX_DRAWABLE_TYPE
,
GLX_PIXMAP_BIT
,
GLX_BIND_TO_TEXTURE_TARGETS_EXT
,
GLX_TEXTURE_2D_BIT_EXT
,
GLX_DOUBLEBUFFER
,
GL_FALSE
,
None
};
int
nelem
=
0
;
GLXFBConfig
*
configs
=
glXChooseFBConfig
(
xdisp
,
XCompcap
::
getRootWindowScreen
(
attr
.
root
),
attrs
,
&
nelem
);
if
(
nelem
<=
0
)
{
blog
(
LOG_ERROR
,
"no matching fb config found"
);
p
->
win
=
0
;
p
->
height
=
0
;
p
->
width
=
0
;
return
;
}
glXGetFBConfigAttrib
(
xdisp
,
configs
[
0
],
GLX_Y_INVERTED_EXT
,
&
nelem
);
p
->
inverted
=
nelem
!=
0
;
xlock
.
resetError
();
p
->
pixmap
=
XCompositeNameWindowPixmap
(
xdisp
,
p
->
win
);
if
(
xlock
.
gotError
())
{
blog
(
LOG_ERROR
,
"XCompositeNameWindowPixmap failed: %s"
,
xlock
.
getErrorText
().
c_str
());
p
->
pixmap
=
0
;
XFree
(
configs
);
return
;
}
const
int
attribs
[]
=
{
GLX_TEXTURE_TARGET_EXT
,
GLX_TEXTURE_2D_EXT
,
GLX_TEXTURE_FORMAT_EXT
,
GLX_TEXTURE_FORMAT_RGBA_EXT
,
None
};
p
->
glxpixmap
=
glXCreatePixmap
(
xdisp
,
configs
[
0
],
p
->
pixmap
,
attribs
);
if
(
xlock
.
gotError
())
{
blog
(
LOG_ERROR
,
"glXCreatePixmap failed: %s"
,
xlock
.
getErrorText
().
c_str
());
XFreePixmap
(
xdisp
,
p
->
pixmap
);
XFree
(
configs
);
p
->
pixmap
=
0
;
p
->
glxpixmap
=
0
;
return
;
}
XFree
(
configs
);
p
->
gltex
=
gs_create_texture
(
p
->
width
,
p
->
height
,
cf
,
1
,
0
,
GS_GL_DUMMYTEX
);
GLuint
gltex
=
*
(
GLuint
*
)
texture_getobj
(
p
->
gltex
);
glBindTexture
(
GL_TEXTURE_2D
,
gltex
);
glXBindTexImageEXT
(
xdisp
,
p
->
glxpixmap
,
GLX_FRONT_LEFT_EXT
,
NULL
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MIN_FILTER
,
GL_LINEAR
);
glTexParameteri
(
GL_TEXTURE_2D
,
GL_TEXTURE_MAG_FILTER
,
GL_LINEAR
);
}
void
XCompcapMain
::
tick
(
float
seconds
)
{
UNUSED_PARAMETER
(
seconds
);
PLock
lock
(
&
p
->
lock
,
true
);
if
(
!
lock
.
isLocked
())
return
;
XCompcap
::
processEvents
();
if
(
XCompcap
::
windowWasReconfigured
(
p
->
win
))
updateSettings
(
0
);
if
(
!
p
->
tex
||
!
p
->
gltex
)
return
;
gs_entercontext
(
obs_graphics
());
if
(
p
->
lockX
)
{
XLockDisplay
(
xdisp
);
XSync
(
xdisp
,
0
);
}
gs_copy_texture_region
(
p
->
tex
,
0
,
0
,
p
->
gltex
,
p
->
cur_cut_left
,
p
->
cur_cut_top
,
width
(),
height
());
if
(
p
->
lockX
)
XUnlockDisplay
(
xdisp
);
gs_leavecontext
();
}
void
XCompcapMain
::
render
(
effect_t
effect
)
{
PLock
lock
(
&
p
->
lock
,
true
);
if
(
!
lock
.
isLocked
()
||
!
p
->
tex
)
return
;
eparam_t
image
=
effect_getparambyname
(
effect
,
"image"
);
effect_settexture
(
effect
,
image
,
p
->
tex
);
gs_enable_blending
(
false
);
gs_draw_sprite
(
p
->
tex
,
0
,
0
,
0
);
}
uint32_t
XCompcapMain
::
width
()
{
return
p
->
width
-
p
->
cur_cut_left
-
p
->
cur_cut_right
;
}
uint32_t
XCompcapMain
::
height
()
{
return
p
->
height
-
p
->
cur_cut_bot
-
p
->
cur_cut_top
;
}
plugins/linux-xcomposite/xcompcap-main.h
0 → 100644
浏览文件 @
f5e85e16
#pragma once
struct
XCompcapMain_private
;
class
XCompcapMain
{
public:
static
bool
init
();
static
void
deinit
();
static
obs_properties_t
properties
(
const
char
*
locale
);
static
void
defaults
(
obs_data_t
settings
);
XCompcapMain
(
obs_data_t
settings
,
obs_source_t
source
);
~
XCompcapMain
();
void
updateSettings
(
obs_data_t
settings
);
void
tick
(
float
seconds
);
void
render
(
effect_t
effect
);
uint32_t
width
();
uint32_t
height
();
private:
XCompcapMain_private
*
p
;
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录