multimedia/obs-studio: Backport patch enabling OBS Studio Virtual Camera

(cherry picked from commit c6f10a7b5e)
This commit is contained in:
Yuri Victorovich 2021-10-14 12:25:21 -07:00
parent 82840fd0ac
commit fee1c0576e
2 changed files with 110 additions and 1 deletions

View File

@ -1,6 +1,6 @@
PORTNAME= obs-studio
DISTVERSION= 27.0.1
PORTREVISION= 3
PORTREVISION= 4
CATEGORIES= multimedia
MAINTAINER= yuri@FreeBSD.org

View File

@ -0,0 +1,109 @@
- backport patch for OBS Studio Virtual Camera on FreeBSD
- see https://www.davidschlachter.com/misc/freebsd-obs-virtualcam
diff --git plugins/linux-v4l2/v4l2-output.c b/plugins/linux-v4l2/v4l2-output.c
index 05ac70b42f0..0ddd3152384 100644
--- plugins/linux-v4l2/v4l2-output.c
+++ plugins/linux-v4l2/v4l2-output.c
@@ -27,6 +27,7 @@ static void virtualcam_destroy(void *data)
bfree(data);
}
+#ifdef __linux__
static bool is_flatpak_sandbox(void)
{
static bool flatpak_info_exists = false;
@@ -98,6 +99,32 @@ static int loopback_module_load()
return run_command(
"pkexec modprobe v4l2loopback exclusive_caps=1 card_label='OBS Virtual Camera' && sleep 0.5");
}
+#else
+bool loopback_module_available()
+{
+ struct v4l2_capability capability;
+ char new_device[16];
+ int fd;
+ int i;
+
+ for (i = 0; i != MAX_DEVICES; i++) {
+ snprintf(new_device, 16, "/dev/video%d", i);
+ fd = open(new_device, O_RDWR);
+ if (fd < 0)
+ continue;
+ if (ioctl(fd, VIDIOC_QUERYCAP, &capability) < 0) {
+ close(fd);
+ continue;
+ }
+ if (capability.capabilities & V4L2_CAP_VIDEO_OUTPUT) {
+ close(fd);
+ return true;
+ }
+ close(fd);
+ }
+ return false;
+}
+#endif
static void *virtualcam_create(obs_data_t *settings, obs_output_t *output)
{
@@ -131,13 +158,19 @@ static bool try_connect(void *data, int device)
if (vcam->device < 0)
return false;
- if (ioctl(vcam->device, VIDIOC_QUERYCAP, &capability) < 0)
+ if (ioctl(vcam->device, VIDIOC_QUERYCAP, &capability) < 0) {
+ close(vcam->device);
+ vcam->device = -1;
return false;
+ }
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- if (ioctl(vcam->device, VIDIOC_G_FMT, &format) < 0)
+ if (ioctl(vcam->device, VIDIOC_G_FMT, &format) < 0) {
+ close(vcam->device);
+ vcam->device = -1;
return false;
+ }
struct obs_video_info ovi;
obs_get_video_info(&ovi);
@@ -149,16 +182,22 @@ static bool try_connect(void *data, int device)
parm.parm.output.timeperframe.numerator = ovi.fps_den;
parm.parm.output.timeperframe.denominator = ovi.fps_num;
- if (ioctl(vcam->device, VIDIOC_S_PARM, &parm) < 0)
+ if (ioctl(vcam->device, VIDIOC_S_PARM, &parm) < 0) {
+ close(vcam->device);
+ vcam->device = -1;
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)
+ if (ioctl(vcam->device, VIDIOC_S_FMT, &format) < 0) {
+ close(vcam->device);
+ vcam->device = -1;
return false;
+ }
struct video_scale_info vsi = {0};
vsi.format = VIDEO_FORMAT_YUY2;
@@ -176,11 +215,12 @@ static bool virtualcam_start(void *data)
{
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
+#ifdef __linux__
if (!loopback_module_loaded()) {
if (loopback_module_load() != 0)
return false;
}
-
+#endif
for (int i = 0; i < MAX_DEVICES; i++) {
if (!try_connect(vcam, i))
continue;