File 11906.patch of Package obs-studio
113
1
From 52d57cf70ca70f55378112f6eeb5708fb7680a6b Mon Sep 17 00:00:00 2001
2
From: stephematician <steph.fn.contact@proton.me>
3
Date: Wed, 19 Mar 2025 13:59:21 +1100
4
Subject: [PATCH] linux-v4l2: Fix virtual camera start failure
5
6
Add function that tries to reset v4l2loopback output for module versions
7
from 0.12.5 to 0.12.7. If successful, then set flag that STREAMON and
8
STREAMOFF are necessary each time the device is opened/closed.
9
---
10
plugins/linux-v4l2/v4l2-output.c | 57 ++++++++++++++++++++++++++++++--
11
1 file changed, 54 insertions(+), 3 deletions(-)
12
13
diff --git a/plugins/linux-v4l2/v4l2-output.c b/plugins/linux-v4l2/v4l2-output.c
14
index 366fc474f69d4e..d5e4e0f6ad57fb 100644
15
--- a/plugins/linux-v4l2/v4l2-output.c
16
+++ b/plugins/linux-v4l2/v4l2-output.c
17
18
obs_output_t *output;
19
int device;
20
uint32_t frame_size;
21
+ bool use_caps_workaround;
22
};
23
24
static const char *virtualcam_name(void *unused)
25
26
return vcam;
27
}
28
29
+bool try_reset_output_caps(const char *device)
30
+{
31
+ struct v4l2_capability capability;
32
+ struct v4l2_format format;
33
+ int fd;
34
+
35
+ blog(LOG_INFO, "Attempting to reset output capability of '%s'", device);
36
+
37
+ fd = open(device, O_RDWR);
38
+ if (fd < 0)
39
+ return false;
40
+
41
+ format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
42
+ if (ioctl(fd, VIDIOC_G_FMT, &format) < 0)
43
+ goto reset_fail_close_fd;
44
+
45
+ if (ioctl(fd, VIDIOC_S_FMT, &format) < 0)
46
+ goto reset_fail_close_fd;
47
+
48
+ if (ioctl(fd, VIDIOC_STREAMON, &format.type) < 0)
49
+ goto reset_fail_close_fd;
50
+
51
+ if (ioctl(fd, VIDIOC_STREAMOFF, &format.type) < 0)
52
+ goto reset_fail_close_fd;
53
+
54
+ close(fd);
55
+
56
+ fd = open(device, O_RDWR);
57
+ if (fd < 0)
58
+ return false;
59
+
60
+ if (ioctl(fd, VIDIOC_QUERYCAP, &capability) < 0)
61
+ goto reset_fail_close_fd;
62
+
63
+ close(fd);
64
+ return (capability.device_caps & V4L2_CAP_VIDEO_OUTPUT) != 0;
65
+
66
+reset_fail_close_fd:
67
+ close(fd);
68
+ return false;
69
+}
70
+
71
static bool try_connect(void *data, const char *device)
72
{
73
+ static bool use_caps_workaround = false;
74
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
75
- struct v4l2_format format;
76
struct v4l2_capability capability;
77
+ struct v4l2_format format;
78
struct v4l2_streamparm parm;
79
80
uint32_t width = obs_output_get_width(vcam->output);
81
82
if (ioctl(vcam->device, VIDIOC_QUERYCAP, &capability) < 0)
83
goto fail_close_device;
84
85
+ if (!use_caps_workaround && !(capability.device_caps & V4L2_CAP_VIDEO_OUTPUT)) {
86
+ if (!try_reset_output_caps(device))
87
+ goto fail_close_device;
88
+ use_caps_workaround = true;
89
+ }
90
+ vcam->use_caps_workaround = use_caps_workaround;
91
+
92
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
93
94
if (ioctl(vcam->device, VIDIOC_G_FMT, &format) < 0)
95
96
memset(&parm, 0, sizeof(parm));
97
parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
98
99
- if (ioctl(vcam->device, VIDIOC_STREAMON, &parm) < 0) {
100
+ if (vcam->use_caps_workaround && ioctl(vcam->device, VIDIOC_STREAMON, &parm.type) < 0) {
101
blog(LOG_ERROR, "Failed to start streaming on '%s' (%s)", device, strerror(errno));
102
goto fail_close_device;
103
}
104
105
struct v4l2_streamparm parm = {0};
106
parm.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
107
108
- if (ioctl(vcam->device, VIDIOC_STREAMOFF, &parm) < 0) {
109
+ if (vcam->use_caps_workaround && ioctl(vcam->device, VIDIOC_STREAMOFF, &parm) < 0) {
110
blog(LOG_WARNING, "Failed to stop streaming on video device %d (%s)", vcam->device, strerror(errno));
111
}
112
113