CNLivePlayerViewController.m 10.4 KB
//
//  CNLivePlayerViewController.m
//  QNLiveStreamingDemo
//
//  Created by iOS on 16/12/29.
//  Copyright © 2016年 zhulin. All rights reserved.
//

#import "CNLivePlayerViewController.h"
#import "PlayerFunctionView.h"
#import "LoadingView.h"
#import "BackgroundView.h"

@interface CNLivePlayerViewController ()<CNLiveMoviePlayerKitDelegate>
{
    NSTimer *_currentTimer;
    BOOL _isGetAnchorStatusError;

}

@property (nonatomic, strong) CNLiveMoviePlayerKit *player;
@property (nonatomic, strong) PlayerFunctionView *playFuncView;
@property (nonatomic, strong) BackgroundView *bgView;
@property (nonatomic, strong) LoadingView *loadingView;
@property (nonatomic, strong) UIButton *quitBtn;

@end

@implementation CNLivePlayerViewController

- (void)dealloc
{
    _player.delegate = nil;
    _player = nil;
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor blackColor];
    
    _currentTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    
    if (_type == PlayerTypeLiving) {        //直播
        
        _player = [[CNLiveMoviePlayerKit alloc] initLivePlayWithChannelId:@"test001" authSuccess:^{
            
            [self setupUI];
            
        } authFailure:^(NSDictionary *errorInfo) {
            NSLog(@"直播播放失败-------%@",errorInfo);
            [_loadingView stopLoading];

        } getAnchorStatusResult:^(BOOL result) {
            if (!result) {
                NSLog(@"无法获取主播状态-------------");
                _isGetAnchorStatusError = YES;
                _loadingView.retryBtn.hidden = NO;
            }
        }];
        
        _player.delegate = self;
     
    } else if (_type == PlayerTypeVOD) {        //点播
        
        _player = [[CNLiveMoviePlayerKit alloc] initVodPlayWithVId:@"test001" authSuccess:^{
    
            [self setupUI];
    
            _currentTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    
        } authFailure:^(NSDictionary *errorInfo) {
    
            NSLog(@"点播播放失败-------%@",errorInfo);
            [_loadingView stopLoading];
            _loadingView.retryBtn.hidden = NO;

        }];
    
        _player.delegate = self;

    } else {        //普通播放

        _player = [[CNLiveMoviePlayerKit alloc] initPlayerWithContentURL:self.videoUrlString];
        [self setupUI];
        _player.delegate = self;
    }

    [self.view addSubview:self.bgView];
    [self.view addSubview:self.loadingView];
    [self.view addSubview:self.playFuncView];
    [self.view addSubview:self.quitBtn];
    //注册通知
    [self addObservers];

}

- (void)setupUI
{
    if (_player.status != CNLivePlayerStatusError) {
        
        UIView *playerView = _player.playerView;
        playerView.backgroundColor = [UIColor blackColor];
        playerView.contentMode = UIViewContentModeScaleAspectFit;
        playerView.frame = CGRectMake(0, 0, kSCREEN_WIDTH, kSCREEN_HEIGHT);
        [self.view addSubview:playerView];
        [self.view sendSubviewToBack:playerView];
        [_player play];
    }
}

#pragma mark -
#pragma mark - action

- (void)playBtnAction:(UIButton *)button
{
    button.selected = !button.selected;
    
    if (!button.selected) {
        [self.player pause];
    } else {
        [self.player play];
    }
}

- (void)quitBtnAction
{
    if (_player.status != CNLivePlayerStatusStopped) {
        [_player stop];
        [_player.playerView removeFromSuperview];
        _player = nil;
    }
    [self dismissViewControllerAnimated:YES completion:NULL];
}

- (void)retryBtnAction
{
    _loadingView.retryBtn.hidden = YES;
    [_loadingView startLoading];
    
   //调用重试方法
    if (_isGetAnchorStatusError) {
        [_player retryToGetAnchorStatusResult:^(BOOL result) {
            if (!result) {
                _loadingView.retryBtn.hidden = NO;
            } else {
                _isGetAnchorStatusError = NO;
            }
            [_loadingView stopLoading];
        }];
    }
    
    [_player play];
}

- (void)beginScrubbing
{
    [self.player pause];
}

- (void)endScrubbing
{
    CGFloat duration = ceilf(CMTimeGetSeconds(self.player.totalDuration));
    CMTime time = CMTimeMakeWithSeconds(_playFuncView.timeSlide.value*duration, 30);
    [self.player seekTo:time];

}

- (void)timeChange
{
    _playFuncView.timeSlide.value = CMTimeGetSeconds(_player.currentTime)/CMTimeGetSeconds(_player.totalDuration);
    _playFuncView.currentTimeLabel.text = [self getMMSSFromSS:[NSString stringWithFormat:@"%f",CMTimeGetSeconds(_player.currentTime)]];
    _playFuncView.durationLabel.text = [self getMMSSFromSS:[NSString stringWithFormat:@"%f",CMTimeGetSeconds(_player.totalDuration)]];
}

