Added XPC based helper process to handle 32-bit Quicktime based sources. Should allow lots of capture cards/cams AND Camtwist to work

This commit is contained in:
Zakk 2012-11-13 05:39:54 -05:00
parent e391580c21
commit 5f47d464c4
17 changed files with 933 additions and 115 deletions

16
CapturedFrameProtocol.h Normal file
View file

@ -0,0 +1,16 @@
//
// CapturedFrameProtocol.h
// CocoaSplit
//
// Created by Zakk on 11/10/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol CapturedFrameProtocol
-(void) newCapturedFrame:(IOSurfaceID)ioxpc reply:(void (^)())reply;
@end

View file

@ -38,6 +38,15 @@
34792AF316103FF60065A859 /* DesktopCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 34792AF216103FF60065A859 /* DesktopCapture.m */; };
34792AF616104AA70065A859 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34792AF516104AA70065A859 /* IOKit.framework */; };
34792AFB1611A6B90065A859 /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34792AFA1611A6B90065A859 /* IOSurface.framework */; };
34AE3C30164E3E020052C95E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34AE3C2F164E3E020052C95E /* Foundation.framework */; };
34AE3C36164E3E020052C95E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 34AE3C34164E3E020052C95E /* InfoPlist.strings */; };
34AE3C39164E3E020052C95E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 34AE3C38164E3E020052C95E /* main.m */; };
34AE3C3F164E3F230052C95E /* zakk.lol.QTCaptureHelper.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = 34AE3C2E164E3E020052C95E /* zakk.lol.QTCaptureHelper.xpc */; };
34AE3C44164E410D0052C95E /* XPCListenerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 34AE3C43164E410D0052C95E /* XPCListenerDelegate.m */; };
34AE3C4B164E68820052C95E /* QTKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 340FE4E015F3581200E4CE4E /* QTKit.framework */; };
34AE3C6B164F04B30052C95E /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34AE3C6A164F04B30052C95E /* IOSurface.framework */; };
34AE3C6D164F04C90052C95E /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34AE3C6C164F04C90052C95E /* CoreVideo.framework */; };
34B74BC91648D23B00818DE2 /* QTCapture.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B74BC81648D23B00818DE2 /* QTCapture.m */; };
34C6C3BF15FB5B440018A18B /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34C6C3BE15FB5B440018A18B /* OpenGL.framework */; };
/* End PBXBuildFile section */
@ -49,6 +58,13 @@
remoteGlobalIDString = 340FE49C15F3417E00E4CE4E;
remoteInfo = CocoaSplit;
};
34AE3C40164E3FAD0052C95E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 340FE49415F3417E00E4CE4E /* Project object */;
proxyType = 1;
remoteGlobalIDString = 34AE3C2D164E3E020052C95E;
remoteInfo = QTCaptureHelper;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@ -62,6 +78,16 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
34AE3C3E164E3EAE0052C95E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = Contents/XPCServices;
dstSubfolderSpec = 1;
files = (
34AE3C3F164E3F230052C95E /* zakk.lol.QTCaptureHelper.xpc in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@ -112,6 +138,20 @@
34792AF216103FF60065A859 /* DesktopCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DesktopCapture.m; sourceTree = "<group>"; };
34792AF516104AA70065A859 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; };
34792AFA1611A6B90065A859 /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = System/Library/Frameworks/IOSurface.framework; sourceTree = SDKROOT; };
34AE3C2E164E3E020052C95E /* zakk.lol.QTCaptureHelper.xpc */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = zakk.lol.QTCaptureHelper.xpc; sourceTree = BUILT_PRODUCTS_DIR; };
34AE3C2F164E3E020052C95E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
34AE3C33164E3E020052C95E /* QTCaptureHelper-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "QTCaptureHelper-Info.plist"; sourceTree = "<group>"; };
34AE3C35164E3E020052C95E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
34AE3C37164E3E020052C95E /* QTCaptureHelper-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "QTCaptureHelper-Prefix.pch"; sourceTree = "<group>"; };
34AE3C38164E3E020052C95E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
34AE3C42164E410D0052C95E /* XPCListenerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPCListenerDelegate.h; sourceTree = "<group>"; };
34AE3C43164E410D0052C95E /* XPCListenerDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XPCListenerDelegate.m; sourceTree = "<group>"; };
34AE3C46164E560C0052C95E /* QTHelperProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QTHelperProtocol.h; sourceTree = "<group>"; };
34AE3C69164F01800052C95E /* CapturedFrameProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CapturedFrameProtocol.h; sourceTree = "<group>"; };
34AE3C6A164F04B30052C95E /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = ../../../../System/Library/Frameworks/IOSurface.framework; sourceTree = "<group>"; };
34AE3C6C164F04C90052C95E /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = ../../../../System/Library/Frameworks/CoreVideo.framework; sourceTree = "<group>"; };
34B74BC71648D23B00818DE2 /* QTCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = QTCapture.h; sourceTree = "<group>"; };
34B74BC81648D23B00818DE2 /* QTCapture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = QTCapture.m; sourceTree = "<group>"; };
34C6C3BE15FB5B440018A18B /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
@ -145,12 +185,26 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
34AE3C2B164E3E020052C95E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
34AE3C6D164F04C90052C95E /* CoreVideo.framework in Frameworks */,
34AE3C6B164F04B30052C95E /* IOSurface.framework in Frameworks */,
34AE3C4B164E68820052C95E /* QTKit.framework in Frameworks */,
34AE3C30164E3E020052C95E /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
340FE49215F3417E00E4CE4E = {
isa = PBXGroup;
children = (
34AE3C6C164F04C90052C95E /* CoreVideo.framework */,
34AE3C6A164F04B30052C95E /* IOSurface.framework */,
34AE3C45164E53D00052C95E /* XPCShared */,
34792AFA1611A6B90065A859 /* IOSurface.framework */,
34792AF516104AA70065A859 /* IOKit.framework */,
34C6C3BE15FB5B440018A18B /* OpenGL.framework */,
@ -160,6 +214,7 @@
340FE4E015F3581200E4CE4E /* QTKit.framework */,
340FE4A715F3417E00E4CE4E /* CocoaSplit */,
340FE4C415F3417E00E4CE4E /* CocoaSplitTests */,
34AE3C31164E3E020052C95E /* QTCaptureHelper */,
340FE4A015F3417E00E4CE4E /* Frameworks */,
340FE49E15F3417E00E4CE4E /* Products */,
);
@ -170,6 +225,7 @@
children = (
340FE49D15F3417E00E4CE4E /* CocoaSplit.app */,
340FE4BE15F3417E00E4CE4E /* CocoaSplitTests.octest */,
34AE3C2E164E3E020052C95E /* zakk.lol.QTCaptureHelper.xpc */,
);
name = Products;
sourceTree = "<group>";
@ -184,6 +240,7 @@
340FE4D815F346CC00E4CE4E /* AVFoundation.framework */,
340FE4A115F3417E00E4CE4E /* Cocoa.framework */,
340FE4BF15F3417E00E4CE4E /* SenTestingKit.framework */,
34AE3C2F164E3E020052C95E /* Foundation.framework */,
340FE4A315F3417E00E4CE4E /* Other Frameworks */,
);
name = Frameworks;
@ -212,6 +269,8 @@
342346D415FA301600C8C77E /* SyphonCapture.m */,
342346CD15F9F07E00C8C77E /* AbstractCaptureDevice.h */,
342346CE15F9F07E00C8C77E /* AbstractCaptureDevice.m */,
34B74BC71648D23B00818DE2 /* QTCapture.h */,
34B74BC81648D23B00818DE2 /* QTCapture.m */,
342346CC15F9D52000C8C77E /* CaptureSessionProtocol.h */,
342346BC15F6103D00C8C77E /* FFMpegTask.h */,
342346BD15F6103D00C8C77E /* FFMpegTask.m */,
@ -258,6 +317,36 @@
name = "Supporting Files";
sourceTree = "<group>";
};
34AE3C31164E3E020052C95E /* QTCaptureHelper */ = {
isa = PBXGroup;
children = (
34AE3C38164E3E020052C95E /* main.m */,
34AE3C42164E410D0052C95E /* XPCListenerDelegate.h */,
34AE3C43164E410D0052C95E /* XPCListenerDelegate.m */,
34AE3C32164E3E020052C95E /* Supporting Files */,
);
path = QTCaptureHelper;
sourceTree = "<group>";
};
34AE3C32164E3E020052C95E /* Supporting Files */ = {
isa = PBXGroup;
children = (
34AE3C33164E3E020052C95E /* QTCaptureHelper-Info.plist */,
34AE3C34164E3E020052C95E /* InfoPlist.strings */,
34AE3C37164E3E020052C95E /* QTCaptureHelper-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
34AE3C45164E53D00052C95E /* XPCShared */ = {
isa = PBXGroup;
children = (
34AE3C46164E560C0052C95E /* QTHelperProtocol.h */,
34AE3C69164F01800052C95E /* CapturedFrameProtocol.h */,
);
name = XPCShared;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -269,10 +358,12 @@
340FE49A15F3417E00E4CE4E /* Frameworks */,
340FE49B15F3417E00E4CE4E /* Resources */,
342346DC15FA34B400C8C77E /* CopyFiles */,
34AE3C3E164E3EAE0052C95E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
34AE3C41164E3FAD0052C95E /* PBXTargetDependency */,
);
name = CocoaSplit;
productName = CocoaSplit;
@ -298,6 +389,23 @@
productReference = 340FE4BE15F3417E00E4CE4E /* CocoaSplitTests.octest */;
productType = "com.apple.product-type.bundle";
};
34AE3C2D164E3E020052C95E /* QTCaptureHelper */ = {
isa = PBXNativeTarget;
buildConfigurationList = 34AE3C3C164E3E020052C95E /* Build configuration list for PBXNativeTarget "QTCaptureHelper" */;
buildPhases = (
34AE3C2A164E3E020052C95E /* Sources */,
34AE3C2B164E3E020052C95E /* Frameworks */,
34AE3C2C164E3E020052C95E /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = QTCaptureHelper;
productName = QTCaptureHelper;
productReference = 34AE3C2E164E3E020052C95E /* zakk.lol.QTCaptureHelper.xpc */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -321,6 +429,7 @@
targets = (
340FE49C15F3417E00E4CE4E /* CocoaSplit */,
340FE4BD15F3417E00E4CE4E /* CocoaSplitTests */,
34AE3C2D164E3E020052C95E /* QTCaptureHelper */,
);
};
/* End PBXProject section */
@ -346,6 +455,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
34AE3C2C164E3E020052C95E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
34AE3C36164E3E020052C95E /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@ -378,6 +495,7 @@
342346D515FA301600C8C77E /* SyphonCapture.m in Sources */,
34210B3E1606001200362FC8 /* OutputDestination.m in Sources */,
34792AF316103FF60065A859 /* DesktopCapture.m in Sources */,
34B74BC91648D23B00818DE2 /* QTCapture.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -389,6 +507,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
34AE3C2A164E3E020052C95E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
34AE3C39164E3E020052C95E /* main.m in Sources */,
34AE3C44164E410D0052C95E /* XPCListenerDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -397,6 +524,11 @@
target = 340FE49C15F3417E00E4CE4E /* CocoaSplit */;
targetProxy = 340FE4C215F3417E00E4CE4E /* PBXContainerItemProxy */;
};
34AE3C41164E3FAD0052C95E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 34AE3C2D164E3E020052C95E /* QTCaptureHelper */;
targetProxy = 34AE3C40164E3FAD0052C95E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@ -432,6 +564,14 @@
name = InfoPlist.strings;
sourceTree = "<group>";
};
34AE3C34164E3E020052C95E /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
34AE3C35164E3E020052C95E /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@ -555,6 +695,49 @@
};
name = Release;
};
34AE3C3A164E3E020052C95E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_EMPTY_BODY = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "QTCaptureHelper/QTCaptureHelper-Prefix.pch";
INFOPLIST_FILE = "QTCaptureHelper/QTCaptureHelper-Info.plist";
MACH_O_TYPE = mh_execute;
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_NAME = "zakk.lol.$(TARGET_NAME:rfc1034identifier)";
SDKROOT = "";
VALID_ARCHS = "i386 x86_64";
WRAPPER_EXTENSION = xpc;
};
name = Debug;
};
34AE3C3B164E3E020052C95E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = NO;
CLANG_WARN_EMPTY_BODY = YES;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "QTCaptureHelper/QTCaptureHelper-Prefix.pch";
INFOPLIST_FILE = "QTCaptureHelper/QTCaptureHelper-Info.plist";
MACH_O_TYPE = mh_execute;
MACOSX_DEPLOYMENT_TARGET = 10.8;
PRODUCT_NAME = "zakk.lol.$(TARGET_NAME:rfc1034identifier)";
SDKROOT = "";
VALID_ARCHS = "i386 x86_64";
WRAPPER_EXTENSION = xpc;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -585,6 +768,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
34AE3C3C164E3E020052C95E /* Build configuration list for PBXNativeTarget "QTCaptureHelper" */ = {
isa = XCConfigurationList;
buildConfigurations = (
34AE3C3A164E3E020052C95E /* Debug */,
34AE3C3B164E3E020052C95E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 340FE49415F3417E00E4CE4E /* Project object */;

View file

@ -59,7 +59,7 @@
for(devinstance in devices)
{
NSLog(@"Inputs %@", devinstance.linkedDevices);
[retArray addObject:[[AbstractCaptureDevice alloc] initWithName:[devinstance localizedName] device:devinstance uniqueID:devinstance.uniqueID]];
}

View file

@ -10,6 +10,7 @@
#import <AVFoundation/AVFoundation.h>
#import <VideoToolbox/VideoToolbox.h>
#import "AVFCapture.h"
#import "QTCapture.h"
#import <CoreMedia/CoreMedia.h>
#import "FFMpegTask.h"
#import "CaptureSessionProtocol.h"

View file

@ -30,12 +30,12 @@
self.streamingDestination = nil;
if ([self.selectedDestinationType isEqualToString:@"file"])
{
//if ([self.selectedDestinationType isEqualToString:@"file"])
//{
panelName = @"FilePanel";
} else {
panelName = @"StreamServicePanel";
}
//} else {
// panelName = @"StreamServicePanel";
//}
[NSBundle loadNibNamed:panelName owner:self];
}
@ -106,6 +106,8 @@
_video_capture_session = [[DesktopCapture alloc ] init];
} else if ([selectedVideoType isEqualToString:@"AVFoundation"]) {
_video_capture_session = [[AVFCapture alloc] init];
} else if ([selectedVideoType isEqualToString:@"QTCapture"]) {
_video_capture_session = [[QTCapture alloc] init];
} else {
_video_capture_session = nil;
}
@ -150,8 +152,9 @@
@"rtmp" : @"RTMP Stream"};
self.videoTypes = @[@"Desktop", @"AVFoundation"];
self.videoTypes = @[@"Desktop", @"AVFoundation", @"QTCapture"];
self.selectedVideoType = [self.videoTypes objectAtIndex:0];
}
return self;

