Commit 9e7e874d7fc20bb023c70ddee32beadc7ccc8573
1 parent
2639f986
no message
Showing
3 changed files
with
166 additions
and
0 deletions
CNLivePlayer/Classes/Header/CNLivePlayerTypeDef.h
| @@ -184,4 +184,18 @@ typedef enum : NSUInteger { | @@ -184,4 +184,18 @@ typedef enum : NSUInteger { | ||
| 184 | 184 | ||
| 185 | } CNLiveClarityLevel; | 185 | } CNLiveClarityLevel; |
| 186 | 186 | ||
| 187 | +/** | ||
| 188 | + * 主播直播状态 | ||
| 189 | + */ | ||
| 190 | +typedef NS_ENUM(NSUInteger, CNLiveAnchorStatus) { | ||
| 191 | + ///主播直播中 | ||
| 192 | + CNLiveAnchorStatusLiving = 0, | ||
| 193 | + ///主播已离开 | ||
| 194 | + CNLiveAnchorStatusLeaving, | ||
| 195 | + ///直播已结束 | ||
| 196 | + CNLiveAnchorStatusEnd, | ||
| 197 | + ///直播错误 | ||
| 198 | + CNLiveAnchorStatusError | ||
| 199 | +}; | ||
| 200 | + | ||
| 187 | #endif /* CNLivePlayerTypeDef_h */ | 201 | #endif /* CNLivePlayerTypeDef_h */ |
CNLivePlayer/Classes/Player/CNLivePlayer.h
| @@ -22,6 +22,7 @@ NS_ASSUME_NONNULL_BEGIN | @@ -22,6 +22,7 @@ NS_ASSUME_NONNULL_BEGIN | ||
| 22 | 22 | ||
| 23 | typedef void (^SuccessBlock) (void); | 23 | typedef void (^SuccessBlock) (void); |
| 24 | typedef void (^FailureBlock) (NSError *error); | 24 | typedef void (^FailureBlock) (NSError *error); |
| 25 | +typedef void (^AnchorStatus)(CNLiveAnchorStatus status); | ||
| 25 | 26 | ||
| 26 | @interface CNLivePlayer : NSObject | 27 | @interface CNLivePlayer : NSObject |
| 27 | 28 | ||
| @@ -59,6 +60,24 @@ typedef void (^FailureBlock) (NSError *error); | @@ -59,6 +60,24 @@ typedef void (^FailureBlock) (NSError *error); | ||
| 59 | - (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId success:(SuccessBlock _Nullable)success failure:(FailureBlock _Nullable)failure; | 60 | - (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId success:(SuccessBlock _Nullable)success failure:(FailureBlock _Nullable)failure; |
| 60 | // 推荐使用 | 61 | // 推荐使用 |
| 61 | - (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId; | 62 | - (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId; |
| 63 | +- (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId | ||
| 64 | + success:(SuccessBlock _Nullable)success failure:(FailureBlock _Nullable)failure isAgree:(BOOL)isAgree anchorStatus:(AnchorStatus)anchorStatus; | ||
| 65 | +/* | ||
| 66 | + 主播直播状态(只读) | ||
| 67 | + | ||
| 68 | + @since v0.0.1 | ||
| 69 | + */ | ||
| 70 | + | ||
| 71 | +@property (nonatomic, assign, readonly) CNLiveAnchorStatus anchorStatus; | ||
| 72 | + | ||
| 73 | +/* | ||
| 74 | + 重新获取主播直播状态 | ||
| 75 | + | ||
| 76 | + @param result 重新获取主播直播状态 | ||
| 77 | + | ||
| 78 | + @since v0.0.1 | ||
| 79 | + */ | ||
| 80 | +- (void)retryToGetAnchorStatusResult:(AnchorStatus)result; | ||
| 62 | 81 | ||
| 63 | #pragma mark - 切换视频 | 82 | #pragma mark - 切换视频 |
| 64 | /** | 83 | /** |
CNLivePlayer/Classes/Player/CNLivePlayer.m
| @@ -14,6 +14,7 @@ | @@ -14,6 +14,7 @@ | ||
| 14 | #import "CNLivePlayerRequest.h" | 14 | #import "CNLivePlayerRequest.h" |
| 15 | #import "CommonCrypto/CommonDigest.h" | 15 | #import "CommonCrypto/CommonDigest.h" |
| 16 | #import "CNLivePlayerUrl.h" | 16 | #import "CNLivePlayerUrl.h" |
| 17 | +#import <CNLiveMsgTools/CNLiveMsgManager.h> | ||
| 17 | 18 | ||
| 18 | #define PlayerStringToKey(a, b) [NSString stringWithFormat:@"%@:%@",a,b] | 19 | #define PlayerStringToKey(a, b) [NSString stringWithFormat:@"%@:%@",a,b] |
| 19 | 20 | ||
| @@ -30,6 +31,10 @@ | @@ -30,6 +31,10 @@ | ||
| 30 | NSString *_rate; | 31 | NSString *_rate; |
| 31 | BOOL _switchRate; | 32 | BOOL _switchRate; |
| 32 | CMTime _switchRateTime; | 33 | CMTime _switchRateTime; |
| 34 | + | ||
| 35 | + //聊天室ID | ||
| 36 | + NSString *_roomId; | ||
| 37 | + | ||
| 33 | } | 38 | } |
| 34 | @property (nonatomic, strong) PLPlayerOption *option; | 39 | @property (nonatomic, strong) PLPlayerOption *option; |
| 35 | @property (nonatomic, strong) PLPlayer *switchPlayer; | 40 | @property (nonatomic, strong) PLPlayer *switchPlayer; |
| @@ -38,6 +43,11 @@ | @@ -38,6 +43,11 @@ | ||
| 38 | @end | 43 | @end |
| 39 | 44 | ||
| 40 | @implementation CNLivePlayer | 45 | @implementation CNLivePlayer |
| 46 | +//收到消息通知 | ||
| 47 | +NSString * const MsgToolsPlayerReceiveNotification = @"CNLiveMsgToolsPlayerReceiveNotification"; | ||
| 48 | +//获取主播状态通知 | ||
| 49 | +NSString * const CNLiveAnchorStatusChangedNotification = @"CNLiveAnchorStatusChangedNotification"; | ||
| 50 | + | ||
| 41 | - (instancetype)initWithUrl:(NSString *)url{ | 51 | - (instancetype)initWithUrl:(NSString *)url{ |
| 42 | self = [super init]; | 52 | self = [super init]; |
| 43 | if (self) { | 53 | if (self) { |
| @@ -107,6 +117,24 @@ | @@ -107,6 +117,24 @@ | ||
| 107 | - (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId{ | 117 | - (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId{ |
| 108 | return [self initLivePlayWithActivityId:activityId channelId:channelId success:nil failure:nil]; | 118 | return [self initLivePlayWithActivityId:activityId channelId:channelId success:nil failure:nil]; |
| 109 | } | 119 | } |
| 120 | +- (instancetype)initLivePlayWithActivityId:(NSString *)activityId channelId:(NSString *)channelId | ||
| 121 | + success:(SuccessBlock _Nullable)success failure:(FailureBlock _Nullable)failure isAgree:(BOOL)isAgree anchorStatus:(AnchorStatus)anchorStatus { | ||
| 122 | + self = [super init]; | ||
| 123 | + if (self) { | ||
| 124 | + _switchRate = NO; | ||
| 125 | + _activityId = activityId; | ||
| 126 | + _channelId = channelId; | ||
| 127 | + _videoId = @""; | ||
| 128 | + _type = @"live"; | ||
| 129 | + _rate = @"2"; | ||
| 130 | + [self getCacheURLSuccess:success failure:failure]; | ||
| 131 | + if (isAgree) { | ||
| 132 | + [self initRCloudWithAppId:Player_AppID appKey:Player_AppKey connectResult:anchorStatus]; | ||
| 133 | + } | ||
| 134 | + } | ||
| 135 | + return self; | ||
| 136 | + | ||
| 137 | +} | ||
| 110 | /** | 138 | /** |
| 111 | 初始化播放器 | 139 | 初始化播放器 |
| 112 | 140 | ||
| @@ -141,6 +169,7 @@ | @@ -141,6 +169,7 @@ | ||
| 141 | } | 169 | } |
| 142 | 170 | ||
| 143 | - (void)dealloc { | 171 | - (void)dealloc { |
| 172 | + [self removeRCloudNotificationObservers]; | ||
| 144 | NSLog(@"CNLivePlayer --> dealloc"); | 173 | NSLog(@"CNLivePlayer --> dealloc"); |
| 145 | } | 174 | } |
| 146 | 175 | ||
| @@ -886,6 +915,110 @@ CVPixelBufferGetPixelFormatType 获取 YUV 的类型。 | @@ -886,6 +915,110 @@ CVPixelBufferGetPixelFormatType 获取 YUV 的类型。 | ||
| 886 | [self.delegate player:self seekToCompleted:isCompleted]; | 915 | [self.delegate player:self seekToCompleted:isCompleted]; |
| 887 | } | 916 | } |
| 888 | } | 917 | } |
| 918 | +#pragma mark - 直播获取主播状态 | ||
| 919 | +#pragma mark - 初始化RM | ||
| 920 | +- (void)initRCloudWithAppId:(NSString *)appId appKey:(NSString *)appKey connectResult:(AnchorStatus)anchorStatus { | ||
| 921 | + [[CNLiveMsgManager sharedCNLiveMsgManager] initCNLiveMsgToolsWithAppKey:appKey appId:appId]; | ||
| 922 | + //连接RM服务器 | ||
| 923 | + [[CNLiveMsgManager sharedCNLiveMsgManager] justOnLineSuccess:^(NSString *toolsId) { | ||
| 924 | + //加入聊天室 | ||
| 925 | + [self joinRoomResult:anchorStatus]; | ||
| 926 | + | ||
| 927 | + } error:^(NSInteger errors) { | ||
| 928 | + if (anchorStatus) { | ||
| 929 | + anchorStatus(NO); | ||
| 930 | + } | ||
| 931 | + }]; | ||
| 932 | + | ||
| 933 | +} | ||
| 934 | + | ||
| 935 | +//加入聊天室 | ||
| 936 | +- (void)joinRoomResult:(AnchorStatus)anchorStatus { | ||
| 937 | + [self addRCloudNotificationObservers]; | ||
| 938 | + | ||
| 939 | + NSString *contentId = _activityId ? _activityId : _channelId; | ||
| 940 | + if (![_channelId containsString:@"_"]) { | ||
| 941 | + NSString *spId = [[Player_AppID componentsSeparatedByString:@"_"] firstObject]; | ||
| 942 | + contentId = [NSString stringWithFormat:@"%@_%@", spId, _channelId]; | ||
| 943 | + } | ||
| 944 | + | ||
| 945 | + _roomId = [NSString stringWithFormat:@"CNLiveAnchorStatus_%@",contentId]; | ||
| 946 | + | ||
| 947 | + //加入聊天室 | ||
| 948 | + [[CNLiveMsgManager sharedCNLiveMsgManager] gatherIfNullCreate:_roomId messageCount:1 success:^(NSString *targetId) { | ||
| 949 | + if (anchorStatus) { | ||
| 950 | + anchorStatus(YES); | ||
| 951 | + } | ||
| 952 | + | ||
| 953 | + } error:^(NSInteger errors, NSString *targetId) { | ||
| 954 | + if (anchorStatus) { | ||
| 955 | + anchorStatus(CNLiveAnchorStatusError); | ||
| 956 | + } | ||
| 957 | + | ||
| 958 | + }]; | ||
| 959 | + | ||
| 960 | +} | ||
| 961 | + | ||
| 962 | +//重新获取主播状态(离开/已结束) | ||
| 963 | +- (void)retryToGetAnchorStatusResult:(AnchorStatus)anchorStatus { | ||
| 964 | + [self initRCloudWithAppId:Player_AppID appKey:Player_AppKey connectResult:anchorStatus]; | ||
| 965 | + | ||
| 966 | +} | ||
| 967 | + | ||
| 968 | +#pragma mark - 通知 | ||
| 969 | +- (void)addRCloudNotificationObservers { | ||
| 970 | + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveMessage:) name:MsgToolsPlayerReceiveNotification object:nil]; | ||
| 971 | + | ||
| 972 | +} | ||
| 973 | + | ||
| 974 | +- (void)removeRCloudNotificationObservers { | ||
| 975 | + [[NSNotificationCenter defaultCenter] removeObserver:self name:MsgToolsPlayerReceiveNotification object:nil]; | ||
| 976 | + | ||
| 977 | + if (!_roomId || [_roomId isEqualToString:@""] || ![_roomId isKindOfClass:[NSString class]] || _roomId.length == 0) { | ||
| 978 | + return; | ||
| 979 | + } | ||
| 980 | + | ||
| 981 | + [[CNLiveMsgManager sharedCNLiveMsgManager] disperse:_roomId success:^(NSString *targetId) { | ||
| 982 | + | ||
| 983 | + } error:^(NSInteger errors, NSString *targetId) { | ||
| 984 | + | ||
| 985 | + }]; | ||
| 986 | + | ||
| 987 | +} | ||
| 988 | + | ||
| 989 | +#pragma mark - 聊天室 | ||
| 990 | +- (void)receiveMessage:(NSNotification *)noti { | ||
| 991 | + | ||
| 992 | + if (!noti.userInfo[@"message"]) return; | ||
| 993 | + | ||
| 994 | + int newValue = [noti.userInfo[@"message"] intValue]; | ||
| 995 | + | ||
| 996 | + if (_anchorStatus == newValue) return; //如果新收到的状态与上一次状态一样不作处理 | ||
| 997 | + _anchorStatus = newValue; | ||
| 998 | + | ||
| 999 | + if (newValue == 1) { | ||
| 1000 | + _anchorStatus = CNLiveAnchorStatusLiving; | ||
| 1001 | + [_player play]; | ||
| 1002 | + | ||
| 1003 | + } else if (newValue == 2) { | ||
| 1004 | + _anchorStatus = CNLiveAnchorStatusEnd; | ||
| 1005 | + [_player stop]; | ||
| 1006 | + | ||
| 1007 | + } else { | ||
| 1008 | + _anchorStatus = CNLiveAnchorStatusLeaving; | ||
| 1009 | + [_player pause]; | ||
| 1010 | + | ||
| 1011 | + } | ||
| 889 | 1012 | ||
| 1013 | + if (Player_TestEnvironment) { | ||
| 1014 | + NSLog(@"CNLiveMoviePlayerController-->主播直播状态%lu",(unsigned long)_anchorStatus); | ||
| 1015 | + } | ||
| 1016 | + | ||
| 1017 | + //发送通知 | ||
| 1018 | + dispatch_async(dispatch_get_main_queue(), ^{ | ||
| 1019 | + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveAnchorStatusChangedNotification object:nil userInfo:nil]; | ||
| 1020 | + }); | ||
| 1021 | + | ||
| 1022 | +} | ||
| 890 | 1023 | ||
| 891 | @end | 1024 | @end |