Fixed dumb bug that was causing metal rendering to be disabled.

Pass output layout name to Stream service plugins so they can potentially use it for naming etc.
More work on Virtual Camera output
Add more pixel formats to Passthrough compressor
This commit is contained in:
Zakk 2020-05-17 03:28:31 -04:00
parent 970bea7db2
commit 62972f1dfb
19 changed files with 237 additions and 33 deletions

View file

@ -13,6 +13,7 @@
3400A07A1BD4533A003E1828 /* CSInputLibraryWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3400A0781BD4533A003E1828 /* CSInputLibraryWindowController.xib */; };
3400A07E1BD49406003E1828 /* CSInputLibraryItemView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3400A07D1BD49406003E1828 /* CSInputLibraryItemView.xib */; };
3400A0841BD522A5003E1828 /* CSLibraryInputItemViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3400A0831BD522A5003E1828 /* CSLibraryInputItemViewController.m */; };
34023294246FB96400B61BF1 /* CSVirtualCameraOutput.bundle in Copy Files */ = {isa = PBXBuildFile; fileRef = 34A40732246320D200BD32BB /* CSVirtualCameraOutput.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
34027499203B6C4B0099328C /* CSColorWell.m in Sources */ = {isa = PBXBuildFile; fileRef = 34027498203B6C4B0099328C /* CSColorWell.m */; };
340274B5203B98130099328C /* CSUndoObjectController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340274B4203B98130099328C /* CSUndoObjectController.m */; };
340620761F2E2BFE0016D997 /* CAMultiAudioInput.m in Sources */ = {isa = PBXBuildFile; fileRef = 340620751F2E2BFE0016D997 /* CAMultiAudioInput.m */; };
@ -623,6 +624,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
34023294246FB96400B61BF1 /* CSVirtualCameraOutput.bundle in Copy Files */,
34799D14243F165100B432BB /* CSLUTFilter.plugin in Copy Files */,
34A8883622A5CB5F0023D8B9 /* CSSyphonCapturePlugin.bundle in Copy Files */,
34E88C9E218DB0A90053913B /* CSAppleWebViewCapturePlugin.bundle in Copy Files */,

View file

