feat(macos/capture): support for capture display other than main display (#2449)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
struct CaptureSession {
|
||||
AVCaptureVideoDataOutput *output;
|
||||
@@ -29,6 +30,7 @@ typedef bool (^FrameCallbackBlock)(CMSampleBufferRef);
|
||||
@property (nonatomic, assign) NSMapTable<AVCaptureConnection *, dispatch_semaphore_t> *captureSignals;
|
||||
|
||||
+ (NSArray<NSDictionary *> *)displayNames;
|
||||
+ (NSString *)getDisplayName:(CGDirectDisplayID)displayID;
|
||||
|
||||
- (id)initWithDisplay:(CGDirectDisplayID)displayID frameRate:(int)frameRate;
|
||||
|
||||
|
||||
@@ -23,13 +23,24 @@
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
[result addObject:@{
|
||||
@"id": [NSNumber numberWithUnsignedInt:displays[i]],
|
||||
@"name": [NSString stringWithFormat:@"%d", displays[i]]
|
||||
@"name": [NSString stringWithFormat:@"%d", displays[i]],
|
||||
@"displayName": [self getDisplayName:displays[i]],
|
||||
}];
|
||||
}
|
||||
|
||||
return [NSArray arrayWithArray:result];
|
||||
}
|
||||
|
||||
+ (NSString *)getDisplayName:(CGDirectDisplayID)displayID {
|
||||
NSScreen *screens = [NSScreen screens];
|
||||
for (NSScreen *screen in screens) {
|
||||
if (screen.deviceDescription[@"NSScreenNumber"] == [NSNumber numberWithUnsignedInt:displayID]) {
|
||||
return screen.localizedName;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id)initWithDisplay:(CGDirectDisplayID)displayID frameRate:(int)frameRate {
|
||||
self = [super init];
|
||||
|
||||
|
||||
@@ -142,18 +142,23 @@ namespace platf {
|
||||
|
||||
auto display = std::make_shared<av_display_t>();
|
||||
|
||||
// Default to main display
|
||||
display->display_id = CGMainDisplayID();
|
||||
if (!display_name.empty()) {
|
||||
auto display_array = [AVVideo displayNames];
|
||||
|
||||
for (NSDictionary *item in display_array) {
|
||||
NSString *name = item[@"name"];
|
||||
if (name.UTF8String == display_name) {
|
||||
NSNumber *display_id = item[@"id"];
|
||||
display->display_id = [display_id unsignedIntValue];
|
||||
}
|
||||
// Print all displays available with it's name and id
|
||||
auto display_array = [AVVideo displayNames];
|
||||
BOOST_LOG(info) << "Detecting displays"sv;
|
||||
for (NSDictionary *item in display_array) {
|
||||
NSNumber *display_id = item[@"id"];
|
||||
// We need show display's product name and corresponding display number given by user
|
||||
NSString *name = item[@"displayName"];
|
||||
// We are using CGGetActiveDisplayList that only returns active displays so hardcoded connected value in log to true
|
||||
BOOST_LOG(info) << "Detected display: "sv << name.UTF8String << " (id: "sv << [NSString stringWithFormat:@"%@", display_id].UTF8String << ") connected: true"sv;
|
||||
if (!display_name.empty() && std::atoi(display_name.c_str()) == [display_id unsignedIntValue]) {
|
||||
display->display_id = [display_id unsignedIntValue];
|
||||
}
|
||||
}
|
||||
BOOST_LOG(info) << "Configuring selected display ("sv << display->display_id << ") to stream"sv;
|
||||
|
||||
display->av_capture = [[AVVideo alloc] initWithDisplay:display->display_id frameRate:config.framerate];
|
||||
|
||||
|
||||
@@ -509,9 +509,28 @@ const KeyCodeMap kKeyCodesMap[] = {
|
||||
|
||||
auto macos_input = (macos_input_t *) result.get();
|
||||
|
||||
// If we don't use the main display in the future, this has to be adapted
|
||||
// Default to main display
|
||||
macos_input->display = CGMainDisplayID();
|
||||
|
||||
auto output_name = config::video.output_name;
|
||||
// If output_name is set, try to find the display with that display id
|
||||
if (!output_name.empty()) {
|
||||
uint32_t max_display = 32;
|
||||
uint32_t display_count;
|
||||
CGDirectDisplayID displays[max_display];
|
||||
if (CGGetActiveDisplayList(max_display, displays, &display_count) != kCGErrorSuccess) {
|
||||
BOOST_LOG(error) << "Unable to get active display list , error: "sv << std::endl;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < display_count; i++) {
|
||||
CGDirectDisplayID display_id = displays[i];
|
||||
if (display_id == std::atoi(output_name.c_str())) {
|
||||
macos_input->display = display_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input coordinates are based on the virtual resolution not the physical, so we need the scaling factor
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(macos_input->display);
|
||||
macos_input->displayScaling = ((CGFloat) CGDisplayPixelsWide(macos_input->display)) / ((CGFloat) CGDisplayModeGetPixelWidth(mode));
|
||||
|
||||
Reference in New Issue
Block a user