SampleHandler.m 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. //
  2. // SampleHandler.m
  3. // ScreenRecorder
  4. //
  5. // Created by Drew on 2019/5/9.
  6. // Copyright © 2019 The Chromium Authors. All rights reserved.
  7. //
  8. #import "SampleHandler.h"
  9. #import <TXLiteAVSDK.h>
  10. #import <UserNotifications/UserNotifications.h>
  11. static TXLivePush *s_txLivePublisher;
  12. static CMSampleBufferRef s_lastSampleBuffer;
  13. static int lastOrientation;
  14. static int count;
  15. //static void onDarwinPushStart(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
  16. // [[NSNotificationCenter defaultCenter] postNotificationName:@"Cocoa_Push_Start" object:nil];
  17. //}
  18. static void onDarwinPushStop(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
  19. [[NSNotificationCenter defaultCenter] postNotificationName:@"Cocoa_Push_Stop" object:nil];
  20. }
  21. @implementation SampleHandler
  22. - (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {
  23. NSString * const licenceURL = @"http://license.vod2.myqcloud.com/license/v1/2aad7d0c26cbafa510f506e2e2d1d236/TXLiveSDK.licence";
  24. NSString * const licenceKey = @"f3c8f4b74b652844487695112ead19cd";
  25. [TXLiveBase setLicenceURL:licenceURL key:licenceKey];
  26. // CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
  27. // (__bridge const void *)(self),
  28. // onDarwinPushStart,
  29. // CFSTR("PUSH_START"),
  30. // NULL,
  31. // CFNotificationSuspensionBehaviorDeliverImmediately);
  32. CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
  33. (__bridge const void *)(self),
  34. onDarwinPushStop,
  35. CFSTR("PUSH_STOP"),
  36. NULL,
  37. CFNotificationSuspensionBehaviorDeliverImmediately);
  38. // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePushStartNotification:) name:@"Cocoa_Push_Start" object:nil];
  39. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlePushStopNotification:) name:@"Cocoa_Push_Stop" object:nil];
  40. if (s_txLivePublisher) {
  41. [s_txLivePublisher stopPush];
  42. }
  43. TXLivePushConfig* config = [[TXLivePushConfig alloc] init];
  44. config.audioChannels = 0;
  45. config.customModeType |= CUSTOM_MODE_VIDEO_CAPTURE; //自定义视频模式
  46. config.enableAutoBitrate = YES;
  47. config.enableHWAcceleration = YES;
  48. config.customModeType |= CUSTOM_MODE_AUDIO_CAPTURE; //自定义音频模式
  49. config.audioSampleRate = AUDIO_SAMPLE_RATE_44100; //系统录屏的音频采样率为44100
  50. config.audioChannels = 1;
  51. //config.autoSampleBufferSize = YES;
  52. config.autoSampleBufferSize = NO;
  53. int width = [UIScreen mainScreen].bounds.size.width;
  54. int height = [UIScreen mainScreen].bounds.size.height;
  55. if(width < height){
  56. int tmp = width;
  57. width = height;
  58. height = tmp;
  59. }
  60. float scale = 1.0;
  61. if(width / (float)height > 1280 / 720.f){
  62. scale = 1280.f / width;
  63. } else {
  64. scale = 720.f / height;
  65. }
  66. config.sampleBufferSize = CGSizeMake((int)(width * scale), (int)(height * scale));
  67. config.homeOrientation = HOME_ORIENTATION_RIGHT;
  68. s_txLivePublisher = [[TXLivePush alloc] initWithConfig:config];
  69. NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.long.dianjing"];
  70. NSString *rtmpUrl = [userDefaults objectForKey:@"rtmpUrl"];
  71. // NSString *rtmpUrl = @"rtmp://202.79.174.56:1935/test/test";
  72. if (rtmpUrl == nil) {
  73. [self sendLocalNotificationToHostAppWithTitle:@"比赛未开始" msg:@"开始比赛后才能录屏" userInfo:@{@"id":@"LOCAL_NOTIFY_SCHEDULE_ID"}];
  74. NSString *domain = @"com.long.dianjing.ScreenRecorder";
  75. NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey : @"比赛未开始" };
  76. NSError *error = [NSError errorWithDomain:domain
  77. code:-101
  78. userInfo:userInfo];
  79. [self finishBroadcastWithError:error];
  80. return;
  81. }
  82. [self sendLocalNotificationToHostAppWithTitle:@"录屏已开始" msg:@"请开始游戏" userInfo:@{@"id":@"LOCAL_NOTIFY_SCHEDULE_ID"}];
  83. [s_txLivePublisher startPush:rtmpUrl];
  84. }
  85. //- (void)handlePushStartNotification:(NSNotification*)noti {
  86. // NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.long.dianjing"];
  87. // NSString *rtmpUrl = [userDefaults objectForKey:@"rtmpUrl"];
  88. // if (rtmpUrl == nil) {
  89. // [self sendLocalNotificationToHostAppWithTitle:@"比赛未开始" msg:@"开始比赛后才能录屏" userInfo:@{@"id":@"LOCAL_NOTIFY_SCHEDULE_ID"}];
  90. // return;
  91. // }
  92. // [s_txLivePublisher startPush:rtmpUrl];
  93. //
  94. // [self sendLocalNotificationToHostAppWithTitle:@"录屏已开始" msg:@"请开始游戏" userInfo:@{@"id":@"LOCAL_NOTIFY_SCHEDULE_ID"}];
  95. //}
  96. //
  97. - (void)handlePushStopNotification:(NSNotification*)noti {
  98. NSString *domain = @"com.long.dianjing.ScreenRecorder";
  99. NSDictionary *userInfo = @{ NSLocalizedFailureReasonErrorKey : @"比赛完成" };
  100. NSError *error = [NSError errorWithDomain:domain
  101. code:-101
  102. userInfo:userInfo];
  103. if (s_txLivePublisher) {
  104. [s_txLivePublisher stopPush];
  105. s_txLivePublisher = nil;
  106. [self sendLocalNotificationToHostAppWithTitle:@"录屏已结束" msg:@"请等待结算" userInfo:@{@"id":@"LOCAL_NOTIFY_SCHEDULE_ID"}];
  107. }
  108. [self finishBroadcastWithError:error];
  109. }
  110. - (void)broadcastPaused {
  111. [s_txLivePublisher setSendAudioSampleBufferMuted:YES];
  112. }
  113. - (void)broadcastResumed {
  114. [s_txLivePublisher setSendAudioSampleBufferMuted:NO];
  115. }
  116. - (void)broadcastFinished {
  117. if (s_txLivePublisher) {
  118. [s_txLivePublisher stopPush];
  119. s_txLivePublisher = nil;
  120. [self sendLocalNotificationToHostAppWithTitle:@"录屏已结束" msg:@"请等待结算" userInfo:@{@"id":@"LOCAL_NOTIFY_SCHEDULE_ID"}];
  121. }
  122. }
  123. - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
  124. count++;
  125. count = count % 3;
  126. switch (sampleBufferType) {
  127. case RPSampleBufferTypeVideo:
  128. {
  129. if (!CMSampleBufferIsValid(sampleBuffer))
  130. return;
  131. //保存一帧在startPush时发送,防止推流启动后或切换横竖屏因无画面数据而推流不成功
  132. if (s_lastSampleBuffer) {
  133. CFRelease(s_lastSampleBuffer);
  134. s_lastSampleBuffer = NULL;
  135. }
  136. s_lastSampleBuffer = sampleBuffer;
  137. CFRetain(s_lastSampleBuffer);
  138. if (count == 2) {
  139. int orientation = [(__bridge NSString *)CMGetAttachment(sampleBuffer, (CFStringRef)RPVideoSampleOrientationKey, nil) intValue];
  140. if (lastOrientation == 0) {
  141. lastOrientation = orientation;
  142. } else if (orientation != lastOrientation) {
  143. if(8 == orientation){
  144. TXLivePushConfig* config = [s_txLivePublisher config];
  145. config.homeOrientation = HOME_ORIENTATION_LEFT;
  146. [s_txLivePublisher setConfig:config];
  147. } else if(6 == orientation){
  148. TXLivePushConfig* config = [s_txLivePublisher config];
  149. config.homeOrientation = HOME_ORIENTATION_RIGHT;
  150. [s_txLivePublisher setConfig:config];
  151. }
  152. NSLog(@"orientation change to %d", orientation);
  153. lastOrientation = orientation;
  154. }
  155. }
  156. [s_txLivePublisher sendVideoSampleBuffer:sampleBuffer];
  157. }
  158. break;
  159. case RPSampleBufferTypeAudioApp:
  160. // Handle audio sample buffer for app audio
  161. break;
  162. case RPSampleBufferTypeAudioMic:
  163. // Handle audio sample buffer for mic audio
  164. break;
  165. default:
  166. break;
  167. }
  168. }
  169. - (void)sendLocalNotificationToHostAppWithTitle:(NSString*)title msg:(NSString*)msg userInfo:(NSDictionary*)userInfo
  170. {
  171. UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
  172. UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
  173. content.title = [NSString localizedUserNotificationStringForKey:title arguments:nil];
  174. content.body = [NSString localizedUserNotificationStringForKey:msg arguments:nil];
  175. content.sound = [UNNotificationSound defaultSound];
  176. content.userInfo = userInfo;
  177. // 在设定时间后推送本地推送
  178. UNTimeIntervalNotificationTrigger* trigger = [UNTimeIntervalNotificationTrigger
  179. triggerWithTimeInterval:0.1f repeats:NO];
  180. UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:@"ReplayKit2Demo"
  181. content:content trigger:trigger];
  182. //添加推送成功后的处理!
  183. [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
  184. }];
  185. }
  186. @end