View file

@ -150,8 +150,12 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size)
AVOutputFormat *av_out_fmt;
if (_stream_format) {
avformat_alloc_output_context2(&_av_fmt_ctx, NULL, [_stream_format UTF8String], [_stream_output UTF8String]);
} else {
avformat_alloc_output_context2(&_av_fmt_ctx, NULL, NULL, [_stream_output UTF8String]);
}
avformat_alloc_output_context2(&_av_fmt_ctx, NULL, [_stream_format UTF8String], [_stream_output UTF8String]);
if (!_av_fmt_ctx)
{
NSLog(@"No av_fmt_ctx");
@ -171,7 +175,6 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size)
AVCodecContext *c_ctx = _av_video_stream->codec;
c_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
c_ctx->codec_id = AV_CODEC_ID_H264;
c_ctx->width = _width;
@ -198,6 +201,7 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size)
a_ctx->channels = 2;
a_ctx->extradata = (unsigned char *)_audio_extradata;
a_ctx->extradata_size = (int)_audio_extradata_size;
a_ctx->frame_size = (_samplerate * 2 * 2) / _framerate;
CMFormatDescriptionRef fmt;

View file

@ -51,6 +51,7 @@
if (_destination)
return _destination;
if ([_type_name isEqualToString:@"rtmp"])
{
_destination = [NSString stringWithFormat:@"%@/%@", self.server_name, self.stream_key];
@ -66,6 +67,10 @@
{
NSLog(@"Destination set to %@", destination);
if ([destination hasPrefix:@"rtmp://"])
{
self.output_format = @"FLV";
}
_destination = destination;
}
@ -74,13 +79,8 @@
{
if (self = [super init])
{
self.output_format = @"FLV";
//self.output_format = @"FLV";
self.type_name = type;
if ([type isEqualToString:@"twitchtv"])
{
self.output_format = @"FLV";
self.name = @"Twitch.TV";
}
}
return self;

36
CocoaSplit/QTCapture.h Normal file
View file

@ -0,0 +1,36 @@
//
// QTCapture.h
// CocoaSplit
//
// Created by Zakk on 11/6/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <VideoToolbox/VideoToolbox.h>
#import <QTKit/QTKit.h>
#import "CaptureSessionProtocol.h"
#import "CapturedFrameProtocol.h"
#import "QTHelperProtocol.h"
@interface QTCapture : NSObject <CaptureSessionProtocol, CapturedFrameProtocol>
{
NSXPCConnection *_xpcConnection;
id <QTHelperProtocol> _xpcProxy;
IOSurfaceRef _currentFrame;
}
@property (strong) id videoInputDevice;
@property (strong) id videoDelegate;
@property (assign) int videoCaptureFPS;
-(bool) startCaptureSession:(NSError **)error;
-(bool) stopCaptureSession;
@end

330
CocoaSplit/QTCapture.m Normal file
View file

@ -0,0 +1,330 @@
//
// QTCapture.m
// CocoaSplit
//
// Created by Zakk on 11/6/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#import "QTCapture.h"
#import "AbstractCaptureDevice.h"
#import "QTHelperProtocol.h"
#import "CapturedFrameProtocol.h"
@implementation QTCapture
-(id) init
{
self = [super init];
if (self)
{
NSXPCInterface *xpcInterface = [NSXPCInterface interfaceWithProtocol:@protocol(QTHelperProtocol)];
NSXPCInterface *xpcCallbackInterface = [NSXPCInterface interfaceWithProtocol:@protocol(CapturedFrameProtocol)];
_xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"zakk.lol.QTCaptureHelper"];
[_xpcConnection setRemoteObjectInterface:xpcInterface];
[_xpcConnection setExportedInterface:xpcCallbackInterface];
[_xpcConnection setExportedObject:self];
NSLog(@"SETUP CONNECTION TO LISTENER");
[_xpcConnection resume];
_xpcProxy = [_xpcConnection remoteObjectProxy];
NSLog(@"GOT PROXY OBJECT");
}
return self;
}
-(void) setVideoDimensions:(int)width height:(int)height
{
return;
}
-(bool) providesVideo
{
return YES;
}
-(bool) providesAudio
{
return NO;
}
-(bool) setActiveVideoDevice:(AbstractCaptureDevice *)newDev
{
NSLog(@"SET VIDEO DEVICE TO %@", [newDev uniqueID]);
_videoInputDevice = [newDev uniqueID];
return YES;
}
-(NSArray *) availableVideoDevices
{
dispatch_semaphore_t reply_s = dispatch_semaphore_create(0);
NSMutableArray *__block retArray;
NSLog(@"PROXY %@", _xpcProxy);
NSLog(@"CONNECTION %@", _xpcConnection);
[_xpcProxy testMethod];
NSLog(@"CALLED TEST METHOD FROM SPLIT");
[_xpcProxy listCaptureDevices:^(NSArray *r_devices) {
NSLog(@"REMOTE DEVICES %@", r_devices);
retArray = [[NSMutableArray alloc] init];
NSDictionary *devinstance;
for (devinstance in r_devices)
{
[retArray addObject:[[AbstractCaptureDevice alloc] initWithName:[devinstance valueForKey:@"name"] device:[devinstance valueForKey:@"id"] uniqueID:[devinstance valueForKey:@"id"]]];
}
dispatch_semaphore_signal(reply_s);
}];
NSLog(@"SEMAPHORE WAIT");
dispatch_semaphore_wait(reply_s, DISPATCH_TIME_FOREVER);
reply_s = nil;
return (NSArray *)retArray;
}
-(void) newCapturedFrame:(IOSurfaceID)ioxpc reply:(void (^)())reply
{
IOSurfaceRef frameIOref = IOSurfaceLookup(ioxpc);
if (frameIOref)
{
@synchronized(self) {
if (_currentFrame)
{
IOSurfaceDecrementUseCount(_currentFrame);
//CFRelease(_currentFrame);
}
_currentFrame = frameIOref;
IOSurfaceIncrementUseCount(_currentFrame);
//CFRetain(_currentFrame);
}
}
// ALWAYS reply
reply();
}
-(bool) stopCaptureSession
{
[_xpcProxy stopXPCCaptureSession];
return YES;
}
-(bool) startCaptureSession:(NSError **)error
{
NSLog(@"CALLING STARTXPC WITH %@", _videoInputDevice);
[_xpcProxy startXPCCaptureSession:_videoInputDevice];
return YES;
}
-(bool) setupCaptureSession:(NSError *__autoreleasing *)therror
{
return YES;
}
/*
-(bool) setupCaptureSession:(NSError **)therror
{
AVCaptureDeviceInput *video_capture_input;
AVCaptureDeviceInput *audio_capture_input;
if (_capture_session)
return YES;
NSLog(@"Starting setup capture");
if (_videoDelegate || _audioDelegate)
{
_capture_session = [[AVCaptureSession alloc] init];
}
if (_videoDelegate)
{
if (!_videoInputDevice)
{
NSLog(@"No video input device");
*therror = [NSError errorWithDomain:@"videoCapture" code:100 userInfo:@{NSLocalizedDescriptionKey : @"Must select video capture device first"}];
return NO;
}
_capture_session = [[AVCaptureSession alloc] init];
video_capture_input = [AVCaptureDeviceInput deviceInputWithDevice:_videoInputDevice error:therror];
if (!video_capture_input)
{
NSLog(@"No video capture input?");
return NO;
}
if ([_capture_session canAddInput:video_capture_input])
{
[_capture_session addInput:video_capture_input];
} else {
NSLog(@"Can't add video_capture_input");
*therror = [NSError errorWithDomain:@"videoCapture" code:120 userInfo:@{NSLocalizedDescriptionKey : @"Could not add video input to capture session"}];
return NO;
}
_video_capture_output = [[AVCaptureVideoDataOutput alloc] init];
if ([_capture_session canAddOutput:_video_capture_output])
{
[_capture_session addOutput:_video_capture_output];
} else {
NSLog(@"Can't add video capture output");
*therror = [NSError errorWithDomain:@"videoCapture" code:130 userInfo:@{NSLocalizedDescriptionKey : @"Could not add video output to capture session"}];
return NO;
}
}
if (_audioDelegate)
{
if (_audioInputDevice)
{
audio_capture_input = [AVCaptureDeviceInput deviceInputWithDevice:_audioInputDevice error:therror];
if (!audio_capture_input)
{
NSLog(@"No audio capture input?");
return NO;
}
if ([_capture_session canAddInput:audio_capture_input])
{
[_capture_session addInput:audio_capture_input];
} else {
NSLog(@"Can't add audio input?");
*therror = [NSError errorWithDomain:@"audioCapture" code:220 userInfo:@{NSLocalizedDescriptionKey : @"Could not add audio input to capture session"}];
return NO;
}
_audio_capture_output = [[AVCaptureAudioDataOutput alloc] init];
_audio_capture_output.audioSettings = @{AVFormatIDKey: [NSNumber numberWithInt:kAudioFormatMPEG4AAC],
AVSampleRateKey: [NSNumber numberWithFloat: 44100.0],
AVEncoderBitRateKey: [NSNumber numberWithInt:_audioBitrate*1000 ],
AVNumberOfChannelsKey: @2
};
if ([_capture_session canAddOutput:_audio_capture_output])
{
[_capture_session addOutput:_audio_capture_output];
} else {
NSLog(@"Can't add audio capture output");
*therror = [NSError errorWithDomain:@"audioCapture" code:230 userInfo:@{NSLocalizedDescriptionKey : @"Could not add audio output to capture session"}];
return NO;
}
} else {
NSLog(@"No audio device?");
*therror = [NSError errorWithDomain:@"audioCapture" code:240 userInfo:@{NSLocalizedDescriptionKey : @"Must select audio capture device first"}];
return NO;
}
}
return YES;
}
*/
void QTPixelBufferRelease(void *releaseRefCon, const void *baseAddress)
{
if (baseAddress)
free((void *)baseAddress);
}
- (CVImageBufferRef) getCurrentFrame
{
CVImageBufferRef newbuf = NULL;
@synchronized(self)
{
if (_currentFrame)
{
CVPixelBufferCreateWithIOSurface(NULL, _currentFrame, NULL, &newbuf);
return newbuf;
}
}
return newbuf;
}
/*
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
if (connection.output == _video_capture_output)
{
CVImageBufferRef videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer);
@synchronized(self)
{
if (_currentFrame)
{
CVPixelBufferRelease(_currentFrame);
}
CVPixelBufferRetain(videoFrame);
_currentFrame = videoFrame;
}
} else if (connection.output == _audio_capture_output) {
[_audioDelegate captureOutputAudio:self didOutputSampleBuffer:sampleBuffer];
}
}
*/
@end

View file

@ -1321,7 +1321,7 @@
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="439893737">
<nil key="NSNextResponder"/>
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSButton" id="389308716">
@ -1329,6 +1329,7 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{250, 25}, {82, 32}}</string>
<reference key="NSSuperview" ref="439893737"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="454886443">
@ -1357,12 +1358,13 @@
<int key="NSvFlags">12</int>
<string key="NSFrame">{{-1, 53}, {584, 329}}</string>
<reference key="NSSuperview" ref="439893737"/>
<reference key="NSNextKeyView" ref="107286857"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<array class="NSMutableArray" key="NSTabViewItems">
<object class="NSTabViewItem" id="302448651">
<string key="NSIdentifier">1</string>
<object class="NSView" key="NSView" id="460084472">
<reference key="NSNextResponder" ref="569688021"/>
<nil key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSPopUpButton" id="889564284">
@ -1911,7 +1913,6 @@
</object>
</array>
<string key="NSFrame">{{10, 33}, {564, 283}}</string>
<reference key="NSSuperview" ref="569688021"/>
<reference key="NSNextKeyView" ref="321001671"/>
<string key="NSReuseIdentifierKey">_NS:11</string>
</object>
@ -2177,7 +2178,7 @@
<object class="NSTabViewItem" id="155388920">
<string key="NSIdentifier">2</string>
<object class="NSView" key="NSView" id="107286857">
<nil key="NSNextResponder"/>
<reference key="NSNextResponder" ref="569688021"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSScrollView" id="710299427">
@ -2194,7 +2195,7 @@
<array class="NSMutableArray" key="NSSubviews"/>
<string key="NSFrameSize">{478, 190}</string>
<reference key="NSSuperview" ref="842508660"/>
<reference key="NSNextKeyView" ref="598397452"/>
<reference key="NSNextKeyView" ref="548143049"/>
<string key="NSReuseIdentifierKey">_NS:13</string>
<bool key="NSEnabled">YES</bool>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
@ -2208,11 +2209,10 @@
<string key="NSReuseIdentifierKey">_NS:16</string>
<reference key="NSTableView" ref="953940268"/>
</object>
<object class="_NSCornerView" key="NSCornerView" id="1050868349">
<reference key="NSNextResponder" ref="710299427"/>
<object class="_NSCornerView" key="NSCornerView">
<nil key="NSNextResponder"/>
<int key="NSvFlags">-2147483392</int>
<string key="NSFrame">{{224, 0}, {16, 17}}</string>
<reference key="NSSuperview" ref="710299427"/>
<string key="NSReuseIdentifierKey">_NS:19</string>
</object>
<array class="NSMutableArray" key="NSTableColumns">
@ -2388,11 +2388,10 @@
<reference key="NSBGColor" ref="574509101"/>
<int key="NScvFlags">4</int>
</object>
<reference ref="1050868349"/>
</array>
<string key="NSFrame">{{42, 31}, {480, 208}}</string>
<reference key="NSSuperview" ref="107286857"/>
<reference key="NSNextKeyView" ref="842508660"/>
<reference key="NSNextKeyView" ref="598397452"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<string key="NSAntiCompressionPriority">{750, 750}</string>
<int key="NSsFlags">133682</int>
@ -2524,6 +2523,7 @@
</object>
</array>
<string key="NSFrame">{{10, 33}, {564, 283}}</string>
<reference key="NSSuperview" ref="569688021"/>
<reference key="NSNextKeyView" ref="449329695"/>
<string key="NSReuseIdentifierKey">_NS:28</string>
</object>
@ -2532,20 +2532,21 @@
<reference key="NSTabView" ref="569688021"/>
</object>
</array>
<reference key="NSSelectedTabViewItem" ref="302448651"/>
<reference key="NSSelectedTabViewItem" ref="155388920"/>
<reference key="NSFont" ref="582680700"/>
<int key="NSTvFlags">0</int>
<bool key="NSAllowTruncatedLabels">YES</bool>
<bool key="NSDrawsBackground">YES</bool>
<array class="NSMutableArray" key="NSSubviews">
<reference ref="460084472"/>
<reference ref="107286857"/>
</array>
</object>
</array>
<string key="NSFrameSize">{582, 388}</string>
<reference key="NSSuperview"/>
<reference key="NSNextKeyView" ref="569688021"/>
</object>
<string key="NSScreenRect">{{0, 0}, {1920, 1058}}</string>
<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<bool key="NSWindowIsRestorable">YES</bool>
</object>
@ -7335,93 +7336,7 @@
<nil key="sourceID"/>
<int key="maxID">1844</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">AppDelegate</string>
<string key="superclassName">NSObject</string>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="captureController">CaptureController</string>
<string key="window">NSWindow</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="captureController">
<string key="name">captureController</string>
<string key="candidateClassName">CaptureController</string>
</object>
<object class="IBToOneOutletInfo" key="window">
<string key="name">window</string>
<string key="candidateClassName">NSWindow</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/AppDelegate.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">CaptureController</string>
<string key="superclassName">NSObject</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="addStreamingService:">id</string>
<string key="closeCreateSheet:">id</string>
<string key="openCreateSheet:">id</string>
<string key="removeDestination:">id</string>
<string key="streamButtonPushed:">id</string>
<string key="videoRefresh:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="addStreamingService:">
<string key="name">addStreamingService:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="closeCreateSheet:">
<string key="name">closeCreateSheet:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="openCreateSheet:">
<string key="name">openCreateSheet:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="removeDestination:">
<string key="name">removeDestination:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="streamButtonPushed:">
<string key="name">streamButtonPushed:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="videoRefresh:">
<string key="name">videoRefresh:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">createSheet</string>
<string key="NS.object.0">NSWindow</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">createSheet</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">createSheet</string>
<string key="candidateClassName">NSWindow</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/CaptureController.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
</array>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2012 Zakk. All rights reserved.</string>
<key>LSBackgroundOnly</key>
<true/>
<key>XPCService</key>
<dict>
<key>RunLoopType</key>
<string>NSRunLoop</string>
<key>ServiceType</key>
<string>Application</string>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,4 @@
//
// Prefix header for all source files of the 'QTCaptureHelper' target in the 'QTCaptureHelper' project
//

