1 #include <obs-module.h>
2 #include <util/platform.h>
3 #include "shared-memory-queue.h"
4
5 struct virtualcam_data {
6 obs_output_t *output;
7 video_queue_t *vq;
8 };
9
virtualcam_name(void * unused)10 static const char *virtualcam_name(void *unused)
11 {
12 UNUSED_PARAMETER(unused);
13 return "Virtual Camera Output";
14 }
15
virtualcam_destroy(void * data)16 static void virtualcam_destroy(void *data)
17 {
18 struct virtualcam_data *vcam = (struct virtualcam_data *)data;
19 video_queue_close(vcam->vq);
20 bfree(data);
21 }
22
virtualcam_create(obs_data_t * settings,obs_output_t * output)23 static void *virtualcam_create(obs_data_t *settings, obs_output_t *output)
24 {
25 struct virtualcam_data *vcam =
26 (struct virtualcam_data *)bzalloc(sizeof(*vcam));
27 vcam->output = output;
28
29 UNUSED_PARAMETER(settings);
30 return vcam;
31 }
32
virtualcam_start(void * data)33 static bool virtualcam_start(void *data)
34 {
35 struct virtualcam_data *vcam = (struct virtualcam_data *)data;
36 uint32_t width = obs_output_get_width(vcam->output);
37 uint32_t height = obs_output_get_height(vcam->output);
38
39 struct obs_video_info ovi;
40 obs_get_video_info(&ovi);
41
42 uint64_t interval = ovi.fps_den * 10000000ULL / ovi.fps_num;
43
44 char res[64];
45 snprintf(res, sizeof(res), "%dx%dx%lld", (int)width, (int)height,
46 (long long)interval);
47
48 char *res_file = os_get_config_path_ptr("obs-virtualcam.txt");
49 os_quick_write_utf8_file_safe(res_file, res, strlen(res), false, "tmp",
50 NULL);
51 bfree(res_file);
52
53 vcam->vq = video_queue_create(width, height, interval);
54 if (!vcam->vq) {
55 blog(LOG_WARNING, "starting virtual-output failed");
56 return false;
57 }
58
59 struct video_scale_info vsi = {0};
60 vsi.format = VIDEO_FORMAT_NV12;
61 vsi.width = width;
62 vsi.height = height;
63 obs_output_set_video_conversion(vcam->output, &vsi);
64
65 blog(LOG_INFO, "Virtual output started");
66 obs_output_begin_data_capture(vcam->output, 0);
67 return true;
68 }
69
virtualcam_stop(void * data,uint64_t ts)70 static void virtualcam_stop(void *data, uint64_t ts)
71 {
72 struct virtualcam_data *vcam = (struct virtualcam_data *)data;
73 obs_output_end_data_capture(vcam->output);
74 video_queue_close(vcam->vq);
75 vcam->vq = NULL;
76
77 blog(LOG_INFO, "Virtual output stopped");
78
79 UNUSED_PARAMETER(ts);
80 }
81
virtual_video(void * param,struct video_data * frame)82 static void virtual_video(void *param, struct video_data *frame)
83 {
84 struct virtualcam_data *vcam = (struct virtualcam_data *)param;
85
86 if (!vcam->vq)
87 return;
88
89 video_queue_write(vcam->vq, frame->data, frame->linesize,
90 frame->timestamp);
91 }
92
93 struct obs_output_info virtualcam_info = {
94 .id = "virtualcam_output",
95 .flags = OBS_OUTPUT_VIDEO,
96 .get_name = virtualcam_name,
97 .create = virtualcam_create,
98 .destroy = virtualcam_destroy,
99 .start = virtualcam_start,
100 .stop = virtualcam_stop,
101 .raw_video = virtual_video,
102 };
103