Skip to content

Commit b241b46

Browse files
committed
multitrack: impl mac support for enhanced broadcasting
* Add Metal framework to get MTLDevice * implement system info for mac
1 parent 61f53ee commit b241b46

File tree

2 files changed

+162
-4
lines changed

2 files changed

+162
-4
lines changed

obs-studio-server/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ if (APPLE)
173173
find_library(IOKit IOKit)
174174
find_library(SECURITY_LIBRARY Security)
175175
find_library(BSM_LIBRARY bsm)
176+
find_library(METAL Metal)
176177
endif ()
177178

178179
# Getting LIBOBS_VERSION from azure script
@@ -437,8 +438,8 @@ if(WIN32)
437438
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDE_PATHS})
438439
target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBRARIES} optimized crashpad strmiids)
439440
else()
440-
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDE_PATHS} ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY})
441-
target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBRARIES} crashpad ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY})
441+
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDE_PATHS} ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY} ${METAL})
442+
target_link_libraries(${PROJECT_NAME} ${PROJECT_LIBRARIES} crashpad ${COREFOUNDATION} ${COCOA} ${IOSURF} ${GLKIT} ${AVFOUNDATION} ${IOKit} ${SECURITY_LIBRARY} ${BSM_LIBRARY} ${METAL})
442443
endif()
443444

444445
if(MSVC)
Lines changed: 159 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,165 @@
11
#include "osn-multitrack-video-system-info.hpp"
2+
#include "shared.hpp"
3+
4+
#import <Foundation/Foundation.h>
5+
#import <Metal/Metal.h>
6+
#import <IOKit/IOKitLib.h>
7+
#import <IOKit/graphics/IOGraphicsLib.h>
8+
//#import <IOKit/pci/IOPCIDevice.h>
29