View file

@ -0,0 +1,35 @@
//
// XPCListenerDelegate.h
// CocoaSplit
//
// Created by Zakk on 11/10/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "QTHelperProtocol.h"
#import "CapturedFrameProtocol.h"
#import <QTKit/QTKit.h>
@interface XPCListenerDelegate : NSObject <NSXPCListenerDelegate, QTHelperProtocol>
{
QTCaptureDevice *captureDevice;
QTCaptureSession *captureSession;
QTCaptureDeviceInput *captureInput;
QTCaptureDecompressedVideoOutput *captureOutput;
id <CapturedFrameProtocol> xpcProxy;
dispatch_queue_t frameQueue;
}
@property (strong) QTCaptureDevice *captureDevice;
@property (strong) QTCaptureSession *captureSession;
@property (strong) QTCaptureDeviceInput *captureInput;
@property (strong) QTCaptureDecompressedVideoOutput *captureOutput;
@property (strong) id xpcProxy;
- (BOOL) listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection;
@end

View file

@ -0,0 +1,198 @@
//
// XPCListenerDelegate.m
// CocoaSplit
//
// Created by Zakk on 11/10/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#import "XPCListenerDelegate.h"
#import "QTHelperProtocol.h"
#import <QTKit/QTKit.h>
#import <IOSurface/IOSurfaceAPI.h>
#import <CoreVideo/CoreVideo.h>
#import <QuickTime/QuickTime.h>
@implementation XPCListenerDelegate
@synthesize captureDevice;
@synthesize captureSession;
@synthesize captureInput;
@synthesize captureOutput;
@synthesize xpcProxy;
- (void) dealloc
{
if (self.xpcProxy)
{
[self.xpcProxy release];
}
[super dealloc];
}
- (BOOL) listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection
{
NSXPCInterface *helperInterface = [[NSXPCInterface interfaceWithProtocol:@protocol(QTHelperProtocol)] retain];
NSXPCInterface *masterInterface = [[NSXPCInterface interfaceWithProtocol:@protocol(CapturedFrameProtocol)] retain];
[newConnection setExportedInterface:helperInterface];
[newConnection setExportedObject:self];
[newConnection setRemoteObjectInterface:masterInterface];
self.xpcProxy = [newConnection remoteObjectProxy];
[self.xpcProxy retain];
[newConnection resume];
[helperInterface release];
[masterInterface release];
return YES;
}
- (void) listCaptureDevices:(void (^)(NSArray *r_devices))reply
{
NSArray *devices = [QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo];
NSMutableArray *retArray = [[NSMutableArray alloc] init];
QTCaptureDevice *devinstance;
for(devinstance in devices)
{
[retArray addObject: @{@"name" : [devinstance localizedDisplayName], @"id":devinstance.uniqueID}];
}
[devices release];
reply((NSArray *)retArray);
[retArray release];
}
- (void) stopXPCCaptureSession
{
if (self.captureSession)
{
[self.captureSession stopRunning];
[self.captureSession release];
}
if (self.captureDevice)
{
[self.captureDevice close];
[self.captureDevice release];
}
if (self.captureInput)
{
[self.captureInput release];
}
if (self.captureOutput)
{
[self.captureOutput release];
}
if (frameQueue)
{
dispatch_release(frameQueue);
}
}
- (void) startXPCCaptureSession:(NSString *)captureID
{
frameQueue = dispatch_queue_create("zakk.lol.frameQueue", NULL);
self.captureSession = [[[QTCaptureSession alloc] init] retain];
self.captureDevice = [[QTCaptureDevice deviceWithUniqueID:captureID] retain];
[self.captureDevice open:nil];
self.captureInput = [[[QTCaptureDeviceInput alloc] initWithDevice:self.captureDevice] retain];
NSError *error;
[self.captureSession addInput:self.captureInput error:&error];
self.captureOutput = [[[QTCaptureDecompressedVideoOutput alloc] init] retain];
NSDictionary *ioAttrs = [NSDictionary dictionaryWithObject: [NSNumber numberWithBool: YES]
forKey: (NSString *)kIOSurfaceIsGlobal];
NSMutableDictionary *pbAttrs = [NSMutableDictionary dictionaryWithObject:ioAttrs
forKey: (NSString*)kCVPixelBufferIOSurfacePropertiesKey];
[pbAttrs setObject:
[NSNumber numberWithInt:kCVPixelFormatType_422YpCbCr8]
forKey:(NSString *)kCVPixelBufferPixelFormatTypeKey];
[self.captureOutput setPixelBufferAttributes:pbAttrs];
[self.captureOutput setDelegate:self];
[self.captureSession addOutput:self.captureOutput error:nil];
[self.captureSession startRunning];
}
- (void) sendFrame:(CVImageBufferRef)newFrame
{
if (newFrame)
{
dispatch_semaphore_t reply_s = dispatch_semaphore_create(0);
IOSurfaceRef frameIOSurface = CVPixelBufferGetIOSurface(newFrame);
IOSurfaceID frameID = IOSurfaceGetID(frameIOSurface);
[self.xpcProxy newCapturedFrame:frameID reply:^{
dispatch_semaphore_signal(reply_s);
}];
dispatch_semaphore_wait(reply_s, DISPATCH_TIME_FOREVER);
CVPixelBufferRelease(newFrame);
dispatch_release(reply_s);
}
}
- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection *)connection
{
CVPixelBufferRetain(videoFrame);
dispatch_async(frameQueue, ^{
[self sendFrame:videoFrame];
});
//IOSurfaceIncrementUseCount(frameIORef);
//[self.xpcProxy newCapturedFrame:IOSurfaceCreateXPCObject(frameIORef)];
//mach_port_deallocate(mach_task_self(), framePort);
//CVPixelBufferRelease(videoFrame);
}
- (void) testMethod
{
NSLog(@"CALLED TEST METHOD");
return;
}
@end