@ -21,7 +21,9 @@
_pixelFormats = @{@"RGBA": @(kCVPixelFormatType_32RGBA),
@"ARGB": @(kCVPixelFormatType_32ARGB),
@"BGRA": @(kCVPixelFormatType_32BGRA),
@"422 YpCbCr8 (2vuy/UYVY)": @(kCVPixelFormatType_422YpCbCr8)
@"422 YpCbCr8 (2vuy/UYVY)": @(kCVPixelFormatType_422YpCbCr8),
@"Planar Component Y'CbCr 8-bit 4:2:0 (y420)": @(kCVPixelFormatType_420YpCbCr8Planar),
@"Component Y'CbCr 8-bit 4:2:2 (yuvs)": @(kCVPixelFormatType_422YpCbCr8_yuvs)
};
}
@ -97,13 +99,16 @@
{
VTPixelTransferSessionCreate(NULL, &_pvt_ref);
}
OSType useFormat = CVPixelBufferGetPixelFormatType(imageBuffer.videoFrame);
if (self.usePixelFormat)
{
useFormat = (OSType)self.usePixelFormat.integerValue;
}
CVPixelBufferCreate(NULL, CVPixelBufferGetWidth(imageBuffer.videoFrame), CVPixelBufferGetHeight(imageBuffer.videoFrame), useFormat, NULL, &useFrame);
NSMutableDictionary *ioProperties = [NSMutableDictionary dictionary];
ioProperties[(id)kCVPixelBufferIOSurfacePropertiesKey] = @{};
CVPixelBufferCreate(NULL, CVPixelBufferGetWidth(imageBuffer.videoFrame), CVPixelBufferGetHeight(imageBuffer.videoFrame), useFormat, (__bridge CFDictionaryRef _Nullable)(ioProperties), &useFrame);
VTPixelTransferSessionTransferImage(_pvt_ref, imageBuffer.videoFrame, useFrame);
} else {
useFrame = imageBuffer.videoFrame;

View file

@ -18,6 +18,8 @@
{
if (self = [super init])
{
_useMetalRenderer = NO;
_layoutChanged = NO;
bool systemMetal = CaptureController.sharedCaptureController.useMetalIfAvailable;
@ -32,7 +34,6 @@
_useMetalRenderer = NO;
}
//
_useMetalRenderer = NO;
}
@ -133,7 +134,7 @@
CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, _cvpool, &dummyFrame);
CVMetalTextureRef dummyTexture = NULL;
CVMetalTextureCacheCreateTextureFromImage(NULL, _cvmetalcache, dummyFrame, NULL, MTLPixelFormatBGRA8Unorm_sRGB, CVPixelBufferGetWidth(dummyFrame), CVPixelBufferGetHeight(dummyFrame), 0, &dummyTexture);
CVMetalTextureCacheCreateTextureFromImage(NULL, _cvmetalcache, dummyFrame, NULL, MTLPixelFormatBGRA8Unorm, CVPixelBufferGetWidth(dummyFrame), CVPixelBufferGetHeight(dummyFrame), 0, &dummyTexture);
if (@available(macOS 10.13, *)) {
self.renderer = [CARenderer rendererWithMTLTexture:CVMetalTextureGetTexture(dummyTexture) options:nil];
} else {
@ -199,7 +200,7 @@
if (_useMetalRenderer)
{
CVMetalTextureRef mtlTexture = NULL;
CVMetalTextureCacheCreateTextureFromImage(NULL, _cvmetalcache, pixelBuffer, NULL, MTLPixelFormatBGRA8Unorm_sRGB, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer), 0, &mtlTexture);
CVMetalTextureCacheCreateTextureFromImage(NULL, _cvmetalcache, pixelBuffer, NULL, MTLPixelFormatBGRA8Unorm, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer), 0, &mtlTexture);
if (!mtlTexture)
{
return;

View file

@ -428,7 +428,14 @@
{
if (self.streamServiceObject)
{
newout = [self.streamServiceObject createOutput];
NSString *layoutName = nil;
if (self.assignedLayout)
{
layoutName = self.assignedLayout.name;
} else {
layoutName = CaptureController.sharedCaptureController.liveLayout.name;
}
newout = [self.streamServiceObject createOutput:layoutName];
if (!newout)
{
newout = [[CSOutputBase alloc] init];

View file

@ -52,11 +52,16 @@
return nil;
}
-(NSObject<CSOutputWriterProtocol> *)createOutput;
-(NSObject<CSOutputWriterProtocol> *)createOutput
{
return [[CSLavfOutput alloc] init];
}
-(NSObject<CSOutputWriterProtocol> *)createOutput:(NSString *)forLayout
{
return [self createOutput];
}
-(void)prepareForStreamStart
{

View file

@ -16,7 +16,7 @@
+(NSString *)label;
+(NSString *)serviceDescription;
+(NSImage *)serviceImage;
-(NSObject<CSOutputWriterProtocol> *)createOutput;
-(NSObject<CSOutputWriterProtocol> *)createOutput:(NSString *)layoutName;
+(bool)shouldLoad;

View file

@ -21,6 +21,8 @@
+(NSImage *)serviceImage;
+(bool)shouldLoad;
-(NSObject<CSOutputWriterProtocol> *)createOutput;
-(NSObject<CSOutputWriterProtocol> *)createOutput:(NSString *)layoutName;
-(void)prepareForStreamStart;

View file

@ -89,7 +89,7 @@
}
-(NSObject <CSOutputWriterProtocol> *)createOutput
-(NSObject <CSOutputWriterProtocol> *)createOutput:(NSString *)forLayout
{
NSObject<CSOutputWriterProtocol>*ret = [super createOutput];
if (self.segmentFile)

View file

@ -36,9 +36,7 @@
return self;
}
-(NSObject <CSOutputWriterProtocol> *)createOutput
-(NSObject<CSOutputWriterProtocol> *)createOutput:(NSString *)layoutName
{
return [[CSNDIOutput alloc] initWithName:self.sendName];
}

View file

@ -7,12 +7,17 @@
objects = {
/* Begin PBXBuildFile section */
340232B72470A28800B61BF1 /* CSVirtualCameraOutputViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 340232B52470A28800B61BF1 /* CSVirtualCameraOutputViewController.m */; };
340232B82470A28800B61BF1 /* CSVirtualCameraOutputViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 340232B62470A28800B61BF1 /* CSVirtualCameraOutputViewController.xib */; };
34A407382463263F00BD32BB /* CSVirtualCameraDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A407372463263F00BD32BB /* CSVirtualCameraDevice.m */; };
34A4073B2463274D00BD32BB /* CSVirtualCameraOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A4073A2463274D00BD32BB /* CSVirtualCameraOutput.m */; };
34A4073E246327DF00BD32BB /* CSVirtualCameraOutputService.m in Sources */ = {isa = PBXBuildFile; fileRef = 34A4073D246327DF00BD32BB /* CSVirtualCameraOutputService.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
340232B42470A28800B61BF1 /* CSVirtualCameraOutputViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSVirtualCameraOutputViewController.h; sourceTree = "<group>"; };
340232B52470A28800B61BF1 /* CSVirtualCameraOutputViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSVirtualCameraOutputViewController.m; sourceTree = "<group>"; };
340232B62470A28800B61BF1 /* CSVirtualCameraOutputViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CSVirtualCameraOutputViewController.xib; sourceTree = "<group>"; };
34A4070B246320D100BD32BB /* CSVirtualCameraOutput.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CSVirtualCameraOutput.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
34A4070E246320D100BD32BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
34A407362463263F00BD32BB /* CSVirtualCameraDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSVirtualCameraDevice.h; sourceTree = "<group>"; };
@ -60,6 +65,9 @@
34A4073A2463274D00BD32BB /* CSVirtualCameraOutput.m */,
34A4073C246327DF00BD32BB /* CSVirtualCameraOutputService.h */,
34A4073D246327DF00BD32BB /* CSVirtualCameraOutputService.m */,
340232B42470A28800B61BF1 /* CSVirtualCameraOutputViewController.h */,
340232B52470A28800B61BF1 /* CSVirtualCameraOutputViewController.m */,
340232B62470A28800B61BF1 /* CSVirtualCameraOutputViewController.xib */,
);
path = CSVirtualCameraOutput;
sourceTree = "<group>";
@ -121,6 +129,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
340232B82470A28800B61BF1 /* CSVirtualCameraOutputViewController.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -133,6 +142,7 @@
files = (
34A4073E246327DF00BD32BB /* CSVirtualCameraOutputService.m in Sources */,
34A407382463263F00BD32BB /* CSVirtualCameraDevice.m in Sources */,
340232B72470A28800B61BF1 /* CSVirtualCameraOutputViewController.m in Sources */,
34A4073B2463274D00BD32BB /* CSVirtualCameraOutput.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View file

@ -27,6 +27,7 @@ NS_ASSUME_NONNULL_BEGIN
{
NSXPCConnection *_XPCconnection;
id<CSVirtualCameraProtocol> _assistant;
}

View file

@ -67,6 +67,8 @@
[_assistant createDevice:self.name withUID:self.deviceUID withModel:self.modelName withManufacturer:self.manufacturer width:self.width height:self.height pixelFormat:self.pixelFormat frameRate:self.frameRate withReply:^(NSString * _Nonnull uid) {
self.isReady = YES;
[_assistant setInternalClock:self.useInternalClock forDevice:self.deviceUID];
[_assistant setPersistOnDisconnect:self.persistOnDisconnect forDevice:self.deviceUID];
if (completionBlock)
{
completionBlock();
@ -94,7 +96,36 @@
{
[self publishIOSurfaceFrame:bufferSurface];
} else {
//Supported later
NSMutableDictionary *ioProperties = [NSMutableDictionary dictionary];
ioProperties[(id)kCVPixelBufferIOSurfacePropertiesKey] = @{};
CVPixelBufferRef newPixelBuffer = NULL;
CVPixelBufferCreate(kCFAllocatorDefault, CVPixelBufferGetWidth(videoFrame), CVPixelBufferGetHeight(videoFrame), CVPixelBufferGetPixelFormatType(videoFrame), (__bridge CFDictionaryRef _Nullable)(ioProperties), &newPixelBuffer);
NSUInteger planeCnt = CVPixelBufferGetPlaneCount(videoFrame);
CVPixelBufferLockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly);
CVPixelBufferLockBaseAddress(newPixelBuffer, 0);
if (!planeCnt)
{
void *srcAddr = CVPixelBufferGetBaseAddress(videoFrame);
void *dstAddr = CVPixelBufferGetBaseAddress(newPixelBuffer);
memcpy(dstAddr, srcAddr, CVPixelBufferGetDataSize(videoFrame));
} else {
for(NSUInteger i = 0; i < planeCnt; i++)
{
void *srcAddr = CVPixelBufferGetBaseAddressOfPlane(videoFrame, i);
void *dstAddr = CVPixelBufferGetBaseAddressOfPlane(newPixelBuffer, i);
memcpy(dstAddr, srcAddr, CVPixelBufferGetBytesPerRowOfPlane(videoFrame, i) * CVPixelBufferGetWidthOfPlane(videoFrame, i));
}
}
CVPixelBufferUnlockBaseAddress(newPixelBuffer, 0);
CVPixelBufferUnlockBaseAddress(videoFrame, kCVPixelBufferLock_ReadOnly);
[self publishIOSurfaceFrame:(__bridge IOSurface *)CVPixelBufferGetIOSurface(newPixelBuffer)];
CVPixelBufferRelease(newPixelBuffer);
}
}

View file

@ -14,8 +14,12 @@ NS_ASSUME_NONNULL_BEGIN
@interface CSVirtualCameraOutput : CSOutputBase
{
CSVirtualCameraDevice *_cameraDevice;
}
@property (strong) CSVirtualCameraDevice *cameraDevice;
@property (strong) NSString *deviceName;
@property (assign) bool persistDevice;
@end
NS_ASSUME_NONNULL_END

View file

@ -11,6 +11,7 @@
@implementation CSVirtualCameraOutput
-(bool)queueFramedata:(CapturedFrameData *)frameData
{
@ -19,24 +20,25 @@
{
return NO;
}
if (!_cameraDevice)
if (!self.cameraDevice)
{
_cameraDevice = [[CSVirtualCameraDevice alloc] init];
_cameraDevice.deviceUID = @"CocoaSplit Test Output";
_cameraDevice.frameRate = 60.0f;
_cameraDevice.width = CVPixelBufferGetWidth(useImage);
_cameraDevice.height = CVPixelBufferGetHeight(useImage);
_cameraDevice.name = @"CocoaSplit Test Output";
_cameraDevice.pixelFormat = CVPixelBufferGetPixelFormatType(useImage);
[_cameraDevice createDeviceWithCompletionBlock:^{
_cameraDevice.persistOnDisconnect = NO;
}];
self.cameraDevice = [[CSVirtualCameraDevice alloc] init];
self.cameraDevice.name = self.deviceName;
self.cameraDevice.persistOnDisconnect = self.persistDevice;
self.cameraDevice.deviceUID = self.cameraDevice.name;
self.cameraDevice.frameRate = 1.0f/CMTimeGetSeconds(frameData.videoDuration);
self.cameraDevice.width = CVPixelBufferGetWidth(useImage);
self.cameraDevice.height = CVPixelBufferGetHeight(useImage);
self.cameraDevice.pixelFormat = CVPixelBufferGetPixelFormatType(useImage);
[self.cameraDevice createDeviceWithCompletionBlock:nil];
return NO; //We'll start next frame or so
} else if (_cameraDevice.isReady) {
[_cameraDevice publishCVPixelBufferFrame:useImage];
} else if (self.cameraDevice.isReady) {
[self.cameraDevice publishCVPixelBufferFrame:useImage];
return YES;
}
return NO;
}
@end

View file

@ -8,10 +8,14 @@
#import <Foundation/Foundation.h>
#import "CSStreamServiceBase.h"
#import "CSVirtualCameraOutput.h"
NS_ASSUME_NONNULL_BEGIN
@interface CSVirtualCameraOutputService : CSStreamServiceBase
@property (strong) CSVirtualCameraOutput *output;
@property (strong) NSString *layoutName;
@property (strong) NSString *deviceName;
@property (assign) bool persistDevice;
@end

View file

@ -8,7 +8,7 @@
#import "CSVirtualCameraOutputService.h"
#import "CSVirtualCameraOutput.h"
#import "CSVirtualCameraOutputViewController.h"
@implementation CSVirtualCameraOutputService
+(NSString *)label
@ -16,15 +16,46 @@
return @"Virtual Camera";
}
-(NSObject <CSOutputWriterProtocol> *)createOutput
-(NSObject<CSOutputWriterProtocol> *)createOutput
{
return [[CSVirtualCameraOutput alloc] init];
return [self createOutput:nil];
}
-(NSObject<CSOutputWriterProtocol> *)createOutput:(NSString *)layoutName
{
self.layoutName = layoutName;
self.output = [[CSVirtualCameraOutput alloc] init];
self.output.deviceName = [self getServiceDestination];
self.output.persistDevice = self.persistDevice;
return self.output;
}
-(NSString *)getServiceDestination
{
return @"COCOASPLIT";
if (self.deviceName)
{
return self.deviceName;
}
if (self.layoutName)
{
return [NSString stringWithFormat:@"CocoaSplit - %@", self.layoutName];
}
return @"CocoaSplit VCam";
}
-(NSViewController *)getConfigurationView
{
CSVirtualCameraOutputViewController *configViewController;
configViewController = [[CSVirtualCameraOutputViewController alloc] initWithNibName:@"CSVirtualCameraOutputViewController" bundle:[NSBundle bundleForClass:self.class]];
configViewController.serviceObj = self;
return configViewController;
}

View file

@ -0,0 +1,19 @@
//
// CSVirtualCameraOutputViewController.h
// CSVirtualCameraOutput
//
// Created by Zakk on 5/16/20.
// Copyright © 2020 Zakk. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import "CSVirtualCameraOutputService.h"
NS_ASSUME_NONNULL_BEGIN
@interface CSVirtualCameraOutputViewController : NSViewController
@property (weak) CSVirtualCameraOutputService *serviceObj;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,22 @@
//
// CSVirtualCameraOutputViewController.m
// CSVirtualCameraOutput
//
// Created by Zakk on 5/16/20.
// Copyright © 2020 Zakk. All rights reserved.
//
#import "CSVirtualCameraOutputViewController.h"
@interface CSVirtualCameraOutputViewController ()
@end
@implementation CSVirtualCameraOutputViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
}
@end

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15505"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="CSVirtualCameraOutputViewController">
<connections>
<outlet property="view" destination="Hz6-mo-xeY" id="0bl-1N-x8E"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customView id="Hz6-mo-xeY">
<rect key="frame" x="0.0" y="0.0" width="480" height="272"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="xog-xk-Nf6">
<rect key="frame" x="18" y="234" width="90" height="16"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" lineBreakMode="clipping" title="Camera Name" id="7aA-Rb-fl7">
<font key="font" usesAppearanceFont="YES"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="V8o-P0-sOm">
<rect key="frame" x="114" y="231" width="132" height="21"/>
<autoresizingMask key="autoresizingMask"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" id="Oor-H9-ckR">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<connections>
<binding destination="nwA-xG-m6e" name="value" keyPath="selection.deviceName" id="EtI-IN-7b2"/>
</connections>
</textField>
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gqU-gi-tWj">
<rect key="frame" x="18" y="207" width="108" height="18"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="check" title="Persist on exit" bezelStyle="regularSquare" imagePosition="trailing" state="on" inset="2" id="eKG-XL-xsx">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<binding destination="nwA-xG-m6e" name="value" keyPath="selection.persistDevice" id="NQb-Pv-c3h"/>
</connections>
</button>
</subviews>
<point key="canvasLocation" x="140" y="154"/>
</customView>
<objectController id="nwA-xG-m6e">
<connections>
<binding destination="-2" name="contentObject" keyPath="self.serviceObj" id="jlu-iQ-kTU"/>
</connections>
</objectController>
</objects>
</document>