├── .gitattributes ├── .DS_Store ├── img ├── .DS_Store └── final.gif ├── BroadcastUploadNew ├── .DS_Store ├── SampleHandler.h ├── BroadcastUploadNew.entitlements ├── Info.plist ├── HJImagesToVideo │ ├── HJImagesToVideo.h │ └── HJImagesToVideo.m └── SampleHandler.m ├── BroadcastNew ├── ViewController.h ├── AppDelegate.h ├── main.m ├── BroadcastNew.entitlements ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── Info.plist ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── AppDelegate.m └── ViewController.m ├── README.md ├── BroadcastNew.xcodeproj ├── xcuserdata │ ├── anirban.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ └── xcschememanagement.plist │ └── wang.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ ├── wang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ │ └── anirban.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── project.pbxproj └── LICENSE /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timeflow1024/iOS-Broadcast-Upload-Extension/HEAD/.DS_Store -------------------------------------------------------------------------------- /img/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timeflow1024/iOS-Broadcast-Upload-Extension/HEAD/img/.DS_Store -------------------------------------------------------------------------------- /img/final.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timeflow1024/iOS-Broadcast-Upload-Extension/HEAD/img/final.gif -------------------------------------------------------------------------------- /BroadcastUploadNew/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timeflow1024/iOS-Broadcast-Upload-Extension/HEAD/BroadcastUploadNew/.DS_Store -------------------------------------------------------------------------------- /BroadcastNew/ViewController.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface ViewController : UIViewController 5 | 6 | 7 | @end 8 | 9 | -------------------------------------------------------------------------------- /BroadcastUploadNew/SampleHandler.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface SampleHandler : RPBroadcastSampleHandler 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS-Broadcast-Upload-Extension 2 | 3 | 使用iOS的Broadcast Upload Extension实现全局录屏,并保存为mp4。 4 | 效果图: 5 | 6 | ![效果图](img/final.gif) 7 | 8 | 简书地址:https://www.jianshu.com/p/85614dcf9b65 9 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/xcuserdata/anirban.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /BroadcastNew/AppDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (strong, nonatomic) UIWindow *window; 7 | 8 | 9 | @end 10 | 11 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/xcuserdata/wang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /BroadcastNew/main.m: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/project.xcworkspace/xcuserdata/wang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timeflow1024/iOS-Broadcast-Upload-Extension/HEAD/BroadcastNew.xcodeproj/project.xcworkspace/xcuserdata/wang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/project.xcworkspace/xcuserdata/anirban.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timeflow1024/iOS-Broadcast-Upload-Extension/HEAD/BroadcastNew.xcodeproj/project.xcworkspace/xcuserdata/anirban.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BroadcastNew/BroadcastNew.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.hyjk.TestForLuPing 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BroadcastUploadNew/BroadcastUploadNew.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.hyjk.TestForLuPing 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/xcuserdata/anirban.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BroadcastNew.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | BroadcastUploadNew.xcscheme 13 | 14 | orderHint 15 | 1 16 | 17 | BroadcastUploadNewSetupUI.xcscheme 18 | 19 | orderHint 20 | 2 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 wincalling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/xcuserdata/wang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | BroadcastNew.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | BroadcastNew.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | BroadcastUploadNew.xcscheme 18 | 19 | orderHint 20 | 1 21 | 22 | BroadcastUploadNew.xcscheme_^#shared#^_ 23 | 24 | orderHint 25 | 1 26 | 27 | BroadcastUploadNewSetupUI.xcscheme 28 | 29 | orderHint 30 | 2 31 | 32 | BroadcastUploadNewSetupUI.xcscheme_^#shared#^_ 33 | 34 | orderHint 35 | 2 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /BroadcastUploadNew/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | BroadcastUploadNew 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | NSExtension 24 | 25 | NSExtensionPointIdentifier 26 | com.apple.broadcast-services-upload 27 | NSExtensionPrincipalClass 28 | SampleHandler 29 | RPBroadcastProcessMode 30 | RPBroadcastProcessModeSampleBuffer 31 | 32 | NSAppTransportSecurity 33 | 34 | NSAllowsArbitraryLoads 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /BroadcastNew/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /BroadcastNew/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | NSAppTransportSecurity 45 | 46 | NSAllowsArbitraryLoads 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /BroadcastNew/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /BroadcastNew/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /BroadcastNew/AppDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | #import "AppDelegate.h" 3 | 4 | @interface AppDelegate () 5 | 6 | @end 7 | 8 | @implementation AppDelegate 9 | 10 | 11 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 12 | // Override point for customization after application launch. 13 | 14 | 15 | return YES; 16 | } 17 | 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application { 20 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 21 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 22 | } 23 | 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application { 26 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 27 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 28 | } 29 | 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application { 32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /BroadcastUploadNew/HJImagesToVideo/HJImagesToVideo.h: -------------------------------------------------------------------------------- 1 | // 2 | // HJImagesToVideo.h 3 | // HJImagesToVideo 4 | // 5 | // Created by Harrison Jackson on 8/4/13. 6 | // Copyright (c) 2013 Harrison Jackson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | /** 16 | * Determines defaults for transitions 17 | */ 18 | FOUNDATION_EXPORT BOOL const DefaultTransitionShouldAnimate; 19 | 20 | /** 21 | * Determines default frame size for videos 22 | */ 23 | FOUNDATION_EXPORT CGSize const DefaultFrameSize; 24 | 25 | /** 26 | * Determines default FPS of video - 10 Images at 10FPS results in a 1 second video clip. 27 | */ 28 | FOUNDATION_EXPORT NSInteger const DefaultFrameRate; 29 | 30 | /** 31 | * Number of frames to use in transition 32 | */ 33 | FOUNDATION_EXPORT NSInteger const TransitionFrameCount; 34 | 35 | /** 36 | * Number of frames to hold each image before beginning alpha fade into the next 37 | */ 38 | FOUNDATION_EXPORT NSInteger const FramesToWaitBeforeTransition; 39 | 40 | 41 | 42 | typedef void(^SuccessBlock)(BOOL success); 43 | 44 | 45 | @interface HJImagesToVideo : NSObject 46 | 47 | 48 | /** 49 | * This is the main function for creating a video from a set of images 50 | * 51 | * FPS of 1 with 10 images results in 10 second video, but not necessarily an only 10 frame video. Transitions will add frames, but maintain expected duration 52 | * 53 | * @param images Images to convert to video 54 | * @param path Path to write video to 55 | * @param size Frame size of image 56 | * @param fps FPS of video 57 | * @param animate Yes results in crossfade between images 58 | * @param callbackBlock Block to execute when video creation completes or fails 59 | */ 60 | + (void)videoFromImages:(NSArray *)images 61 | toPath:(NSString *)path 62 | withSize:(CGSize)size 63 | withFPS:(int)fps 64 | animateTransitions:(BOOL)animate 65 | withCallbackBlock:(SuccessBlock)callbackBlock; 66 | 67 | + (void)videoFromImages:(NSArray *)images 68 | toPath:(NSString *)path 69 | withFPS:(int)fps 70 | animateTransitions:(BOOL)animate 71 | withCallbackBlock:(SuccessBlock)callbackBlock; 72 | 73 | + (void)videoFromImages:(NSArray *)images 74 | toPath:(NSString *)path 75 | withSize:(CGSize)size 76 | animateTransitions:(BOOL)animate 77 | withCallbackBlock:(SuccessBlock)callbackBlock; 78 | 79 | + (void)videoFromImages:(NSArray *)images 80 | toPath:(NSString *)path 81 | animateTransitions:(BOOL)animate 82 | withCallbackBlock:(SuccessBlock)callbackBlock; 83 | 84 | + (void)videoFromImages:(NSArray *)images 85 | toPath:(NSString *)path 86 | withCallbackBlock:(SuccessBlock)callbackBlock; 87 | 88 | /** 89 | * Convenience methods for saving to camera roll 90 | * 91 | * @param images Images to convert to video 92 | * @param size Frame size of image 93 | * @param fps FPS of video 94 | * @param animate Yes results in crossfade between images 95 | * @param callbackBlock Block to execute when video creation completes or fails 96 | */ 97 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 98 | withSize:(CGSize)size 99 | withFPS:(int)fps 100 | animateTransitions:(BOOL)animate 101 | withCallbackBlock:(SuccessBlock)callbackBlock; 102 | 103 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 104 | withSize:(CGSize)size 105 | animateTransitions:(BOOL)animate 106 | withCallbackBlock:(SuccessBlock)callbackBlock; 107 | 108 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 109 | withFPS:(int)fps 110 | animateTransitions:(BOOL)animate 111 | withCallbackBlock:(SuccessBlock)callbackBlock; 112 | 113 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 114 | animateTransitions:(BOOL)animate 115 | withCallbackBlock:(SuccessBlock)callbackBlock; 116 | 117 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 118 | withCallbackBlock:(SuccessBlock)callbackBlock; 119 | 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /BroadcastUploadNew/SampleHandler.m: -------------------------------------------------------------------------------- 1 | 2 | #import "SampleHandler.h" 3 | 4 | @interface SampleHandler() 5 | 6 | @property(nonatomic,strong)RPScreenRecorder* screenRecorder; 7 | @property(nonatomic,strong)AVAssetWriter* assetWriter; 8 | @property(nonatomic,strong)AVAssetWriterInput* assetWriterInput; 9 | @property(nonatomic,strong)NSString* videoOutPath; 10 | @property(nonatomic,strong)AVAssetWriterInputPixelBufferAdaptor *pixelBufferAdaptor; 11 | @property(nonatomic,strong)AVCaptureSession *captureSession; 12 | 13 | @end 14 | 15 | @implementation SampleHandler 16 | 17 | - (void)broadcastStartedWithSetupInfo:(NSDictionary *)setupInfo { 18 | // User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional. 19 | NSLog(@"开始录屏"); 20 | [self startScreenRecording]; 21 | 22 | } 23 | 24 | #pragma mark - 初始化录屏所需类 25 | - (void)startScreenRecording { 26 | 27 | self.captureSession = [[AVCaptureSession alloc]init]; 28 | self.screenRecorder = [RPScreenRecorder sharedRecorder]; 29 | if (self.screenRecorder.isRecording) { 30 | return; 31 | } 32 | NSError *error = nil; 33 | NSArray *pathDocuments = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 34 | NSString *outputURL = pathDocuments[0]; 35 | self.videoOutPath = [[outputURL stringByAppendingPathComponent:@"demo"] stringByAppendingPathExtension:@"mp4"]; 36 | NSLog(@"self.videoOutPath=%@",self.videoOutPath); 37 | 38 | self.assetWriter = [AVAssetWriter assetWriterWithURL:[NSURL fileURLWithPath:self.videoOutPath] fileType:AVFileTypeMPEG4 error:&error]; 39 | 40 | NSDictionary *compressionProperties = 41 | @{AVVideoProfileLevelKey : AVVideoProfileLevelH264HighAutoLevel, 42 | AVVideoH264EntropyModeKey : AVVideoH264EntropyModeCABAC, 43 | AVVideoAverageBitRateKey : @(1920 * 1080 * 11.4), 44 | AVVideoMaxKeyFrameIntervalKey : @60, 45 | AVVideoAllowFrameReorderingKey : @NO}; 46 | 47 | NSNumber* width= [NSNumber numberWithFloat:[[UIScreen mainScreen] bounds].size.width]; 48 | NSNumber* height = [NSNumber numberWithFloat:[[UIScreen mainScreen] bounds].size.height]; 49 | 50 | NSDictionary *videoSettings = 51 | @{ 52 | AVVideoCompressionPropertiesKey : compressionProperties, 53 | AVVideoCodecKey : AVVideoCodecTypeH264, 54 | AVVideoWidthKey : width, 55 | AVVideoHeightKey : height 56 | }; 57 | 58 | self.assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; 59 | self.pixelBufferAdaptor = 60 | [[AVAssetWriterInputPixelBufferAdaptor alloc]initWithAssetWriterInput:self.assetWriterInput 61 | sourcePixelBufferAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA],kCVPixelBufferPixelFormatTypeKey,nil]]; 62 | [self.assetWriter addInput:self.assetWriterInput]; 63 | [self.assetWriterInput setMediaTimeScale:60]; 64 | [self.assetWriter setMovieTimeScale:60]; 65 | [self.assetWriterInput setExpectsMediaDataInRealTime:YES]; 66 | 67 | //写入视频 68 | [self.assetWriter startWriting]; 69 | [self.assetWriter startSessionAtSourceTime:kCMTimeZero]; 70 | 71 | [self.captureSession startRunning]; 72 | 73 | } 74 | 75 | #pragma mark - 直播 76 | - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType { 77 | NSLog(@"录屏中..."); 78 | switch (sampleBufferType) { 79 | 80 | case RPSampleBufferTypeVideo: 81 | // Handle video sample buffer for app audio 82 | { 83 | CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 84 | static int64_t frameNumber = 0; 85 | if(self.assetWriterInput.readyForMoreMediaData){ 86 | NSLog(@"录屏中写入..."); 87 | [self.pixelBufferAdaptor appendPixelBuffer:imageBuffer 88 | withPresentationTime:CMTimeMake(frameNumber, 25)]; 89 | } 90 | 91 | frameNumber++; 92 | 93 | NSLog(@"已获取的长度%lu",[NSData dataWithContentsOfFile:self.videoOutPath].length); 94 | } 95 | break; 96 | case RPSampleBufferTypeAudioApp: 97 | // Handle audio sample buffer for app audio 98 | break; 99 | case RPSampleBufferTypeAudioMic: 100 | // Handle audio sample buffer for mic audio 101 | break; 102 | default: 103 | break; 104 | } 105 | } 106 | 107 | - (void)broadcastPaused { 108 | // User has requested to pause the broadcast. Samples will stop being delivered. 109 | NSLog(@"暂停录屏"); 110 | 111 | } 112 | 113 | - (void)broadcastResumed { 114 | // User has requested to resume the broadcast. Samples delivery will resume. 115 | NSLog(@"继续录屏"); 116 | 117 | } 118 | 119 | - (void)broadcastFinished { 120 | // User has requested to finish the broadcast. 121 | NSLog(@"结束录屏"); 122 | [self.captureSession stopRunning]; 123 | [self.assetWriter finishWriting]; 124 | 125 | NSData* data = [NSData dataWithContentsOfFile:self.videoOutPath]; 126 | NSLog(@"获取的总长度%lu",data.length); 127 | 128 | //存储数据到共享区:SuiteName和宿主必须一致 129 | NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.hyjk.TestForLuPing"]; 130 | [userDefaults setValue:data forKey:@"key"]; 131 | [userDefaults synchronize]; 132 | 133 | //向宿主发送通知 134 | [self sendNotificationForMessageWithIdentifier:@"broadcastFinished" userInfo:nil]; 135 | 136 | } 137 | 138 | - (void)sendNotificationForMessageWithIdentifier:(nullable NSString *)identifier userInfo:(NSDictionary *)info { 139 | CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); 140 | CFDictionaryRef userInfo = (__bridge CFDictionaryRef)info; 141 | BOOL const deliverImmediately = YES; 142 | CFStringRef identifierRef = (__bridge CFStringRef)identifier; 143 | CFNotificationCenterPostNotification(center, identifierRef, NULL, userInfo, deliverImmediately); 144 | } 145 | 146 | @end 147 | -------------------------------------------------------------------------------- /BroadcastNew/ViewController.m: -------------------------------------------------------------------------------- 1 | 2 | #import "ViewController.h" 3 | #import 4 | #import 5 | #import 6 | 7 | @interface ViewController () 8 | @property(nonatomic,strong)AVPlayerViewController* moviePlayer; 9 | @property(nonatomic,strong)NSString* videoPath; 10 | @end 11 | 12 | static NSString * const ScreenHoleNotificationName = @"ScreenHoleNotificationName"; 13 | 14 | void MyHoleNotificationCallback(CFNotificationCenterRef center, 15 | void * observer, 16 | CFStringRef name, 17 | void const * object, 18 | CFDictionaryRef userInfo) { 19 | NSString *identifier = (__bridge NSString *)name; 20 | NSObject *sender = (__bridge NSObject *)observer; 21 | //NSDictionary *info = (__bridge NSDictionary *)userInfo; 22 | NSDictionary *info = CFBridgingRelease(userInfo); 23 | 24 | NSLog(@"userInfo %@ %@",userInfo,info); 25 | 26 | NSDictionary *notiUserInfo = @{@"identifier":identifier}; 27 | [[NSNotificationCenter defaultCenter] postNotificationName:ScreenHoleNotificationName 28 | object:sender 29 | userInfo:notiUserInfo]; 30 | } 31 | 32 | @implementation ViewController 33 | 34 | #pragma mark - Life Cycle 35 | - (void)viewDidLoad { 36 | [super viewDidLoad]; 37 | // Do any additional setup after loading the view, typically from a nib. 38 | 39 | //注册Observer 40 | [self addUploaderEventMonitor]; 41 | 42 | [self.view addSubview:self.moviePlayer.view]; 43 | 44 | if (@available(iOS 12.0, *)) { 45 | 46 | RPSystemBroadcastPickerView *picker = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(0, 0, 100, 50)]; 47 | picker.showsMicrophoneButton = YES; 48 | //extension的bundle id,必须要填写对 49 | picker.preferredExtension = @"hyjk.TestForLuPing.upload"; 50 | [self.view addSubview:picker]; 51 | picker.center = self.view.center; 52 | 53 | UILabel* label = [[UILabel alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(picker.frame), self.view.frame.size.width, 30)]; 54 | label.text = @"点击上方按钮开始录屏"; 55 | label.textAlignment = NSTextAlignmentCenter; 56 | [self.view addSubview:label]; 57 | 58 | } else { 59 | // Fallback on earlier versions 60 | } 61 | 62 | } 63 | 64 | -(void)dealloc{ 65 | 66 | [self removeUploaderEventMonitor]; 67 | 68 | } 69 | 70 | #pragma mark - 接收来自extension的消息 71 | - (void)addUploaderEventMonitor { 72 | 73 | [self registerForNotificationsWithIdentifier:@"broadcastFinished"]; 74 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(broadcastInfo:) name:ScreenHoleNotificationName object:nil]; 75 | } 76 | 77 | - (void)broadcastInfo:(NSNotification *)noti { 78 | 79 | NSDictionary *userInfo = noti.userInfo; 80 | NSString *identifier = userInfo[@"identifier"]; 81 | 82 | if ([identifier isEqualToString:@"broadcastFinished"]) { 83 | 84 | //reload数据 85 | NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.hyjk.TestForLuPing"]; 86 | NSData* videoData = [userDefaults valueForKey:@"key"]; 87 | 88 | if(videoData.length != 0){ 89 | [self writeFile:videoData]; 90 | AVPlayerItem *item = [[AVPlayerItem alloc]initWithURL:[NSURL fileURLWithPath:self.videoPath]]; 91 | [self.moviePlayer.player replaceCurrentItemWithPlayerItem:item]; 92 | } 93 | } 94 | 95 | } 96 | 97 | #pragma mark - 移除Observer 98 | - (void)removeUploaderEventMonitor { 99 | 100 | [self unregisterForNotificationsWithIdentifier:@"broadcastFinished"]; 101 | [[NSNotificationCenter defaultCenter] removeObserver:self name:ScreenHoleNotificationName object:nil]; 102 | 103 | } 104 | 105 | #pragma mark - 宿主与extension之间的通知 106 | - (void)registerForNotificationsWithIdentifier:(nullable NSString *)identifier { 107 | [self unregisterForNotificationsWithIdentifier:identifier]; 108 | CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); 109 | CFStringRef str = (__bridge CFStringRef)identifier; 110 | CFNotificationCenterAddObserver(center, 111 | (__bridge const void *)(self), 112 | MyHoleNotificationCallback, 113 | str, 114 | NULL, 115 | CFNotificationSuspensionBehaviorDeliverImmediately); 116 | } 117 | 118 | - (void)unregisterForNotificationsWithIdentifier:(nullable NSString *)identifier { 119 | CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); 120 | CFStringRef str = (__bridge CFStringRef)identifier; 121 | CFNotificationCenterRemoveObserver(center, 122 | (__bridge const void *)(self), 123 | str, 124 | NULL); 125 | } 126 | 127 | #pragma mark - SEL 128 | -(void)writeFile:(NSData* )d{ 129 | 130 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 131 | NSString *documentsPath =[paths objectAtIndex:0]; 132 | NSString *iOSPath = [documentsPath stringByAppendingPathComponent:@"recored.mp4"]; 133 | BOOL isSuccess = [d writeToFile:iOSPath atomically:YES]; 134 | if (isSuccess) { 135 | NSLog(@"write success"); 136 | } else { 137 | NSLog(@"write fail,please record first"); 138 | } 139 | } 140 | 141 | #pragma mark - Lazy load 142 | -(NSString* )videoPath{ 143 | if (!_videoPath) { 144 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 145 | NSString *documentsPath =[paths objectAtIndex:0]; 146 | _videoPath = [documentsPath stringByAppendingPathComponent:@"recored.mp4"]; 147 | } 148 | return _videoPath; 149 | } 150 | 151 | -(AVPlayerViewController *)moviePlayer{ 152 | 153 | if (!_moviePlayer) { 154 | _moviePlayer=[[AVPlayerViewController alloc]init]; 155 | AVPlayerItem *item = [[AVPlayerItem alloc]initWithURL:[NSURL fileURLWithPath:self.videoPath]]; 156 | _moviePlayer.player = [[AVPlayer alloc]initWithPlayerItem:item]; 157 | _moviePlayer.view.frame=CGRectMake(0, 0, self.view.frame.size.width, 200); 158 | _moviePlayer.view.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; 159 | _moviePlayer.showsPlaybackControls = YES; 160 | } 161 | return _moviePlayer; 162 | 163 | } 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /BroadcastUploadNew/HJImagesToVideo/HJImagesToVideo.m: -------------------------------------------------------------------------------- 1 | // 2 | // HJImagesToVideo.m 3 | // HJImagesToVideo 4 | // 5 | // Created by Harrison Jackson on 8/4/13. 6 | // Copyright (c) 2013 Harrison Jackson. All rights reserved. 7 | // 8 | 9 | #import "HJImagesToVideo.h" 10 | 11 | CGSize const DefaultFrameSize = (CGSize){480, 320}; 12 | 13 | NSInteger const DefaultFrameRate = 1; 14 | NSInteger const TransitionFrameCount = 50; 15 | NSInteger const FramesToWaitBeforeTransition = 40; 16 | 17 | BOOL const DefaultTransitionShouldAnimate = YES; 18 | 19 | @implementation HJImagesToVideo 20 | 21 | + (void)videoFromImages:(NSArray *)images 22 | toPath:(NSString *)path 23 | withCallbackBlock:(SuccessBlock)callbackBlock 24 | { 25 | [HJImagesToVideo videoFromImages:images 26 | toPath:path 27 | withSize:DefaultFrameSize 28 | withFPS:DefaultFrameRate 29 | animateTransitions:DefaultTransitionShouldAnimate 30 | withCallbackBlock:callbackBlock]; 31 | } 32 | 33 | + (void)videoFromImages:(NSArray *)images 34 | toPath:(NSString *)path 35 | animateTransitions:(BOOL)animate 36 | withCallbackBlock:(SuccessBlock)callbackBlock 37 | { 38 | [HJImagesToVideo videoFromImages:images 39 | toPath:path 40 | withSize:DefaultFrameSize 41 | withFPS:DefaultFrameRate 42 | animateTransitions:animate 43 | withCallbackBlock:callbackBlock]; 44 | } 45 | 46 | + (void)videoFromImages:(NSArray *)images 47 | toPath:(NSString *)path 48 | withFPS:(int)fps 49 | animateTransitions:(BOOL)animate 50 | withCallbackBlock:(SuccessBlock)callbackBlock 51 | { 52 | [HJImagesToVideo videoFromImages:images 53 | toPath:path 54 | withSize:DefaultFrameSize 55 | withFPS:fps 56 | animateTransitions:animate 57 | withCallbackBlock:callbackBlock]; 58 | } 59 | 60 | + (void)videoFromImages:(NSArray *)images 61 | toPath:(NSString *)path 62 | withSize:(CGSize)size 63 | animateTransitions:(BOOL)animate 64 | withCallbackBlock:(SuccessBlock)callbackBlock 65 | { 66 | [HJImagesToVideo videoFromImages:images 67 | toPath:path 68 | withSize:size 69 | withFPS:DefaultFrameRate 70 | animateTransitions:animate 71 | withCallbackBlock:callbackBlock]; 72 | } 73 | 74 | + (void)videoFromImages:(NSArray *)images 75 | toPath:(NSString *)path 76 | withSize:(CGSize)size 77 | withFPS:(int)fps 78 | animateTransitions:(BOOL)animate 79 | withCallbackBlock:(SuccessBlock)callbackBlock 80 | { 81 | [HJImagesToVideo writeImageAsMovie:images 82 | toPath:path 83 | size:size 84 | fps:fps 85 | animateTransitions:animate 86 | withCallbackBlock:callbackBlock]; 87 | } 88 | 89 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 90 | withCallbackBlock:(SuccessBlock)callbackBlock 91 | { 92 | [HJImagesToVideo saveVideoToPhotosWithImages:images 93 | withSize:DefaultFrameSize 94 | animateTransitions:DefaultTransitionShouldAnimate 95 | withCallbackBlock:callbackBlock]; 96 | } 97 | 98 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 99 | animateTransitions:(BOOL)animate 100 | withCallbackBlock:(SuccessBlock)callbackBlock 101 | { 102 | [HJImagesToVideo saveVideoToPhotosWithImages:images 103 | withSize:DefaultFrameSize 104 | animateTransitions:animate 105 | withCallbackBlock:callbackBlock]; 106 | } 107 | 108 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 109 | withSize:(CGSize)size 110 | animateTransitions:(BOOL)animate 111 | withCallbackBlock:(SuccessBlock)callbackBlock 112 | { 113 | [HJImagesToVideo saveVideoToPhotosWithImages:images 114 | withSize:size 115 | withFPS:DefaultFrameRate 116 | animateTransitions:animate 117 | withCallbackBlock:callbackBlock]; 118 | } 119 | 120 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 121 | withFPS:(int)fps 122 | animateTransitions:(BOOL)animate 123 | withCallbackBlock:(SuccessBlock)callbackBlock 124 | { 125 | [HJImagesToVideo saveVideoToPhotosWithImages:images 126 | withSize:DefaultFrameSize 127 | withFPS:fps 128 | animateTransitions:animate 129 | withCallbackBlock:callbackBlock]; 130 | } 131 | 132 | + (void)saveVideoToPhotosWithImages:(NSArray *)images 133 | withSize:(CGSize)size 134 | withFPS:(int)fps 135 | animateTransitions:(BOOL)animate 136 | withCallbackBlock:(SuccessBlock)callbackBlock 137 | { 138 | NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent: 139 | [NSString stringWithFormat:@"temp.mp4"]]; 140 | [[NSFileManager defaultManager] removeItemAtPath:tempPath error:NULL]; 141 | 142 | [HJImagesToVideo videoFromImages:images 143 | toPath:tempPath 144 | withSize:size 145 | withFPS:fps 146 | animateTransitions:animate 147 | withCallbackBlock:^(BOOL success) { 148 | 149 | if (success) { 150 | UISaveVideoAtPathToSavedPhotosAlbum(tempPath, self, nil, nil); 151 | } 152 | 153 | if (callbackBlock) { 154 | callbackBlock(success); 155 | } 156 | }]; 157 | } 158 | 159 | + (void)writeImageAsMovie:(NSArray *)array 160 | toPath:(NSString*)path 161 | size:(CGSize)size 162 | fps:(int)fps 163 | animateTransitions:(BOOL)shouldAnimateTransitions 164 | withCallbackBlock:(SuccessBlock)callbackBlock 165 | { 166 | NSLog(@"%@", path); 167 | NSError *error = nil; 168 | AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] 169 | fileType:AVFileTypeMPEG4 170 | error:&error]; 171 | if (error) { 172 | if (callbackBlock) { 173 | callbackBlock(NO); 174 | } 175 | return; 176 | } 177 | NSParameterAssert(videoWriter); 178 | 179 | NSDictionary *videoSettings = @{AVVideoCodecKey: AVVideoCodecH264, 180 | AVVideoWidthKey: [NSNumber numberWithInt:size.width], 181 | AVVideoHeightKey: [NSNumber numberWithInt:size.height]}; 182 | 183 | AVAssetWriterInput* writerInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo 184 | outputSettings:videoSettings]; 185 | 186 | AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput 187 | sourcePixelBufferAttributes:nil]; 188 | NSParameterAssert(writerInput); 189 | NSParameterAssert([videoWriter canAddInput:writerInput]); 190 | [videoWriter addInput:writerInput]; 191 | 192 | //Start a session: 193 | [videoWriter startWriting]; 194 | [videoWriter startSessionAtSourceTime:kCMTimeZero]; 195 | 196 | CVPixelBufferRef buffer; 197 | CVPixelBufferPoolCreatePixelBuffer(NULL, adaptor.pixelBufferPool, &buffer); 198 | 199 | CMTime presentTime = CMTimeMake(0, fps); 200 | 201 | int i = 0; 202 | while (1) 203 | { 204 | 205 | if(writerInput.readyForMoreMediaData){ 206 | 207 | presentTime = CMTimeMake(i, fps); 208 | 209 | if (i >= [array count]) { 210 | buffer = NULL; 211 | } else { 212 | buffer = [HJImagesToVideo pixelBufferFromCGImage:[array[i] CGImage] size:CGSizeMake(480, 320)]; 213 | } 214 | 215 | if (buffer) { 216 | //append buffer 217 | 218 | BOOL appendSuccess = [HJImagesToVideo appendToAdapter:adaptor 219 | pixelBuffer:buffer 220 | atTime:presentTime 221 | withInput:writerInput]; 222 | NSAssert(appendSuccess, @"Failed to append"); 223 | 224 | if (shouldAnimateTransitions && i + 1 < array.count) { 225 | 226 | //Create time each fade frame is displayed 227 | CMTime fadeTime = CMTimeMake(1, fps*TransitionFrameCount); 228 | 229 | //Add a delay, causing the base image to have more show time before fade begins. 230 | for (int b = 0; b < FramesToWaitBeforeTransition; b++) { 231 | presentTime = CMTimeAdd(presentTime, fadeTime); 232 | } 233 | 234 | //Adjust fadeFrameCount so that the number and curve of the fade frames and their alpha stay consistant 235 | NSInteger framesToFadeCount = TransitionFrameCount - FramesToWaitBeforeTransition; 236 | 237 | //Apply fade frames 238 | for (double j = 1; j < framesToFadeCount; j++) { 239 | 240 | buffer = [HJImagesToVideo crossFadeImage:[array[i] CGImage] 241 | toImage:[array[i + 1] CGImage] 242 | atSize:CGSizeMake(480, 320) 243 | withAlpha:j/framesToFadeCount]; 244 | 245 | BOOL appendSuccess = [HJImagesToVideo appendToAdapter:adaptor 246 | pixelBuffer:buffer 247 | atTime:presentTime 248 | withInput:writerInput]; 249 | presentTime = CMTimeAdd(presentTime, fadeTime); 250 | 251 | NSAssert(appendSuccess, @"Failed to append"); 252 | } 253 | } 254 | 255 | i++; 256 | } else { 257 | 258 | //Finish the session: 259 | [writerInput markAsFinished]; 260 | 261 | [videoWriter finishWritingWithCompletionHandler:^{ 262 | NSLog(@"Successfully closed video writer"); 263 | if (videoWriter.status == AVAssetWriterStatusCompleted) { 264 | if (callbackBlock) { 265 | callbackBlock(YES); 266 | } 267 | } else { 268 | if (callbackBlock) { 269 | callbackBlock(NO); 270 | } 271 | } 272 | }]; 273 | 274 | CVPixelBufferPoolRelease(adaptor.pixelBufferPool); 275 | 276 | NSLog (@"Done"); 277 | break; 278 | } 279 | } 280 | } 281 | } 282 | 283 | + (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image 284 | size:(CGSize)imageSize 285 | { 286 | NSDictionary *options = @{(id)kCVPixelBufferCGImageCompatibilityKey: @YES, 287 | (id)kCVPixelBufferCGBitmapContextCompatibilityKey: @YES}; 288 | CVPixelBufferRef pxbuffer = NULL; 289 | CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, imageSize.width, 290 | imageSize.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 291 | &pxbuffer); 292 | NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 293 | 294 | CVPixelBufferLockBaseAddress(pxbuffer, 0); 295 | void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 296 | NSParameterAssert(pxdata != NULL); 297 | 298 | CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 299 | CGContextRef context = CGBitmapContextCreate(pxdata, imageSize.width, 300 | imageSize.height, 8, 4*imageSize.width, rgbColorSpace, 301 | kCGImageAlphaNoneSkipFirst); 302 | NSParameterAssert(context); 303 | 304 | CGContextDrawImage(context, CGRectMake(0 + (imageSize.width-CGImageGetWidth(image))/2, 305 | (imageSize.height-CGImageGetHeight(image))/2, 306 | CGImageGetWidth(image), 307 | CGImageGetHeight(image)), image); 308 | CGColorSpaceRelease(rgbColorSpace); 309 | CGContextRelease(context); 310 | 311 | CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 312 | 313 | return pxbuffer; 314 | } 315 | 316 | + (CVPixelBufferRef)crossFadeImage:(CGImageRef)baseImage 317 | toImage:(CGImageRef)fadeInImage 318 | atSize:(CGSize)imageSize 319 | withAlpha:(CGFloat)alpha 320 | { 321 | NSDictionary *options = @{(id)kCVPixelBufferCGImageCompatibilityKey: @YES, 322 | (id)kCVPixelBufferCGBitmapContextCompatibilityKey: @YES}; 323 | CVPixelBufferRef pxbuffer = NULL; 324 | CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, imageSize.width, 325 | imageSize.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 326 | &pxbuffer); 327 | NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 328 | 329 | CVPixelBufferLockBaseAddress(pxbuffer, 0); 330 | void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 331 | NSParameterAssert(pxdata != NULL); 332 | 333 | CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 334 | CGContextRef context = CGBitmapContextCreate(pxdata, imageSize.width, 335 | imageSize.height, 8, 4*imageSize.width, rgbColorSpace, 336 | kCGImageAlphaNoneSkipFirst); 337 | NSParameterAssert(context); 338 | 339 | CGRect drawRect = CGRectMake(0 + (imageSize.width-CGImageGetWidth(baseImage))/2, 340 | (imageSize.height-CGImageGetHeight(baseImage))/2, 341 | CGImageGetWidth(baseImage), 342 | CGImageGetHeight(baseImage)); 343 | 344 | CGContextDrawImage(context, drawRect, baseImage); 345 | 346 | CGContextBeginTransparencyLayer(context, nil); 347 | CGContextSetAlpha( context, alpha ); 348 | CGContextDrawImage(context, drawRect, fadeInImage); 349 | CGContextEndTransparencyLayer(context); 350 | 351 | CGColorSpaceRelease(rgbColorSpace); 352 | CGContextRelease(context); 353 | 354 | CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 355 | 356 | return pxbuffer; 357 | } 358 | 359 | + (BOOL)appendToAdapter:(AVAssetWriterInputPixelBufferAdaptor*)adaptor 360 | pixelBuffer:(CVPixelBufferRef)buffer 361 | atTime:(CMTime)presentTime 362 | withInput:(AVAssetWriterInput*)writerInput 363 | { 364 | while (!writerInput.readyForMoreMediaData) { 365 | usleep(1); 366 | } 367 | 368 | return [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime]; 369 | } 370 | 371 | 372 | 373 | 374 | @end 375 | -------------------------------------------------------------------------------- /BroadcastNew.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 21AF2D22238E6560002BC302 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21AF2D21238E6560002BC302 /* AVFoundation.framework */; }; 11 | 5AFC3ED62032014900E53419 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC3ED52032014900E53419 /* AppDelegate.m */; }; 12 | 5AFC3ED92032014900E53419 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC3ED82032014900E53419 /* ViewController.m */; }; 13 | 5AFC3EDC2032014900E53419 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5AFC3EDA2032014900E53419 /* Main.storyboard */; }; 14 | 5AFC3EDE2032014900E53419 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5AFC3EDD2032014900E53419 /* Assets.xcassets */; }; 15 | 5AFC3EE12032014900E53419 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5AFC3EDF2032014900E53419 /* LaunchScreen.storyboard */; }; 16 | 5AFC3EE42032014900E53419 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC3EE32032014900E53419 /* main.m */; }; 17 | 5AFC3F0D2032017400E53419 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5AFC3F0C2032017400E53419 /* ReplayKit.framework */; }; 18 | 5AFC3F112032017500E53419 /* SampleHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5AFC3F102032017500E53419 /* SampleHandler.m */; }; 19 | 5AFC3F252032017500E53419 /* BroadcastUploadNew.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 5AFC3F0A2032017400E53419 /* BroadcastUploadNew.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 5AFC3F232032017500E53419 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 5AFC3EC92032014900E53419 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 5AFC3F092032017400E53419; 28 | remoteInfo = BroadcastUploadNew; 29 | }; 30 | /* End PBXContainerItemProxy section */ 31 | 32 | /* Begin PBXCopyFilesBuildPhase section */ 33 | 5AFC3F2C2032017500E53419 /* Embed App Extensions */ = { 34 | isa = PBXCopyFilesBuildPhase; 35 | buildActionMask = 2147483647; 36 | dstPath = ""; 37 | dstSubfolderSpec = 13; 38 | files = ( 39 | 5AFC3F252032017500E53419 /* BroadcastUploadNew.appex in Embed App Extensions */, 40 | ); 41 | name = "Embed App Extensions"; 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXCopyFilesBuildPhase section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 215936DE238D183900FF4864 /* BroadcastNew.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BroadcastNew.entitlements; sourceTree = ""; }; 48 | 215936DF238D185E00FF4864 /* BroadcastUploadNew.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = BroadcastUploadNew.entitlements; sourceTree = ""; }; 49 | 21AF2D21238E6560002BC302 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 50 | 5AFC3ED12032014900E53419 /* BroadcastNew.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BroadcastNew.app; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 5AFC3ED42032014900E53419 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 52 | 5AFC3ED52032014900E53419 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 53 | 5AFC3ED72032014900E53419 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 54 | 5AFC3ED82032014900E53419 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 55 | 5AFC3EDB2032014900E53419 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 56 | 5AFC3EDD2032014900E53419 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 57 | 5AFC3EE02032014900E53419 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 58 | 5AFC3EE22032014900E53419 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 5AFC3EE32032014900E53419 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 60 | 5AFC3F0A2032017400E53419 /* BroadcastUploadNew.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = BroadcastUploadNew.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 5AFC3F0C2032017400E53419 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; }; 62 | 5AFC3F0F2032017500E53419 /* SampleHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleHandler.h; sourceTree = ""; }; 63 | 5AFC3F102032017500E53419 /* SampleHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleHandler.m; sourceTree = ""; }; 64 | 5AFC3F122032017500E53419 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | 5AFC3ECE2032014900E53419 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 5AFC3F072032017400E53419 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | 21AF2D22238E6560002BC302 /* AVFoundation.framework in Frameworks */, 80 | 5AFC3F0D2032017400E53419 /* ReplayKit.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | 5AFC3EC82032014900E53419 = { 88 | isa = PBXGroup; 89 | children = ( 90 | 5AFC3ED32032014900E53419 /* BroadcastNew */, 91 | 5AFC3F0E2032017500E53419 /* BroadcastUploadNew */, 92 | 5AFC3F0B2032017400E53419 /* Frameworks */, 93 | 5AFC3ED22032014900E53419 /* Products */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | 5AFC3ED22032014900E53419 /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 5AFC3ED12032014900E53419 /* BroadcastNew.app */, 101 | 5AFC3F0A2032017400E53419 /* BroadcastUploadNew.appex */, 102 | ); 103 | name = Products; 104 | sourceTree = ""; 105 | }; 106 | 5AFC3ED32032014900E53419 /* BroadcastNew */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 215936DE238D183900FF4864 /* BroadcastNew.entitlements */, 110 | 5AFC3ED42032014900E53419 /* AppDelegate.h */, 111 | 5AFC3ED52032014900E53419 /* AppDelegate.m */, 112 | 5AFC3ED72032014900E53419 /* ViewController.h */, 113 | 5AFC3ED82032014900E53419 /* ViewController.m */, 114 | 5AFC3EDA2032014900E53419 /* Main.storyboard */, 115 | 5AFC3EDD2032014900E53419 /* Assets.xcassets */, 116 | 5AFC3EDF2032014900E53419 /* LaunchScreen.storyboard */, 117 | 5AFC3EE22032014900E53419 /* Info.plist */, 118 | 5AFC3EE32032014900E53419 /* main.m */, 119 | ); 120 | path = BroadcastNew; 121 | sourceTree = ""; 122 | }; 123 | 5AFC3F0B2032017400E53419 /* Frameworks */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 21AF2D21238E6560002BC302 /* AVFoundation.framework */, 127 | 5AFC3F0C2032017400E53419 /* ReplayKit.framework */, 128 | ); 129 | name = Frameworks; 130 | sourceTree = ""; 131 | }; 132 | 5AFC3F0E2032017500E53419 /* BroadcastUploadNew */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 215936DF238D185E00FF4864 /* BroadcastUploadNew.entitlements */, 136 | 5AFC3F0F2032017500E53419 /* SampleHandler.h */, 137 | 5AFC3F102032017500E53419 /* SampleHandler.m */, 138 | 5AFC3F122032017500E53419 /* Info.plist */, 139 | ); 140 | path = BroadcastUploadNew; 141 | sourceTree = ""; 142 | }; 143 | /* End PBXGroup section */ 144 | 145 | /* Begin PBXNativeTarget section */ 146 | 5AFC3ED02032014900E53419 /* BroadcastNew */ = { 147 | isa = PBXNativeTarget; 148 | buildConfigurationList = 5AFC3EFD2032014900E53419 /* Build configuration list for PBXNativeTarget "BroadcastNew" */; 149 | buildPhases = ( 150 | 5AFC3ECD2032014900E53419 /* Sources */, 151 | 5AFC3ECE2032014900E53419 /* Frameworks */, 152 | 5AFC3ECF2032014900E53419 /* Resources */, 153 | 5AFC3F2C2032017500E53419 /* Embed App Extensions */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | 5AFC3F242032017500E53419 /* PBXTargetDependency */, 159 | ); 160 | name = BroadcastNew; 161 | productName = BroadcastNew; 162 | productReference = 5AFC3ED12032014900E53419 /* BroadcastNew.app */; 163 | productType = "com.apple.product-type.application"; 164 | }; 165 | 5AFC3F092032017400E53419 /* BroadcastUploadNew */ = { 166 | isa = PBXNativeTarget; 167 | buildConfigurationList = 5AFC3F292032017500E53419 /* Build configuration list for PBXNativeTarget "BroadcastUploadNew" */; 168 | buildPhases = ( 169 | 5AFC3F062032017400E53419 /* Sources */, 170 | 5AFC3F072032017400E53419 /* Frameworks */, 171 | 5AFC3F082032017400E53419 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | ); 177 | name = BroadcastUploadNew; 178 | productName = BroadcastUploadNew; 179 | productReference = 5AFC3F0A2032017400E53419 /* BroadcastUploadNew.appex */; 180 | productType = "com.apple.product-type.app-extension"; 181 | }; 182 | /* End PBXNativeTarget section */ 183 | 184 | /* Begin PBXProject section */ 185 | 5AFC3EC92032014900E53419 /* Project object */ = { 186 | isa = PBXProject; 187 | attributes = { 188 | LastUpgradeCheck = 0920; 189 | ORGANIZATIONNAME = Anirban; 190 | TargetAttributes = { 191 | 5AFC3ED02032014900E53419 = { 192 | CreatedOnToolsVersion = 9.2; 193 | ProvisioningStyle = Automatic; 194 | SystemCapabilities = { 195 | com.apple.ApplicationGroups.iOS = { 196 | enabled = 1; 197 | }; 198 | }; 199 | }; 200 | 5AFC3F092032017400E53419 = { 201 | CreatedOnToolsVersion = 9.2; 202 | ProvisioningStyle = Automatic; 203 | SystemCapabilities = { 204 | com.apple.ApplicationGroups.iOS = { 205 | enabled = 1; 206 | }; 207 | }; 208 | }; 209 | }; 210 | }; 211 | buildConfigurationList = 5AFC3ECC2032014900E53419 /* Build configuration list for PBXProject "BroadcastNew" */; 212 | compatibilityVersion = "Xcode 8.0"; 213 | developmentRegion = en; 214 | hasScannedForEncodings = 0; 215 | knownRegions = ( 216 | en, 217 | Base, 218 | ); 219 | mainGroup = 5AFC3EC82032014900E53419; 220 | productRefGroup = 5AFC3ED22032014900E53419 /* Products */; 221 | projectDirPath = ""; 222 | projectRoot = ""; 223 | targets = ( 224 | 5AFC3ED02032014900E53419 /* BroadcastNew */, 225 | 5AFC3F092032017400E53419 /* BroadcastUploadNew */, 226 | ); 227 | }; 228 | /* End PBXProject section */ 229 | 230 | /* Begin PBXResourcesBuildPhase section */ 231 | 5AFC3ECF2032014900E53419 /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 5AFC3EE12032014900E53419 /* LaunchScreen.storyboard in Resources */, 236 | 5AFC3EDE2032014900E53419 /* Assets.xcassets in Resources */, 237 | 5AFC3EDC2032014900E53419 /* Main.storyboard in Resources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | 5AFC3F082032017400E53419 /* Resources */ = { 242 | isa = PBXResourcesBuildPhase; 243 | buildActionMask = 2147483647; 244 | files = ( 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXResourcesBuildPhase section */ 249 | 250 | /* Begin PBXSourcesBuildPhase section */ 251 | 5AFC3ECD2032014900E53419 /* Sources */ = { 252 | isa = PBXSourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | 5AFC3ED92032014900E53419 /* ViewController.m in Sources */, 256 | 5AFC3EE42032014900E53419 /* main.m in Sources */, 257 | 5AFC3ED62032014900E53419 /* AppDelegate.m in Sources */, 258 | ); 259 | runOnlyForDeploymentPostprocessing = 0; 260 | }; 261 | 5AFC3F062032017400E53419 /* Sources */ = { 262 | isa = PBXSourcesBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | 5AFC3F112032017500E53419 /* SampleHandler.m in Sources */, 266 | ); 267 | runOnlyForDeploymentPostprocessing = 0; 268 | }; 269 | /* End PBXSourcesBuildPhase section */ 270 | 271 | /* Begin PBXTargetDependency section */ 272 | 5AFC3F242032017500E53419 /* PBXTargetDependency */ = { 273 | isa = PBXTargetDependency; 274 | target = 5AFC3F092032017400E53419 /* BroadcastUploadNew */; 275 | targetProxy = 5AFC3F232032017500E53419 /* PBXContainerItemProxy */; 276 | }; 277 | /* End PBXTargetDependency section */ 278 | 279 | /* Begin PBXVariantGroup section */ 280 | 5AFC3EDA2032014900E53419 /* Main.storyboard */ = { 281 | isa = PBXVariantGroup; 282 | children = ( 283 | 5AFC3EDB2032014900E53419 /* Base */, 284 | ); 285 | name = Main.storyboard; 286 | sourceTree = ""; 287 | }; 288 | 5AFC3EDF2032014900E53419 /* LaunchScreen.storyboard */ = { 289 | isa = PBXVariantGroup; 290 | children = ( 291 | 5AFC3EE02032014900E53419 /* Base */, 292 | ); 293 | name = LaunchScreen.storyboard; 294 | sourceTree = ""; 295 | }; 296 | /* End PBXVariantGroup section */ 297 | 298 | /* Begin XCBuildConfiguration section */ 299 | 5AFC3EFB2032014900E53419 /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ALWAYS_SEARCH_USER_PATHS = NO; 303 | CLANG_ANALYZER_NONNULL = YES; 304 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 305 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 306 | CLANG_CXX_LIBRARY = "libc++"; 307 | CLANG_ENABLE_MODULES = YES; 308 | CLANG_ENABLE_OBJC_ARC = YES; 309 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 310 | CLANG_WARN_BOOL_CONVERSION = YES; 311 | CLANG_WARN_COMMA = YES; 312 | CLANG_WARN_CONSTANT_CONVERSION = YES; 313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 314 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INFINITE_RECURSION = YES; 318 | CLANG_WARN_INT_CONVERSION = YES; 319 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 320 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 321 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 322 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 323 | CLANG_WARN_STRICT_PROTOTYPES = YES; 324 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 325 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 326 | CLANG_WARN_UNREACHABLE_CODE = YES; 327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 328 | CODE_SIGN_IDENTITY = "iPhone Developer"; 329 | COPY_PHASE_STRIP = NO; 330 | DEBUG_INFORMATION_FORMAT = dwarf; 331 | ENABLE_STRICT_OBJC_MSGSEND = YES; 332 | ENABLE_TESTABILITY = YES; 333 | GCC_C_LANGUAGE_STANDARD = gnu11; 334 | GCC_DYNAMIC_NO_PIC = NO; 335 | GCC_NO_COMMON_BLOCKS = YES; 336 | GCC_OPTIMIZATION_LEVEL = 0; 337 | GCC_PREPROCESSOR_DEFINITIONS = ( 338 | "DEBUG=1", 339 | "$(inherited)", 340 | ); 341 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 342 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 343 | GCC_WARN_UNDECLARED_SELECTOR = YES; 344 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 345 | GCC_WARN_UNUSED_FUNCTION = YES; 346 | GCC_WARN_UNUSED_VARIABLE = YES; 347 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 348 | MTL_ENABLE_DEBUG_INFO = YES; 349 | ONLY_ACTIVE_ARCH = YES; 350 | SDKROOT = iphoneos; 351 | }; 352 | name = Debug; 353 | }; 354 | 5AFC3EFC2032014900E53419 /* Release */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | ALWAYS_SEARCH_USER_PATHS = NO; 358 | CLANG_ANALYZER_NONNULL = YES; 359 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 360 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 361 | CLANG_CXX_LIBRARY = "libc++"; 362 | CLANG_ENABLE_MODULES = YES; 363 | CLANG_ENABLE_OBJC_ARC = YES; 364 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 365 | CLANG_WARN_BOOL_CONVERSION = YES; 366 | CLANG_WARN_COMMA = YES; 367 | CLANG_WARN_CONSTANT_CONVERSION = YES; 368 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 369 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 370 | CLANG_WARN_EMPTY_BODY = YES; 371 | CLANG_WARN_ENUM_CONVERSION = YES; 372 | CLANG_WARN_INFINITE_RECURSION = YES; 373 | CLANG_WARN_INT_CONVERSION = YES; 374 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 375 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 376 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 377 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 378 | CLANG_WARN_STRICT_PROTOTYPES = YES; 379 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 380 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 381 | CLANG_WARN_UNREACHABLE_CODE = YES; 382 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 383 | CODE_SIGN_IDENTITY = "iPhone Developer"; 384 | COPY_PHASE_STRIP = NO; 385 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 386 | ENABLE_NS_ASSERTIONS = NO; 387 | ENABLE_STRICT_OBJC_MSGSEND = YES; 388 | GCC_C_LANGUAGE_STANDARD = gnu11; 389 | GCC_NO_COMMON_BLOCKS = YES; 390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 392 | GCC_WARN_UNDECLARED_SELECTOR = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 394 | GCC_WARN_UNUSED_FUNCTION = YES; 395 | GCC_WARN_UNUSED_VARIABLE = YES; 396 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 397 | MTL_ENABLE_DEBUG_INFO = NO; 398 | SDKROOT = iphoneos; 399 | VALIDATE_PRODUCT = YES; 400 | }; 401 | name = Release; 402 | }; 403 | 5AFC3EFE2032014900E53419 /* Debug */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 407 | CODE_SIGN_ENTITLEMENTS = BroadcastNew/BroadcastNew.entitlements; 408 | CODE_SIGN_STYLE = Automatic; 409 | DEVELOPMENT_TEAM = M98QB5EGZ2; 410 | INFOPLIST_FILE = BroadcastNew/Info.plist; 411 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 412 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 413 | PRODUCT_BUNDLE_IDENTIFIER = hyjk.TestForLuPing; 414 | PRODUCT_NAME = "$(TARGET_NAME)"; 415 | TARGETED_DEVICE_FAMILY = "1,2"; 416 | }; 417 | name = Debug; 418 | }; 419 | 5AFC3EFF2032014900E53419 /* Release */ = { 420 | isa = XCBuildConfiguration; 421 | buildSettings = { 422 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 423 | CODE_SIGN_ENTITLEMENTS = BroadcastNew/BroadcastNew.entitlements; 424 | CODE_SIGN_STYLE = Automatic; 425 | DEVELOPMENT_TEAM = M98QB5EGZ2; 426 | INFOPLIST_FILE = BroadcastNew/Info.plist; 427 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 428 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 429 | PRODUCT_BUNDLE_IDENTIFIER = hyjk.TestForLuPing; 430 | PRODUCT_NAME = "$(TARGET_NAME)"; 431 | TARGETED_DEVICE_FAMILY = "1,2"; 432 | }; 433 | name = Release; 434 | }; 435 | 5AFC3F2A2032017500E53419 /* Debug */ = { 436 | isa = XCBuildConfiguration; 437 | buildSettings = { 438 | CODE_SIGN_ENTITLEMENTS = BroadcastUploadNew/BroadcastUploadNew.entitlements; 439 | CODE_SIGN_IDENTITY = "Apple Development"; 440 | CODE_SIGN_STYLE = Automatic; 441 | DEVELOPMENT_TEAM = M98QB5EGZ2; 442 | INFOPLIST_FILE = BroadcastUploadNew/Info.plist; 443 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 444 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 445 | PRODUCT_BUNDLE_IDENTIFIER = hyjk.TestForLuPing.upload; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | PROVISIONING_PROFILE_SPECIFIER = ""; 448 | SKIP_INSTALL = YES; 449 | TARGETED_DEVICE_FAMILY = "1,2"; 450 | }; 451 | name = Debug; 452 | }; 453 | 5AFC3F2B2032017500E53419 /* Release */ = { 454 | isa = XCBuildConfiguration; 455 | buildSettings = { 456 | CODE_SIGN_ENTITLEMENTS = BroadcastUploadNew/BroadcastUploadNew.entitlements; 457 | CODE_SIGN_IDENTITY = "Apple Development"; 458 | CODE_SIGN_STYLE = Automatic; 459 | DEVELOPMENT_TEAM = M98QB5EGZ2; 460 | INFOPLIST_FILE = BroadcastUploadNew/Info.plist; 461 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 462 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 463 | PRODUCT_BUNDLE_IDENTIFIER = hyjk.TestForLuPing.upload; 464 | PRODUCT_NAME = "$(TARGET_NAME)"; 465 | PROVISIONING_PROFILE_SPECIFIER = ""; 466 | SKIP_INSTALL = YES; 467 | TARGETED_DEVICE_FAMILY = "1,2"; 468 | }; 469 | name = Release; 470 | }; 471 | /* End XCBuildConfiguration section */ 472 | 473 | /* Begin XCConfigurationList section */ 474 | 5AFC3ECC2032014900E53419 /* Build configuration list for PBXProject "BroadcastNew" */ = { 475 | isa = XCConfigurationList; 476 | buildConfigurations = ( 477 | 5AFC3EFB2032014900E53419 /* Debug */, 478 | 5AFC3EFC2032014900E53419 /* Release */, 479 | ); 480 | defaultConfigurationIsVisible = 0; 481 | defaultConfigurationName = Release; 482 | }; 483 | 5AFC3EFD2032014900E53419 /* Build configuration list for PBXNativeTarget "BroadcastNew" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | 5AFC3EFE2032014900E53419 /* Debug */, 487 | 5AFC3EFF2032014900E53419 /* Release */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | 5AFC3F292032017500E53419 /* Build configuration list for PBXNativeTarget "BroadcastUploadNew" */ = { 493 | isa = XCConfigurationList; 494 | buildConfigurations = ( 495 | 5AFC3F2A2032017500E53419 /* Debug */, 496 | 5AFC3F2B2032017500E53419 /* Release */, 497 | ); 498 | defaultConfigurationIsVisible = 0; 499 | defaultConfigurationName = Release; 500 | }; 501 | /* End XCConfigurationList section */ 502 | }; 503 | rootObject = 5AFC3EC92032014900E53419 /* Project object */; 504 | } 505 | --------------------------------------------------------------------------------