mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 13:08:50 +02:00
mac-virtualcam: Do not rely on global state
This change updates the implementation of the mac-virtualcam plugin to not use any global state and instead rely on the state object that is passed by the OBS module system. This approach is similar to the virtual camera implementations for Linux and Windows.
This commit is contained in:
parent
5edabfe7c1
commit
db733032e0
@ -1,5 +1,4 @@
|
||||
#include <obs-module.h>
|
||||
#include <AppKit/AppKit.h>
|
||||
#include "OBSDALMachServer.h"
|
||||
#include "Defines.h"
|
||||
|
||||
@ -10,10 +9,12 @@ MODULE_EXPORT const char *obs_module_description(void)
|
||||
return "macOS virtual webcam output";
|
||||
}
|
||||
|
||||
obs_output_t *outputRef;
|
||||
obs_video_info videoInfo;
|
||||
CVPixelBufferPoolRef pool;
|
||||
static OBSDALMachServer *sMachServer;
|
||||
struct virtualcam_data {
|
||||
obs_output_t *output;
|
||||
obs_video_info videoInfo;
|
||||
CVPixelBufferPoolRef pool;
|
||||
OBSDALMachServer *machServer;
|
||||
};
|
||||
|
||||
static bool check_dal_plugin()
|
||||
{
|
||||
@ -129,31 +130,29 @@ static const char *virtualcam_output_get_name(void *type_data)
|
||||
return obs_module_text("Plugin_Name");
|
||||
}
|
||||
|
||||
// This is a dummy pointer so we have something to return from virtualcam_output_create
|
||||
static void *data = &data;
|
||||
|
||||
static void *virtualcam_output_create(obs_data_t *settings,
|
||||
obs_output_t *output)
|
||||
{
|
||||
UNUSED_PARAMETER(settings);
|
||||
|
||||
outputRef = output;
|
||||
struct virtualcam_data *vcam =
|
||||
(struct virtualcam_data *)bzalloc(sizeof(*vcam));
|
||||
|
||||
blog(LOG_DEBUG, "output_create");
|
||||
sMachServer = [[OBSDALMachServer alloc] init];
|
||||
return data;
|
||||
vcam->output = output;
|
||||
vcam->machServer = [[OBSDALMachServer alloc] init];
|
||||
return vcam;
|
||||
}
|
||||
|
||||
static void virtualcam_output_destroy(void *data)
|
||||
{
|
||||
UNUSED_PARAMETER(data);
|
||||
blog(LOG_DEBUG, "output_destroy");
|
||||
sMachServer = nil;
|
||||
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
||||
|
||||
vcam->machServer = nil;
|
||||
}
|
||||
|
||||
static bool virtualcam_output_start(void *data)
|
||||
{
|
||||
UNUSED_PARAMETER(data);
|
||||
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
||||
|
||||
bool hasDalPlugin = check_dal_plugin();
|
||||
|
||||
@ -161,24 +160,22 @@ static bool virtualcam_output_start(void *data)
|
||||
return false;
|
||||
}
|
||||
|
||||
blog(LOG_DEBUG, "output_start");
|
||||
|
||||
obs_get_video_info(&videoInfo);
|
||||
obs_get_video_info(&vcam->videoInfo);
|
||||
|
||||
FourCharCode video_format =
|
||||
convert_video_format_to_mac(videoInfo.output_format);
|
||||
convert_video_format_to_mac(vcam->videoInfo.output_format);
|
||||
|
||||
if (!video_format) {
|
||||
// Selected output format is not supported natively by CoreVideo, CPU conversion necessary
|
||||
blog(LOG_WARNING,
|
||||
"Selected output format (%s) not supported by CoreVideo, enabling CPU transcoding...",
|
||||
get_video_format_name(videoInfo.output_format));
|
||||
get_video_format_name(vcam->videoInfo.output_format));
|
||||
|
||||
struct video_scale_info conversion = {};
|
||||
conversion.format = VIDEO_FORMAT_NV12;
|
||||
conversion.width = videoInfo.output_width;
|
||||
conversion.height = videoInfo.output_height;
|
||||
obs_output_set_video_conversion(outputRef, &conversion);
|
||||
conversion.width = vcam->videoInfo.output_width;
|
||||
conversion.height = vcam->videoInfo.output_height;
|
||||
obs_output_set_video_conversion(vcam->output, &conversion);
|
||||
|
||||
video_format = convert_video_format_to_mac(conversion.format);
|
||||
}
|
||||
@ -186,22 +183,22 @@ static bool virtualcam_output_start(void *data)
|
||||
NSDictionary *pAttr = @{};
|
||||
NSDictionary *pbAttr = @{
|
||||
(id)kCVPixelBufferPixelFormatTypeKey: @(video_format),
|
||||
(id)kCVPixelBufferWidthKey: @(videoInfo.output_width),
|
||||
(id)kCVPixelBufferHeightKey: @(videoInfo.output_height),
|
||||
(id)kCVPixelBufferWidthKey: @(vcam->videoInfo.output_width),
|
||||
(id)kCVPixelBufferHeightKey: @(vcam->videoInfo.output_height),
|
||||
(id)kCVPixelBufferIOSurfacePropertiesKey: @{}
|
||||
};
|
||||
CVReturn status = CVPixelBufferPoolCreate(
|
||||
kCFAllocatorDefault, (__bridge CFDictionaryRef)pAttr,
|
||||
(__bridge CFDictionaryRef)pbAttr, &pool);
|
||||
(__bridge CFDictionaryRef)pbAttr, &vcam->pool);
|
||||
if (status != kCVReturnSuccess) {
|
||||
blog(LOG_ERROR,
|
||||
"unable to allocate pixel buffer pool (error %d)", status);
|
||||
return false;
|
||||
}
|
||||
|
||||
[sMachServer run];
|
||||
[vcam->machServer run];
|
||||
|
||||
if (!obs_output_begin_data_capture(outputRef, 0)) {
|
||||
if (!obs_output_begin_data_capture(vcam->output, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -210,23 +207,23 @@ static bool virtualcam_output_start(void *data)
|
||||
|
||||
static void virtualcam_output_stop(void *data, uint64_t ts)
|
||||
{
|
||||
UNUSED_PARAMETER(data);
|
||||
UNUSED_PARAMETER(ts);
|
||||
|
||||
blog(LOG_DEBUG, "output_stop");
|
||||
obs_output_end_data_capture(outputRef);
|
||||
[sMachServer stop];
|
||||
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
||||
|
||||
CVPixelBufferPoolRelease(pool);
|
||||
obs_output_end_data_capture(vcam->output);
|
||||
[vcam->machServer stop];
|
||||
|
||||
CVPixelBufferPoolRelease(vcam->pool);
|
||||
}
|
||||
|
||||
static void virtualcam_output_raw_video(void *data, struct video_data *frame)
|
||||
{
|
||||
UNUSED_PARAMETER(data);
|
||||
struct virtualcam_data *vcam = (struct virtualcam_data *)data;
|
||||
|
||||
CVPixelBufferRef frameRef = NULL;
|
||||
CVPixelBufferRef frameRef = nil;
|
||||
CVReturn status = CVPixelBufferPoolCreatePixelBuffer(
|
||||
kCFAllocatorDefault, pool, &frameRef);
|
||||
kCFAllocatorDefault, vcam->pool, &frameRef);
|
||||
|
||||
if (status != kCVReturnSuccess) {
|
||||
blog(LOG_ERROR, "unable to allocate pixel buffer (error %d)",
|
||||
@ -295,10 +292,10 @@ static void virtualcam_output_raw_video(void *data, struct video_data *frame)
|
||||
CVPixelBufferUnlockBaseAddress(frameRef, 0);
|
||||
|
||||
// Share pixel buffer with clients
|
||||
[sMachServer sendPixelBuffer:frameRef
|
||||
[vcam->machServer sendPixelBuffer:frameRef
|
||||
timestamp:frame->timestamp
|
||||
fpsNumerator:videoInfo.fps_num
|
||||
fpsDenominator:videoInfo.fps_den];
|
||||
fpsNumerator:vcam->videoInfo.fps_num
|
||||
fpsDenominator:vcam->videoInfo.fps_den];
|
||||
|
||||
CVPixelBufferRelease(frameRef);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user