Commit bc4de5f01589a3d3f21f392045a8252d6725a907
1 parent
071d59de
no message
Showing
4 changed files
with
150 additions
and
43 deletions
CNLivePlayer/Classes/Header/CNLivePlayerDefines.h
| ... | ... | @@ -18,6 +18,19 @@ typedef NS_ENUM(NSUInteger, CNLivePlayerType) { |
| 18 | 18 | CNLivePlayerAudio //音频 |
| 19 | 19 | |
| 20 | 20 | }; |
| 21 | +/** | |
| 22 | + * 视频解码模式 | |
| 23 | + */ | |
| 24 | +typedef NS_ENUM(NSUInteger, CNLiveMovieVideoDecoderMode) { | |
| 25 | + ///视频解码方式采用软解 | |
| 26 | + CNLiveMovieVideoDecoderMode_Software = 0, | |
| 27 | + ///视频解码方式采用硬解 | |
| 28 | + CNLiveMovieVideoDecoderMode_Hardware, | |
| 29 | + ///自动选择解码方式,8.0以上的系统优先选择硬解 | |
| 30 | + CNLiveMovieVideoDecoderMode_AUTO, | |
| 31 | + ///使用系统接口进行解码和渲染,只适用于8.0及以上系统,低于8.0的系统自动使用软解 | |
| 32 | + CNLiveMovieVideoDecoderMode_DisplayLayer, | |
| 33 | +}; | |
| 21 | 34 | |
| 22 | 35 | /** |
| 23 | 36 | * 主播直播状态 | ... | ... |
CNLivePlayer/Classes/Player/CNLivePlayer.h
| ... | ... | @@ -120,6 +120,14 @@ typedef void(^AuthFailureBlock)(NSDictionary *errorInfo); |
| 120 | 120 | */ |
| 121 | 121 | @property (nonatomic, assign, readonly) CNLiveHostStatus hostStatus; |
| 122 | 122 | |
| 123 | +/* 解码方式(硬解/软解/自动/使用系统接口进行解码和渲染) | |
| 124 | + * | |
| 125 | + * 建议系统版本高于8.0 选择硬解,或者自动选择解码方式,8.0以上的系统优先选择硬解 | |
| 126 | + * 只在[prepareToPlay]调用前设置生效 | |
| 127 | + * | |
| 128 | + */ | |
| 129 | +@property(nonatomic) CNLiveMovieVideoDecoderMode videoDecoderMode; | |
| 130 | + | |
| 123 | 131 | /** |
| 124 | 132 | @abstract 是否静音 |
| 125 | 133 | @discussion | ... | ... |
CNLivePlayer/Classes/Player/CNLivePlayer.m
| ... | ... | @@ -45,7 +45,7 @@ |
| 45 | 45 | } |
| 46 | 46 | @property (nonatomic, strong, readwrite) UIView *view; |
| 47 | 47 | @property (nonatomic, copy) NSString *videoUrl; |
| 48 | -@property (nonatomic, strong) KSYMoviePlayerController *switchPlayer; | |
| 48 | +@property (nonatomic, weak) KSYMoviePlayerController *switchPlayer; | |
| 49 | 49 | |
| 50 | 50 | @end |
| 51 | 51 | |
| ... | ... | @@ -281,7 +281,7 @@ NSString * const CNLiveHostStatusChangedNotification = @"CNLiveAnchorStatusChang |
| 281 | 281 | * rate 码率 1-流畅,2-标清,3-高清,4-超清,默认为2 |
| 282 | 282 | */ |
| 283 | 283 | - (void)setPlayerWithContentId:(NSString *)contentId rate:(NSString *)rate authSuccess:(AuthSuccessBlock)authSuccessBlock authFailure:(AuthFailureBlock)authFailureBlock { |
| 284 | - if(!_contentId&&[_rate isEqualToString:rate]){ | |
| 284 | + if(!contentId&&[_rate isEqualToString:rate]){ | |
| 285 | 285 | return; |
| 286 | 286 | } |
| 287 | 287 | if([_contentId isEqualToString:contentId]&&[_rate isEqualToString:rate]){ |
| ... | ... | @@ -396,15 +396,17 @@ NSString * const CNLiveHostStatusChangedNotification = @"CNLiveAnchorStatusChang |
| 396 | 396 | if(self->_switchRate){ |
| 397 | 397 | //切换码率 |
| 398 | 398 | NSString *proxyUrl = [[CNLiveHTTPProxyService manager] getProxyUrl:self.videoUrl]; |
| 399 | - self.switchPlayer = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:PLAYER_OpenCache?proxyUrl:self.videoUrl]]; | |
| 400 | -// self.switchPlayer.view.frame = CGRectMake(0, 0, 200, 100); | |
| 401 | - self.switchPlayer.view.frame = self.view.bounds; | |
| 402 | - self.switchPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; | |
| 403 | - self.switchPlayer.shouldAutoplay = NO; | |
| 404 | - self.switchPlayer.shouldEnableKSYStatModule = NO; | |
| 405 | - [self.switchPlayer seekTo:self.player.currentPlaybackTime accurate:YES]; | |
| 406 | - [self.switchPlayer prepareToPlay]; | |
| 407 | - [self.view addSubview:self.switchPlayer.view]; | |
| 399 | + KSYMoviePlayerController *switchPlayer = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:PLAYER_OpenCache?proxyUrl:self.videoUrl]]; | |
| 400 | +// switchPlayer.view.frame = self.view.bounds; | |
| 401 | + switchPlayer.view.frame = CGRectMake(100, 200, 200, 100); | |
| 402 | + switchPlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; | |
| 403 | + switchPlayer.shouldAutoplay = NO; | |
| 404 | + switchPlayer.shouldEnableKSYStatModule = NO; | |
| 405 | + [switchPlayer prepareToPlay]; | |
| 406 | + [switchPlayer play]; | |
| 407 | + [switchPlayer seekTo:self.player.currentPlaybackTime accurate:YES]; | |
| 408 | + [self.view addSubview:switchPlayer.view]; | |
| 409 | + self.switchPlayer = switchPlayer; | |
| 408 | 410 | |
| 409 | 411 | }else{ |
| 410 | 412 | if(!self.player){ |
| ... | ... | @@ -698,10 +700,51 @@ NSString * const CNLiveHostStatusChangedNotification = @"CNLiveAnchorStatusChang |
| 698 | 700 | |
| 699 | 701 | #pragma mark - 通知响应方法 |
| 700 | 702 | - (void)loadStateDidChange:(NSNotification *)notification { |
| 701 | - MPMovieLoadState loadState = _player.loadState; | |
| 703 | + KSYMoviePlayerController *player = [notification object]; | |
| 704 | + MPMovieLoadState loadState = player.loadState; | |
| 702 | 705 | if (PLAYER_TestEnvironment) { |
| 703 | 706 | NSLog(@"CNLivePlayer-->播放器加载状态改变MPMovieLoadState:%ld", (unsigned long)loadState); |
| 704 | 707 | } |
| 708 | + | |
| 709 | + //切换码率 | |
| 710 | + if(_switchRate){ | |
| 711 | + if((self.switchPlayer == player)&&(loadState == 3)){ | |
| 712 | + [player seekTo:self.player.currentPlaybackTime accurate:NO]; | |
| 713 | + [player play]; | |
| 714 | + [self.player stop]; | |
| 715 | + KSYMoviePlayerController *temp = self.player; | |
| 716 | + self.player = player; | |
| 717 | + self.switchPlayer = temp; | |
| 718 | +// __weak typeof(self)weakSelf = self; | |
| 719 | +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ | |
| 720 | +// __strong typeof (weakSelf) strongSelf = weakSelf; | |
| 721 | +// if(!strongSelf){ | |
| 722 | +// return ; | |
| 723 | +// } | |
| 724 | +// [strongSelf.switchPlayer stop]; | |
| 725 | +// }); | |
| 726 | + _switchRate = NO; | |
| 727 | + } | |
| 728 | + } | |
| 729 | + [_player play]; | |
| 730 | + | |
| 731 | +} | |
| 732 | + | |
| 733 | +- (void)mediaIsPreparedToPlayDidChange:(NSNotification *)notification { | |
| 734 | + KSYMoviePlayerController *player = [notification object]; | |
| 735 | + MPMovieLoadState loadState = player.loadState; | |
| 736 | + | |
| 737 | + if (PLAYER_TestEnvironment) { | |
| 738 | + NSLog(@"CNLivePlayer-->播放器缓冲至可播放状态"); | |
| 739 | + } | |
| 740 | + | |
| 741 | + if (!_contentType || _contentType.length == 0) { | |
| 742 | + return; | |
| 743 | + } | |
| 744 | + if(!_statTimer){ | |
| 745 | + _statTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(statTimerAction) userInfo:nil repeats:YES]; | |
| 746 | + | |
| 747 | + } | |
| 705 | 748 | |
| 706 | 749 | } |
| 707 | 750 | |
| ... | ... | @@ -746,29 +789,6 @@ NSString * const CNLiveHostStatusChangedNotification = @"CNLiveAnchorStatusChang |
| 746 | 789 | |
| 747 | 790 | } |
| 748 | 791 | |
| 749 | -- (void)mediaIsPreparedToPlayDidChange:(NSNotification *)notification { | |
| 750 | - if (PLAYER_TestEnvironment) { | |
| 751 | - NSLog(@"CNLivePlayer-->播放器缓冲至可播放状态"); | |
| 752 | - } | |
| 753 | - //切换码率 | |
| 754 | - if(_switchRate){ | |
| 755 | - [self.switchPlayer seekTo:self.player.currentPlaybackTime accurate:YES]; | |
| 756 | - [self.player stop]; | |
| 757 | - self.player = self.switchPlayer; | |
| 758 | - self.switchPlayer.shouldMute = NO; | |
| 759 | - _switchRate = NO; | |
| 760 | - } | |
| 761 | - [_player play]; | |
| 762 | - if (!_contentType || _contentType.length == 0) { | |
| 763 | - return; | |
| 764 | - } | |
| 765 | - if(!_statTimer){ | |
| 766 | - _statTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(statTimerAction) userInfo:nil repeats:YES]; | |
| 767 | - | |
| 768 | - } | |
| 769 | - | |
| 770 | -} | |
| 771 | - | |
| 772 | 792 | - (void)mediaCacheDidChanged:(NSNotification *)notification { |
| 773 | 793 | NSDictionary *userInfo = notification.userInfo; |
| 774 | 794 | float progress = [userInfo[CacheProgressKey] floatValue]; |
| ... | ... | @@ -850,6 +870,10 @@ NSString * const CNLiveHostStatusChangedNotification = @"CNLiveAnchorStatusChang |
| 850 | 870 | return _view; |
| 851 | 871 | } |
| 852 | 872 | |
| 873 | +- (void)setVideoDecoderMode:(CNLiveMovieVideoDecoderMode)videoDecoderMode{ | |
| 874 | + _player.videoDecoderMode = (MPMovieVideoDecoderMode)videoDecoderMode; | |
| 875 | +} | |
| 876 | + | |
| 853 | 877 | - (void)setShouldMute:(BOOL)shouldMute { |
| 854 | 878 | _player.shouldMute = shouldMute; |
| 855 | 879 | } | ... | ... |
Example/CNLivePlayer/Player/CNLivePlayerController.m
| ... | ... | @@ -28,7 +28,9 @@ |
| 28 | 28 | selector:@selector(mediaIsPreparedToPlayDidChange:) |
| 29 | 29 | name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification |
| 30 | 30 | object:nil]; |
| 31 | - self.player = [[CNLivePlayer alloc]initVodPlayerWithVideoId:@"82_c8ff347048414b7295cef882f8361073" authSuccess:^{ | |
| 31 | + //82_c8ff347048414b7295cef882f8361073 | |
| 32 | +// 223_9855888ddc68402ca738bf302e535805 | |
| 33 | + self.player = [[CNLivePlayer alloc]initVodPlayerWithVideoId:@"223_9855888ddc68402ca738bf302e535805" authSuccess:^{ | |
| 32 | 34 | _player.view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width*9/16.0); |
| 33 | 35 | [_player prepareToPlay]; |
| 34 | 36 | |
| ... | ... | @@ -74,22 +76,49 @@ |
| 74 | 76 | |
| 75 | 77 | UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom]; |
| 76 | 78 | btn2.frame = CGRectMake(0, 0, 100, 50); |
| 77 | - btn2.center = CGPointMake(self.view.center.x, self.view.center.y+100); | |
| 79 | + btn2.center = CGPointMake(self.view.center.x-80, self.view.center.y+100); | |
| 78 | 80 | btn2.backgroundColor = [UIColor redColor]; |
| 79 | - [btn2 setTitle:@"切换码率" forState:UIControlStateNormal]; | |
| 81 | + [btn2 setTitle:@"切换码率1" forState:UIControlStateNormal]; | |
| 80 | 82 | [btn2 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; |
| 81 | 83 | [btn2 addTarget:self action:@selector(btnDidClicked2) forControlEvents:UIControlEventTouchUpInside]; |
| 82 | 84 | [self.view addSubview:btn2]; |
| 83 | 85 | |
| 84 | 86 | UIButton *btn3 = [UIButton buttonWithType:UIButtonTypeCustom]; |
| 85 | 87 | btn3.frame = CGRectMake(0, 0, 100, 50); |
| 86 | - btn3.center = CGPointMake(self.view.center.x, self.view.center.y+200); | |
| 88 | + btn3.center = CGPointMake(self.view.center.x+80, self.view.center.y+100); | |
| 87 | 89 | btn3.backgroundColor = [UIColor redColor]; |
| 88 | - [btn3 setTitle:@"返回" forState:UIControlStateNormal]; | |
| 90 | + [btn3 setTitle:@"切换码率2" forState:UIControlStateNormal]; | |
| 89 | 91 | [btn3 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; |
| 90 | 92 | [btn3 addTarget:self action:@selector(btnDidClicked3) forControlEvents:UIControlEventTouchUpInside]; |
| 91 | 93 | [self.view addSubview:btn3]; |
| 92 | 94 | |
| 95 | + UIButton *btn4 = [UIButton buttonWithType:UIButtonTypeCustom]; | |
| 96 | + btn4.frame = CGRectMake(0, 0, 100, 50); | |
| 97 | + btn4.center = CGPointMake(self.view.center.x-80, self.view.center.y+200); | |
| 98 | + btn4.backgroundColor = [UIColor redColor]; | |
| 99 | + [btn4 setTitle:@"切换码率3" forState:UIControlStateNormal]; | |
| 100 | + [btn4 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; | |
| 101 | + [btn4 addTarget:self action:@selector(btnDidClicked4) forControlEvents:UIControlEventTouchUpInside]; | |
| 102 | + [self.view addSubview:btn4]; | |
| 103 | + | |
| 104 | + UIButton *btn5 = [UIButton buttonWithType:UIButtonTypeCustom]; | |
| 105 | + btn5.frame = CGRectMake(0, 0, 100, 50); | |
| 106 | + btn5.center = CGPointMake(self.view.center.x+80, self.view.center.y+200); | |
| 107 | + btn5.backgroundColor = [UIColor redColor]; | |
| 108 | + [btn5 setTitle:@"切换码率4" forState:UIControlStateNormal]; | |
| 109 | + [btn5 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; | |
| 110 | + [btn5 addTarget:self action:@selector(btnDidClicked5) forControlEvents:UIControlEventTouchUpInside]; | |
| 111 | + [self.view addSubview:btn5]; | |
| 112 | + | |
| 113 | + UIButton *btn6 = [UIButton buttonWithType:UIButtonTypeCustom]; | |
| 114 | + btn6.frame = CGRectMake(0, 0, 100, 50); | |
| 115 | + btn6.center = CGPointMake(self.view.center.x, self.view.center.y+300); | |
| 116 | + btn6.backgroundColor = [UIColor redColor]; | |
| 117 | + [btn6 setTitle:@"返回" forState:UIControlStateNormal]; | |
| 118 | + [btn6 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; | |
| 119 | + [btn6 addTarget:self action:@selector(btnDidClicked6) forControlEvents:UIControlEventTouchUpInside]; | |
| 120 | + [self.view addSubview:btn6]; | |
| 121 | + | |
| 93 | 122 | // CNLivePlayerDownloader *dowa = [[CNLivePlayerDownloader alloc]initWithUrlString:@"http://wideo02.cnlive.com/video/data1/2017/0423/206473/800/c8ff347048414b7295cef882f8361073_206473_800.m3u8" progressBlock:^(float progress) { |
| 94 | 123 | // NSLog(@"缓存进度中%f",progress); |
| 95 | 124 | // }]; |
| ... | ... | @@ -119,7 +148,7 @@ |
| 119 | 148 | __weak typeof(self) weakSelf = self; |
| 120 | 149 | [_player setPlayerWithContentId:@"1066_716fabeaafb64236b60ecf74167c5c96" type:CNLivePlayerVod authSuccess:^{ |
| 121 | 150 | __strong typeof(self) strongSelf = weakSelf; |
| 122 | -// [strongSelf.player prepareToPlay]; | |
| 151 | + [strongSelf.player prepareToPlay]; | |
| 123 | 152 | |
| 124 | 153 | } authFailure:^(NSDictionary * _Nonnull errorInfo) { |
| 125 | 154 | |
| ... | ... | @@ -130,9 +159,8 @@ |
| 130 | 159 | - (void)btnDidClicked2{ |
| 131 | 160 | self.state.text = @"切换中"; |
| 132 | 161 | __weak typeof(self) weakSelf = self; |
| 133 | - [_player setPlayerWithContentId:nil rate:@"4" authSuccess:^{ | |
| 162 | + [_player setPlayerWithContentId:nil rate:@"1" authSuccess:^{ | |
| 134 | 163 | __strong typeof(self) strongSelf = weakSelf; |
| 135 | - [strongSelf.player prepareToPlay]; | |
| 136 | 164 | } authFailure:^(NSDictionary * _Nonnull errorInfo) { |
| 137 | 165 | |
| 138 | 166 | }]; |
| ... | ... | @@ -140,6 +168,40 @@ |
| 140 | 168 | } |
| 141 | 169 | |
| 142 | 170 | - (void)btnDidClicked3{ |
| 171 | + self.state.text = @"切换中"; | |
| 172 | + __weak typeof(self) weakSelf = self; | |
| 173 | + [_player setPlayerWithContentId:nil rate:@"2" authSuccess:^{ | |
| 174 | + __strong typeof(self) strongSelf = weakSelf; | |
| 175 | + } authFailure:^(NSDictionary * _Nonnull errorInfo) { | |
| 176 | + | |
| 177 | + }]; | |
| 178 | + | |
| 179 | +} | |
| 180 | + | |
| 181 | +- (void)btnDidClicked4{ | |
| 182 | + self.state.text = @"切换中"; | |
| 183 | + __weak typeof(self) weakSelf = self; | |
| 184 | + [_player setPlayerWithContentId:nil rate:@"3" authSuccess:^{ | |
| 185 | + __strong typeof(self) strongSelf = weakSelf; | |
| 186 | + } authFailure:^(NSDictionary * _Nonnull errorInfo) { | |
| 187 | + | |
| 188 | + }]; | |
| 189 | + | |
| 190 | +} | |
| 191 | + | |
| 192 | +- (void)btnDidClicked5{ | |
| 193 | + self.state.text = @"切换中"; | |
| 194 | + __weak typeof(self) weakSelf = self; | |
| 195 | + [_player setPlayerWithContentId:nil rate:@"4" authSuccess:^{ | |
| 196 | + __strong typeof(self) strongSelf = weakSelf; | |
| 197 | + } authFailure:^(NSDictionary * _Nonnull errorInfo) { | |
| 198 | + | |
| 199 | + }]; | |
| 200 | + | |
| 201 | +} | |
| 202 | + | |
| 203 | + | |
| 204 | +- (void)btnDidClicked6{ | |
| 143 | 205 | [self dismissViewControllerAnimated:YES completion:nil]; |
| 144 | 206 | |
| 145 | 207 | } | ... | ... |