View file

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

28
QTCaptureHelper/main.m Normal file
View file

@ -0,0 +1,28 @@
//
// main.m
// QTCaptureHelper
//
// Created by Zakk on 11/10/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#include <Foundation/Foundation.h>
#import "XPCListenerDelegate.h"
int main(int argc, const char *argv[])
{
XPCListenerDelegate *listenDelegate = [[XPCListenerDelegate new] retain];
NSLog(@"LISTEN DELEGATE %@", listenDelegate);
NSXPCListener *listener = [[NSXPCListener serviceListener] retain];
//NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
//NSXPCListener *listener = [[NSXPCListener alloc] initWithMachServiceName:bundleId];
NSLog(@"LISTENER %@", listener);
listener.delegate = listenDelegate;
[listener resume];
NSLog(@"SETUP XPC LISTENER");
exit(EXIT_FAILURE);
}

19
QTHelperProtocol.h Normal file
View file

@ -0,0 +1,19 @@
//
// QTHelperProtocol.h
// CocoaSplit
//
// Created by Zakk on 11/10/12.
// Copyright (c) 2012 Zakk. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol QTHelperProtocol
- (void)listCaptureDevices:(void (^)(NSArray *r_devices))reply;
- (void)startXPCCaptureSession:(NSString *)captureID;
- (void)stopXPCCaptureSession;
- (void)testMethod;
@end