webRtcPlayerViewController.m 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453
  1. //
  2. // webRtcPlayerViewController.m
  3. // 双子星云手机
  4. //
  5. // Created by xd h on 2024/9/2.
  6. //
  7. #import "webRtcPlayerViewController.h"
  8. #import "webRtcPlayerViewController+AdjustBtnFrame.h"
  9. #import "webRtcPlayerViewController+AdjustPlayerViewFrame.h"
  10. #import "webRtcPlayerViewController+AppDelegate.h"
  11. #import "playerSetView.h"
  12. @interface webRtcPlayerViewController ()<MediaStreamClientEventsDelegate>
  13. {
  14. BOOL outputVolumeKVO;/*标记声音监听通知*/
  15. double lastTimestamp;/*最后一帧时间戳*/
  16. NSNumber *lastBytesReceived;/*最后一帧数据量*/
  17. //记录上次 线性增长接收包数
  18. long lasPacketsReceived;
  19. //记录上次 总丢包数据
  20. long lastAlllostData;
  21. BOOL isExitType;//退出云机
  22. NSInteger checkLinkTimerNumber;//0 --2 开始发起重连
  23. NSInteger preDelayedMS;//记录上一次延时数据 控制controlBtn 的图片刷新 非必要 不刷新
  24. NSInteger tryRelinkNum;//重连次数
  25. }
  26. @property (nonatomic, copy) NSTimer *playerSecondTimer; // 定时器-控制按钮
  27. @property (nonatomic, assign) RTCIceConnectionState linkState;
  28. @property (nonatomic, assign) BOOL didHandleRotation;//第一次处理旋转
  29. @property (nonatomic, assign) BOOL didReportWebRtcType;//上报打洞是否成功
  30. @property (nonatomic, strong)playerSetView *playerSetV;//推流设置页
  31. @end
  32. @implementation webRtcPlayerViewController
  33. @synthesize controlBtn;
  34. @synthesize isLan;
  35. - (void)viewDidLoad {
  36. [super viewDidLoad];
  37. // Do any additional setup after loading the view.
  38. [self.toolBar setHidden:YES];
  39. [self.navigationBar setHidden:YES];
  40. [self.navBarBGView setHidden:YES];
  41. [self.view setBackgroundColor:[UIColor blackColor]];
  42. if([DFPlayer sharedPlayer].state == DFPlayerStateBuffering
  43. ||[DFPlayer sharedPlayer].state == DFPlayerStatePlaying){
  44. _isCodeSuspendAudioType = YES;
  45. [[DFPlayer sharedPlayer] df_pause];
  46. }
  47. }
  48. - (void)viewWillAppear:(BOOL)animated {
  49. [super viewWillAppear:animated];
  50. // 屏幕常亮
  51. [UIApplication sharedApplication].idleTimerDisabled = YES;
  52. [[UIApplication sharedApplication] setStatusBarHidden:YES];
  53. }
  54. - (void)viewDidAppear:(BOOL)animated
  55. {
  56. [super viewDidAppear:animated];
  57. [self noEnablePanRightBack];
  58. [self addKVOObserverFun];
  59. //ksharedAppDelegate.supportScreenRotateType = YES;
  60. }
  61. - (void)viewDidDisappear:(BOOL)animated{
  62. [super viewDidDisappear:animated];
  63. [self HandleSomethingByExitVC];
  64. }
  65. //- (BOOL)shouldAutorotate {
  66. // // 根据你的需求来决定是否允许自动旋转
  67. // // 这里我们默认不允许,除非有特定的逻辑允许
  68. // return NO; // 或者根据某个条件返回YES
  69. //}
  70. #pragma mark 退出事件处理
  71. -(void)HandleSomethingByExitVC
  72. {
  73. [UIApplication sharedApplication].idleTimerDisabled = NO;
  74. [[UIApplication sharedApplication] setStatusBarHidden:NO];
  75. isExitType = YES;
  76. if(_mediaStream){
  77. [_mediaStream disconnect];
  78. _mediaStream = nil;
  79. }
  80. [self enablePanRightBack];
  81. [self removeKVOObserverFun];
  82. ksharedAppDelegate.supportScreenRotateType = NO;
  83. ksharedAppDelegate.isPlayerScreenLandscapeType = NO;
  84. [self removeNewIndicator];
  85. if(_playerSecondTimer){
  86. [_playerSecondTimer invalidate];
  87. _playerSecondTimer = nil;
  88. }
  89. _webRtcMsgMod = nil;
  90. }
  91. - (void)setWebRtcMsgMod:(webRtcMsgModel *)webRtcMsgMod
  92. {
  93. _webRtcMsgMod = webRtcMsgMod;
  94. [self beginWebRtcPlayFun];
  95. }
  96. #pragma mark 开始拉流
  97. - (void)beginWebRtcPlayFun
  98. {
  99. if(_mediaStream){
  100. //[_mediaStream disconnect];
  101. //[_mediaStream removeFromSuperview];
  102. //_mediaStream = nil;
  103. }
  104. _mediaStream = [[RTC_OBJC_TYPE(AMediaStream) alloc] initWithFrame:CGRectZero];
  105. [_mediaStream setEventDelegate:self];
  106. [self.view addSubview:_mediaStream];
  107. HLog(@"_mediaStream:%@",_mediaStream)
  108. [_mediaStream mas_makeConstraints:^(MASConstraintMaker *make) {
  109. make.left.mas_equalTo(0.f);
  110. make.bottom.mas_equalTo(0.f);
  111. make.right.mas_equalTo(0.f);
  112. make.top.mas_equalTo(0.f);
  113. }];
  114. //判断是否是全屏
  115. BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show];
  116. NSInteger curResolution = [HWDataManager getIntegerWithKey:Const_cloudPhone_cur_resolution];
  117. CGFloat curWidth = 720.0;
  118. CGFloat curHeight = 1280.0;
  119. if(curResolution == 0 || curResolution == 1){
  120. curWidth = 720.0;
  121. curHeight = 1280.0;
  122. }
  123. else{
  124. curWidth = 1080.0;
  125. curHeight = 1920.0;
  126. }
  127. CGSize phoneSize = CGSizeMake(curWidth, curHeight);
  128. //云机分辨率被改成 720.0, 1280.0
  129. // if(ksharedAppDelegate.couldPhone_W_PHONE == 720 && ksharedAppDelegate.couldPhone_H_PHONE == 1280) {//云机可能存在的分辨率
  130. // phoneSize = CGSizeMake(720.0, 1280.0);
  131. // }
  132. if(fullscreenType){
  133. phoneSize = [RCCommandHelp commondToSetFullScreenPhoneSizeBySize];
  134. }
  135. [self linkWebRtcFunWithSize:phoneSize];
  136. [self initBaseUIFun];
  137. [self setTimerCountDown];
  138. [self showNewIndicatorWithCanBack:YES canTouch:NO];
  139. }
  140. #pragma mark 链接webrtc
  141. - (void)linkWebRtcFunWithSize:(CGSize)phoneSize
  142. {
  143. //链接用
  144. NSString *signallingUrl = [[NSString alloc] initWithFormat:@"%@:%@",_webRtcMsgMod.data.signalling.domainName,_webRtcMsgMod.data.signalling.port];
  145. NSURL *url = [NSURL URLWithString:signallingUrl];
  146. //ice用
  147. NSString *iceUrl = [[NSString alloc] initWithFormat:@"%@:%@",_webRtcMsgMod.data.turn.domainName,_webRtcMsgMod.data.turn.port];
  148. NSMutableDictionary *ice = [NSMutableDictionary new];
  149. if(iceUrl){
  150. [ice setValue:iceUrl forKey:@"CHINANET"];
  151. [ice setValue:iceUrl forKey:@"CMNET"];
  152. [ice setValue:iceUrl forKey:@"UNICOM"];
  153. }
  154. NSString *roomName = _webRtcMsgMod.data.uniqueIdentifier;
  155. NSInteger cardDensity = 320;//480;
  156. //判断是否是全屏
  157. BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show];
  158. if(fullscreenType){
  159. //cardDensity = 380;
  160. //cardDensity = 320;
  161. //cardDensity = 480;
  162. }
  163. //码率根据网络设置 wifi 8M 移动网络 4M ->改为 4M 2M
  164. NSInteger bitrate = 4*1024;
  165. if([AFNetworkReachabilityManager sharedManager].isReachableViaWWAN){
  166. bitrate = 2*1024;
  167. }
  168. //1.盒子开始写20秒日志
  169. //start 拉流前调用设置本次拉流记录推流端日志到指定文件与记录时间 秒 单位。
  170. //filePathName = /sdcard/webrtc_box.log captureTime = 30s
  171. [_mediaStream setCardLogToFile:@"/sdcard/webrtc_box.log" captureTime:@"20"];
  172. //2.客户端开始写日志
  173. [ksharedAppDelegate.WebRtcLogger start];
  174. NSInteger result = [_mediaStream start:url
  175. ice:ice
  176. sn:roomName
  177. direct:0
  178. fmt:1//1(h264) 5(h265)
  179. videoWidth:(NSInteger)phoneSize.width
  180. videoHeight:(NSInteger)phoneSize.height
  181. fps:30
  182. bitrate:bitrate//3200//3000
  183. cardWidth:(NSInteger)phoneSize.width//0//1080//0
  184. cardHeight:(NSInteger)phoneSize.height//0//1920//0
  185. cardDensity:cardDensity
  186. token:@"vclusters"];
  187. HLog(@"result:%ld",result)
  188. [_mediaStream setShouldGetStats:YES];
  189. //清晰度码率最大上限 流畅1800 标清2200 高清2800 跟上面的 bitrate是同一个意思
  190. //[_mediaStream setMaxBitrate:@2800];
  191. }
  192. #pragma mark 重连
  193. - (void)relinkWebRtcFun
  194. {
  195. // if(_linkState == RTCIceConnectionStateConnected
  196. // || _linkState == RTCIceConnectionStateCompleted)
  197. // {//链接中 不处理重连事件
  198. // HLog(@"链接中 不处理重连事件")
  199. // return;
  200. // }
  201. if(isExitType){
  202. return;
  203. }
  204. HLog(@"发起重连 ......")
  205. KWeakSelf
  206. mainBlock(^{
  207. [weakSelf showNewIndicatorWithCanBack:YES canTouch:NO];
  208. NSInteger curResolution = [HWDataManager getIntegerWithKey:Const_cloudPhone_cur_resolution];
  209. CGFloat curWidth = 720.0;
  210. CGFloat curHeight = 1280.0;
  211. if(curResolution == 0 || curResolution == 1){
  212. curWidth = 720.0;
  213. curHeight = 1280.0;
  214. }
  215. else{
  216. curWidth = 1080.0;
  217. curHeight = 1920.0;
  218. }
  219. //判断是否是全屏
  220. BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show];
  221. CGSize phoneSize = CGSizeMake(curWidth, curHeight);
  222. if(fullscreenType){
  223. phoneSize = [RCCommandHelp commondToSetFullScreenPhoneSizeBySize];
  224. }
  225. //客户端停止写日志
  226. [ksharedAppDelegate.WebRtcLogger stop];
  227. [weakSelf linkWebRtcFunWithSize:phoneSize];
  228. });
  229. }
  230. #pragma mark 重连
  231. - (void)relinkWebRtcFunByBecomeActive{
  232. [self.mediaStream disconnect];// 断开会自动重连 防止多路流的清理
  233. }
  234. #pragma mark 初始化其他UI
  235. - (void)initBaseUIFun
  236. {
  237. if(_bottomContrView){
  238. [_bottomContrView removeFromSuperview];
  239. _bottomContrView = nil;
  240. }
  241. _bottomContrView = [[webRtcPlayerBottomContrView alloc] init];
  242. [self.view addSubview:_bottomContrView];
  243. [self getPlayerBottomNavShowOrHidefun];
  244. KWeakSelf
  245. _bottomContrView.didClickButtonFun = ^(NSInteger tag) {
  246. [weakSelf didClickBottomFunBy:tag];
  247. };
  248. /*控制按钮*/
  249. if(controlBtn){
  250. [controlBtn removeFromSuperview];
  251. controlBtn = nil;
  252. }
  253. UIImage *driftBtnImage = [UIImage imageNamed:@"you_icon"];
  254. controlBtn = [[UIButton alloc] init];
  255. [controlBtn setBackgroundColor:[UIColor clearColor]];
  256. [controlBtn setBackgroundImage:driftBtnImage forState:(UIControlStateNormal)];
  257. [controlBtn addTarget:self
  258. action:@selector(controlBtnPressed:)
  259. forControlEvents:(UIControlEventTouchUpInside)];
  260. [self.view addSubview:controlBtn];
  261. //拖拽事件等
  262. UIPanGestureRecognizer *gester = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(controlBtnPanGestureCallback:)];
  263. [controlBtn addGestureRecognizer:gester];
  264. //gester.delegate = self;
  265. [self initPointForControlBtnFun];
  266. }
  267. #pragma mark 设置 controlBtn 的初始位置
  268. - (void)initPointForControlBtnFun
  269. {
  270. CGFloat h_w_controlBtn = 60.f;
  271. /*区分横竖屏*/
  272. if (_mediaStream.hw_w > _mediaStream.hw_h){
  273. [controlBtn setFrame:CGRectMake((_mediaStream.hw_w - h_w_controlBtn)/2.f, _mediaStream.hw_h - h_w_controlBtn - 20.f, h_w_controlBtn, h_w_controlBtn)];
  274. }else{
  275. //默认居右
  276. //[mPlayerView.controlBtn setFrame:CGRectMake(mPlayerView.width - h_w_controlBtn - 20.f, (SCREEN_H - h_w_controlBtn)/2.f, h_w_controlBtn, h_w_controlBtn)];
  277. //默认居左
  278. [controlBtn setFrame:CGRectMake( h_w_controlBtn + 10.f, (SCREEN_H - h_w_controlBtn)/2.f, h_w_controlBtn, h_w_controlBtn)];
  279. }
  280. }
  281. #pragma mark 定时器
  282. - (void)setTimerCountDown {
  283. HLog(@"开启一个");
  284. if (_playerSecondTimer) {
  285. // 取消定时器
  286. [_playerSecondTimer invalidate];
  287. _playerSecondTimer = nil;
  288. }
  289. // 初始化值计时数据
  290. //self.adjustTime = 1;
  291. //self.concentTime = [iTools getNowTimeStamp];
  292. _playerSecondTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(timerChange) userInfo:nil repeats:YES];
  293. [[NSRunLoop currentRunLoop] addTimer:_playerSecondTimer forMode:NSRunLoopCommonModes];
  294. }
  295. #pragma mark 定时器响应事件
  296. - (void)timerChange {
  297. [self extensionAdjustBtnFrameCheckAdjustTime];// 1、悬浮球3s后 自动靠边隐藏
  298. //[self checkConcentTime];// 3、30s之后 没有收到拉流数据 自动断开链接
  299. checkLinkTimerNumber ++;
  300. if(checkLinkTimerNumber == 3){
  301. checkLinkTimerNumber = 0;
  302. if(_linkState != RTCIceConnectionStateConnected
  303. && _linkState != RTCIceConnectionStateCompleted){
  304. if(!_didReportWebRtcType){//还没上报过通道链接情况
  305. tryRelinkNum ++;
  306. if(tryRelinkNum == 6){
  307. tryRelinkNum = 0;
  308. _didReportWebRtcType = YES;
  309. [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:YES withStats:nil];
  310. [self showLinkPhoneErrorFun];
  311. }
  312. }
  313. [self relinkWebRtcFun];
  314. }
  315. }
  316. }
  317. #pragma mark 云机连接不上
  318. - (void)showLinkPhoneErrorFun
  319. {
  320. KWeakSelf
  321. [[errorAlertTool shareInstance] showNetErrorAlertFun:5 didClickBut:^(NSInteger tag) {
  322. if(tag == 1){
  323. [weakSelf relinkWebRtcFun];
  324. }
  325. else if(tag == 5){
  326. [weakSelf exitCloudPhoneFun];
  327. }
  328. }];
  329. }
  330. #pragma mark 控制按钮点击事件
  331. - (void)controlBtnPressed:(UIButton*)but
  332. {
  333. if(_playerSetV){
  334. [ksharedAppDelegate.window addSubview:_playerSetV];
  335. [_playerSetV mas_remakeConstraints:^(MASConstraintMaker *make) {
  336. make.left.mas_equalTo(0);
  337. make.right.mas_equalTo(0);
  338. make.top.mas_equalTo(0.f);
  339. make.bottom.mas_equalTo(0.f);
  340. }];
  341. [_playerSetV setAllSwitchFun];
  342. return;
  343. }
  344. _playerSetV = [[playerSetView alloc] init];
  345. [ksharedAppDelegate.window addSubview:_playerSetV];
  346. [_playerSetV mas_makeConstraints:^(MASConstraintMaker *make) {
  347. make.left.mas_equalTo(0);
  348. make.right.mas_equalTo(0);
  349. make.top.mas_equalTo(0.f);
  350. make.bottom.mas_equalTo(0.f);
  351. }];
  352. KWeakSelf
  353. _playerSetV.didClickButtonFun = ^(NSInteger tag) {
  354. switch (tag) {
  355. case 1:
  356. {//设置分辨率 720
  357. [weakSelf didClickSetResolution720Fun];
  358. }
  359. break;
  360. case 2:
  361. {//设置分辨率 1080
  362. [weakSelf didClickSetResolution1080Fun];
  363. }
  364. break;
  365. case 200:
  366. {//截图
  367. [weakSelf didClickshortCatFun];
  368. }
  369. break;
  370. #pragma mark 重启盒子
  371. case 202:
  372. {
  373. [weakSelf didClickRestartFun];
  374. }
  375. break;
  376. case 100:
  377. {//退出云机
  378. [weakSelf exitCloudPhoneFun];
  379. }
  380. break;
  381. case 201:
  382. {
  383. BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show];
  384. if(fullscreenType){
  385. [weakSelf showOpenTVP2PFun];
  386. }
  387. else{
  388. [weakSelf openTvShowFun];
  389. }
  390. }
  391. break;
  392. case 301:
  393. {
  394. weakSelf.controlBtn.userInteractionEnabled = NO;
  395. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  396. weakSelf.controlBtn.userInteractionEnabled = YES;
  397. });
  398. [weakSelf showCloseTVP2PFun];
  399. }
  400. break;
  401. default:
  402. break;
  403. }
  404. };
  405. }
  406. #pragma mark 设置分辨率 720*1280
  407. - (void)didClickSetResolution720Fun
  408. {
  409. CGFloat tempRate = 0.0;
  410. NSInteger cardDensity = 320;//480;
  411. CGSize size = CGSizeMake(720.0, 1280.0);
  412. if(isLan){
  413. size = CGSizeMake(1280.0, 720.0);
  414. }
  415. [self setCardSize:(NSInteger)size.width cardHeight:(NSInteger)size.height cardDensity:cardDensity];
  416. tempRate = size.width/size.height;
  417. if (tempRate > 1) {/*横屏*/
  418. [self setLanMas_makeWithImageRate:tempRate];
  419. }else{/*竖屏*/
  420. [self setPoMas_makeWithImageRate:tempRate];
  421. }
  422. }
  423. #pragma mark 设置分辨率 1080*1920
  424. - (void)didClickSetResolution1080Fun
  425. {
  426. CGFloat tempRate = 0.0;
  427. NSInteger cardDensity = 320;//480;
  428. CGSize size = CGSizeMake(1080.0, 1920.0);
  429. if(isLan){
  430. size = CGSizeMake(1920.0, 1080.0);
  431. }
  432. [self setCardSize:(NSInteger)size.width cardHeight:(NSInteger)size.height cardDensity:cardDensity];
  433. tempRate = size.width/size.height;
  434. if (tempRate > 1) {/*横屏*/
  435. [self setLanMas_makeWithImageRate:tempRate];
  436. }else{/*竖屏*/
  437. [self setPoMas_makeWithImageRate:tempRate];
  438. }
  439. }
  440. #pragma mark 点击了截图
  441. - (void)didClickshortCatFun
  442. {
  443. [[webRtcManager shareManager] screenshotInCloudPhoneFun];
  444. }
  445. #pragma mark 点击了重启云机
  446. - (void)didClickRestartFun
  447. {
  448. KWeakSelf
  449. /*弹窗提示重启*/
  450. ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"my_set_no_restart_phone_tips",nil)
  451. msg:@""
  452. imageStr:@""
  453. cancelTitle:NSLocalizedString(@"other_cancel",nil)
  454. okTitle:NSLocalizedString(@"my_set_no_restart_phone_btn_ok",nil) isOkBtnHighlight:NO
  455. didClickOk:^{
  456. [weakSelf needToRebootFun];
  457. //提示语
  458. [[iToast makeText:NSLocalizedString(@"player_link_rebooting_Tips",nil)] show];
  459. } didClickCancel:^{
  460. }];
  461. nextVC.modalPresentationStyle = UIModalPresentationCustom;
  462. [self presentViewController:nextVC animated:YES completion:^{
  463. nextVC.view.superview.backgroundColor = [UIColor clearColor];
  464. }];
  465. }
  466. #pragma mark p2p通道 重启云机
  467. - (void)needToRebootFun
  468. {
  469. [[webRtcManager shareManager] needToRebootFun];
  470. [self startForceStartTimerFun];
  471. [self pauseStream];
  472. [webRtcManager shareManager].isRebootIngType = YES;
  473. [self showNewIndicatorWithCanBack:YES canTouch:NO];
  474. }
  475. #pragma mark X 秒后检查是否软件重启成功
  476. - (void)startForceStartTimerFun
  477. {
  478. KWeakSelf
  479. //1. 5秒后跟硬件发起硬重启
  480. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  481. [weakSelf updateForceStartFun];
  482. });
  483. //2. 20秒后尝试重连
  484. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  485. [weakSelf relinkWebRtcFun];
  486. [[webRtcManager shareManager] relinkWebRtcFun];
  487. });
  488. }
  489. #pragma mark 需要强制重启
  490. - (void)updateForceStartFun{
  491. NSString* curSn = ksharedAppDelegate.DeviceThirdIdMod.data.changeSn;
  492. NSMutableDictionary *paraDict = [NSMutableDictionary dictionary];
  493. [paraDict setValue:curSn forKey:@"sn"];
  494. [paraDict setValue:[NSNumber numberWithBool:YES] forKey:@"isForceStart"];
  495. [[netWorkManager shareInstance] CommonPostCallBackCode:updateForceStart Parameters:paraDict success:^(id _Nonnull responseObject) {
  496. SuperModel *model = [[SuperModel alloc] initWithDictionary:responseObject error:nil];
  497. if (model.status == 0) {
  498. }
  499. else
  500. {
  501. }
  502. } failure:^(NSError * _Nonnull error) {
  503. HLog(@"%@", error);
  504. }];
  505. }
  506. #pragma mark 退出云机
  507. - (void)exitCloudPhoneFun
  508. {
  509. //[self setShowImgAndVoiceTypeFun:NO];
  510. if(isLan){//保证竖屏
  511. [self player_rotateToInterfaceOrientation:UIInterfaceOrientationPortrait];
  512. }
  513. [self.navigationController popViewControllerAnimated:YES];
  514. ksharedAppDelegate.supportScreenRotateType = NO;
  515. [self HandleSomethingByExitVC];
  516. if(_isCodeSuspendAudioType){
  517. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  518. [[DFPlayer sharedPlayer] df_play];
  519. });
  520. }
  521. }
  522. #pragma mark 显示关闭投屏提示语
  523. - (void)showOpenTVP2PFun{
  524. /*弹窗提示TV投屏*/
  525. ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"File_upload_Record_clear_Tip_title",nil)
  526. msg:NSLocalizedString(@"cloudPhone_fullscreen_tvshow_tip",nil)
  527. imageStr:@""
  528. cancelTitle:NSLocalizedString(@"other_cancel",nil)
  529. okTitle:NSLocalizedString(@"my_set_TVP2P_Open_sure",nil) isOkBtnHighlight:YES
  530. didClickOk:^{
  531. [self openTvShowFun];
  532. //关闭全屏屏
  533. [HWDataManager setBoolWithKey:Consn_player_full_screen_show value:NO];
  534. [self setPlayerFullScreenNotFun];
  535. } didClickCancel:^{
  536. }];
  537. nextVC.modalPresentationStyle = UIModalPresentationCustom;
  538. [self presentViewController:nextVC animated:YES completion:^{
  539. nextVC.view.superview.backgroundColor = [UIColor clearColor];
  540. }];
  541. }
  542. #pragma mark 开始投屏
  543. - (void)openTvShowFun
  544. {
  545. self.controlBtn.userInteractionEnabled = NO;
  546. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  547. self->controlBtn.userInteractionEnabled = YES;
  548. });
  549. [[webRtcManager shareManager] onTvFun];
  550. [[iToast makeText:NSLocalizedString(@"cloudPhone_TV_show_tip",nil)] show];
  551. //数据埋点
  552. [[netWorkManager shareInstance] DataEmbeddingPointBy:3 withEventValue:@"Cloud_tv"];
  553. }
  554. #pragma mark 显示关闭投屏提示语
  555. - (void)showCloseTVP2PFun{
  556. /*弹窗提示TV投屏*/
  557. ComontAlretViewController *nextVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"my_set_no_close_TV_p2p_tip",nil)
  558. msg:@""
  559. imageStr:@""
  560. cancelTitle:NSLocalizedString(@"other_cancel",nil)
  561. okTitle:NSLocalizedString(@"my_set_TVP2P_Open_sure",nil) isOkBtnHighlight:YES
  562. didClickOk:^{
  563. [self gotoCloseTVP2PFun];
  564. } didClickCancel:^{
  565. //HLog(@"2222");
  566. }];
  567. nextVC.modalPresentationStyle = UIModalPresentationCustom;
  568. [self presentViewController:nextVC animated:YES completion:^{
  569. nextVC.view.superview.backgroundColor = [UIColor clearColor];
  570. }];
  571. }
  572. #pragma mark 确认开始TV投屏
  573. -(void)gotoCloseTVP2PFun
  574. {
  575. [[webRtcManager shareManager] offTvFun];
  576. }
  577. #pragma mark 挤下线功能
  578. -(void)offlineOtherPhoneFun
  579. {
  580. NSString *curOaidStr = [RcGameWQKeyChain getOaidStringFun];
  581. if(!curOaidStr){
  582. curOaidStr = @"";
  583. }
  584. NSString *commondStr = [[NSString alloc] initWithFormat:@"{\"type\":\"login\",\"value\":\"%@\"}",curOaidStr];
  585. [self send_dataInPlayer:commondStr];
  586. }
  587. #pragma mark 单点登录被挤下线弹框
  588. - (void)LogoutByOtherFun:(NSString*)oaid
  589. {
  590. if(logoutAlertVC){
  591. return;
  592. }
  593. NSString *curOaidStr = [RcGameWQKeyChain getOaidStringFun];
  594. if(oaid
  595. && oaid.length >0
  596. && [oaid isEqualToString:curOaidStr]){
  597. return;
  598. }
  599. //[self didReceiveLogoutMsgFun];
  600. //yyyy-MM-dd HH:mm:ss
  601. NSString*dateStr = [iTools getNowTimeString2];
  602. if(dateStr && dateStr.length == 19){
  603. dateStr = [dateStr substringWithRange:NSMakeRange(11, 5)];
  604. }
  605. NSString *LogoutTimerStr = [[NSString alloc] initWithFormat:@"%@%@%@",NSLocalizedString(@"single_sign_on_Tips_one",nil),dateStr,NSLocalizedString(@"single_sign_on_Tips_two",nil)];
  606. NSString * loginAgainStr = NSLocalizedString(@"single_sign_on_login_again",nil);
  607. BOOL isOkBtnHighlight = YES;
  608. if(!ksharedAppDelegate.DeviceThirdIdMod.data.isPrivacyMode){
  609. loginAgainStr = @"";
  610. isOkBtnHighlight = NO;
  611. }
  612. KWeakSelf
  613. if(ksharedAppDelegate.isDidShowPwdType){
  614. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  615. [weakSelf LogoutByOtherFun:oaid];
  616. HLog(@"weakSelf LogoutByOtherFun")
  617. });
  618. return;
  619. }
  620. //被挤下线 停止拉流
  621. [self pauseStream];
  622. if(isLan){//保证竖屏
  623. [self player_rotateToInterfaceOrientation:UIInterfaceOrientationPortrait];
  624. }
  625. //退出推流页
  626. [self.navigationController popViewControllerAnimated:NO];
  627. //与安卓保存一致 tabbar 退倒nas页
  628. // [ksharedAppDelegate.mainTabBar setSelectedIndex:0];
  629. [self HandleSomethingByExitVC];
  630. /*弹窗提示重启*/
  631. //KWeakSelf
  632. logoutAlertVC = [[ComontAlretViewController alloc] initWithTiTle:NSLocalizedString(@"single_sign_on_Tips_logout",nil)
  633. msg:LogoutTimerStr
  634. imageStr:@""
  635. cancelTitle:NSLocalizedString(@"single_sign_on_exit",nil)
  636. okTitle:loginAgainStr isOkBtnHighlight:isOkBtnHighlight
  637. didClickOk:^{
  638. self->logoutAlertVC = nil;
  639. [[NSNotificationCenter defaultCenter] postNotificationName:lockBypwdNotification object:nil];
  640. } didClickCancel:^{
  641. //exit(0);/*强制退出app*/
  642. }];
  643. logoutAlertVC.modalPresentationStyle = UIModalPresentationCustom;
  644. logoutAlertVC.view.backgroundColor = [UIColor blackColor];
  645. [[iTools appRootViewController] presentViewController:logoutAlertVC animated:YES completion:^{
  646. self->logoutAlertVC.view.superview.backgroundColor = [UIColor clearColor];
  647. }];
  648. }
  649. #pragma mark 底部按钮事件
  650. - (void)didClickBottomFunBy:(NSInteger)tag
  651. {
  652. int keyType = 0;
  653. if(tag == 1){//task
  654. keyType = 187;
  655. }
  656. else if(tag == 2){//home
  657. keyType = 3;
  658. }
  659. else if(tag == 3){//back
  660. keyType = 4;
  661. }
  662. if(keyType > 0){
  663. [self didClickKeyEventFunBy:keyType];
  664. }
  665. }
  666. #pragma mark 按键事件
  667. // home 3 back 4 task 187 volumeUp 24 volumeDown 25
  668. - (void)didClickKeyEventFunBy:(int)keyType
  669. {
  670. [_mediaStream sendKey:keyType];
  671. }
  672. #pragma mark 云机交互的消息发送 走P2P通道
  673. -(void)send_data:(NSString*)commandStr
  674. {
  675. [[webRtcManager shareManager] send_data:commandStr];
  676. }
  677. #pragma mark 云机交互的消息发送 走音视频推拉流通道
  678. -(void)send_dataInPlayer:(NSString*)commandStr
  679. {
  680. [_mediaStream sendData:commandStr];
  681. }
  682. #pragma mark -- /*底部导航栏开关通知*/
  683. - (void)getPlayerBottomNavShowOrHidefun
  684. {
  685. BOOL haveShowBottonNavType = ![HWDataManager getBoolWithKey:Consn_player_Nav_hide];
  686. if(haveShowBottonNavType){
  687. _bottomContrView.hidden = NO;
  688. }
  689. else{
  690. _bottomContrView.hidden = YES;
  691. }
  692. }
  693. #pragma mark -- /*全面屏开关通知*/
  694. - (void)setPlayerFullScreenNotFun
  695. {
  696. BOOL fullscreenType = [HWDataManager getBoolWithKey:Consn_player_full_screen_show];
  697. CGFloat tempRate = 0.0;
  698. NSInteger cardDensity = 320;//480;
  699. //重新设置分辨率
  700. if(fullscreenType){
  701. //cardDensity = 380;//480;//422;//380;//460;
  702. CGSize size = [RCCommandHelp commondToSetFullScreenPhoneSizeBySize];
  703. if(isLan){
  704. if(size.width < size.height){
  705. size = CGSizeMake(size.height,size.width);
  706. }
  707. }
  708. [self setCardSize:size.width cardHeight:size.height cardDensity:cardDensity];
  709. tempRate = (size.width *1.0)/(size.height *1.0);
  710. }
  711. else{
  712. NSInteger curResolution = [HWDataManager getIntegerWithKey:Const_cloudPhone_cur_resolution];
  713. CGFloat curWidth = 720.0;
  714. CGFloat curHeight = 1280.0;
  715. if(curResolution == 0 || curResolution == 1){
  716. curWidth = 720.0;
  717. curHeight = 1280.0;
  718. }
  719. else{
  720. curWidth = 1080.0;
  721. curHeight = 1920.0;
  722. }
  723. CGSize size = CGSizeMake(curWidth, curHeight);
  724. if(isLan){
  725. size = CGSizeMake(curHeight, curWidth);
  726. }
  727. [self setCardSize:(NSInteger)size.width cardHeight:(NSInteger)size.height cardDensity:cardDensity];
  728. tempRate = size.width/size.height;
  729. }
  730. //dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  731. if (tempRate > 1) {/*横屏*/
  732. [self setLanMas_makeWithImageRate:tempRate];
  733. }else{/*竖屏*/
  734. [self setPoMas_makeWithImageRate:tempRate];
  735. }
  736. // });
  737. }
  738. #pragma mark -- /*推流中修改卡的分辨率*/
  739. - (void)setCardSize:(NSInteger)cardWidth
  740. cardHeight:(NSInteger)cardHeight
  741. cardDensity:(NSInteger)cardDensit
  742. {
  743. if(isLan){
  744. HLog(@"云机屏幕 设置 宽:%ld 高:%ld",cardHeight,cardWidth);
  745. [_mediaStream setCardSize:cardHeight cardHeight:cardWidth cardDensity:cardDensit];
  746. [_mediaStream setVideoSize:cardHeight videoHeight:cardWidth frameRate:0];
  747. }
  748. else{
  749. HLog(@"云机屏幕 设置 宽:%ld 高:%ld",cardWidth,cardHeight);
  750. [_mediaStream setCardSize:cardWidth cardHeight:cardHeight cardDensity:cardDensit];
  751. [_mediaStream setVideoSize:cardWidth videoHeight:cardHeight frameRate:0];
  752. }
  753. }
  754. #pragma mark -- /*通知添加与移除*/
  755. - (void)addKVOObserverFun
  756. {
  757. outputVolumeKVO = YES;
  758. [[AVAudioSession sharedInstance] addObserver:self forKeyPath:@"outputVolume" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:(void *)[AVAudioSession sharedInstance]];
  759. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getPlayerBottomNavShowOrHidefun) name:getPlayerBottomNavNotification object:nil];
  760. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setPlayerFullScreenNotFun) name:setPlayerFullScreenNotification object:nil];
  761. //监听系统 前后台事件
  762. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
  763. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
  764. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
  765. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
  766. //输入密码完成
  767. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didInpuPwdOkFun) name:didInputPWDNotification object:nil];
  768. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkStateChange:) name:NetWorkChangeNotification object:nil];
  769. }
  770. - (void)removeKVOObserverFun
  771. {
  772. if (outputVolumeKVO)
  773. {
  774. [[AVAudioSession sharedInstance] removeObserver:self forKeyPath:@"outputVolume" context:(void *)[AVAudioSession sharedInstance]];
  775. outputVolumeKVO = NO;
  776. }
  777. [[NSNotificationCenter defaultCenter] removeObserver:self];
  778. }
  779. #pragma mark 系统音量键监听
  780. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
  781. if(context == (__bridge void *)[AVAudioSession sharedInstance])
  782. {
  783. /*音量开关打开时 允许发送指令 否则直接返回*/
  784. float newValue = [[change objectForKey:@"new"] floatValue];
  785. float oldValue = [[change objectForKey:@"old"] floatValue];
  786. //HLog(@"音量 --old: %f ---new: %f",oldValue,newValue)
  787. if (newValue > oldValue)
  788. {
  789. HLog(@"\n-----音量增加");
  790. [self didClickKeyEventFunBy:24];
  791. }
  792. else
  793. {
  794. HLog(@"\n-----音量降低");
  795. [self didClickKeyEventFunBy:25];
  796. }
  797. }
  798. }
  799. #pragma - mark - 监听网络变化
  800. - (void)networkStateChange:(NSNotification *)notification
  801. {
  802. /*处理*/
  803. KWeakSelf
  804. switch ([AFNetworkReachabilityManager sharedManager].networkReachabilityStatus)
  805. {
  806. case AFNetworkReachabilityStatusUnknown:/*网络状态未知*/
  807. {
  808. ;
  809. }
  810. break;
  811. case AFNetworkReachabilityStatusNotReachable:/*网络不可用*/
  812. {
  813. }
  814. break;
  815. case AFNetworkReachabilityStatusReachableViaWWAN:/*流量*/
  816. {
  817. mainBlock(^{
  818. [weakSelf.mediaStream setMaxBitrate:[NSNumber numberWithInteger:4*1024]];
  819. });
  820. }
  821. break;
  822. case AFNetworkReachabilityStatusReachableViaWiFi:/*WiFi*/
  823. {
  824. mainBlock(^{
  825. [weakSelf.mediaStream setMaxBitrate:[NSNumber numberWithInteger:8*1024]];
  826. });
  827. }
  828. break;
  829. default:
  830. break;
  831. }
  832. }
  833. #pragma mark 监听到云机的宽高以及屏幕方向
  834. - (void)handlUIAfterGetCloudPhoneVideoWidth:(int)videoWidth videoHeight:(int)videoHeight rotation:(int)rotation
  835. {
  836. HLog(@"云机屏幕 回调 宽:%d 高:%d 横竖屏:%d",videoWidth,videoHeight,rotation);
  837. CGFloat curRate = (CGFloat)videoWidth/(CGFloat)videoHeight;
  838. if(lastVideoWHRate == curRate){
  839. return;
  840. }
  841. didAdjusBtnType = NO;
  842. if(rotation == 0){//竖屏
  843. //切换到竖屏
  844. isLan = NO;
  845. [self player_rotateToInterfaceOrientation:UIInterfaceOrientationPortrait];
  846. [self setPoMas_makeWithImageRate:curRate];
  847. }
  848. else if(rotation == 1){//横屏
  849. //切换到横屏屏
  850. isLan = YES;
  851. [self player_rotateToInterfaceOrientation:UIInterfaceOrientationLandscapeRight];
  852. [self setLanMas_makeWithImageRate:curRate];
  853. }
  854. _didHandleRotation = YES;
  855. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  856. [self extensionAdjustBtnFrameCheckAdjustTime];
  857. });
  858. }
  859. #pragma mark WebRTC 回调 MediaStreamClientEventsDelegate
  860. #pragma mark - 宽高变化
  861. -(void)onFrameResolutionChangedFromPeerName:(NSString*)peerName videoWidth:(int)videoWidth videoHeight:(int)videoHeight rotation:(int)rotation {
  862. HLog(@"推拉流 onFrameResolutionChangedFromPeerName:%@---%d---%d--%d",peerName,videoWidth,videoHeight,rotation)
  863. HLog(@"ok _mediaStream:%@",_mediaStream)
  864. mainBlock(^{
  865. [self handlUIAfterGetCloudPhoneVideoWidth:videoWidth videoHeight:videoHeight rotation:rotation];
  866. });
  867. }
  868. //code 0 成功 1失败
  869. -(void)onAuthResultFromPeerName:(NSString*)peerName code:(int)code descriptions:(NSString*)descriptions
  870. {
  871. HLog(@"onAuthResultFromPeerName:%@---%d---%@",peerName,code,descriptions)
  872. }
  873. #pragma mark 链接发生变化
  874. -(void)onChangeConnectionStateFromPeerName:(NSString*)peerName didChangeIceConnectionState:(RTCIceConnectionState)state
  875. {
  876. HLog(@"推拉流 onChangeConnectionStateFromPeerName: state:%ld",state)
  877. _linkState = state;
  878. switch (state) {
  879. case RTCIceConnectionStateConnected:{
  880. //链接成功
  881. mainBlock(^{
  882. [self removeNewIndicator];
  883. //客户端停止写日志
  884. [ksharedAppDelegate.WebRtcLogger stop];
  885. });
  886. }
  887. break;
  888. case RTCIceConnectionStateCompleted:
  889. //链接完成
  890. break;
  891. case RTCIceConnectionStateFailed:
  892. case RTCIceConnectionStateDisconnected:
  893. case RTCIceConnectionStateClosed:{
  894. if(!_didReportWebRtcType){//还没上报过通道链接情况
  895. [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:YES withStats:nil];
  896. [[addLogObject shareInstance] gotoAddLogFun];
  897. }
  898. //链接关闭
  899. [self relinkWebRtcFun];
  900. }
  901. break;
  902. default:
  903. break;
  904. }
  905. }
  906. - (void)dataChannelDidChangeFromPeerName:(NSString*)peerName State:(RTCDataChannelState)state;
  907. {
  908. HLog(@"推拉流 dataChannelDidChangeFromPeerName: state:%ld",state)
  909. switch (state) {
  910. case RTCDataChannelStateConnecting:
  911. {
  912. }
  913. break;
  914. case RTCDataChannelStateOpen:
  915. {
  916. //链接成功
  917. [self offlineOtherPhoneFun];
  918. }
  919. break;
  920. case RTCDataChannelStateClosing:
  921. {
  922. }
  923. break;
  924. case RTCDataChannelStateClosed:
  925. {
  926. //链接断开
  927. [self relinkWebRtcFun];
  928. }
  929. break;
  930. default:
  931. break;
  932. }
  933. }
  934. -(void)onChannelDataFromPeerName:(NSString*)peerName buffer:(RTC_OBJC_TYPE(RTCDataBuffer) *)buffer
  935. {
  936. //HLog(@"onIceConnectedFromPeerName:%@",buffer.data);
  937. if(buffer && buffer.data){
  938. KWeakSelf
  939. mainBlock(^{
  940. [weakSelf handleWebRtcMsgResponseBy:buffer.data];
  941. });
  942. }
  943. }
  944. -(void)didGetStats:(NSString*)peerName stats:(RTC_OBJC_TYPE(RTCStatisticsReport) *)stats {
  945. if(!_didReportWebRtcType){
  946. [[webRtcManager shareManager] reportWebRtcRePoportTypeIsChannel:NO withStats:stats];
  947. _didReportWebRtcType = YES;
  948. }
  949. NSString *selectedCandidatePairId = nil;
  950. NSString *localCandidateId = nil;
  951. NSString *remoteCandidateId = nil;
  952. /*延时数据*/
  953. NSNumber *currentRoundTripTime = nil;
  954. //线性增长接收包数
  955. long packetsReceived = 0;
  956. //视频丢包数据
  957. long videolostData = 0;
  958. //音频丢包数据
  959. long audiolostData = 0;
  960. //总丢包数据
  961. long alllostData = 0;
  962. //每秒帧数 ----界面展示的帧率
  963. NSInteger framesPerSecond = 0;
  964. //计算传输速度
  965. long preReceive = 0;
  966. KWeakSelf
  967. for (NSString *key in [stats.statistics allKeys]) {
  968. RTCStatistics *rtcStatistics = [stats.statistics objectForKey:key];
  969. //HLog(@"hxd11111---->%@",rtcStatistics.type);
  970. if ([rtcStatistics.type isEqualToString:@"transport"]) {
  971. //HLog(@"传输数据---->%@",rtcStatistics.values);
  972. double timestamp = rtcStatistics.timestamp_us;
  973. NSNumber *bytesReceived = (NSNumber *)[rtcStatistics.values objectForKey:@"bytesReceived"];
  974. NSNumber *packetsReceivedNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"packetsReceived"];
  975. packetsReceived = [packetsReceivedNumber longValue];
  976. if (lastTimestamp > 0) {
  977. long diffReceive = [bytesReceived longValue] - [lastBytesReceived longValue];
  978. double diffTime = timestamp - lastTimestamp;
  979. preReceive = (diffReceive / diffTime) * 1000000;
  980. //HLog(@"传输数据速度---->%ld",preReceive);
  981. // mainBlock((^{
  982. // if (self->mPlayerView.upControlView.hidden == NO){
  983. // NSString *str = [NSString stringWithFormat:@"清晰度 %ldk/s",preReceive/1024];
  984. // NSMutableAttributedString *underAttr = [[NSMutableAttributedString alloc] initWithString:str attributes:@{NSForegroundColorAttributeName:[UIColor hwColor:@"#FFFFFF"]}];
  985. // [underAttr addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12]} range:NSMakeRange(0, str.length - 2)];
  986. // [underAttr addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10]} range:NSMakeRange(str.length - 2,2)];
  987. // [self->mPlayerView.upControlView.articulationBtn setAttributedTitle:underAttr forState:(UIControlStateNormal)];
  988. // }else{
  989. // NSString *str = [NSString stringWithFormat:@"%ldk/s",preReceive/1024];
  990. // NSMutableAttributedString *underAttr = [[NSMutableAttributedString alloc] initWithString:str attributes:@{NSForegroundColorAttributeName:[UIColor hwColor:@"#FFFFFF"]}];
  991. // [underAttr addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12]} range:NSMakeRange(0, str.length - 2)];
  992. // [underAttr addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:10]} range:NSMakeRange(str.length - 2,2)];
  993. // [self->mPlayerView.controlBtn setAttributedTitle:underAttr forState:(UIControlStateNormal)];
  994. // }
  995. // }));
  996. }else{
  997. lastTimestamp = timestamp;
  998. lastBytesReceived = bytesReceived;
  999. }
  1000. selectedCandidatePairId = (NSString *)[rtcStatistics.values objectForKey:@"selectedCandidatePairId"];
  1001. //HLog(@"三网数据--selectedCandidatePairId-->%@",selectedCandidatePairId);
  1002. }
  1003. /*丢包数据*/
  1004. if ([rtcStatistics.type isEqualToString:@"inbound-rtp"]) {
  1005. NSString *kind = (NSString *)[rtcStatistics.values objectForKey:@"kind"];
  1006. if([kind isEqualToString:@"video"]){
  1007. NSNumber*videolostDataNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"packetsLost"];
  1008. videolostData = [videolostDataNumber longValue];
  1009. NSNumber*framesPerSecondNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"framesPerSecond"];
  1010. framesPerSecond = [framesPerSecondNumber integerValue];
  1011. }
  1012. else if([kind isEqualToString:@"audio"]){
  1013. NSNumber*audiolostDataNumber = (NSNumber *)[rtcStatistics.values objectForKey:@"packetsLost"];
  1014. audiolostData = [audiolostDataNumber longValue];
  1015. }
  1016. }
  1017. for (NSString *keyin in [rtcStatistics.values allKeys]) {
  1018. if ([keyin isEqualToString:@"currentRoundTripTime"]){
  1019. /*延时数据*/
  1020. currentRoundTripTime = (NSNumber*)[rtcStatistics.values objectForKey:@"currentRoundTripTime"];
  1021. //[self updateAutoRateAndNetWorkStatesWithDelatyMS:(NSInteger)currentRoundTripTime.floatValue*1000];
  1022. break;
  1023. }
  1024. }
  1025. }
  1026. //netWorkInfoLabel 网络信息 测试用
  1027. if (selectedCandidatePairId) {
  1028. for (NSString *key in [stats.statistics allKeys]) {
  1029. RTCStatistics *rtcStatistics = [stats.statistics objectForKey:key];
  1030. if ([rtcStatistics.type isEqualToString:@"candidate-pair"]){
  1031. NSString *tempselectedCandidatePairId = rtcStatistics.id;
  1032. if ([tempselectedCandidatePairId isEqualToString:selectedCandidatePairId]) {
  1033. localCandidateId = (NSString *)[rtcStatistics.values objectForKey:@"localCandidateId"];
  1034. remoteCandidateId = (NSString *)[rtcStatistics.values objectForKey:@"remoteCandidateId"];
  1035. // HLog(@"三网数据--localCandidateId-->%@",localCandidateId);
  1036. // HLog(@"三网数据--remoteCandidateId-->%@",remoteCandidateId);
  1037. }
  1038. }
  1039. }
  1040. }
  1041. NSString *remoteCandidateStr = nil;
  1042. NSString *localCandidateStr = nil;
  1043. if (localCandidateId && remoteCandidateId) {
  1044. for (NSString *key in [stats.statistics allKeys]) {
  1045. RTCStatistics *rtcStatistics = [stats.statistics objectForKey:key];
  1046. if ([rtcStatistics.type isEqualToString:@"local-candidate"]){
  1047. NSString *templocalCandidateId = rtcStatistics.id;
  1048. if ([templocalCandidateId isEqualToString:localCandidateId]) {
  1049. //HLog(@"三网数据--localCandidateIdInfo-->%@",rtcStatistics.values);
  1050. localCandidateStr = @"本地\n";
  1051. NSString *candidateType = (NSString *)[rtcStatistics.values objectForKey:@"candidateType"];
  1052. if (candidateType) {
  1053. localCandidateStr = [localCandidateStr stringByAppendingString:[NSString stringWithFormat:@"candidateType:%@",candidateType]];
  1054. localCandidateStr = [localCandidateStr stringByAppendingString:@"\n"];
  1055. }
  1056. NSString *address = (NSString *)[rtcStatistics.values objectForKey:@"address"];
  1057. if (address) {
  1058. localCandidateStr = [localCandidateStr stringByAppendingString:[NSString stringWithFormat:@"address:%@",address]];
  1059. localCandidateStr = [localCandidateStr stringByAppendingString:@"\n"];
  1060. }
  1061. NSString *ip = (NSString *)[rtcStatistics.values objectForKey:@"ip"];
  1062. if (ip) {
  1063. localCandidateStr = [localCandidateStr stringByAppendingString:[NSString stringWithFormat:@"ip:%@",ip]];
  1064. localCandidateStr = [localCandidateStr stringByAppendingString:@"\n"];
  1065. }
  1066. NSString *relatedAddress = (NSString *)[rtcStatistics.values objectForKey:@"relatedAddress"];
  1067. if (relatedAddress) {
  1068. localCandidateStr = [localCandidateStr stringByAppendingString:[NSString stringWithFormat:@"relatedAddress:%@",relatedAddress]];
  1069. localCandidateStr = [localCandidateStr stringByAppendingString:@"\n"];
  1070. }
  1071. }
  1072. }else if ([rtcStatistics.type isEqualToString:@"remote-candidate"]){
  1073. NSString *tempRemoteCandidateId = rtcStatistics.id;
  1074. if ([tempRemoteCandidateId isEqualToString:remoteCandidateId]) {
  1075. //HLog(@"三网数据--remoteCandidateIdInfo-->%@",rtcStatistics.values);
  1076. remoteCandidateStr = @"远端\n";
  1077. NSString *candidateType = (NSString *)[rtcStatistics.values objectForKey:@"candidateType"];
  1078. if (candidateType) {
  1079. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:[NSString stringWithFormat:@"candidateType:%@",candidateType]];
  1080. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:@"\n"];
  1081. }
  1082. NSString *address = (NSString *)[rtcStatistics.values objectForKey:@"address"];
  1083. if (address) {
  1084. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:[NSString stringWithFormat:@"address:%@",address]];
  1085. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:@"\n"];
  1086. }
  1087. NSString *ip = (NSString *)[rtcStatistics.values objectForKey:@"ip"];
  1088. if (ip) {
  1089. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:[NSString stringWithFormat:@"ip:%@",ip]];
  1090. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:@"\n"];
  1091. }
  1092. NSString *relatedAddress = (NSString *)[rtcStatistics.values objectForKey:@"relatedAddress"];
  1093. if (relatedAddress) {
  1094. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:[NSString stringWithFormat:@"relatedAddress:%@",relatedAddress]];
  1095. remoteCandidateStr = [remoteCandidateStr stringByAppendingString:@"\n"];
  1096. }
  1097. }
  1098. }
  1099. }
  1100. }
  1101. // NSString *showStr = @"";
  1102. // if (localCandidateStr) {
  1103. // showStr = [showStr stringByAppendingString:localCandidateStr];
  1104. // }
  1105. // if (remoteCandidateStr) {
  1106. // showStr = [showStr stringByAppendingString:remoteCandidateStr];
  1107. // }
  1108. //网络延迟, 丢包率,FPS,网速 分辨率 流量
  1109. //延时数据
  1110. NSInteger delayedMS = (NSInteger)(currentRoundTripTime.floatValue*1000);
  1111. // NSString*currentRoundTripTimeStr = [[NSString alloc] initWithFormat:@"延时:%ldms\n",delayedMS];
  1112. // showStr = [showStr stringByAppendingString:currentRoundTripTimeStr];
  1113. //计算上次报道到这一次的丢包率---------界面展示百分比丢包率
  1114. long allPacketsReceived = packetsReceived - lasPacketsReceived;
  1115. alllostData = audiolostData + videolostData;
  1116. NSInteger lostRate = ((alllostData - lastAlllostData) *1.0 / (allPacketsReceived + (alllostData - lastAlllostData))) *100;
  1117. //记录上一次丢包数
  1118. lastAlllostData = alllostData;
  1119. //记录上一次接收包数
  1120. lasPacketsReceived = packetsReceived;
  1121. NSString*lostDataStr = [[NSString alloc] initWithFormat:@"%ld%%\n",lostRate];
  1122. //showStr = [showStr stringByAppendingString:lostDataStr];
  1123. //FPS
  1124. NSString*FPSStr = [[NSString alloc] initWithFormat:@"%ld\n",framesPerSecond];
  1125. //showStr = [showStr stringByAppendingString:FPSStr];
  1126. //网速 传输数据速度
  1127. NSString *netDataSpeedStr = @"";
  1128. if(preReceive/1024.0 > 1024){
  1129. netDataSpeedStr = [NSString stringWithFormat:@"%.01fMB/S\n",preReceive/1024.0/1024.0];
  1130. }
  1131. else{
  1132. netDataSpeedStr = [NSString stringWithFormat:@"%ldkB/S\n",preReceive/1024];
  1133. }
  1134. //showStr = [showStr stringByAppendingString:netDataSpeedStr];
  1135. mainBlock(^{
  1136. if(weakSelf.playerSetV){
  1137. [weakSelf updateControlBtnBgImageWith:delayedMS];
  1138. [weakSelf.playerSetV setWebRctMsgBydelayed:delayedMS withPacketLoss:lostDataStr withSpeed:netDataSpeedStr withFPS:FPSStr];
  1139. }
  1140. });
  1141. }
  1142. #pragma mark 更新悬浮图标的颜色
  1143. - (void)updateControlBtnBgImageWith:(NSInteger)delayedMS{
  1144. if (delayedMS < 50) {
  1145. if(preDelayedMS > 0 && preDelayedMS < 50){
  1146. return;//没有变化 不处理
  1147. }
  1148. [controlBtn setBackgroundImage:[UIImage imageNamed:@"you_icon"] forState:(UIControlStateNormal)];
  1149. }
  1150. else if (delayedMS < 100){
  1151. if(preDelayedMS > 50 && preDelayedMS < 100){
  1152. return;//没有变化 不处理
  1153. }
  1154. [controlBtn setBackgroundImage:[UIImage imageNamed:@"you_yellow"] forState:(UIControlStateNormal)];
  1155. }
  1156. else{
  1157. if( preDelayedMS > 100){
  1158. return;//没有变化 不处理
  1159. }
  1160. [controlBtn setBackgroundImage:[UIImage imageNamed:@"you_red"] forState:(UIControlStateNormal)];
  1161. }
  1162. preDelayedMS = delayedMS;
  1163. }
  1164. #pragma mark 收到的webrtc消息处理
  1165. - (void)handleWebRtcMsgResponseBy:(NSData*)message
  1166. {
  1167. if([message isKindOfClass:[NSMutableString class]] || [message isKindOfClass:[NSString class]])
  1168. {
  1169. message = [(NSString *)message dataUsingEncoding:(NSUTF8StringEncoding)];
  1170. }
  1171. NSError *error = nil;
  1172. NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:message options:NSJSONReadingMutableContainers error:&error];
  1173. HLog(@"webRtc 音视频推拉流 通道接收消息:------------------%@",dataDict);
  1174. if(!dataDict){
  1175. //[weakSelf handleDownloadResponseFunBy:message];
  1176. return;
  1177. }
  1178. if(![dataDict isKindOfClass:[NSDictionary class]]){
  1179. //[__NSCFString allKeys] unrecognized selector sent to ins
  1180. return;
  1181. }
  1182. if(![[dataDict allKeys] containsObject:@"type"]){
  1183. return;
  1184. }
  1185. NSString *messageType = dataDict[@"type"];
  1186. if ([messageType isEqualToString:@"login"]) {
  1187. if([[dataDict allKeys] containsObject:@"value"]){
  1188. NSString *value = dataDict[@"value"];
  1189. [self LogoutByOtherFun:value];
  1190. }
  1191. }
  1192. }
  1193. //延迟系统触摸事件
  1194. - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures{
  1195. return UIRectEdgeAll;
  1196. }
  1197. @end