抓娃娃版1127

LiveRoomViewController.m 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //
  2. // LiveRoomViewController.m
  3. // OpenLive
  4. //
  5. // Created by GongYuhua on 2016/9/12.
  6. // Copyright © 2016年 Agora. All rights reserved.
  7. //
  8. #import "LiveRoomViewController.h"
  9. #import "VideoSession.h"
  10. #import "VideoViewLayouter.h"
  11. #import "KeyCenter.h"
  12. #import "Reachability/Reachability.h"
  13. @interface LiveRoomViewController () <AgoraRtcEngineDelegate>
  14. /*标题*/
  15. @property (weak, nonatomic) IBOutlet UILabel *roomNameLabel;
  16. /*视图 远程容器视图*/
  17. @property (weak, nonatomic) IBOutlet UIView *remoteContainerView;
  18. /*左下角第一个按钮*/
  19. @property (weak, nonatomic) IBOutlet UIButton *broadcastButton;
  20. /*左下角第二个按钮*/
  21. @property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *sessionButtons;
  22. /*左下角第三个按钮*/
  23. @property (weak, nonatomic) IBOutlet UIButton *audioMuteButton;
  24. /*没用的按钮*/
  25. @property (weak, nonatomic) IBOutlet UIButton *enhancerButton;
  26. /*猜测_直播相关类*/
  27. @property (strong, nonatomic) AgoraRtcEngineKit *rtcEngine;
  28. @property (assign, nonatomic) BOOL isBroadcaster;
  29. @property (assign, nonatomic) BOOL isMuted;
  30. @property (assign, nonatomic) BOOL shouldEnhancer;
  31. /*分屏*/
  32. @property (strong, nonatomic) NSMutableArray<VideoSession *> *videoSessions;
  33. @property (strong, nonatomic) VideoSession *mySession;
  34. /*猜不透*/
  35. @property (strong, nonatomic) VideoSession *fullSession;
  36. /*猜不透2*/
  37. @property (strong, nonatomic) VideoViewLayouter *viewLayouter;
  38. /*网络监听*/
  39. @property (nonatomic, strong) Reachability *hostReachability;
  40. @property(assign,nonatomic) BOOL isReachability;
  41. /*失败显示*/
  42. @property(nonatomic,strong) UILabel *lostNetwork;
  43. @end
  44. @implementation LiveRoomViewController
  45. /*懒加载*/
  46. -(UILabel *)lostNetwork{
  47. if (!_lostNetwork) {
  48. _lostNetwork=[[UILabel alloc]initWithFrame:self.view.bounds];
  49. _lostNetwork.text=@"网络连接失败";
  50. _lostNetwork.textAlignment=NSTextAlignmentCenter;
  51. }
  52. return _lostNetwork;
  53. }
  54. /*成员属性*/
  55. - (BOOL)isBroadcaster {
  56. NSLog(@"isBroadcaster");
  57. return self.clientRole == AgoraRtc_ClientRole_Broadcaster;
  58. //return self.clientRole=AgoraRtc_ClientRole_Audience;
  59. }
  60. - (VideoViewLayouter *)viewLayouter {
  61. if (!_viewLayouter) {
  62. _viewLayouter = [[VideoViewLayouter alloc] init];
  63. }
  64. return _viewLayouter;
  65. }
  66. /*设置角色*/
  67. - (void)setClientRole:(AgoraRtcClientRole)clientRole {
  68. _clientRole = clientRole;
  69. if (self.isBroadcaster) {
  70. self.shouldEnhancer = YES;
  71. }
  72. [self updateButtonsVisiablity];
  73. }
  74. - (void)setIsMuted:(BOOL)isMuted {
  75. _isMuted = isMuted;
  76. [self.rtcEngine muteLocalAudioStream:isMuted];
  77. [self.audioMuteButton setImage:[UIImage imageNamed:(isMuted ? @"btn_mute_cancel" : @"btn_mute")] forState:UIControlStateNormal];
  78. }
  79. - (void)setVideoSessions:(NSMutableArray<VideoSession *> *)videoSessions {
  80. _videoSessions = videoSessions;
  81. if (self.remoteContainerView) {
  82. [self updateInterfaceWithAnimation:YES];
  83. }
  84. }
  85. - (void)setFullSession:(VideoSession *)fullSession {
  86. _fullSession = fullSession;
  87. if (self.remoteContainerView) {
  88. [self updateInterfaceWithAnimation:YES];
  89. }
  90. }
  91. /*生命周期*/
  92. - (void)viewDidLoad {
  93. [super viewDidLoad];
  94. self.videoSessions = [[NSMutableArray alloc] init];
  95. self.roomNameLabel.text = self.roomName;
  96. [self updateButtonsVisiablity];
  97. //当网络改变后,有网络之后重新推流
  98. [self network];
  99. }
  100. /*网络重连*/
  101. -(void)network{
  102. /**网络连接*/
  103. [[NSNotificationCenter defaultCenter] addObserver:self
  104. selector:@selector(reachabilityChanged:)
  105. name: kReachabilityChangedNotification
  106. object: nil];
  107. NSString *remoteHostName = @"www.baidu.com";
  108. NSString *remoteHostLabelFormatString = NSLocalizedString(@"Remote Host: %@", @"Remote host label format string");
  109. UILabel *remoteHostLabel = [[UILabel alloc] init];
  110. remoteHostLabel.text = [NSString stringWithFormat:remoteHostLabelFormatString, remoteHostName];
  111. self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
  112. [self.hostReachability startNotifier];
  113. }
  114. -(void)reachabilityChanged:(NSNotification*)no{
  115. Reachability* curReach = [no object];
  116. NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
  117. NetworkStatus status = [curReach currentReachabilityStatus];
  118. if(status!=NotReachable){
  119. [self.lostNetwork removeFromSuperview];
  120. NSLog(@"可以联网");
  121. //测试删除
  122. if (NO==self.isReachability) {
  123. NSLog(@"可以联网");
  124. // [self.rtcEngine switchCamera];//转换后置
  125. [self loadAgoraKit];
  126. self.isReachability=YES;
  127. }
  128. }else{
  129. [self.view addSubview:self.lostNetwork];
  130. if(self.mySession){
  131. [self.mySession.hostingView removeFromSuperview];
  132. [self.videoSessions removeObject:self.mySession];
  133. }
  134. self.isReachability=NO;
  135. NSLog(@"联网失败");
  136. }
  137. }
  138. /*转换摄像头*/
  139. - (IBAction)doSwitchCameraPressed:(UIButton *)sender {
  140. [self.rtcEngine switchCamera];
  141. }
  142. /*是否有声音*/
  143. - (IBAction)doMutePressed:(UIButton *)sender {
  144. // self.isMuted = !self.isMuted;
  145. //删除
  146. self.isMuted =YES;
  147. }
  148. /*最小化摄像*/
  149. - (IBAction)doBroadcastPressed:(UIButton *)sender {
  150. if (self.isBroadcaster) {
  151. self.clientRole = AgoraRtc_ClientRole_Audience;
  152. if (self.fullSession.uid == 0) {
  153. self.fullSession = nil;
  154. }
  155. } else {
  156. self.clientRole = AgoraRtc_ClientRole_Broadcaster;
  157. }
  158. [self.rtcEngine setClientRole:self.clientRole withKey:nil];
  159. [self updateInterfaceWithAnimation:YES];
  160. }
  161. /*轻击*/
  162. - (IBAction)doDoubleTapped:(UITapGestureRecognizer *)sender {
  163. if (!self.fullSession) {
  164. VideoSession *tappedSession = [self.viewLayouter responseSessionOfGesture:sender inSessions:self.videoSessions inContainerView:self.remoteContainerView];
  165. if (tappedSession) {
  166. self.fullSession = tappedSession;
  167. }
  168. } else {
  169. self.fullSession = nil;
  170. }
  171. }
  172. //关闭
  173. - (IBAction)doLeavePressed:(UIButton *)sender {
  174. // [self.rtcEngine switchCamera];
  175. [self leaveChannel];
  176. }
  177. - (void)updateButtonsVisiablity {
  178. [self.broadcastButton setImage:[UIImage imageNamed:self.isBroadcaster ? @"btn_join_cancel" : @"btn_join"] forState:UIControlStateNormal];
  179. for (UIButton *button in self.sessionButtons) {
  180. button.hidden = !self.isBroadcaster;
  181. }
  182. }
  183. /*离开频道*/
  184. - (void)leaveChannel {
  185. [self setIdleTimerActive:YES];
  186. [self.rtcEngine setupLocalVideo:nil];
  187. [self.rtcEngine leaveChannel:nil];
  188. if (self.isBroadcaster) {
  189. [self.rtcEngine stopPreview];
  190. }
  191. for (VideoSession *session in self.videoSessions) {
  192. [session.hostingView removeFromSuperview];
  193. }
  194. [self.videoSessions removeAllObjects];
  195. if ([self.delegate respondsToSelector:@selector(liveVCNeedClose:)]) {
  196. [self.delegate liveVCNeedClose:self];
  197. }
  198. }
  199. //是否自动锁屏
  200. - (void)setIdleTimerActive:(BOOL)active {
  201. [UIApplication sharedApplication].idleTimerDisabled = !active;
  202. }
  203. /*弹出alert框*/
  204. - (void)alertString:(NSString *)string {
  205. if (!string.length) {
  206. return;
  207. }
  208. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:string preferredStyle:UIAlertControllerStyleAlert];
  209. [alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleCancel handler:nil]];
  210. [self presentViewController:alert animated:YES completion:nil];
  211. }
  212. //带动画更新
  213. - (void)updateInterfaceWithAnimation:(BOOL)animation {
  214. if (animation) {
  215. [UIView animateWithDuration:0.3 animations:^{
  216. [self updateInterface];
  217. //如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
  218. [self.view layoutIfNeeded];
  219. }];
  220. } else {
  221. [self updateInterface];
  222. }
  223. }
  224. /*更新界面*/
  225. - (void)updateInterface {
  226. NSArray *displaySessions;
  227. if (!self.isBroadcaster && self.videoSessions.count) {
  228. displaySessions = [self.videoSessions subarrayWithRange:NSMakeRange(1, self.videoSessions.count - 1)];
  229. } else {
  230. displaySessions = [self.videoSessions copy];
  231. }
  232. [self.viewLayouter layoutSessions:displaySessions fullSession:self.fullSession inContainer:self.remoteContainerView];
  233. [self setStreamTypeForSessions:displaySessions fullSession:self.fullSession];
  234. }
  235. /*更新界面时调用*/
  236. - (void)setStreamTypeForSessions:(NSArray<VideoSession *> *)sessions fullSession:(VideoSession *)fullSession {
  237. if (fullSession) {
  238. for (VideoSession *session in sessions) {
  239. [self.rtcEngine setRemoteVideoStream:session.uid type:(session == self.fullSession ? AgoraRtc_VideoStream_High : AgoraRtc_VideoStream_Low)];
  240. }
  241. } else {
  242. for (VideoSession *session in sessions) {
  243. [self.rtcEngine setRemoteVideoStream:session.uid type:AgoraRtc_VideoStream_High];
  244. }
  245. }
  246. }
  247. - (void)addLocalSession {
  248. VideoSession *localSession = [VideoSession localSession];
  249. self.mySession=localSession;
  250. [self.videoSessions addObject:localSession];
  251. //设置显示画面
  252. [self.rtcEngine setupLocalVideo:localSession.canvas];
  253. [self updateInterfaceWithAnimation:YES];
  254. }
  255. - (VideoSession *)fetchSessionOfUid:(NSUInteger)uid {
  256. for (VideoSession *session in self.videoSessions) {
  257. if (session.uid == uid) {
  258. return session;
  259. }
  260. }
  261. return nil;
  262. }
  263. - (VideoSession *)videoSessionOfUid:(NSUInteger)uid {
  264. VideoSession *fetchedSession = [self fetchSessionOfUid:uid];
  265. if (fetchedSession) {
  266. return fetchedSession;
  267. } else {
  268. VideoSession *newSession = [[VideoSession alloc] initWithUid:uid];
  269. [self.videoSessions addObject:newSession];
  270. [self updateInterfaceWithAnimation:YES];
  271. return newSession;
  272. }
  273. }
  274. //MARK: - Agora Media SDK
  275. - (void)loadAgoraKit {
  276. NSLog(@"%s",__FUNCTION__);
  277. //单例
  278. self.rtcEngine = [AgoraRtcEngineKit sharedEngineWithAppId:[KeyCenter AppId] delegate:self];
  279. //开启静音模式 删除
  280. [self.rtcEngine muteAllRemoteAudioStreams:YES];
  281. [self.rtcEngine setChannelProfile:AgoraRtc_ChannelProfile_LiveBroadcasting];//直播模式
  282. [self.rtcEngine enableDualStreamMode:YES];//双流
  283. [self.rtcEngine enableVideo];
  284. [self.rtcEngine setVideoProfile:self.videoProfile swapWidthAndHeight:YES];
  285. [self.rtcEngine setClientRole:self.clientRole withKey:nil];
  286. if (self.isBroadcaster) {
  287. //开始视频预览
  288. [self.rtcEngine startPreview];
  289. }
  290. //添加会话
  291. [self addLocalSession];
  292. [self.rtcEngine enableWebSdkInteroperability:YES];
  293. // [self.rtcEngine switchCamera];//转换后置
  294. //这儿好像不对。。。
  295. int code = [self.rtcEngine joinChannelByKey:nil channelName:self.roomName info:nil uid:self.uid joinSuccess:^(NSString *channel, NSUInteger uid, NSInteger elapsed) {
  296. NSLog(@"加入成功");
  297. }];
  298. if (code == 0) {
  299. [self setIdleTimerActive:NO];
  300. } else {
  301. dispatch_async(dispatch_get_main_queue(), ^{
  302. [self alertString:[NSString stringWithFormat:@"Join channel failed: %d", code]];
  303. });
  304. }
  305. if (self.isBroadcaster) {
  306. self.shouldEnhancer = YES;
  307. }
  308. }
  309. //有主播加入时,调用该方法
  310. - (void)rtcEngine:(AgoraRtcEngineKit *)engine didJoinedOfUid:(NSUInteger)uid elapsed:(NSInteger)elapsed {
  311. VideoSession *userSession = [self videoSessionOfUid:uid];
  312. NSLog(@"%s __%li",__FUNCTION__,uid);
  313. [self.rtcEngine setupRemoteVideo:userSession.canvas];
  314. }
  315. //本地显示首帧调用
  316. - (void)rtcEngine:(AgoraRtcEngineKit *)engine firstLocalVideoFrameWithSize:(CGSize)size elapsed:(NSInteger)elapsed {
  317. NSLog(@"%s",__FUNCTION__);
  318. if (self.videoSessions.count) {
  319. [self updateInterfaceWithAnimation:NO];
  320. }
  321. }
  322. //主播离线回调
  323. - (void)rtcEngine:(AgoraRtcEngineKit *)engine didOfflineOfUid:(NSUInteger)uid reason:(AgoraRtcUserOfflineReason)reason {
  324. NSLog(@"%s__uid:%li",__FUNCTION__,uid);
  325. VideoSession *deleteSession;
  326. for (VideoSession *session in self.videoSessions) {
  327. if (session.uid == uid) {
  328. deleteSession = session;
  329. }
  330. }
  331. if (deleteSession) {
  332. [self.videoSessions removeObject:deleteSession];
  333. [deleteSession.hostingView removeFromSuperview];
  334. [self updateInterfaceWithAnimation:YES];
  335. if (deleteSession == self.fullSession) {
  336. self.fullSession = nil;
  337. }
  338. }
  339. }
  340. - (void)rtcEngine:(AgoraRtcEngineKit *)engine didOccurError:(AgoraRtcErrorCode)errorCode{
  341. NSLog(@"engine:%@",engine);
  342. NSLog(@"errorCode:%li",errorCode);
  343. }
  344. @end