BGTPlayControllerForPK.m 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. //
  2. // BGTPlayControllerForPK.m
  3. // BuguLive
  4. //
  5. // Created by xfg on 16/12/5.
  6. // Copyright © 2016年 xfg. All rights reserved.
  7. //
  8. #import "BGTPlayControllerForPK.h"
  9. #import <TXLiteAVSDK_Professional/TXLivePlayListener.h>
  10. #import <TXLiteAVSDK_Professional/TXLiveBase.h>
  11. #import <mach/mach.h>
  12. #define TEST_MUTE 0
  13. #define RTMP_URL ASLocalizedString(@"请输入或扫二维码获取播放地址")
  14. #define kRePlayTime 1 // 断开后重新尝试的次数
  15. typedef NS_ENUM(NSInteger, ENUM_TYPE_CACHE_STRATEGY)
  16. {
  17. CACHE_STRATEGY_FAST = 1, //极速
  18. CACHE_STRATEGY_SMOOTH = 2, //流畅
  19. CACHE_STRATEGY_AUTO = 3, //自动
  20. };
  21. #define CACHE_TIME_FAST 1
  22. #define CACHE_TIME_SMOOTH 5
  23. #define CACHE_TIME_AUTO_MIN 5
  24. #define CACHE_TIME_AUTO_MAX 10
  25. @interface BGTPlayControllerForPK ()<UITextFieldDelegate, TXLivePlayListener>
  26. @end
  27. @implementation BGTPlayControllerForPK
  28. {
  29. BOOL _bHWDec;
  30. UIButton *_btnPlayMode;
  31. UIButton *_btnHWDec;
  32. long long _trackingTouchTS;
  33. BOOL _startSeek;
  34. BOOL _videoPause;
  35. CGRect _videoWidgetFrame; // 改变videoWidget的frame时候记得对其重新进行赋值
  36. UIImageView *_loadingImageView;
  37. BOOL _appIsInterrupt;
  38. float _sliderValue;
  39. TX_Enum_PlayType _playType;
  40. long long _startPlayTS;
  41. NSString *_playDurationStr; // 播放时长
  42. // 普通播放配置
  43. TXLivePlayConfig *_txLivePlayConfig;
  44. }
  45. - (void)dealloc
  46. {
  47. if (_play_switch == YES)
  48. {
  49. [self stopRtmp];
  50. }
  51. }
  52. - (void)viewDidLoad
  53. {
  54. [super viewDidLoad];
  55. if (_liveType == FW_LIVE_TYPE_AUDIENCE)
  56. {
  57. _play_switch = NO;
  58. self.isLivePlay = YES;
  59. }
  60. [self initUI];
  61. }
  62. - (void)initUI
  63. {
  64. self.view.backgroundColor = [UIColor blackColor];
  65. _playDurationStr = @"00:00";
  66. _videoWidgetFrame = [UIScreen mainScreen].bounds;
  67. // remove all subview
  68. for (UIView *view in [self.view subviews])
  69. {
  70. [view removeFromSuperview];
  71. }
  72. CGSize size = [[UIScreen mainScreen] bounds].size;
  73. int icon_size = size.width / 10;
  74. _cover = [[UIView alloc]init];
  75. _cover.frame = CGRectMake(10.0f, 55 + 2*icon_size, size.width - 20, size.height - 75 - 3 * icon_size);
  76. _cover.backgroundColor = [UIColor grayColor];
  77. _cover.alpha = 0.5;
  78. _cover.hidden = YES;
  79. [self.view addSubview:_cover];
  80. int logheadH = 65;
  81. _statusView = [[UITextView alloc] initWithFrame:CGRectMake(10.0f, 55 + 2*icon_size, size.width - 20, logheadH)];
  82. _statusView.backgroundColor = [UIColor clearColor];
  83. _statusView.alpha = 1;
  84. _statusView.textColor = [UIColor blackColor];
  85. _statusView.editable = NO;
  86. _statusView.hidden = YES;
  87. [self.view addSubview:_statusView];
  88. _logViewEvt = [[UITextView alloc] initWithFrame:CGRectMake(10.0f, 55 + 2*icon_size + logheadH, size.width - 20, size.height - 75 - 3 * icon_size - logheadH)];
  89. _logViewEvt.backgroundColor = [UIColor clearColor];
  90. _logViewEvt.alpha = 1;
  91. _logViewEvt.textColor = [UIColor blackColor];
  92. _logViewEvt.editable = NO;
  93. _logViewEvt.hidden = YES;
  94. [self.view addSubview:_logViewEvt];
  95. int icon_length = 8;
  96. if (!self.isLivePlay)
  97. {
  98. icon_length = 6;
  99. }
  100. else
  101. {
  102. icon_length = 7;
  103. }
  104. int icon_gap = (size.width - icon_size*(icon_length-1))/icon_length;
  105. int btn_index = 0;
  106. _play_switch = NO;
  107. _log_switch = YES;
  108. [self createBottomBtnIndex:btn_index++ Icon:@"log" Action:@selector(clickLog:) Gap:icon_gap Size:icon_size];
  109. _bHWDec = NO;
  110. _btnHWDec = [self createBottomBtnIndex:btn_index++ Icon:@"quick2" Action:@selector(onClickHardware:) Gap:icon_gap Size:icon_size];
  111. _screenPortrait = NO;
  112. [self createBottomBtnIndex:btn_index++ Icon:@"portrait" Action:@selector(clickScreenOrientation:) Gap:icon_gap Size:icon_size];
  113. _renderFillScreen = YES;
  114. [self createBottomBtnIndex:btn_index++ Icon:@"adjust" Action:@selector(clickRenderMode:) Gap:icon_gap Size:icon_size];
  115. _txLivePlayer = [[TXLivePlayer alloc] init];
  116. [TXLiveBase setLogLevel:LOGLEVEL_NULL];
  117. if (!self.isLivePlay)
  118. {
  119. _btnCacheStrategy = nil;
  120. }
  121. else
  122. {
  123. _btnCacheStrategy = [self createBottomBtnIndex:btn_index++ Icon:@"cache_time" Action:@selector(onAdjustCacheStrategy:) Gap:icon_gap Size:icon_size];
  124. }
  125. [self setCacheStrategy:CACHE_STRATEGY_AUTO];
  126. _videoPause = NO;
  127. _trackingTouchTS = 0;
  128. if (!self.isLivePlay)
  129. {
  130. _playStart.hidden = NO;
  131. _playProgress.hidden = NO;
  132. }
  133. else
  134. {
  135. _playStart.hidden = YES;
  136. _playProgress.hidden = YES;
  137. }
  138. //loading imageview
  139. float width = 34;
  140. float height = 34;
  141. float offsetX = (self.view.frame.size.width - width) / 2;
  142. float offsetY = (self.view.frame.size.height - height) / 2;
  143. NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:@"loading_image0.png"],[UIImage imageNamed:@"loading_image1.png"],[UIImage imageNamed:@"loading_image2.png"],[UIImage imageNamed:@"loading_image3.png"],[UIImage imageNamed:@"loading_image4.png"],[UIImage imageNamed:@"loading_image5.png"],[UIImage imageNamed:@"loading_image6.png"],[UIImage imageNamed:@"loading_image7.png"], nil];
  144. _loadingImageView = [[UIImageView alloc] initWithFrame:CGRectMake(offsetX, offsetY, width, height)];
  145. _loadingImageView.animationImages = array;
  146. _loadingImageView.animationDuration = 1;
  147. _loadingImageView.hidden = YES;
  148. [self.view addSubview:_loadingImageView];
  149. _videoContrainerView = [[UIView alloc] initWithFrame:self.view.bounds];
  150. [self.view insertSubview:_videoContrainerView atIndex:0];
  151. _videoContrainerView.center = self.view.center;
  152. [self startRtmp:1];
  153. }
  154. - (void)setPlayUrlStr:(NSString *)playUrlStr
  155. {
  156. _playUrlStr = playUrlStr;
  157. }
  158. #pragma -- example code bellow
  159. - (void)clearLog
  160. {
  161. _tipsMsg = @"";
  162. _logMsg = @"";
  163. [_statusView setText:@""];
  164. [_logViewEvt setText:@""];
  165. _startTime = [[NSDate date]timeIntervalSince1970]*1000;
  166. _lastTime = _startTime;
  167. }
  168. - (BOOL)checkPlayUrl:(NSString*)playUrl
  169. {
  170. #warning 暂时注释
  171. /*
  172. if (!([playUrl hasPrefix:@"http:"] || [playUrl hasPrefix:@"https:"] || [playUrl hasPrefix:@"rtmp:"]))
  173. {
  174. [self toastTip:ASLocalizedString(@"播放地址不合法,目前仅支持rtmp,flv,hls,mp4播放方式!")];
  175. return NO;
  176. }
  177. if (self.isLivePlay)
  178. {
  179. if ([playUrl hasPrefix:@"rtmp:"])
  180. {
  181. _playType = PLAY_TYPE_LIVE_RTMP;
  182. }
  183. else if (([playUrl hasPrefix:@"https:"] || [playUrl hasPrefix:@"http:"]) && [playUrl rangeOfString:@".flv"].length > 0)
  184. {
  185. _playType = PLAY_TYPE_LIVE_FLV;
  186. }
  187. else
  188. {
  189. [self toastTip:ASLocalizedString(@"播放地址不合法,直播目前仅支持rtmp,flv播放方式!")];
  190. return NO;
  191. }
  192. _playType = PLAY_TYPE_LIVE_RTMP_ACC;
  193. }
  194. else
  195. {
  196. if ([playUrl hasPrefix:@"https:"] || [playUrl hasPrefix:@"http:"])
  197. {
  198. if ([playUrl rangeOfString:@".flv"].length > 0)
  199. {
  200. _playType = PLAY_TYPE_VOD_FLV;
  201. }
  202. else if ([playUrl rangeOfString:@".m3u8"].length > 0)
  203. {
  204. _playType= PLAY_TYPE_VOD_HLS;
  205. }
  206. else if ([playUrl rangeOfString:@".mp4"].length > 0)
  207. {
  208. _playType= PLAY_TYPE_VOD_MP4;
  209. }
  210. else
  211. {
  212. [self toastTip:ASLocalizedString(@"播放地址不合法,点播目前仅支持flv,hls,mp4播放方式!")];
  213. return NO;
  214. }
  215. }
  216. else
  217. {
  218. [self toastTip:ASLocalizedString(@"播放地址不合法,点播目前仅支持flv,hls,mp4播放方式!")];
  219. return NO;
  220. }
  221. }
  222. */
  223. return YES;
  224. }
  225. - (BOOL)startRtmp:(NSInteger)create_type
  226. {
  227. _create_type = create_type;
  228. NSString* playUrl = _playUrlStr;
  229. if (playUrl.length == 0)
  230. {
  231. playUrl = RTMP_URL;
  232. }
  233. if (![self checkPlayUrl:playUrl])
  234. {
  235. return NO;
  236. }
  237. [self clearLog];
  238. if(_txLivePlayer != nil)
  239. {
  240. _txLivePlayer.delegate = self;
  241. [_txLivePlayer setupVideoWidget:CGRectMake(0, 0, 0, 0) containView:self.view insertIndex:0];
  242. //设置播放器缓存策略
  243. //这里将播放器的策略设置为自动调整,调整的范围设定为1到4s,您也可以通过setCacheTime将播放器策略设置为采用
  244. //固定缓存时间。如果您什么都不调用,播放器将采用默认的策略(默认策略为自动调整,调整范围为1到4s)
  245. //[_txLivePlayer setCacheTime:5];
  246. //[_txLivePlayer setMinCacheTime:1];
  247. //[_txLivePlayer setMaxCacheTime:4];
  248. int result = [_txLivePlayer startLivePlay:playUrl type:_playType];
  249. if (result == -1)
  250. {
  251. [self toastTip:ASLocalizedString(@"非腾讯云链接,若要放开限制请联系腾讯云商务团队")];
  252. return NO;
  253. }
  254. if( result != 0)
  255. {
  256. NSLog(ASLocalizedString(@"播放器启动失败"));
  257. return NO;
  258. }
  259. if (_screenPortrait)
  260. {
  261. [_txLivePlayer setRenderRotation:HOME_ORIENTATION_RIGHT];
  262. }
  263. else
  264. {
  265. [_txLivePlayer setRenderRotation:HOME_ORIENTATION_DOWN];
  266. }
  267. if (_renderFillScreen)
  268. {
  269. [_txLivePlayer setRenderMode:RENDER_MODE_FILL_SCREEN];
  270. }
  271. else
  272. {
  273. [_txLivePlayer setRenderMode:RENDER_MODE_FILL_EDGE];
  274. }
  275. if (_create_type == 1)
  276. {
  277. [_txLivePlayer setRenderMode:RENDER_MODE_FILL_EDGE];
  278. }
  279. else
  280. {
  281. [_txLivePlayer setRenderMode:RENDER_MODE_FILL_SCREEN];
  282. }
  283. [self startLoadingAnimation];
  284. _videoPause = NO;
  285. [_btnPlay setImage:[UIImage imageNamed:@"fw_relive_suspend"] forState:UIControlStateNormal];
  286. }
  287. _startPlayTS = [[NSDate date]timeIntervalSince1970]*1000;
  288. return YES;
  289. }
  290. - (void)stopRtmp
  291. {
  292. [self stopLoadingAnimation];
  293. if(_txLivePlayer != nil)
  294. {
  295. _txLivePlayer.delegate = nil;
  296. [_txLivePlayer stopPlay];
  297. [_txLivePlayer removeVideoWidget];
  298. }
  299. }
  300. - (void)rePlay
  301. {
  302. if (_delegate && [_delegate respondsToSelector:@selector(playAgain:isHideLeaveTip:)])
  303. {
  304. [_delegate playAgain:self isHideLeaveTip:NO];
  305. }
  306. }
  307. #pragma mark - ----------------------- TXLivePlayListener代理事件 -----------------------
  308. - (void)onPlayEvent:(int)EvtID withParam:(NSDictionary*)param;
  309. {
  310. if (EvtID != PLAY_EVT_PLAY_PROGRESS)
  311. {
  312. NSLog(@"==========playEvtID1:%d",EvtID);
  313. }
  314. NSDictionary* dict = param;
  315. dispatch_async(dispatch_get_main_queue(), ^{
  316. if (EvtID == PLAY_EVT_RCV_FIRST_I_FRAME)
  317. {
  318. if (_delegate && [_delegate respondsToSelector:@selector(firstFrame:)])
  319. {
  320. [_delegate firstFrame:self];
  321. _rePlayTime = 0;
  322. }
  323. }
  324. else if (EvtID == PLAY_EVT_PLAY_BEGIN)
  325. {
  326. [self stopLoadingAnimation];
  327. long long playDelay = [[NSDate date]timeIntervalSince1970]*1000 - _startPlayTS;
  328. NSLog(@"AutoMonitor:PlayFirstRender,cost=%lld", playDelay);
  329. }
  330. else if (EvtID == PLAY_EVT_PLAY_PROGRESS && !_startSeek)
  331. {
  332. // 避免滑动进度条松开的瞬间可能出现滑动条瞬间跳到上一个位置
  333. long long curTs = [[NSDate date]timeIntervalSince1970]*1000;
  334. if (llabs(curTs - _trackingTouchTS) < 500) {
  335. return;
  336. }
  337. _trackingTouchTS = curTs;
  338. float progress = [dict[EVT_PLAY_PROGRESS] floatValue];
  339. int intProgress = progress + 0.5;
  340. _playStart.text = [[NSString stringWithFormat:@"%02d:%02d", (int)(intProgress / 60), (int)(intProgress % 60)] stringByAppendingString:[NSString stringWithFormat:@"/%@",_playDurationStr]];
  341. [_playProgress setValue:progress];
  342. float duration = [dict[EVT_PLAY_DURATION] floatValue];
  343. int intDuration = duration + 0.5;
  344. if (duration > 0 && _playProgress.maximumValue != duration) {
  345. [_playProgress setMaximumValue:duration];
  346. _playDurationStr = [NSString stringWithFormat:@"%02d:%02d", (int)(intDuration / 60), (int)(intDuration % 60)];
  347. }
  348. return ;
  349. }
  350. else if (EvtID == PLAY_ERR_NET_DISCONNECT)
  351. {
  352. [self stopRtmp];
  353. _play_switch = NO;
  354. [_btnPlay setImage:[UIImage imageNamed:@"fw_relive_start"] forState:UIControlStateNormal];
  355. [_playProgress setValue:0];
  356. _playStart.text = @"00:00/00:00";
  357. _videoPause = NO;
  358. [self performSelector:@selector(rePlay) withObject:nil afterDelay:3];
  359. }
  360. else if (EvtID == PLAY_EVT_PLAY_END)
  361. {
  362. [_txLivePlayer pause];
  363. [_btnPlay setImage:[UIImage imageNamed:@"fw_relive_start"] forState:UIControlStateNormal];
  364. }
  365. else if (EvtID == PLAY_EVT_PLAY_LOADING)
  366. {
  367. [self startLoadingAnimation];
  368. }
  369. long long time = [(NSNumber*)[dict valueForKey:EVT_TIME] longLongValue];
  370. int mil = time % 1000;
  371. NSDate* date = [NSDate dateWithTimeIntervalSince1970:time/1000];
  372. NSString* Msg = (NSString*)[dict valueForKey:EVT_MSG];
  373. [self appendLog:Msg time:date mills:mil];
  374. });
  375. }
  376. - (void)onNetStatus:(NSDictionary*) param
  377. {
  378. NSDictionary* dict = param;
  379. _qualityDict = param;
  380. /*
  381. dispatch_async(dispatch_get_main_queue(), ^{
  382. int netspeed = [(NSNumber*)[dict valueForKey:NET_STATUS_NET_SPEED] intValue];
  383. int vbitrate = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_BITRATE] intValue];
  384. int settrate = [(NSNumber*)[dict valueForKey:NET_STATUS_SET_VIDEO_BITRATE] intValue];
  385. _kbpsRecvStr = StringFromInt(vbitrate);
  386. _kbpsSendStr = StringFromInt(settrate);
  387. int abitrate = [(NSNumber*)[dict valueForKey:NET_STATUS_AUDIO_BITRATE] intValue];
  388. int cachesize = [(NSNumber*)[dict valueForKey:NET_STATUS_CACHE_SIZE] intValue];
  389. int dropsize = [(NSNumber*)[dict valueForKey:NET_STATUS_DROP_SIZE] intValue];
  390. int jitter = [(NSNumber*)[dict valueForKey:NET_STATUS_NET_JITTER] intValue];
  391. int fps = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_FPS] intValue];
  392. int width = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_WIDTH] intValue];
  393. int height = [(NSNumber*)[dict valueForKey:NET_STATUS_VIDEO_HEIGHT] intValue];
  394. float cpu_usage = [(NSNumber*)[dict valueForKey:NET_STATUS_CPU_USAGE] floatValue];
  395. NSString *serverIP = [dict valueForKey:NET_STATUS_SERVER_IP];
  396. int codecCacheSize = [(NSNumber*)[dict valueForKey:NET_STATUS_CODEC_CACHE] intValue];
  397. int nCodecDropCnt = [(NSNumber*)[dict valueForKey:NET_STATUS_CODEC_DROP_CNT] intValue];
  398. NSString* log = [NSString stringWithFormat:@"CPU:%.1f%%\tRES:%d*%d\tSPD:%dkb/s\nJITT:%d\tFPS:%d\tARA:%dkb/s\nQUE:%d|%d\tDRP:%d|%d\tVRA:%dkb/s\nSVR:%@\t",
  399. cpu_usage*100,
  400. width,
  401. height,
  402. netspeed,
  403. jitter,
  404. fps,
  405. abitrate,
  406. codecCacheSize,
  407. cachesize,
  408. nCodecDropCnt,
  409. dropsize,
  410. vbitrate,
  411. serverIP];
  412. [_statusView setText:log];
  413. });
  414. */
  415. }
  416. - (void)startLoadingAnimation
  417. {
  418. if (_loadingImageView != nil)
  419. {
  420. _loadingImageView.hidden = NO;
  421. [_loadingImageView startAnimating];
  422. }
  423. }
  424. - (void)stopLoadingAnimation
  425. {
  426. if (_loadingImageView != nil)
  427. {
  428. _loadingImageView.hidden = YES;
  429. [_loadingImageView stopAnimating];
  430. }
  431. }
  432. #pragma ###TXLivePlayListener
  433. - (void)appendLog:(NSString*) evt time:(NSDate*) date mills:(int)mil
  434. {
  435. if (evt == nil)
  436. {
  437. return;
  438. }
  439. NSDateFormatter* format = [[NSDateFormatter alloc] init];
  440. format.dateFormat = @"hh:mm:ss";
  441. NSString* time = [format stringFromDate:date];
  442. NSString* log = [NSString stringWithFormat:@"[%@.%-3.3d] %@", time, mil, evt];
  443. if (_logMsg == nil) {
  444. _logMsg = @"";
  445. }
  446. _logMsg = [NSString stringWithFormat:@"%@\n%@", _logMsg, log ];
  447. [_logViewEvt setText:_logMsg];
  448. }
  449. #pragma mark - ----------------------- 底部按钮事件 -----------------------
  450. #pragma mark 点击日志按钮
  451. - (void)clickLog:(UIButton*) sender
  452. {
  453. if (_log_switch == YES)
  454. {
  455. _statusView.hidden = YES;
  456. _logViewEvt.hidden = YES;
  457. [sender setImage:[UIImage imageNamed:@"log"] forState:UIControlStateNormal];
  458. _cover.hidden = YES;
  459. _log_switch = NO;
  460. }
  461. else
  462. {
  463. _statusView.hidden = NO;
  464. _logViewEvt.hidden = NO;
  465. [sender setImage:[UIImage imageNamed:@"log2"] forState:UIControlStateNormal];
  466. _cover.hidden = NO;
  467. _log_switch = YES;
  468. }
  469. // 2019年08月24日
  470. sender.hidden = YES;
  471. }
  472. #pragma mark 点击横竖屏按钮
  473. - (void) clickScreenOrientation:(UIButton*) sender
  474. {
  475. _screenPortrait = !_screenPortrait;
  476. if (_screenPortrait)
  477. {
  478. [sender setImage:[UIImage imageNamed:@"landscape"] forState:UIControlStateNormal];
  479. [_txLivePlayer setRenderRotation:HOME_ORIENTATION_RIGHT];
  480. }
  481. else
  482. {
  483. [sender setImage:[UIImage imageNamed:@"portrait"] forState:UIControlStateNormal];
  484. [_txLivePlayer setRenderRotation:HOME_ORIENTATION_DOWN];
  485. }
  486. }
  487. #pragma mark 点击填充模式按钮
  488. - (void) clickRenderMode:(UIButton*) sender
  489. {
  490. _renderFillScreen = !_renderFillScreen;
  491. if (_renderFillScreen) {
  492. [sender setImage:[UIImage imageNamed:@"adjust"] forState:UIControlStateNormal];
  493. [_txLivePlayer setRenderMode:RENDER_MODE_FILL_SCREEN];
  494. } else {
  495. [sender setImage:[UIImage imageNamed:@"fill"] forState:UIControlStateNormal];
  496. [_txLivePlayer setRenderMode:RENDER_MODE_FILL_EDGE];
  497. }
  498. }
  499. #pragma mark 点击硬件加速按钮
  500. - (void) onClickHardware:(UIButton*)sender
  501. {
  502. if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
  503. [self toastTip:ASLocalizedString(@"iOS 版本低于8.0,不支持硬件加速.")];
  504. return;
  505. }
  506. if (_play_switch == YES)
  507. {
  508. [self stopRtmp];
  509. }
  510. _txLivePlayer.enableHWAcceleration = !_bHWDec;
  511. _bHWDec = _txLivePlayer.enableHWAcceleration;
  512. if(_bHWDec)
  513. {
  514. [sender setImage:[UIImage imageNamed:@"quick"] forState:UIControlStateNormal];
  515. }
  516. else
  517. {
  518. [sender setImage:[UIImage imageNamed:@"quick2"] forState:UIControlStateNormal];
  519. }
  520. if (_play_switch == YES) {
  521. if (_bHWDec) {
  522. [self toastTip:ASLocalizedString(@"切换为硬解码. 重启播放流程")];
  523. }
  524. else
  525. {
  526. [self toastTip:ASLocalizedString(@"切换为软解码. 重启播放流程")];
  527. }
  528. [self startRtmp:_create_type];
  529. }
  530. }
  531. #pragma mark UISlider代理方法
  532. - (void)onSeek:(UISlider *)slider
  533. {
  534. #warning 暂时注释
  535. // [_txLivePlayer seek:_sliderValue];
  536. _trackingTouchTS = [[NSDate date]timeIntervalSince1970]*1000;
  537. _startSeek = NO;
  538. NSLog(@"vod seek drag end");
  539. }
  540. - (void)onSeekBegin:(UISlider *)slider
  541. {
  542. _startSeek = YES;
  543. NSLog(@"vod seek drag begin");
  544. }
  545. - (void)onDrag:(UISlider *)slider
  546. {
  547. float progress = slider.value;
  548. int intProgress = progress + 0.5;
  549. _playStart.text = [[NSString stringWithFormat:@"%02d:%02d",(int)(intProgress / 60), (int)(intProgress % 60)] stringByAppendingString:[NSString stringWithFormat:@"/%@",_playDurationStr]];
  550. _sliderValue = slider.value;
  551. }
  552. - (void)dragSliderDidEnd:(UISlider *)slider
  553. {
  554. _startSeek = NO;
  555. }
  556. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
  557. {
  558. _vCacheStrategy.hidden = YES;
  559. }
  560. #pragma mark - ----------------------- 清晰度设置 -----------------------
  561. - (void) setCacheStrategy:(NSInteger) nCacheStrategy
  562. {
  563. if (_btnCacheStrategy == nil || _cacheStrategy == nCacheStrategy) return;
  564. if (_txLivePlayConfig == nil)
  565. {
  566. _txLivePlayConfig = [[TXLivePlayConfig alloc] init];
  567. }
  568. _cacheStrategy = nCacheStrategy;
  569. switch (_cacheStrategy) {
  570. case CACHE_STRATEGY_FAST:
  571. _txLivePlayConfig.bAutoAdjustCacheTime = YES;
  572. _txLivePlayConfig.minAutoAdjustCacheTime = CACHE_TIME_FAST;
  573. _txLivePlayConfig.maxAutoAdjustCacheTime = CACHE_TIME_FAST;
  574. [_txLivePlayer setConfig:_txLivePlayConfig];
  575. break;
  576. case CACHE_STRATEGY_SMOOTH:
  577. _txLivePlayConfig.bAutoAdjustCacheTime = NO;
  578. _txLivePlayConfig.cacheTime = CACHE_TIME_SMOOTH;
  579. [_txLivePlayer setConfig:_txLivePlayConfig];
  580. break;
  581. case CACHE_STRATEGY_AUTO:
  582. _txLivePlayConfig.bAutoAdjustCacheTime = YES;
  583. _txLivePlayConfig.minAutoAdjustCacheTime = CACHE_TIME_AUTO_MIN;
  584. _txLivePlayConfig.maxAutoAdjustCacheTime = CACHE_TIME_AUTO_MAX;
  585. [_txLivePlayer setConfig:_txLivePlayConfig];
  586. break;
  587. default:
  588. break;
  589. }
  590. }
  591. - (void) onAdjustCacheStrategy:(UIButton*) sender
  592. {
  593. #if TEST_MUTE
  594. static BOOL flag = YES;
  595. [_txLivePlayer setMute:flag];
  596. flag = !flag;
  597. #else
  598. if (_vCacheStrategy == nil)
  599. {
  600. CGSize size = [[UIScreen mainScreen] bounds].size;
  601. _vCacheStrategy = [[UIControl alloc]init];
  602. _vCacheStrategy.frame = CGRectMake(0, size.height-120, size.width, 120);
  603. [_vCacheStrategy setBackgroundColor:[UIColor whiteColor]];
  604. UILabel* title= [[UILabel alloc]init];
  605. title.frame = CGRectMake(0, 0, size.width, 50);
  606. [title setText:ASLocalizedString(@"缓存策略")];
  607. title.textAlignment = NSTextAlignmentCenter;
  608. [title setFont:[UIFont fontWithName:@"" size:14]];
  609. [_vCacheStrategy addSubview:title];
  610. int gap = 30;
  611. int width = (size.width - gap*2 - 20) / 3;
  612. _radioBtnFast = [UIButton buttonWithType:UIButtonTypeCustom];
  613. _radioBtnFast.frame = CGRectMake(10, 60, width, 40);
  614. [_radioBtnFast setTitle:ASLocalizedString(@"极速")forState:UIControlStateNormal];
  615. [_radioBtnFast addTarget:self action:@selector(onAdjustFast:) forControlEvents:UIControlEventTouchUpInside];
  616. _radioBtnSmooth = [UIButton buttonWithType:UIButtonTypeCustom];
  617. _radioBtnSmooth.frame = CGRectMake(10 + gap + width, 60, width, 40);
  618. [_radioBtnSmooth setTitle:ASLocalizedString(@"流畅")forState:UIControlStateNormal];
  619. [_radioBtnSmooth addTarget:self action:@selector(onAdjustSmooth:) forControlEvents:UIControlEventTouchUpInside];
  620. _radioBtnAUTO = [UIButton buttonWithType:UIButtonTypeCustom];
  621. _radioBtnAUTO.frame = CGRectMake(size.width - 10 - width, 60, width, 40);
  622. [_radioBtnAUTO setTitle:ASLocalizedString(@"自动")forState:UIControlStateNormal];
  623. [_radioBtnAUTO addTarget:self action:@selector(onAdjustAuto:) forControlEvents:UIControlEventTouchUpInside];
  624. [_vCacheStrategy addSubview:_radioBtnFast];
  625. [_vCacheStrategy addSubview:_radioBtnSmooth];
  626. [_vCacheStrategy addSubview:_radioBtnAUTO];
  627. [self.view addSubview:_vCacheStrategy];
  628. }
  629. _vCacheStrategy.hidden = NO;
  630. switch (_cacheStrategy) {
  631. case CACHE_STRATEGY_FAST:
  632. [_radioBtnFast setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
  633. [_radioBtnFast setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  634. [_radioBtnSmooth setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  635. [_radioBtnSmooth setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  636. [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  637. [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  638. break;
  639. case CACHE_STRATEGY_SMOOTH:
  640. [_radioBtnFast setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  641. [_radioBtnFast setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  642. [_radioBtnSmooth setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
  643. [_radioBtnSmooth setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  644. [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  645. [_radioBtnAUTO setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  646. break;
  647. case CACHE_STRATEGY_AUTO:
  648. [_radioBtnFast setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  649. [_radioBtnFast setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  650. [_radioBtnSmooth setBackgroundImage:[UIImage imageNamed:@"white"] forState:UIControlStateNormal];
  651. [_radioBtnSmooth setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  652. [_radioBtnAUTO setBackgroundImage:[UIImage imageNamed:@"black"] forState:UIControlStateNormal];
  653. [_radioBtnAUTO setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  654. break;
  655. default:
  656. break;
  657. }
  658. #endif
  659. }
  660. - (void) onAdjustFast:(UIButton*) sender
  661. {
  662. _vCacheStrategy.hidden = YES;
  663. [self setCacheStrategy:CACHE_STRATEGY_FAST];
  664. }
  665. - (void) onAdjustSmooth:(UIButton*) sender
  666. {
  667. _vCacheStrategy.hidden = YES;
  668. [self setCacheStrategy:CACHE_STRATEGY_SMOOTH];
  669. }
  670. - (void) onAdjustAuto:(UIButton*) sender
  671. {
  672. _vCacheStrategy.hidden = YES;
  673. [self setCacheStrategy:CACHE_STRATEGY_AUTO];
  674. }
  675. #pragma mark - ----------------------- 进入前后台 -----------------------
  676. - (void)onAppDidEnterBackGround
  677. {
  678. #warning 暂时注释
  679. /*
  680. if (_play_switch == YES && _appIsInterrupt == NO)
  681. {
  682. if (_playType == PLAY_TYPE_VOD_FLV || _playType == PLAY_TYPE_VOD_HLS || _playType == PLAY_TYPE_VOD_MP4)
  683. {
  684. if (!_videoPause)
  685. {
  686. [_txLivePlayer pause];
  687. }
  688. }
  689. _appIsInterrupt = YES;
  690. }
  691. */
  692. }
  693. - (void)onAppWillEnterForeground
  694. {
  695. #warning 暂时注释
  696. /*
  697. if (_play_switch == YES && _appIsInterrupt == YES)
  698. {
  699. if (_playType == PLAY_TYPE_VOD_FLV || _playType == PLAY_TYPE_VOD_HLS || _playType == PLAY_TYPE_VOD_MP4)
  700. {
  701. if (!_videoPause)
  702. {
  703. [_txLivePlayer resume];
  704. }
  705. }
  706. _appIsInterrupt = NO;
  707. }
  708. */
  709. }
  710. #pragma mark - ----------------------- 声音打断监听 -----------------------
  711. - (void)onAudioInterruption:(NSNotification *)notification
  712. {
  713. #warning 暂时注释
  714. /*
  715. NSDictionary *info = notification.userInfo;
  716. AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
  717. if (type == AVAudioSessionInterruptionTypeBegan)
  718. {
  719. if (_play_switch == YES && _appIsInterrupt == NO)
  720. {
  721. if (_playType == PLAY_TYPE_VOD_FLV || _playType == PLAY_TYPE_VOD_HLS || _playType == PLAY_TYPE_VOD_MP4)
  722. {
  723. if (!_videoPause)
  724. {
  725. [_txLivePlayer pause];
  726. }
  727. }
  728. _appIsInterrupt = YES;
  729. }
  730. }
  731. else
  732. {
  733. AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
  734. if (options == AVAudioSessionInterruptionOptionShouldResume)
  735. {
  736. if (_play_switch == YES && _appIsInterrupt == YES)
  737. {
  738. if (_playType == PLAY_TYPE_VOD_FLV || _playType == PLAY_TYPE_VOD_HLS || _playType == PLAY_TYPE_VOD_MP4)
  739. {
  740. if (!_videoPause)
  741. {
  742. [_txLivePlayer resume];
  743. }
  744. }
  745. _appIsInterrupt = NO;
  746. }
  747. }
  748. }
  749. */
  750. }
  751. #pragma mark - ----------------------- 自定义Toast -----------------------
  752. /**
  753. 获取指定宽度width的字符串在UITextView上的高度
  754. @param textView 待计算的UITextView
  755. @param width 限制字符串显示区域的宽度
  756. @return 返回的高度
  757. */
  758. - (float)heightForString:(UITextView *)textView andWidth:(float)width
  759. {
  760. CGSize sizeToFit = [textView sizeThatFits:CGSizeMake(width, MAXFLOAT)];
  761. return sizeToFit.height;
  762. }
  763. - (void)toastTip:(NSString*)toastInfo
  764. {
  765. NSLog(@"======playtoastInfo:%@",toastInfo);
  766. CGRect frameRC = [[UIScreen mainScreen] bounds];
  767. frameRC.origin.y = frameRC.size.height - 110;
  768. frameRC.size.height -= 110;
  769. __block UITextView * toastView = [[UITextView alloc] init];
  770. toastView.editable = NO;
  771. toastView.selectable = NO;
  772. frameRC.size.height = [self heightForString:toastView andWidth:frameRC.size.width];
  773. toastView.frame = frameRC;
  774. toastView.text = toastInfo;
  775. toastView.backgroundColor = [UIColor whiteColor];
  776. toastView.alpha = 0.5;
  777. [self.view addSubview:toastView];
  778. dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
  779. dispatch_after(popTime, dispatch_get_main_queue(), ^(){
  780. [toastView removeFromSuperview];
  781. toastView = nil;
  782. });
  783. }
  784. #pragma mark - ----------------------- 创建按钮 -----------------------
  785. - (UIButton*)createBottomBtnIndex:(int)index Icon:(NSString*)icon Action:(SEL)action Gap:(int)gap Size:(int)size
  786. {
  787. UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
  788. btn.frame = CGRectMake((index+1)*gap + index*size, [[UIScreen mainScreen] bounds].size.height - size - 10, size, size);
  789. [btn setImage:[UIImage imageNamed:icon] forState:UIControlStateNormal];
  790. [btn addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
  791. [self.view addSubview:btn];
  792. return btn;
  793. }
  794. @end