git: fee1c0576e73 - 2021Q4 - multimedia/obs-studio: Backport patch enabling OBS Studio Virtual Camera

From: Yuri Victorovich <yuri_at_FreeBSD.org>
Date: Thu, 14 Oct 2021 19:28:05 UTC
The branch 2021Q4 has been updated by yuri:

URL: https://cgit.FreeBSD.org/ports/commit/?id=fee1c0576e7306fd7ab7853e073b34f291bb410e

commit fee1c0576e7306fd7ab7853e073b34f291bb410e
Author:     Yuri Victorovich <yuri@FreeBSD.org>
AuthorDate: 2021-10-14 19:25:21 +0000
Commit:     Yuri Victorovich <yuri@FreeBSD.org>
CommitDate: 2021-10-14 19:28:02 +0000

    multimedia/obs-studio: Backport patch enabling OBS Studio Virtual Camera
    
    (cherry picked from commit c6f10a7b5ed6b991cf4c47254628ed7130e0116e)
---
 multimedia/obs-studio/Makefile                     |   2 +-
 .../files/patch-plugins_linux-v4l2_v4l2-output.c   | 109 +++++++++++++++++++++
 2 files changed, 110 insertions(+), 1 deletion(-)

diff --git a/multimedia/obs-studio/Makefile b/multimedia/obs-studio/Makefile
index 9336e33d7833..31c69cff2ad7 100644
--- a/multimedia/obs-studio/Makefile
+++ b/multimedia/obs-studio/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	obs-studio
 DISTVERSION=	27.0.1
-PORTREVISION=	3
+PORTREVISION=	4
 CATEGORIES=	multimedia
 
 MAINTAINER=	yuri@FreeBSD.org
diff --git a/multimedia/obs-studio/files/patch-plugins_linux-v4l2_v4l2-output.c b/multimedia/obs-studio/files/patch-plugins_linux-v4l2_v4l2-output.c
new file mode 100644
index 000000000000..0c1120159c0c
--- /dev/null
+++ b/multimedia/obs-studio/files/patch-plugins_linux-v4l2_v4l2-output.c
@@ -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;