BGKSYPlayerController.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. //
  2. // BGKSYPlayerController.m
  3. // FanweApp
  4. //
  5. // Created by xfg on 2017/2/10.
  6. // Copyright © 2017年 xfg. All rights reserved.
  7. //
  8. #import "BGKSYPlayerController.h"
  9. @interface BGKSYPlayerController ()
  10. {
  11. double _lastSize; //上一秒读取的数据量
  12. NSTimeInterval _lastCheckTime; //上一秒的时间点
  13. BOOL _reloading;
  14. NSTimer *_proTimer;
  15. }
  16. @end
  17. @implementation BGKSYPlayerController
  18. - (void)dealloc
  19. {
  20. [self releaseAll];
  21. }
  22. - (void)releaseAll
  23. {
  24. [[NSNotificationCenter defaultCenter] removeObserver:self];
  25. [_moviePlayer removeObserver:self forKeyPath:@"currentPlaybackTime" context:nil];
  26. [_moviePlayer removeObserver:self forKeyPath:@"clientIP" context:nil];
  27. [_moviePlayer removeObserver:self forKeyPath:@"localDNSIP" context:nil];
  28. if ([self observationInfo])
  29. {
  30. }
  31. @try {
  32. [self removeObserver:self forKeyPath:@"moviePlayer"];
  33. } @catch (NSException *exception) {
  34. } @finally {
  35. }
  36. [_moviePlayer.view removeFromSuperview];
  37. self.moviePlayer = nil;
  38. if (_proTimer)
  39. {
  40. [_proTimer invalidate];
  41. _proTimer = nil;
  42. }
  43. }
  44. - (void)viewDidLoad
  45. {
  46. [super viewDidLoad];
  47. // 添加视频容器视图
  48. _videoContrainerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenW, kScreenH)];
  49. _videoContrainerView.backgroundColor = [UIColor whiteColor];
  50. [self.view addSubview:_videoContrainerView];
  51. [self addObserver:self forKeyPath:@"moviePlayer" options:NSKeyValueObservingOptionNew context:nil];
  52. }
  53. #pragma mark 初始化视频播放类
  54. - (void)initPlayerWithUrl:(NSURL *)playUrl createType:(NSInteger)createType
  55. {
  56. if (!playUrl)
  57. {
  58. return;
  59. }
  60. if (_moviePlayer)
  61. {
  62. [self reloadPlay];
  63. return;
  64. }
  65. _playUrl = playUrl;
  66. _lastSize = 0.0;
  67. self.moviePlayer = [[KSYMoviePlayerController alloc] initWithContentURL:playUrl];
  68. [self setupObservers];
  69. // _moviePlayer.logBlock = ^(NSString *logJson){
  70. // // NSLog(@"logJson is %@",logJson);
  71. // };
  72. _moviePlayer.controlStyle = MPMovieControlStyleNone;
  73. [_moviePlayer.view setFrame:_videoContrainerView.frame]; // player's frame must match parent's
  74. [_videoContrainerView addSubview:_moviePlayer.view];
  75. _videoContrainerView.autoresizesSubviews = TRUE;
  76. _moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
  77. // 播放视频时是否需要自动播放,默认值为YES。
  78. _moviePlayer.shouldAutoplay = TRUE;
  79. // 是否开启视频后处理
  80. // _moviePlayer.shouldEnableVideoPostProcessing = TRUE;
  81. // [_moviePlayer setVolume:2.0 rigthVolume:2.0];
  82. //2020-1-3 PC段开播不要拉伸全屏
  83. // 当前缩放显示模式
  84. if (createType == 1)
  85. {
  86. _moviePlayer.scalingMode = MPMovieScalingModeNone;
  87. }
  88. else
  89. {
  90. _moviePlayer.scalingMode = MPMovieScalingModeFill;
  91. }
  92. // 是否开启硬件解码
  93. // _moviePlayer.videoDecoderMode = MPMovieVideoDecoderMode_AUTO;
  94. // 是否静音
  95. // _moviePlayer.shouldMute = NO;
  96. // 收集日志的状态,默认开启
  97. _moviePlayer.shouldEnableKSYStatModule = NO;
  98. // 是否循环播放
  99. _moviePlayer.shouldLoop = NO;
  100. // 是否进行视频反交错处理
  101. // _moviePlayer.deinterlaceMode = MPMovieVideoDeinterlaceMode_Auto;
  102. // 指定拉流超时时间,单位是秒
  103. [_moviePlayer setTimeout:10 readTimeout:60];
  104. NSKeyValueObservingOptions opts = NSKeyValueObservingOptionNew;
  105. [_moviePlayer addObserver:self forKeyPath:@"currentPlaybackTime" options:opts context:nil];
  106. [_moviePlayer addObserver:self forKeyPath:@"clientIP" options:opts context:nil];
  107. [_moviePlayer addObserver:self forKeyPath:@"localDNSIP" options:opts context:nil];
  108. NSLog(@"sdk version:%@", [_moviePlayer getVersion]);
  109. [_moviePlayer prepareToPlay];
  110. [self isCurPlaying:YES];
  111. }
  112. #pragma mark - ----------------------- 播放事件 -----------------------
  113. - (void)isCurPlaying:(BOOL)isPlaying
  114. {
  115. if (isPlaying)
  116. {
  117. [_reLiveProgressView.playBtn setImage:[UIImage imageNamed:@"fw_relive_suspend"] forState:UIControlStateNormal];
  118. }
  119. else
  120. {
  121. [_reLiveProgressView.playBtn setImage:[UIImage imageNamed:@"fw_relive_start"] forState:UIControlStateNormal];
  122. }
  123. }
  124. #pragma mark 暂停播放
  125. - (void)pausePlay
  126. {
  127. [self isCurPlaying:NO];
  128. if (_moviePlayer)
  129. {
  130. [_moviePlayer pause];
  131. }
  132. }
  133. #pragma mark 继续播放
  134. - (void)resumePlay
  135. {
  136. [self isCurPlaying:YES];
  137. if (_moviePlayer)
  138. {
  139. [_moviePlayer play];
  140. }
  141. }
  142. #pragma mark 重新播放
  143. - (void)reloadPlay
  144. {
  145. [self isCurPlaying:YES];
  146. if (_moviePlayer && _playUrl)
  147. {
  148. [_moviePlayer reload:_playUrl flush:NO mode:MPMovieReloadMode_Accurate];
  149. }
  150. }
  151. #pragma mark 结束播放
  152. - (void)stopPlay
  153. {
  154. [self isCurPlaying:NO];
  155. if (_moviePlayer)
  156. {
  157. [_moviePlayer stop];
  158. }
  159. [self releaseAll];
  160. }
  161. #pragma mark - ----------------------- 时间监听 -----------------------
  162. - (void)setupObservers
  163. {
  164. [[NSNotificationCenter defaultCenter]addObserver:self
  165. selector:@selector(handlePlayerNotify:)
  166. name:(MPMediaPlaybackIsPreparedToPlayDidChangeNotification)
  167. object:_moviePlayer];
  168. [[NSNotificationCenter defaultCenter]addObserver:self
  169. selector:@selector(handlePlayerNotify:)
  170. name:(MPMoviePlayerPlaybackStateDidChangeNotification)
  171. object:_moviePlayer];
  172. [[NSNotificationCenter defaultCenter]addObserver:self
  173. selector:@selector(handlePlayerNotify:)
  174. name:(MPMoviePlayerPlaybackDidFinishNotification)
  175. object:_moviePlayer];
  176. [[NSNotificationCenter defaultCenter]addObserver:self
  177. selector:@selector(handlePlayerNotify:)
  178. name:(MPMoviePlayerLoadStateDidChangeNotification)
  179. object:_moviePlayer];
  180. [[NSNotificationCenter defaultCenter]addObserver:self
  181. selector:@selector(handlePlayerNotify:)
  182. name:(MPMovieNaturalSizeAvailableNotification)
  183. object:_moviePlayer];
  184. [[NSNotificationCenter defaultCenter]addObserver:self
  185. selector:@selector(handlePlayerNotify:)
  186. name:(MPMoviePlayerFirstVideoFrameRenderedNotification)
  187. object:_moviePlayer];
  188. [[NSNotificationCenter defaultCenter]addObserver:self
  189. selector:@selector(handlePlayerNotify:)
  190. name:(MPMoviePlayerFirstAudioFrameRenderedNotification)
  191. object:_moviePlayer];
  192. [[NSNotificationCenter defaultCenter]addObserver:self
  193. selector:@selector(handlePlayerNotify:)
  194. name:(MPMoviePlayerSuggestReloadNotification)
  195. object:_moviePlayer];
  196. [[NSNotificationCenter defaultCenter]addObserver:self
  197. selector:@selector(handlePlayerNotify:)
  198. name:(MPMoviePlayerPlaybackStatusNotification)
  199. object:_moviePlayer];
  200. }
  201. - (void)handlePlayerNotify:(NSNotification*)notify
  202. {
  203. if (!_moviePlayer)
  204. {
  205. return;
  206. }
  207. if (MPMediaPlaybackIsPreparedToPlayDidChangeNotification == notify.name)
  208. {
  209. NSLog(ASLocalizedString(@"========接收监听:KSYPlayerVC: %@ -- ip:%@"), [[_moviePlayer contentURL] absoluteString], [_moviePlayer serverAddress]);
  210. [self startProTimer];
  211. }
  212. if (MPMoviePlayerPlaybackStateDidChangeNotification == notify.name)
  213. {
  214. NSLog(ASLocalizedString(@"========接收监听:player playback state: %ld"), (long)_moviePlayer.playbackState);
  215. }
  216. if (MPMoviePlayerLoadStateDidChangeNotification == notify.name)
  217. {
  218. NSLog(ASLocalizedString(@"========接收监听:player load state: %ld"), (long)_moviePlayer.loadState);
  219. if (MPMovieLoadStateStalled & _moviePlayer.loadState)
  220. {
  221. NSLog(@"player start caching");
  222. }
  223. if (_moviePlayer.bufferEmptyCount && (MPMovieLoadStatePlayable & _moviePlayer.loadState || MPMovieLoadStatePlaythroughOK & _moviePlayer.loadState))
  224. {
  225. NSLog(@"player finish caching");
  226. NSString *message = [[NSString alloc]initWithFormat:@"loading occurs, %d - %0.3fs",
  227. (int)_moviePlayer.bufferEmptyCount,
  228. _moviePlayer.bufferEmptyDuration];
  229. NSLog(@"=======:%@",message);
  230. }
  231. }
  232. if (MPMoviePlayerPlaybackDidFinishNotification == notify.name)
  233. {
  234. NSLog(ASLocalizedString(@"========接收监听:player finish state: %ld"), (long)_moviePlayer.playbackState);
  235. NSLog(@"player download flow size: %f MB", _moviePlayer.readSize);
  236. NSLog(@"buffer monitor result: \n empty count: %d, lasting: %f seconds",
  237. (int)_moviePlayer.bufferEmptyCount,
  238. _moviePlayer.bufferEmptyDuration);
  239. int reason = [[[notify userInfo] valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
  240. if (reason == MPMovieFinishReasonPlaybackEnded)
  241. {
  242. NSString *tipStr = [NSString stringWithFormat:@"player finish"];
  243. NSLog(@"%@",tipStr);
  244. }
  245. else if (reason == MPMovieFinishReasonPlaybackError)
  246. {
  247. NSString *tipStr = [NSString stringWithFormat:@"player Error : %@", [[notify userInfo] valueForKey:@"error"]];
  248. NSLog(@"%@",tipStr);
  249. }
  250. else if (reason == MPMovieFinishReasonUserExited)
  251. {
  252. NSString *tipStr = [NSString stringWithFormat:@"player userExited"];
  253. NSLog(@"%@",tipStr);
  254. }
  255. [_reLiveProgressView.playBtn setImage:[UIImage imageNamed:@"fw_relive_start"] forState:UIControlStateNormal];
  256. }
  257. if (MPMovieNaturalSizeAvailableNotification == notify.name)
  258. {
  259. NSLog(ASLocalizedString(@"========接收监听:video size %.0f-%.0f"), _moviePlayer.naturalSize.width, _moviePlayer.naturalSize.height);
  260. }
  261. if (MPMoviePlayerFirstVideoFrameRenderedNotification == notify.name)
  262. {
  263. _reloading = NO;
  264. if (_delegate && [_delegate respondsToSelector:@selector(firstFrame:)])
  265. {
  266. [_delegate firstFrame:self];
  267. }
  268. }
  269. if (MPMoviePlayerFirstAudioFrameRenderedNotification == notify.name)
  270. {
  271. NSLog(ASLocalizedString(@"========接收监听:first audio frame render"));
  272. }
  273. if (MPMoviePlayerSuggestReloadNotification == notify.name)
  274. {
  275. NSLog(ASLocalizedString(@"========接收监听:suggest using reload function!\n"));
  276. if(!_reloading)
  277. {
  278. _reloading = YES;
  279. __weak typeof(self) ws = self;
  280. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(){
  281. [ws reloadPlay];
  282. });
  283. }
  284. }
  285. if(MPMoviePlayerPlaybackStatusNotification == notify.name)
  286. {
  287. int status = [[[notify userInfo] valueForKey:MPMoviePlayerPlaybackStatusUserInfoKey] intValue];
  288. if(MPMovieStatusVideoDecodeWrong == status)
  289. {
  290. NSLog(ASLocalizedString(@"========接收监听:Video Decode Wrong!\n"));
  291. }
  292. else if(MPMovieStatusAudioDecodeWrong == status)
  293. {
  294. NSLog(ASLocalizedString(@"========接收监听:Audio Decode Wrong!\n"));
  295. }
  296. else if (MPMovieStatusHWCodecUsed == status )
  297. {
  298. NSLog(ASLocalizedString(@"========接收监听:Hardware Codec used\n"));
  299. }
  300. else if (MPMovieStatusSWCodecUsed == status )
  301. {
  302. NSLog(ASLocalizedString(@"========接收监听:Software Codec used\n"));
  303. }
  304. }
  305. }
  306. - (void)observeValueForKeyPath:(NSString *)keyPath
  307. ofObject:(id)object
  308. change:(NSDictionary *)change
  309. context:(void *)context
  310. {
  311. if([keyPath isEqual:@"currentPlaybackTime"])
  312. {
  313. if (_moviePlayer && _reLiveProgressView)
  314. {
  315. _reLiveProgressView.playProgress = _moviePlayer.currentPlaybackTime / _moviePlayer.duration;
  316. }
  317. }
  318. else if([keyPath isEqual:@"clientIP"])
  319. {
  320. NSLog(@"client IP is %@\n", [change objectForKey:NSKeyValueChangeNewKey]);
  321. }
  322. else if([keyPath isEqual:@"localDNSIP"])
  323. {
  324. NSLog(@"local DNS IP is %@\n", [change objectForKey:NSKeyValueChangeNewKey]);
  325. }
  326. else if ([keyPath isEqualToString:@"moviePlayer"])
  327. {
  328. if (_reLiveProgressView)
  329. {
  330. if (_moviePlayer)
  331. {
  332. _reLiveProgressView.hidden = NO;
  333. __weak KSYMoviePlayerController * weakPlayer = _moviePlayer;
  334. _reLiveProgressView.dragingSliderCallback = ^(float progress){
  335. typeof(weakPlayer) strongPlayer = weakPlayer;
  336. double seekPos = progress * strongPlayer.duration;
  337. //strongPlayer.currentPlaybackTime = progress * strongPlayer.duration;
  338. //使用currentPlaybackTime设置为依靠关键帧定位
  339. //使用seekTo:accurate并且将accurate设置为YES时为精确定位
  340. [strongPlayer seekTo:seekPos accurate:YES];
  341. };
  342. }
  343. else
  344. {
  345. _reLiveProgressView.hidden = YES;
  346. }
  347. }
  348. }
  349. }
  350. #pragma mark - ----------------------- 点播模块独有的 -----------------------
  351. - (void)startProTimer
  352. {
  353. if (_reLiveProgressView)
  354. {
  355. _reLiveProgressView.totalTimeInSeconds = _moviePlayer.duration;
  356. }
  357. if(_proTimer != nil)
  358. {
  359. return;
  360. }
  361. _proTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateStat:) userInfo:nil repeats:YES];
  362. }
  363. - (void)updateStat:(NSTimer *)timer
  364. {
  365. double flowSize = [_moviePlayer readSize];
  366. _speedK = 8*1024.0*(flowSize - _lastSize)/([self getCurrentTime] - _lastCheckTime);
  367. _lastCheckTime = [self getCurrentTime];
  368. _lastSize = flowSize;
  369. if (_reLiveProgressView)
  370. {
  371. CGFloat duration = _moviePlayer.duration;
  372. CGFloat playableDuration = _moviePlayer.playableDuration;
  373. if(duration > 0)
  374. {
  375. _reLiveProgressView.cacheProgress = playableDuration / duration;
  376. }
  377. else
  378. {
  379. _reLiveProgressView.cacheProgress = 0.0;
  380. }
  381. }
  382. }
  383. - (NSTimeInterval) getCurrentTime
  384. {
  385. return [[NSDate date] timeIntervalSince1970];
  386. }
  387. @end