Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Obs Studio
提交
6af8726c
O
Obs Studio
项目概览
小白菜888
/
Obs Studio
通知
4
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Obs Studio
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
6af8726c
编写于
7月 18, 2020
作者:
C
Clayton Groeneveld
提交者:
Jim
10月 30, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
linux-v4l2: Add virtual camera output
上级
4b363997
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
216 addition
and
3 deletion
+216
-3
.github/workflows/main.yml
.github/workflows/main.yml
+3
-1
CI/install-dependencies-linux.sh
CI/install-dependencies-linux.sh
+3
-1
plugins/linux-v4l2/CMakeLists.txt
plugins/linux-v4l2/CMakeLists.txt
+1
-0
plugins/linux-v4l2/linux-v4l2.c
plugins/linux-v4l2/linux-v4l2.c
+30
-1
plugins/linux-v4l2/v4l2-output.c
plugins/linux-v4l2/v4l2-output.c
+179
-0
未找到文件。
.github/workflows/main.yml
浏览文件 @
6af8726c
...
...
@@ -391,7 +391,9 @@ jobs:
qtbase5-dev \
libqt5svg5-dev \
swig \
libcmocka-dev
libcmocka-dev \
linux-generic \
v4l2loopback-dkms
-
name
:
'
Restore
Chromium
Embedded
Framework
from
cache'
id
:
cef-cache
uses
:
actions/cache@v2.1.2
...
...
CI/install-dependencies-linux.sh
浏览文件 @
6af8726c
...
...
@@ -43,7 +43,9 @@ sudo apt-get install -y \
python3-dev
\
qtbase5-dev
\
libqt5svg5-dev
\
swig
swig
\
linux-generic
\
v4l2loopback-dkms
# build cef
wget
--quiet
--retry-connrefused
--waitretry
=
1 https://cdn-fastly.obsproject.com/downloads/cef_binary_
${
CEF_BUILD_VERSION
}
_linux64.tar.bz2
...
...
plugins/linux-v4l2/CMakeLists.txt
浏览文件 @
6af8726c
...
...
@@ -39,6 +39,7 @@ set(linux-v4l2_SOURCES
v4l2-controls.c
v4l2-input.c
v4l2-helpers.c
v4l2-output.c
${
linux-v4l2-udev_SOURCES
}
)
...
...
plugins/linux-v4l2/linux-v4l2.c
浏览文件 @
6af8726c
...
...
@@ -15,18 +15,47 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <obs-module.h>
#include <util/platform.h>
OBS_DECLARE_MODULE
()
OBS_MODULE_USE_DEFAULT_LOCALE
(
"linux-v4l2"
,
"en-US"
)
MODULE_EXPORT
const
char
*
obs_module_description
(
void
)
{
return
"Video4Linux2(V4L2) sources"
;
return
"Video4Linux2(V4L2) sources
/virtual camera
"
;
}
extern
struct
obs_source_info
v4l2_input
;
extern
struct
obs_output_info
virtualcam_info
;
static
bool
v4l2loopback_installed
()
{
bool
loaded
=
false
;
int
ret
=
system
(
"modinfo v4l2loopback"
);
if
(
ret
==
0
)
loaded
=
true
;
return
loaded
;
}
bool
obs_module_load
(
void
)
{
obs_register_source
(
&
v4l2_input
);
obs_data_t
*
obs_settings
=
obs_data_create
();
if
(
v4l2loopback_installed
())
{
obs_register_output
(
&
virtualcam_info
);
obs_data_set_bool
(
obs_settings
,
"vcamEnabled"
,
true
);
}
else
{
obs_data_set_bool
(
obs_settings
,
"vcamEnabled"
,
false
);
blog
(
LOG_WARNING
,
"v4l2loopback not installed, virtual camera disabled"
);
}
obs_apply_private_data
(
obs_settings
);
obs_data_release
(
obs_settings
);
return
true
;
}
plugins/linux-v4l2/v4l2-output.c
0 → 100644
浏览文件 @
6af8726c
#include <obs-module.h>
#include <util/platform.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_DEVICES 64
struct
virtualcam_data
{
obs_output_t
*
output
;
int
device
;
uint32_t
frame_size
;
};
static
const
char
*
virtualcam_name
(
void
*
unused
)
{
UNUSED_PARAMETER
(
unused
);
return
"Virtual Camera Output"
;
}
static
void
virtualcam_destroy
(
void
*
data
)
{
struct
virtualcam_data
*
vcam
=
(
struct
virtualcam_data
*
)
data
;
close
(
vcam
->
device
);
bfree
(
data
);
}
static
bool
loopback_module_loaded
()
{
bool
loaded
=
false
;
char
temp
[
512
];
FILE
*
fp
=
fopen
(
"/proc/modules"
,
"r"
);
if
(
!
fp
)
return
false
;
while
(
fgets
(
temp
,
sizeof
(
temp
),
fp
))
{
if
(
strstr
(
temp
,
"v4l2loopback"
))
{
loaded
=
true
;
break
;
}
}
if
(
fp
)
fclose
(
fp
);
return
loaded
;
}
static
int
loopback_module_load
()
{
return
system
(
"pkexec modprobe v4l2loopback exclusive_caps=1 card_label='OBS Virtual Camera' && sleep 0.5"
);
}
static
void
*
virtualcam_create
(
obs_data_t
*
settings
,
obs_output_t
*
output
)
{
struct
virtualcam_data
*
vcam
=
(
struct
virtualcam_data
*
)
bzalloc
(
sizeof
(
*
vcam
));
vcam
->
output
=
output
;
UNUSED_PARAMETER
(
settings
);
return
vcam
;
}
static
bool
try_connect
(
void
*
data
,
int
device
)
{
struct
virtualcam_data
*
vcam
=
(
struct
virtualcam_data
*
)
data
;
struct
v4l2_format
format
;
struct
v4l2_capability
capability
;
struct
v4l2_streamparm
parm
;
uint32_t
width
=
obs_output_get_width
(
vcam
->
output
);
uint32_t
height
=
obs_output_get_height
(
vcam
->
output
);
vcam
->
frame_size
=
width
*
height
*
2
;
char
new_device
[
16
];
sprintf
(
new_device
,
"/dev/video%d"
,
device
);
vcam
->
device
=
open
(
new_device
,
O_RDWR
);
if
(
vcam
->
device
<
0
)
return
false
;
if
(
ioctl
(
vcam
->
device
,
VIDIOC_QUERYCAP
,
&
capability
)
<
0
)
return
false
;
format
.
type
=
V4L2_BUF_TYPE_VIDEO_OUTPUT
;
if
(
ioctl
(
vcam
->
device
,
VIDIOC_G_FMT
,
&
format
)
<
0
)
return
false
;
struct
obs_video_info
ovi
;
obs_get_video_info
(
&
ovi
);
parm
.
type
=
V4L2_BUF_TYPE_VIDEO_OUTPUT
;
parm
.
parm
.
output
.
capability
=
V4L2_CAP_TIMEPERFRAME
;
parm
.
parm
.
output
.
timeperframe
.
numerator
=
ovi
.
fps_den
;
parm
.
parm
.
output
.
timeperframe
.
denominator
=
ovi
.
fps_num
;
parm
.
parm
.
output
.
outputmode
=
0
;
parm
.
parm
.
output
.
writebuffers
=
0
;
parm
.
parm
.
output
.
extendedmode
=
0
;
parm
.
parm
.
output
.
reserved
[
4
]
=
0
;
if
(
ioctl
(
vcam
->
device
,
VIDIOC_S_PARM
,
&
parm
)
<
0
)
return
false
;
format
.
fmt
.
pix
.
width
=
width
;
format
.
fmt
.
pix
.
height
=
height
;
format
.
fmt
.
pix
.
pixelformat
=
V4L2_PIX_FMT_YUYV
;
format
.
fmt
.
pix
.
sizeimage
=
vcam
->
frame_size
;
if
(
ioctl
(
vcam
->
device
,
VIDIOC_S_FMT
,
&
format
)
<
0
)
return
false
;
struct
video_scale_info
vsi
=
{
0
};
vsi
.
format
=
VIDEO_FORMAT_YUY2
;
vsi
.
width
=
width
;
vsi
.
height
=
height
;
obs_output_set_video_conversion
(
vcam
->
output
,
&
vsi
);
blog
(
LOG_INFO
,
"Virtual camera started"
);
obs_output_begin_data_capture
(
vcam
->
output
,
0
);
return
true
;
}
static
bool
virtualcam_start
(
void
*
data
)
{
struct
virtualcam_data
*
vcam
=
(
struct
virtualcam_data
*
)
data
;
if
(
!
loopback_module_loaded
())
{
if
(
loopback_module_load
()
!=
0
)
return
false
;
}
for
(
int
i
=
0
;
i
<
MAX_DEVICES
;
i
++
)
{
if
(
!
try_connect
(
vcam
,
i
))
continue
;
else
return
true
;
}
blog
(
LOG_WARNING
,
"Failed to start virtual camera"
);
return
false
;
}
static
void
virtualcam_stop
(
void
*
data
,
uint64_t
ts
)
{
struct
virtualcam_data
*
vcam
=
(
struct
virtualcam_data
*
)
data
;
obs_output_end_data_capture
(
vcam
->
output
);
close
(
vcam
->
device
);
blog
(
LOG_INFO
,
"Virtual camera stopped"
);
UNUSED_PARAMETER
(
ts
);
}
static
void
virtual_video
(
void
*
param
,
struct
video_data
*
frame
)
{
struct
virtualcam_data
*
vcam
=
(
struct
virtualcam_data
*
)
param
;
write
(
vcam
->
device
,
frame
->
data
[
0
],
vcam
->
frame_size
);
}
struct
obs_output_info
virtualcam_info
=
{
.
id
=
"virtualcam_output"
,
.
flags
=
OBS_OUTPUT_VIDEO
,
.
get_name
=
virtualcam_name
,
.
create
=
virtualcam_create
,
.
destroy
=
virtualcam_destroy
,
.
start
=
virtualcam_start
,
.
stop
=
virtualcam_stop
,
.
raw_video
=
virtual_video
,
};
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录