mirror of
https://github.com/obsproject/obs-studio.git
synced 2026-08-30 17:58:37 +08:00
d314d4725d
This deprecates the following functions, replacing them with new versions: - `obs_output_can_begin_data_capture()` - now `*capture2()` - `obs_output_initialize_encoders()` - now `*encoders2()` - `obs_output_begin_data_capture()` - now `*capture2()` The flags parameter was initially designed to support audio-only or video-only operation of an output which had the `OBS_OUTPUT_AV` flag, however, full support for that was never implemented, and there are likely fundamental issues with an implementation, mainly that most outputs are programmed assuming that there will always be at least one audio and one video track. This requires new flags specifying support for optional audio/video, among other things. An implementation to allow audio/video to be optional is best done using the flag technique above, with audio/video enablement specified by whether media (raw, `video_t/audio_t`) or encoder (`obs_encoder_t`) objects are specified. Since every implementation I could find always specifies `flags` as 0, I was able to safely conclude that immediately removing the parameter's functionality is safe to do.
126 lines
3.0 KiB
C
126 lines
3.0 KiB
C
#include <obs-module.h>
|
|
#include <util/platform.h>
|
|
#include "util/threading.h"
|
|
#include "shared-memory-queue.h"
|
|
|
|
struct virtualcam_data {
|
|
obs_output_t *output;
|
|
video_queue_t *vq;
|
|
volatile bool active;
|
|
volatile bool stopping;
|
|
};
|
|
|
|
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);
|
|
|
|
os_atomic_set_bool(&vcam->active, true);
|
|
os_atomic_set_bool(&vcam->stopping, false);
|
|
blog(LOG_INFO, "Virtual output started");
|
|
obs_output_begin_data_capture2(vcam->output);
|
|
return true;
|
|
}
|
|
|
|
static void virtualcam_deactive(struct virtualcam_data *vcam)
|
|
{
|
|
obs_output_end_data_capture(vcam->output);
|
|
video_queue_close(vcam->vq);
|
|
vcam->vq = NULL;
|
|
|
|
os_atomic_set_bool(&vcam->active, false);
|
|
os_atomic_set_bool(&vcam->stopping, false);
|
|
|
|
blog(LOG_INFO, "Virtual output stopped");
|
|
}
|
|
|
|
static void virtualcam_stop(void *data, uint64_t ts)
|
|
{
|
|
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
|
os_atomic_set_bool(&vcam->stopping, true);
|
|
|
|
blog(LOG_INFO, "Virtual output stopping");
|
|
|
|
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;
|
|
|
|
if (!os_atomic_load_bool(&vcam->active))
|
|
return;
|
|
|
|
if (os_atomic_load_bool(&vcam->stopping)) {
|
|
virtualcam_deactive(vcam);
|
|
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,
|
|
};
|