103 lines
2.4 KiB
C
103 lines
2.4 KiB
C
#include <obs-module.h>
|
|
#include <util/platform.h>
|
|
#include "shared-memory-queue.h"
|
|
|
|
struct virtualcam_data {
|
|
obs_output_t *output;
|
|
video_queue_t *vq;
|
|
};
|
|
|
|
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;
|
|
video_queue_close(vcam->vq);
|
|
bfree(data);
|
|
}
|
|
|
|
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 virtualcam_start(void *data)
|
|
{
|
|
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
|
uint32_t width = obs_output_get_width(vcam->output);
|
|
uint32_t height = obs_output_get_height(vcam->output);
|
|
|
|
struct obs_video_info ovi;
|
|
obs_get_video_info(&ovi);
|
|
|
|
uint64_t interval = ovi.fps_den * 10000000ULL / ovi.fps_num;
|
|
|
|
char res[64];
|
|
snprintf(res, sizeof(res), "%dx%dx%lld", (int)width, (int)height,
|
|
(long long)interval);
|
|
|
|
char *res_file = os_get_config_path_ptr("obs-virtualcam.txt");
|
|
os_quick_write_utf8_file_safe(res_file, res, strlen(res), false, "tmp",
|
|
NULL);
|
|
bfree(res_file);
|
|
|
|
vcam->vq = video_queue_create(width, height, interval);
|
|
if (!vcam->vq) {
|
|
blog(LOG_WARNING, "starting virtual-output failed");
|
|
return false;
|
|
}
|
|
|
|
struct video_scale_info vsi = {0};
|
|
vsi.format = VIDEO_FORMAT_NV12;
|
|
vsi.width = width;
|
|
vsi.height = height;
|
|
obs_output_set_video_conversion(vcam->output, &vsi);
|
|
|
|
blog(LOG_INFO, "Virtual output started");
|
|
obs_output_begin_data_capture(vcam->output, 0);
|
|
return true;
|
|
}
|
|
|
|
static void virtualcam_stop(void *data, uint64_t ts)
|
|
{
|
|
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
|
obs_output_end_data_capture(vcam->output);
|
|
video_queue_close(vcam->vq);
|
|
vcam->vq = NULL;
|
|
|
|
blog(LOG_INFO, "Virtual output stopped");
|
|
|
|
UNUSED_PARAMETER(ts);
|
|
}
|
|
|
|
static void virtual_video(void *param, struct video_data *frame)
|
|
{
|
|
struct virtualcam_data *vcam = (struct virtualcam_data *)param;
|
|
|
|
if (!vcam->vq)
|
|
return;
|
|
|
|
video_queue_write(vcam->vq, frame->data, frame->linesize,
|
|
frame->timestamp);
|
|
}
|
|
|
|
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,
|
|
};
|