310
namespace osn {
411

5-
// This feature is currently unused on Mac
6-
void system_info(Capabilities &capabilities) {}
12+
/*
13+
struct Gpu {
14+
std::string model;
15+
uint32_t vendor_id;
16+
uint32_t device_id;
17+
uint64_t dedicated_video_memory;
18+
uint64_t shared_system_memory;
19+
std::optional<std::string> driver_version;
20+
21+
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Gpu, model, vendor_id, device_id, dedicated_video_memory, shared_system_memory, driver_version)
22+
};
23+
*/
24+
25+
static uint64_t GetUInt64Property(io_registry_entry_t entry, CFStringRef key)
26+
{
27+
uint64_t value = 0;
28+
CFTypeRef ref = IORegistryEntryCreateCFProperty(
29+
entry, key, kCFAllocatorDefault, 0);
30+
31+
if (ref) {
32+
if (CFGetTypeID(ref) == CFNumberGetTypeID()) {
33+
CFNumberGetValue((CFNumberRef)ref, kCFNumberSInt64Type, &value);
34+
}
35+
CFRelease(ref);
36+
}
37+
return value;
38+
}
39+
40+
static uint32_t GetUInt32Property(io_registry_entry_t entry, CFStringRef key)
41+
{
42+
uint32_t value = 0;
43+
CFTypeRef ref = IORegistryEntryCreateCFProperty(
44+
entry, key, kCFAllocatorDefault, 0);
45+
46+
if (ref) {
47+
if (CFGetTypeID(ref) == CFDataGetTypeID()) {
48+
CFDataGetBytes((CFDataRef)ref,
49+
CFRangeMake(0, sizeof(uint32_t)),
50+
reinterpret_cast<UInt8*>(&value));
51+
}
52+
CFRelease(ref);
53+
}
54+
return value;
55+
}
56+
57+
Gpu getPrimaryGpu()
58+
{
59+
Gpu gpu;
60+
gpu.driver_version = std::nullopt;
61+
gpu.vendor_id = 0;
62+
gpu.device_id = 0;
63+
64+
// ---- Metal: GPU name + memory model ----
65+
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
66+
if (device) {
67+
gpu.model = [[device name] UTF8String];
68+
69+
if ([device hasUnifiedMemory]) {
70+
gpu.shared_system_memory = device.recommendedMaxWorkingSetSize;
71+
gpu.dedicated_video_memory = 0;
72+
} else {
73+
gpu.dedicated_video_memory = device.recommendedMaxWorkingSetSize;
74+
gpu.shared_system_memory = 0;
75+
}
76+
}
77+
78+
// Get a matching dictionary for the IOGraphicsAccelerator2
79+
CFMutableDictionaryRef matchingDict = IORegistryEntryIDMatching([device registryID]);
80+
if (matchingDict == nullptr) {
81+
return;// DAWN_CONTEXT_LOST_ERROR("Failed to create the matching dict for the device");
82+
}
83+
// IOServiceGetMatchingService will consume the reference on the matching dictionary,
84+
// so we don't need to release the dictionary.
85+
io_registry_entry_t acceleratorEntry =
86+
IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
87+
if (acceleratorEntry == IO_OBJECT_NULL) {
88+
return;// DAWN_CONTEXT_LOST_ERROR("Failed to get the IO registry entry for the accelerator");
89+
}
90+
// Get the parent entry that will be the IOPCIDevice
91+
io_registry_entry_t deviceEntry = IO_OBJECT_NULL;
92+
kern_return_t ret = IORegistryEntryGetParentEntry(acceleratorEntry, kIOServicePlane, &deviceEntry);
93+
if (ret != KERN_SUCCESS) {
94+
IOObjectRelease(acceleratorEntry);
95+
return;// DAWN_CONTEXT_LOST_ERROR("Failed to get the IO registry entry for the device");
96+
}
97+
if (deviceEntry != IO_OBJECT_NULL) {
98+
gpu.vendor_id = GetUInt32Property(deviceEntry, CFSTR("vendor-id"));
99+
gpu.device_id = GetUInt32Property(deviceEntry, CFSTR("device-id"));
100+
IOObjectRelease(deviceEntry);
101+
}
102+
IOObjectRelease(acceleratorEntry);
103+
return gpu;
104+
}
105+
106+
Cpu getCpu()
107+
{
108+
Cpu cpu;
109+
cpu.physical_cores = g_util_osx->getPhysicalCores();
110+
cpu.logical_cores = os_get_logical_cores();
111+
return cpu;
112+
}
113+
114+
void system_info(Capabilities &capabilities) {
115+
/*
116+
117+
{
118+
auto &cpu_data = capabilities.cpu;
119+
cpu_data.physical_cores = os_get_physical_cores();
120+
cpu_data.logical_cores = os_get_logical_cores();
121+
DWORD processorSpeed;
122+
char *processorName;
123+
get_processor_info(&processorName, &processorSpeed);
124+
if (processorSpeed)
125+
cpu_data.speed = processorSpeed;
126+
if (processorName)
127+
cpu_data.name = processorName;
128+
bfree(processorName);
129+
}
130+
131+
{
132+
auto &memory_data = capabilities.memory;
133+
memory_data.total = os_get_sys_total_size();
134+
memory_data.free = os_get_sys_free_size();
135+
}
136+
137+
struct win_version_info ver;
138+
get_win_ver(&ver);
139+
get_reg_ver(&ver);
140+
141+
// Gaming features
142+
capabilities.gaming_features = get_gaming_features_data(ver);
143+
144+
{
145+
auto &system_data = capabilities.system;
146+
147+
snprintf(tmpstr, sizeof(tmpstr), "%d.%d", ver.major, ver.minor);
148+
149+
system_data.version = tmpstr;
150+
system_data.name = "Windows";
151+
system_data.build = ver.build;
152+
system_data.release = win_release_id;
153+
system_data.revision = std::to_string(ver.revis);
154+
;
155+
system_data.bits = is_64_bit_windows() ? 64 : 32;
156+
system_data.arm = is_arm64_windows();
157+
system_data.armEmulation = os_get_emulation_status();
158+
}
159+
*/
160+
std::vector<Gpu> gpu_list = { getPrimaryGpu() };
161+
capabilities.gpu = gpu_list;
162+
capabilities.cpu = getCpu();
163+
}
7164

8165
} // namespace osn

0 commit comments

Comments
 (0)