diff --git a/CapturePlugins/CSAVFCapturePlugin/CSAVFCapturePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSAVFCapturePlugin.xcscheme b/CapturePlugins/CSAVFCapturePlugin/CSAVFCapturePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSAVFCapturePlugin.xcscheme index 09ca5b04..4dba6543 100644 --- a/CapturePlugins/CSAVFCapturePlugin/CSAVFCapturePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSAVFCapturePlugin.xcscheme +++ b/CapturePlugins/CSAVFCapturePlugin/CSAVFCapturePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSAVFCapturePlugin.xcscheme @@ -1,6 +1,6 @@ defaultCompressor = self.compressors[@"default"]; + id defaultCompressor = self.compressors[@"default"]; if (defaultCompressor) { [self.compressors removeObjectForKey:@"default"]; @@ -1174,6 +1174,16 @@ self.compressors[@"AppleVT"] = newCompressor; [[NSNotificationCenter defaultCenter] postNotificationName:CSNotificationCompressorAdded object:newCompressor]; } + + if (!self.compressors[@"AppleProRes"]) + { + AppleProResCompressor *newCompressor = [[AppleProResCompressor alloc] init]; + newCompressor.name = @"AppleProRes".mutableCopy; + self.compressors[@"AppleProRes"] = newCompressor; + [[NSNotificationCenter defaultCenter] postNotificationName:CSNotificationCompressorAdded object:newCompressor]; + + + } } @@ -1599,7 +1609,7 @@ for (id cKey in self.compressors) { - id tmpcomp = self.compressors[cKey]; + id tmpcomp = self.compressors[cKey]; tmpcomp.settingsController = self; } @@ -1698,7 +1708,7 @@ for (id cKey in self.compressors) { - id ctmp = self.compressors[cKey]; + id ctmp = self.compressors[cKey]; if (ctmp) { [ctmp reset]; @@ -1796,7 +1806,7 @@ for(id cKey in self.compressors) { - id compressor; + id compressor; compressor = self.compressors[cKey]; [compressor addAudioData:sampleBuffer]; @@ -2191,7 +2201,7 @@ newFrameData.frameTime = _frame_time; newFrameData.videoFrame = videoFrame; - id compressor; + id compressor; compressor = self.compressors[cKey]; [compressor compressFrame:newFrameData]; diff --git a/CocoaSplit/Compressor/AppleProResCompressor.h b/CocoaSplit/Compressor/AppleProResCompressor.h new file mode 100644 index 00000000..fc39314f --- /dev/null +++ b/CocoaSplit/Compressor/AppleProResCompressor.h @@ -0,0 +1,33 @@ +// +// AppleProResCompressor.h +// CocoaSplit +// +// Created by Zakk on 3/27/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import +#import "CaptureController.h" +#import "CompressorBase.h" + +#import +#import + +@interface AppleProResCompressor : CompressorBase +{ + + VTCompressionSessionRef _compression_session; + VTPixelTransferSessionRef _vtpt_ref; + +} + + +//@property (strong) id settingsController; +//@property (strong) id outputDelegate; + +@property (strong) NSNumber *proResType; + + +-(bool)compressFrame:(CapturedFrameData *)frameData; + +@end diff --git a/CocoaSplit/Compressor/AppleProResCompressor.m b/CocoaSplit/Compressor/AppleProResCompressor.m new file mode 100644 index 00000000..7d3d05fa --- /dev/null +++ b/CocoaSplit/Compressor/AppleProResCompressor.m @@ -0,0 +1,315 @@ +// +// AppleProResCompressor.m +// CocoaSplit +// +// Created by Zakk on 3/27/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import "AppleProResCompressor.h" +#import "OutputDestination.h" +#import "CSAppleProResCompressorViewController.h" + +@implementation AppleProResCompressor + +- (id)copyWithZone:(NSZone *)zone +{ + AppleProResCompressor *copy = [[[self class] allocWithZone:zone] init]; + + copy.settingsController = self.settingsController; + + copy.isNew = self.isNew; + + copy.name = self.name; + + copy.compressorType = self.compressorType; + + copy.width = self.width; + copy.height = self.height; + copy.working_width = self.width; + copy.working_height = self.height; + + copy.resolutionOption = self.resolutionOption; + + copy.proResType = self.proResType; + + return copy; +} + + +-(void) encodeWithCoder:(NSCoder *)aCoder +{ + + + [aCoder encodeObject:self.name forKey:@"name"]; + [aCoder encodeInteger:self.width forKey:@"videoWidth"]; + [aCoder encodeInteger:self.height forKey:@"videoHeight"]; + + [aCoder encodeObject:self.resolutionOption forKey:@"resolutionOption"]; + [aCoder encodeObject:self.proResType forKey:@"proResType"]; + +} + +-(id) initWithCoder:(NSCoder *)aDecoder +{ + if (self = [self init]) + { + self.name = [aDecoder decodeObjectForKey:@"name"]; + self.width = (int)[aDecoder decodeIntegerForKey:@"videoWidth"]; + self.height = (int)[aDecoder decodeIntegerForKey:@"videoHeight"]; + if ([aDecoder containsValueForKey:@"resolutionOption"]) + { + self.resolutionOption = [aDecoder decodeObjectForKey:@"resolutionOption"]; + } + + self.proResType = [aDecoder decodeObjectForKey:@"proResType"]; + + if (!self.proResType) + { + self.proResType = @(kCMVideoCodecType_AppleProRes422); + + } + + } + + return self; +} + + +-(id)init +{ + if (self = [super init]) + { + + + + self.compressorType = @"AppleProResCompressor"; + self.codec_id = AV_CODEC_ID_PRORES; + self.proResType = @(kCMVideoCodecType_AppleProRes422); + } + + return self; +} + + +-(void) reset +{ + + + self.errored = NO; + VTCompressionSessionInvalidate(_compression_session); + if (_compression_session) + { + CFRelease(_compression_session); + } + + _compression_session = nil; + +} + + + +- (void) dealloc +{ + [self reset]; +} + + + +-(NSString *)description +{ + + return @"Apple ProRes Compressor"; + +} + + +void __ProResPixelBufferRelease( void *releaseRefCon, const void *baseAddress ) +{ + free((int *)baseAddress); +} + + + +-(bool)compressFrame:(CapturedFrameData *)frameData +{ + + + if (![self hasOutputs]) + { + return NO; + } + + if (!_compression_session) + { + + if (![self setupCompressor:frameData.videoFrame]) + { + return NO; + } + return NO; + } + + + + CFMutableDictionaryRef frameProperties; + + /* + if (isKeyFrame) + { + + frameProperties = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(frameProperties, kVTEncodeFrameOptionKey_ForceKeyFrame, kCFBooleanTrue); + } else { + */ + frameProperties = NULL; + //} + + if (!_vtpt_ref) + { + VTPixelTransferSessionCreate(kCFAllocatorDefault, &_vtpt_ref); + VTSessionSetProperty(_vtpt_ref, kVTPixelTransferPropertyKey_ScalingMode, kVTScalingMode_Letterbox); + } + CVPixelBufferRef converted_frame; + + CVImageBufferRef imageBuffer = frameData.videoFrame; + CVPixelBufferRetain(imageBuffer); + + CVPixelBufferCreate(kCFAllocatorDefault, self.working_width, self.working_height, kCVPixelFormatType_420YpCbCr8Planar, 0, &converted_frame); + + VTPixelTransferSessionTransferImage(_vtpt_ref, imageBuffer, converted_frame); + + //set it to nil since this is our private copy and this will force the frameData instance to release the video data + + frameData.videoFrame = nil; + frameData.encoderData = converted_frame; + + + CVPixelBufferRelease(imageBuffer); + + [self setAudioData:frameData syncObj:self]; + + VTCompressionSessionEncodeFrame(_compression_session, converted_frame, frameData.videoPTS, frameData.videoDuration, frameProperties, (__bridge_retained void *)(frameData), NULL); + + if (frameProperties) + { + CFRelease(frameProperties); + } + + + return YES; +} + + + + +- (bool)setupCompressor:(CVPixelBufferRef)videoFrame +{ + OSStatus status; + + if (!self.settingsController) + { + return NO; + } + + [self setupResolution:videoFrame]; + + if (!self.working_height || !self.working_width) + { + self.errored = YES; + return NO; + } + + NSDictionary *encoderSpec = @{ + }; + + _compression_session = NULL; + NSLog(@"PRORES TYPE %@", self.proResType); + + status = VTCompressionSessionCreate(NULL, self.working_width, self.working_height, self.proResType.intValue, (__bridge CFDictionaryRef)encoderSpec, NULL, NULL, __ProResVideoCompressorReceiveFrame, (__bridge void *)self, &_compression_session); + + //CFDictionaryRef props; + //VTCompressionSessionCopySupportedPropertyDictionary(_compression_session, &props); + + if (status != noErr || !_compression_session) + { + NSLog(@"COMPRESSOR SETUP ERROR"); + self.errored = YES; + return NO; + } + + _audioBuffer = [[NSMutableArray alloc] init]; + return YES; + +} + + +void __ProResVideoCompressorReceiveFrame(void *VTref, void *VTFrameRef, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) +{ + + /* + if (VTFrameRef) + { + CVPixelBufferRelease(VTFrameRef); + } + */ + + + //@autoreleasepool { + + + + if(!sampleBuffer) + return; + + + + CFRetain(sampleBuffer); + + CapturedFrameData *frameData; + + + frameData = (__bridge_transfer CapturedFrameData *)(VTFrameRef); + + + if (!frameData) + { + //What? + return; + } + + + CVPixelBufferRelease(frameData.encoderData); + + + //frameData.videoFrame = nil; + frameData.encodedSampleBuffer = sampleBuffer; + + + AppleVTCompressor *selfobj = (__bridge AppleVTCompressor *)VTref; + + + + + for (id dKey in selfobj.outputs) + { + + OutputDestination *dest = selfobj.outputs[dKey]; + + [dest writeEncodedData:frameData]; + + + } + + + CFRelease(sampleBuffer); + //} +} + +-(id )getConfigurationView +{ + return [[CSAppleProResCompressorViewController alloc] init]; +} + + +@end diff --git a/CocoaSplit/Compressor/AppleVTCompressor.h b/CocoaSplit/Compressor/AppleVTCompressor.h index 0a213882..28c7319d 100644 --- a/CocoaSplit/Compressor/AppleVTCompressor.h +++ b/CocoaSplit/Compressor/AppleVTCompressor.h @@ -13,7 +13,7 @@ #import #import -@interface AppleVTCompressor : CompressorBase +@interface AppleVTCompressor : CompressorBase { VTCompressionSessionRef _compression_session; diff --git a/CocoaSplit/Compressor/AppleVTCompressor.m b/CocoaSplit/Compressor/AppleVTCompressor.m index f4c5b400..3f5fe38a 100644 --- a/CocoaSplit/Compressor/AppleVTCompressor.m +++ b/CocoaSplit/Compressor/AppleVTCompressor.m @@ -8,6 +8,7 @@ #import "AppleVTCompressor.h" #import "OutputDestination.h" +#import "CSAppleH264CompressorViewController.h" OSStatus VTCompressionSessionCopySupportedPropertyDictionary(VTCompressionSessionRef, CFDictionaryRef *); @@ -443,5 +444,10 @@ void VideoCompressorReceiveFrame(void *VTref, void *VTFrameRef, OSStatus status, //} } +-(id )getConfigurationView +{ + return [[CSAppleH264CompressorViewController alloc] init]; +} + @end diff --git a/CocoaSplit/Compressor/CompressorBase.h b/CocoaSplit/Compressor/CompressorBase.h index 4a185bac..002199ab 100644 --- a/CocoaSplit/Compressor/CompressorBase.h +++ b/CocoaSplit/Compressor/CompressorBase.h @@ -7,12 +7,13 @@ // #import -#import "h264Compressor.h" +#import "VideoCompressor.h" +#import "CSCompressorViewControllerProtocol.h" @class captureController; -@interface CompressorBase : NSObject +@interface CompressorBase : NSObject { NSMutableArray *_audioBuffer; } @@ -38,6 +39,7 @@ @property (strong) NSMutableString *name; @property (assign) bool errored; @property (assign) bool active; +@property (assign) enum AVCodecID codec_id; @@ -46,6 +48,7 @@ -(BOOL) setupResolution:(CVImageBufferRef)withFrame; -(void) addAudioData:(CMSampleBufferRef)audioData; -(void) setAudioData:(CapturedFrameData *)forFrame syncObj:(id)syncObj; +-(id )getConfigurationView; diff --git a/CocoaSplit/Compressor/CompressorBase.m b/CocoaSplit/Compressor/CompressorBase.m index f349a669..71980fd0 100644 --- a/CocoaSplit/Compressor/CompressorBase.m +++ b/CocoaSplit/Compressor/CompressorBase.m @@ -26,6 +26,8 @@ self.resolutionOption = @"Use Source"; + self.codec_id = AV_CODEC_ID_H264; + self.outputs = [[NSMutableDictionary alloc] init]; _audioBuffer = [[NSMutableArray alloc] init]; @@ -132,11 +134,13 @@ -(id) initWithCoder:(NSCoder *)aDecoder { + self.codec_id = AV_CODEC_ID_H264; return self; } + -(bool) compressFrame:(CapturedFrameData *)imageBuffer { return YES; @@ -217,6 +221,10 @@ return YES; } +-(id )getConfigurationView +{ + return nil; +} @end diff --git a/CocoaSplit/Compressor/h264Compressor.h b/CocoaSplit/Compressor/VideoCompressor.h similarity index 80% rename from CocoaSplit/Compressor/h264Compressor.h rename to CocoaSplit/Compressor/VideoCompressor.h index 88b44825..ab357e44 100644 --- a/CocoaSplit/Compressor/h264Compressor.h +++ b/CocoaSplit/Compressor/VideoCompressor.h @@ -1,5 +1,5 @@ // -// h264Compressor.h +// VideoCompressor.h // streamOutput // // Created by Zakk on 3/17/13. @@ -9,6 +9,8 @@ #import #import #import "CapturedFrameData.h" +#import "libavformat/avformat.h" +#import "CSCompressorViewControllerProtocol.h" //#import "OutputDestination.h" @@ -18,7 +20,7 @@ @protocol ControllerProtocol; -@protocol h264Compressor +@protocol VideoCompressor //compressFrame is expected to be non-blocking. Create a serial dispatch queue if the underlying compressor //is blocking @@ -40,6 +42,7 @@ @property (strong) NSString *resolutionOption; @property (assign) bool errored; @property (assign) bool active; +@property (assign) enum AVCodecID codec_id; -(void) addOutput:(id)destination; -(void) removeOutput:(id)destination; @@ -47,6 +50,7 @@ -(void) reset; -(bool) validate:(NSError **)therror; -(void) addAudioData:(CMSampleBufferRef)audioData; +-(id )getConfigurationView; diff --git a/CocoaSplit/Compressor/x264Compressor.h b/CocoaSplit/Compressor/x264Compressor.h index e9e04fc4..b2789de4 100644 --- a/CocoaSplit/Compressor/x264Compressor.h +++ b/CocoaSplit/Compressor/x264Compressor.h @@ -11,7 +11,7 @@ #import "libavcodec/avcodec.h" #import "libswscale/swscale.h" #import -#import "h264Compressor.h" +#import "VideoCompressor.h" #import "CaptureController.h" #import #import "CapturedFrameData.h" diff --git a/CocoaSplit/Compressor/x264Compressor.m b/CocoaSplit/Compressor/x264Compressor.m index 7c7d2a36..d41c1588 100644 --- a/CocoaSplit/Compressor/x264Compressor.m +++ b/CocoaSplit/Compressor/x264Compressor.m @@ -9,6 +9,7 @@ #import "x264Compressor.h" #import "OutputDestination.h" #import +#import "CSx264CompressorViewController.h" @@ -562,6 +563,10 @@ [super setNilValueForKey:key]; } +-(id )getConfigurationView +{ + return [[CSx264CompressorViewController alloc] init]; +} @end diff --git a/CocoaSplit/ControllerProtocol.h b/CocoaSplit/ControllerProtocol.h index cbdc7786..cf7244fb 100644 --- a/CocoaSplit/ControllerProtocol.h +++ b/CocoaSplit/ControllerProtocol.h @@ -10,7 +10,7 @@ #import "libavformat/avformat.h" #import "CapturedFrameData.h" #import -#import "h264Compressor.h" +#import "VideoCompressor.h" #import "InputSource.h" @@ -26,7 +26,7 @@ @property (assign) int maxOutputPending; @property (assign) int maxOutputDropped; -@property (strong) id selectedCompressor; +@property (strong) id selectedCompressor; @property (strong) NSMutableDictionary *compressors; diff --git a/CocoaSplit/FFMpegTask.h b/CocoaSplit/FFMpegTask.h index 4ebdc660..50b08656 100644 --- a/CocoaSplit/FFMpegTask.h +++ b/CocoaSplit/FFMpegTask.h @@ -11,6 +11,8 @@ #import "libavformat/avformat.h" #import "CapturedFrameData.h" #import "CaptureController.h" +#import "libavutil/opt.h" + @@ -75,6 +77,8 @@ @property (assign) double output_bitrate; @property (assign) int dropped_frame_count; @property (assign) BOOL errored; +@property (assign) enum AVCodecID video_codec_id; + @property (strong) CaptureController *settingsController; diff --git a/CocoaSplit/FFMpegTask.m b/CocoaSplit/FFMpegTask.m index 782e0b04..69a4ed17 100644 --- a/CocoaSplit/FFMpegTask.m +++ b/CocoaSplit/FFMpegTask.m @@ -278,6 +278,24 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) } } +-(void) setVideoFormatOptions:(AVFormatContext *)ctx +{ + + AVOutputFormat *ofmt = ctx->oformat; + + if (!ofmt) + { + return; + } + + const char *fmt_name = ofmt->name; + + if (!strcasecmp(fmt_name, "mov")) + { + av_opt_set_int(ctx->priv_data, "frag_duration", 10000000, 0); + } +} + -(bool) createAVFormatOut:(CMSampleBufferRef)theBuffer codec_ctx:(AVCodecContext *)codec_ctx { @@ -299,7 +317,10 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) } + [self setVideoFormatOptions:_av_fmt_ctx]; + av_out_fmt = _av_fmt_ctx->oformat; + _av_video_stream = avformat_new_stream(_av_fmt_ctx, 0); if (!_av_video_stream) @@ -312,7 +333,7 @@ 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->codec_id = self.video_codec_id; _av_video_stream->time_base.num = 1000000; _av_video_stream->time_base.den = self.framerate*1000000; @@ -332,8 +353,8 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) a_ctx->codec_type = AVMEDIA_TYPE_AUDIO; a_ctx->codec_id = AV_CODEC_ID_AAC; - _av_audio_stream->time_base.num = 1000000; - _av_audio_stream->time_base.den = self.framerate*1000000; + _av_audio_stream->time_base.num = 100000; + _av_audio_stream->time_base.den = self.framerate*100000; a_ctx->sample_rate = _samplerate; a_ctx->bit_rate = _audio_bitrate; a_ctx->channels = 2; @@ -360,14 +381,16 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) atoms = CMFormatDescriptionGetExtension(fmt, kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms); avccKey = CFSTR("avcC"); - NSLog(@"ATOMS %@", atoms); - avcc_data = CFDictionaryGetValue(atoms, avccKey); - avcc_size = CFDataGetLength(avcc_data); - c_ctx->extradata = malloc(avcc_size); + if (atoms) + { + avcc_data = CFDictionaryGetValue(atoms, avccKey); + avcc_size = CFDataGetLength(avcc_data); + c_ctx->extradata = malloc(avcc_size); - CFDataGetBytes(avcc_data, CFRangeMake(0,avcc_size), c_ctx->extradata); + CFDataGetBytes(avcc_data, CFRangeMake(0,avcc_size), c_ctx->extradata); - c_ctx->extradata_size = (int)avcc_size; + c_ctx->extradata_size = (int)avcc_size; + } } else if (codec_ctx) { self.width = codec_ctx->width; self.height = codec_ctx->height; @@ -536,7 +559,6 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) NSLog(@"INTERLEAVED WRITE FRAME FAILED FOR %@ frame number %lld", self.stream_output, frameData.frameNumber); } - //av_free_packet(p); //av_free(p); _output_framecnt++; @@ -652,6 +674,7 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) pkt.size = (int)buffer_length; + pkt.dts = av_rescale_q(CMSampleBufferGetDecodeTimeStamp(theBuffer).value, (AVRational) {1.0, CMSampleBufferGetDecodeTimeStamp(theBuffer).timescale}, _av_video_stream->time_base); pkt.pts = av_rescale_q(CMSampleBufferGetPresentationTimeStamp(theBuffer).value, (AVRational) {1.0, CMSampleBufferGetPresentationTimeStamp(theBuffer).timescale}, _av_video_stream->time_base); @@ -672,22 +695,23 @@ void getAudioExtradata(char *cookie, char **buffer, size_t *size) } - + if (av_interleaved_write_frame(_av_fmt_ctx, &pkt) < 0) { NSLog(@"VIDEO WRITE FRAME failed for %@", self.stream_output); //[self stopProcess]; } - + _output_framecnt++; - _output_bytes += pkt.size; + _output_bytes += buffer_length; //CMSampleBufferInvalidate(theBuffer); CFRelease(theBuffer); @synchronized(self) { _pending_frame_count--; - _pending_frame_size -= pkt.size; + _pending_frame_size -= buffer_length; + } }); diff --git a/CocoaSplit/Interface/CSAppleH264CompressorViewController.h b/CocoaSplit/Interface/CSAppleH264CompressorViewController.h new file mode 100644 index 00000000..05f632bb --- /dev/null +++ b/CocoaSplit/Interface/CSAppleH264CompressorViewController.h @@ -0,0 +1,19 @@ +// +// CSAppleH264CompressorViewController.h +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import +#import "AppleVTCompressor.h" +#import "CSCompressorViewControllerProtocol.h" + +@interface CSAppleH264CompressorViewController : NSViewController + +@property (strong) AppleVTCompressor *compressor; +@property (strong) NSObjectController *compressorController; +@property (strong) NSArray *profiles; + +@end diff --git a/CocoaSplit/Interface/CSAppleH264CompressorViewController.m b/CocoaSplit/Interface/CSAppleH264CompressorViewController.m new file mode 100644 index 00000000..34068df7 --- /dev/null +++ b/CocoaSplit/Interface/CSAppleH264CompressorViewController.m @@ -0,0 +1,23 @@ +// +// CSAppleH264CompressorViewController.m +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import "CSAppleH264CompressorViewController.h" + +@interface CSAppleH264CompressorViewController () + +@end + +@implementation CSAppleH264CompressorViewController + +- (void)viewDidLoad { + self.profiles = @[[NSNull null], @"Baseline", @"Main", @"High"]; + [super viewDidLoad]; + // Do view setup here. +} + +@end diff --git a/CocoaSplit/Interface/CSAppleH264CompressorViewController.xib b/CocoaSplit/Interface/CSAppleH264CompressorViewController.xib new file mode 100644 index 00000000..2a2ed7d9 --- /dev/null +++ b/CocoaSplit/Interface/CSAppleH264CompressorViewController.xib @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CocoaSplit/Interface/CSAppleProResCompressorViewController.h b/CocoaSplit/Interface/CSAppleProResCompressorViewController.h new file mode 100644 index 00000000..460dbff9 --- /dev/null +++ b/CocoaSplit/Interface/CSAppleProResCompressorViewController.h @@ -0,0 +1,19 @@ +// +// CSAppleProResCompressorViewController.h +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import +#import "AppleProResCompressor.h" +#import "CSCompressorViewControllerProtocol.h" + +@interface CSAppleProResCompressorViewController : NSViewController + +@property (strong) NSObjectController *compressorController; + +@property (strong) NSDictionary *compressorTypes; + +@end diff --git a/CocoaSplit/Interface/CSAppleProResCompressorViewController.m b/CocoaSplit/Interface/CSAppleProResCompressorViewController.m new file mode 100644 index 00000000..9c41793d --- /dev/null +++ b/CocoaSplit/Interface/CSAppleProResCompressorViewController.m @@ -0,0 +1,32 @@ +// +// CSAppleProResCompressorViewController.m +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import "CSAppleProResCompressorViewController.h" + +@interface CSAppleProResCompressorViewController () + +@end + +@implementation CSAppleProResCompressorViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do view setup here. + + self.compressorTypes = @{@"ProRes 4444": @(kCMVideoCodecType_AppleProRes4444), + @"ProRes 422": @(kCMVideoCodecType_AppleProRes422), + @"ProRes 422HQ": @(kCMVideoCodecType_AppleProRes422HQ), + @"ProRes 422LT": @(kCMVideoCodecType_AppleProRes422LT), + @"ProRes 422Proxy": @(kCMVideoCodecType_AppleProRes422Proxy), + }; +} + + + + +@end diff --git a/CocoaSplit/Interface/CSAppleProResCompressorViewController.xib b/CocoaSplit/Interface/CSAppleProResCompressorViewController.xib new file mode 100644 index 00000000..c3c56bd9 --- /dev/null +++ b/CocoaSplit/Interface/CSAppleProResCompressorViewController.xib @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CocoaSplit/Interface/CSCompressorViewControllerProtocol.h b/CocoaSplit/Interface/CSCompressorViewControllerProtocol.h new file mode 100644 index 00000000..232dff17 --- /dev/null +++ b/CocoaSplit/Interface/CSCompressorViewControllerProtocol.h @@ -0,0 +1,17 @@ +// +// CSCompressorViewControllerProtocol.h +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import +#import + +@protocol CSCompressorViewControllerProtocol + +@property (strong) NSObjectController *compressorController; + + +@end diff --git a/CocoaSplit/Interface/CSNewOutputWindowController.h b/CocoaSplit/Interface/CSNewOutputWindowController.h index 00aaa02b..a603a1a5 100644 --- a/CocoaSplit/Interface/CSNewOutputWindowController.h +++ b/CocoaSplit/Interface/CSNewOutputWindowController.h @@ -25,7 +25,7 @@ @property (strong) NSString *selectedOutputType; @property (strong) NSObject*streamServiceObject; @property (strong) NSArray *outputTypes; -@property (weak) IBOutlet NSView *serviceConfigView; +@property (strong) IBOutlet NSView *serviceConfigView; @property (strong) NSViewController *pluginViewController; @property (strong) NSMutableDictionary *compressors; @property (strong) CompressionSettingsPanelController *compressionPanelController; diff --git a/CocoaSplit/Interface/CSNewOutputWindowController.m b/CocoaSplit/Interface/CSNewOutputWindowController.m index 47cf2b26..34e803ad 100644 --- a/CocoaSplit/Interface/CSNewOutputWindowController.m +++ b/CocoaSplit/Interface/CSNewOutputWindowController.m @@ -45,7 +45,7 @@ if (self.outputDestination.compressor_name) { - id oCompressor = self.compressors[self.outputDestination.compressor_name]; + id oCompressor = self.compressors[self.outputDestination.compressor_name]; if (!oCompressor) { self.outputDestination.compressor_name = nil; @@ -62,6 +62,13 @@ -(void)setupServiceView { + + if (!self.serviceConfigView) + { + return; + } + + if (!self.streamServiceObject) { if (self.pluginViewController) @@ -124,7 +131,11 @@ - (void)windowDidLoad { [super windowDidLoad]; - [self setupServiceView]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self setupServiceView]; + + + }); // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. } @@ -147,7 +158,7 @@ - (IBAction)openCompressorEdit:(id)sender { - NSObject *editCompressor; + NSObject *editCompressor; if (!self.outputDestination.compressor_name) { diff --git a/CocoaSplit/Interface/CSNewOutputWindowController.xib b/CocoaSplit/Interface/CSNewOutputWindowController.xib index 5c1ab685..4c40da06 100644 --- a/CocoaSplit/Interface/CSNewOutputWindowController.xib +++ b/CocoaSplit/Interface/CSNewOutputWindowController.xib @@ -1,8 +1,8 @@ - + - + @@ -25,7 +25,6 @@ - @@ -34,7 +33,6 @@ - @@ -54,7 +52,6 @@ - @@ -89,7 +84,6 @@ Gw - @@ -101,11 +95,9 @@ Gw - - @@ -114,7 +106,6 @@ Gw - @@ -123,7 +114,6 @@ Gw - @@ -143,7 +133,6 @@ Gw - @@ -155,7 +144,6 @@ Gw - @@ -175,7 +162,6 @@ Gw - @@ -186,7 +172,6 @@ Gw - diff --git a/CocoaSplit/Interface/CSx264CompressorViewController.h b/CocoaSplit/Interface/CSx264CompressorViewController.h new file mode 100644 index 00000000..7d29a1bb --- /dev/null +++ b/CocoaSplit/Interface/CSx264CompressorViewController.h @@ -0,0 +1,19 @@ +// +// CSx264CompressorViewController.h +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import +#import "x264Compressor.h" +#import "CSCompressorViewControllerProtocol.h" + +@interface CSx264CompressorViewController : NSViewController + + +@property (strong) x264Compressor *compressor; +@property (strong) NSObjectController *compressorController; + +@end diff --git a/CocoaSplit/Interface/CSx264CompressorViewController.m b/CocoaSplit/Interface/CSx264CompressorViewController.m new file mode 100644 index 00000000..d0b5e9f4 --- /dev/null +++ b/CocoaSplit/Interface/CSx264CompressorViewController.m @@ -0,0 +1,24 @@ +// +// CSx264CompressorViewController.m +// CocoaSplit +// +// Created by Zakk on 3/28/16. +// Copyright © 2016 Zakk. All rights reserved. +// + +#import "CSx264CompressorViewController.h" + +@interface CSx264CompressorViewController () + +@end + +@implementation CSx264CompressorViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do view setup here. +} + + + +@end diff --git a/CocoaSplit/Interface/CSx264CompressorViewController.xib b/CocoaSplit/Interface/CSx264CompressorViewController.xib new file mode 100644 index 00000000..3599ef8c --- /dev/null +++ b/CocoaSplit/Interface/CSx264CompressorViewController.xib @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CocoaSplit/Interface/CompressionSettingsPanel.xib b/CocoaSplit/Interface/CompressionSettingsPanel.xib index a52ee236..3c921cbf 100644 --- a/CocoaSplit/Interface/CompressionSettingsPanel.xib +++ b/CocoaSplit/Interface/CompressionSettingsPanel.xib @@ -1,14 +1,15 @@ - + - + + @@ -25,7 +26,6 @@ - @@ -34,7 +34,6 @@ - @@ -96,7 +92,6 @@ Gw - @@ -108,7 +103,6 @@ Gw - @@ -120,7 +114,6 @@ Gw - @@ -129,7 +122,6 @@ Gw - @@ -153,7 +145,6 @@ Gw - @@ -165,7 +156,6 @@ Gw - @@ -186,550 +175,34 @@ Gw - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - No Value - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - No Value - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - + + + + + + + + + + - + + + NSNegateBoolean + + + - + + + + + + + + + - diff --git a/CocoaSplit/Interface/CompressionSettingsPanelController.h b/CocoaSplit/Interface/CompressionSettingsPanelController.h index 7dbbb633..5148e041 100644 --- a/CocoaSplit/Interface/CompressionSettingsPanelController.h +++ b/CocoaSplit/Interface/CompressionSettingsPanelController.h @@ -7,13 +7,18 @@ // #import -#import "h264Compressor.h" +#import "VideoCompressor.h" +#import "CSCompressorViewControllerProtocol.h" + @interface CompressionSettingsPanelController : NSWindowController +@property (weak) IBOutlet NSView *compressorSettingsView; +@property (strong) NSViewController *compressorViewController; + @property (strong) IBOutlet NSObjectController *compressorObjectController; -@property (strong) id compressor; +@property (strong) id compressor; @property (strong) NSArray *compressorTypes; @property (strong) NSString *selectedCompressorType; @property (strong) NSString *saveProfileName; diff --git a/CocoaSplit/Interface/CompressionSettingsPanelController.m b/CocoaSplit/Interface/CompressionSettingsPanelController.m index 30d76bcd..aa3036a0 100644 --- a/CocoaSplit/Interface/CompressionSettingsPanelController.m +++ b/CocoaSplit/Interface/CompressionSettingsPanelController.m @@ -18,7 +18,7 @@ { if (self = [self initWithWindowNibName:@"CompressionSettingsPanel"]) { - self.compressorTypes = @[@"x264", @"AppleVTCompressor", @"None"]; + self.compressorTypes = @[@"x264", @"AppleVTCompressor", @"AppleProResCompressor", @"None"]; } return self; @@ -26,11 +26,43 @@ - (void)windowDidLoad { [super windowDidLoad]; + [self setupCompressorView]; // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. } +-(void)setupCompressorView +{ + + if (!self.compressorSettingsView) + { + return; + } + + + if (!self.compressor) + { + if (self.compressorViewController) + { + [self.compressorViewController.view removeFromSuperview]; + self.compressorViewController = nil; + } + } else { + id compressorConfigView = [self.compressor getConfigurationView]; + if (compressorConfigView) + { + compressorConfigView.compressorController = self.compressorObjectController; + + [self.compressorSettingsView addSubview:((NSViewController *)compressorConfigView).view]; + + [((NSViewController *)compressorConfigView).view setFrameOrigin:NSMakePoint(0, self.compressorSettingsView.frame.size.height - ((NSViewController *)compressorConfigView).view.frame.size.height)]; + self.compressorViewController = (NSViewController *)compressorConfigView; + } + } +} + + -(void)saveCompressPanel { [self.compressorObjectController commitEditing]; diff --git a/CocoaSplit/OutputDestination.h b/CocoaSplit/OutputDestination.h index 89238d14..cb028cf2 100644 --- a/CocoaSplit/OutputDestination.h +++ b/CocoaSplit/OutputDestination.h @@ -8,7 +8,7 @@ #import #import -#import "h264Compressor.h" +#import "VideoCompressor.h" #import "CaptureController.h" @@ -53,7 +53,7 @@ @property (assign) int dropped_frame_count; @property (assign) double output_framerate; @property (assign) double output_bitrate; -@property (strong) NSObject *compressor; +@property (strong) NSObject *compressor; @property (strong) NSString *compressor_name; diff --git a/CocoaSplit/OutputDestination.m b/CocoaSplit/OutputDestination.m index 678d1df3..11e4dde2 100644 --- a/CocoaSplit/OutputDestination.m +++ b/CocoaSplit/OutputDestination.m @@ -232,7 +232,7 @@ -(void)compressorDeleted:(NSNotification *)notification { - id compressor = notification.object; + id compressor = notification.object; if (self.compressor_name && [self.compressor_name isEqualToString:compressor.name]) { @@ -248,7 +248,7 @@ NSDictionary *infoDict = notification.object; NSString *oldName = infoDict[@"oldName"]; - id compressor = infoDict[@"compressor"]; + id compressor = infoDict[@"compressor"]; if (self.compressor_name && [self.compressor_name isEqualToString:oldName]) { @@ -281,7 +281,7 @@ } */ - + newout.video_codec_id = self.compressor.codec_id; newout.framerate = self.settingsController.captureFPS; newout.stream_output = [self.destination stringByStandardizingPath]; newout.stream_format = self.output_format; @@ -308,7 +308,7 @@ return; } - NSObject *old_compressor = self.compressor; + NSObject *old_compressor = self.compressor; if (self.compressor_name) { diff --git a/CocoaSplit/SourceLayout.m b/CocoaSplit/SourceLayout.m index e841ce4b..3c0d6ac6 100644 --- a/CocoaSplit/SourceLayout.m +++ b/CocoaSplit/SourceLayout.m @@ -32,7 +32,7 @@ _uuidMap = [NSMutableDictionary dictionary]; _animationQueue = dispatch_queue_create("CSAnimationQueue", NULL); - _containedLayouts = [NSMutableArray array]; + _containedLayouts = [[NSMutableArray alloc] init]; _noSceneTransactions = NO; self.rootLayer = [self newRootLayer]; @@ -359,7 +359,7 @@ if ([aDecoder containsValueForKey:@"containedLayouts"]) { - self.containedLayouts = [aDecoder decodeObjectForKey:@"containedLayouts"]; + self.containedLayouts = [[aDecoder decodeObjectForKey:@"containedLayouts"] mutableCopy]; //set live/staging status for each layout } @@ -546,20 +546,21 @@ } //Only run animations that aren't already in the layout - NSMutableArray *runAnimations = [NSMutableArray array]; + NSMutableArray *runAnimations = [[NSMutableArray alloc] init]; for (CSAnimationItem *anim in layout.animationList) { if (![self animationForUUID:anim.uuid] && anim.onLive) { [runAnimations addObject:anim.uuid]; + } } [self.animationList removeAllObjects]; //If an input exists in both lists, only remove it if the new one is different/changed - NSMutableArray *rList = [NSMutableArray array]; + NSMutableArray *rList = [[NSMutableArray alloc] init]; for (InputSource *src in self.sourceList) { InputSource *nSrc = [layout inputForUUID:src.uuid]; diff --git a/CocoaSplit/en.lproj/MainMenu.xib b/CocoaSplit/en.lproj/MainMenu.xib index de8f79b2..4780a945 100644 --- a/CocoaSplit/en.lproj/MainMenu.xib +++ b/CocoaSplit/en.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -323,15 +323,12 @@ - - - @@ -344,7 +341,6 @@ - @@ -353,7 +349,6 @@ - @@ -364,7 +359,6 @@ - @@ -379,7 +373,6 @@ - @@ -390,7 +383,6 @@ - @@ -406,7 +398,6 @@ - @@ -421,7 +412,6 @@ - @@ -433,7 +423,6 @@ - @@ -449,7 +438,6 @@ - @@ -482,7 +470,6 @@ - @@ -506,7 +493,6 @@ - @@ -518,7 +504,6 @@ - @@ -530,14 +515,12 @@ - - @@ -553,7 +536,6 @@ - @@ -792,7 +756,6 @@ - @@ -811,7 +774,6 @@ - @@ -838,7 +800,6 @@ - @@ -847,7 +808,6 @@ - @@ -856,7 +816,6 @@ - @@ -868,7 +827,6 @@ - @@ -880,7 +838,6 @@ - @@ -889,7 +846,6 @@ - @@ -898,7 +854,6 @@ - @@ -933,7 +888,6 @@ - @@ -941,18 +895,14 @@ - - @@ -1005,7 +955,6 @@ - @@ -1015,7 +964,6 @@ - @@ -1307,7 +1244,6 @@ - diff --git a/ImageUnitPlugins/CSChromaKey/CSChromaKey.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSChromaKey.xcscheme b/ImageUnitPlugins/CSChromaKey/CSChromaKey.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSChromaKey.xcscheme index 8ef5c004..7687f7fc 100644 --- a/ImageUnitPlugins/CSChromaKey/CSChromaKey.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSChromaKey.xcscheme +++ b/ImageUnitPlugins/CSChromaKey/CSChromaKey.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSChromaKey.xcscheme @@ -1,6 +1,6 @@ - + - + + @@ -11,14 +12,13 @@ - + - @@ -27,7 +27,6 @@ - diff --git a/StreamServicePlugins/CSTwitchStreamServicePlugin/CSTwitchStreamServicePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSTwitchStreamServicePlugin.xcscheme b/StreamServicePlugins/CSTwitchStreamServicePlugin/CSTwitchStreamServicePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSTwitchStreamServicePlugin.xcscheme index 8f5e530b..0dcf1f93 100644 --- a/StreamServicePlugins/CSTwitchStreamServicePlugin/CSTwitchStreamServicePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSTwitchStreamServicePlugin.xcscheme +++ b/StreamServicePlugins/CSTwitchStreamServicePlugin/CSTwitchStreamServicePlugin.xcodeproj/xcuserdata/zakk.xcuserdatad/xcschemes/CSTwitchStreamServicePlugin.xcscheme @@ -1,6 +1,6 @@