-(NSString *)getMMSSFromSS:(NSString *)totalTime {
    NSInteger seconds = [totalTime integerValue];
    NSString *str_hour = [NSString stringWithFormat:@"%02ld",seconds/3600];
    NSString *str_minute = [NSString stringWithFormat:@"%02ld",(seconds%3600)/60];
    NSString *str_second = [NSString stringWithFormat:@"%02ld",seconds%60];
    NSString *format_time = [NSString stringWithFormat:@"%@:%@:%@",str_hour,str_minute,str_second];
    return format_time;
}

- (void)willEnterBackground
{
    [_player pause];
}

- (void)willBackFromBackground
{
    [_player resume];
}

#pragma mark -
#pragma mark - Notification
- (void)addObservers
{
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(willEnterBackground)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(willBackFromBackground)
                                                 name:UIApplicationDidBecomeActiveNotification
                                               object:nil];
    
    //获取主播状态通知(点播和普通播放不需要注册该通知)
    if (_type != PlayerTypeLiving) return;
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(anchorStatusChanged:)
                                                 name:CNLiveAnchorStatusChangedNotification
                                               object:nil];
}

- (void)anchorStatusChanged:(NSNotification *)notification
{
    [self.loadingView stopLoading];
    _bgView.anchorStatus = _player.anchorStatus;
}

- (void)anchorStatusConnectFailed
{
    //重新连接获取主播状态
    _loadingView.retryBtn.hidden = NO;
}

#pragma mark -
#pragma mark - CNLiveMoviePlayerKitDelegate
- (void)player:(CNLiveMoviePlayerKit *)player statusDidChanged:(CNLivePlayerStatus)state
{

    switch (state) {
        case CNLivePlayerStatusReady:
            _playFuncView.playOrPauseBtn.selected = YES;
            break;
            
        case CNLivePlayerStatusCaching:
            [_loadingView startLoading];
            break;
            
        case CNLivePlayerStatusPlaying:
            [_loadingView stopLoading];
            break;
            
        case CNLivePlayerStatusStopped:
            [_loadingView stopLoading];
            _playFuncView.playOrPauseBtn.selected = NO;
            
            if (_currentTimer) {
                [_currentTimer invalidate];
                _currentTimer = nil;
            }
            break;
            
        case CNLivePlayerStatusError:
            _playFuncView.playOrPauseBtn.selected = NO;
            _loadingView.retryBtn.hidden = NO;
            break;
            
        case CNLivePlayerStateAutoReconnecting:
            _playFuncView.playOrPauseBtn.selected = NO;
            break;
            
        default:
            break;
    }

}

- (void)player:(CNLiveMoviePlayerKit *)player stoppedWithError:(NSError *)error
{
    NSLog(@"error ----- %@",error);
    [_loadingView stopLoading];
    _loadingView.retryBtn.hidden = NO;
    _playFuncView.playOrPauseBtn.selected = NO;
}

- (void)player:(CNLiveMoviePlayerKit *)player codecError:(NSError *)error
{
    NSLog(@"解码器错误error ----- %@",error);
    [_loadingView stopLoading];
    _loadingView.retryBtn.hidden = NO;
}

#pragma mark -
#pragma mark - getter
- (PlayerFunctionView *)playFuncView
{
    if (!_playFuncView) {
        _playFuncView = [[PlayerFunctionView alloc] initWithFrame:CGRectMake(0, kSCREEN_HEIGHT-60, kSCREEN_WIDTH, 60)];
        [_playFuncView.playOrPauseBtn addTarget:self action:@selector(playBtnAction:) forControlEvents:UIControlEventTouchUpInside];
        [_playFuncView.timeSlide addTarget:self action:@selector(beginScrubbing) forControlEvents:UIControlEventTouchDown];
        [_playFuncView.timeSlide addTarget:self action:@selector(endScrubbing) forControlEvents:UIControlEventTouchUpInside];
        [_playFuncView.timeSlide addTarget:self action:@selector(endScrubbing) forControlEvents:UIControlEventTouchUpOutside];
    }
    return _playFuncView;
}

- (LoadingView *)loadingView
{
    if (!_loadingView) {
        _loadingView = [[LoadingView alloc] initWithFrame:CGRectMake(0, 0, 70, 70)];
        _loadingView.center = self.view.center;
        [_loadingView.retryBtn addTarget:self action:@selector(retryBtnAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _loadingView;
}

- (BackgroundView *)bgView
{
    if (!_bgView) {
        _bgView = [[BackgroundView alloc] initWithFrame:self.view.bounds];
        _bgView.hidden = YES;
    }
    return _bgView;
}

- (UIButton *)quitBtn
{
    if (!_quitBtn) {
        _quitBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        _quitBtn.frame = CGRectMake(CGRectGetWidth(self.view.frame)-45, 25, 30, 30);
        [_quitBtn setImage:[UIImage imageNamed:@"cancel"] forState:UIControlStateNormal];
        [_quitBtn addTarget:self action:@selector(quitBtnAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _quitBtn;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end