Commit c7d9b14980fe27f546ef3614264f2bdb4e75fb6f

Authored by zhangxiaowen
1 parent ee67e19b

no message

CNLivePlayer.podspec
... ... @@ -47,10 +47,13 @@ TODO: Add long description of the pod here.
47 47 ss.source_files = 'CNLivePlayer/Classes/Tools/*.{h,m}'
48 48 end
49 49  
  50 + s.static_framework = true
  51 +
50 52 # s.public_header_files = 'Pod/Classes/**/*.h'
51 53 s.frameworks = 'UIKit', 'MediaPlayer'
52 54 s.dependency 'libksygpulive/KSYGPUResource'
53 55 s.dependency 'libksygpulive/libksygpulive'
  56 + s.dependency 'ksyhttpcache'
54 57 s.dependency 'GPUImage'
55 58 s.dependency 'YYCache'
56 59  
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerCache.h
... ... @@ -68,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
68 68 * 磁盘最大缓存开销
69 69 * 默认是30*1024*1024
70 70 */
71   -+ (void)setCostLimit:(NSInteger)costLimit;
  71 ++ (void)player_SetCostLimit:(NSInteger)costLimit;
72 72  
73 73 @end
74 74  
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerCache.m
... ... @@ -18,7 +18,7 @@ static YYCache *_dataCache;
18 18 [super initialize];
19 19 // 实例化方式一
20 20 _dataCache = [[YYCache alloc] initWithName:PlayerCache];
21   - [CNLivePlayerCache setCostLimit:1024*1024*20];
  21 + [CNLivePlayerCache player_SetCostLimit:1024*1024*30];
22 22  
23 23 }
24 24  
... ... @@ -29,7 +29,6 @@ static YYCache *_dataCache;
29 29 * @param key 保存的key
30 30 */
31 31 + (void)player_SaveDataCache:(id)data forKey:(NSString *)key {
32   - // [[self sharedManager]setObject:data forKey:key];
33 32 // 默认会开启线程缓存
34 33 [_dataCache setObject:data forKey:key withBlock:nil];
35 34  
... ... @@ -111,7 +110,9 @@ static YYCache *_dataCache;
111 110 * 磁盘最大缓存开销
112 111 * 默认是30*1024*1024
113 112 */
114   -+ (void)setCostLimit:(NSInteger)costLimit {
  113 ++ (void)player_SetCostLimit:(NSInteger)costLimit {
115 114 [_dataCache.diskCache setCostLimit:costLimit];//磁盘最大缓存开销
  115 +
116 116 }
  117 +
117 118 @end
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerNetworkManager.h
... ... @@ -9,6 +9,7 @@
9 9 #import <Foundation/Foundation.h>
10 10  
11 11 NS_ASSUME_NONNULL_BEGIN
  12 +typedef void(^GetVideoURLSuccessBlock)(NSString * _Nullable videoURL, NSInteger code);
12 13  
13 14 @interface CNLivePlayerNetworkManager : NSObject
14 15 /**
... ... @@ -51,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN
51 52 /**
52 53 * 获取视频url
53 54 */
54   -+ (void)getVideoURL:(nullable NSString *)URL success:(nullable void (^)(NSString *_Nullable videoURL, NSInteger code))success;
  55 ++ (void)getVideoURL:(nullable NSString *)URL success:(GetVideoURLSuccessBlock)success;
55 56  
56 57  
57 58 @end
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerNetworkManager.m
... ... @@ -26,8 +26,6 @@ static NSTimeInterval TimeoutInterval = 30.0 ;
26 26 */
27 27 static NSURLRequestCachePolicy CachePolicy = NSURLRequestUseProtocolCachePolicy;
28 28  
29   -typedef void(^GetVideoURLSuccessBlock)(NSString * _Nullable videoURL, NSInteger code);
30   -
31 29 @interface CNLivePlayerNetworkManager()<NSURLSessionDelegate>
32 30 @property (nonatomic, assign) BOOL result;
33 31 @property (nonatomic, copy) GetVideoURLSuccessBlock successBlock;
... ... @@ -119,7 +117,8 @@ static CNLivePlayerNetworkManager *_manager = nil;
119 117 dispatch_async(dispatch_get_main_queue(), ^{
120 118 if (error) {
121 119 failure(response,error);
122   - }else{
  120 + }
  121 + else{
123 122 if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
124 123 NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
125 124 if (httpResponse.statusCode < 400) {
... ... @@ -129,7 +128,8 @@ static CNLivePlayerNetworkManager *_manager = nil;
129 128 NSError *failureError = [NSError errorWithDomain:NSURLErrorDomain code:httpResponse.statusCode userInfo:httpResponse.allHeaderFields];
130 129 failure(httpResponse, failureError);
131 130 }
132   - } else {
  131 + }
  132 + else {
133 133 failure(response, error);
134 134 }
135 135 }
... ... @@ -176,7 +176,7 @@ static CNLivePlayerNetworkManager *_manager = nil;
176 176 /**
177 177 * 获取视频url
178 178 */
179   -+ (void)getVideoURL:(NSString *)URL success:(void (^)(NSString * _Nullable, NSInteger))success {
  179 ++ (void)getVideoURL:(nullable NSString *)URL success:(GetVideoURLSuccessBlock)success {
180 180 [CNLivePlayerNetworkManager manager].successBlock = success;
181 181 _manager.result = NO;
182 182  
... ...
CNLivePlayer/Classes/Player/CNLivePlayer.h
... ... @@ -17,10 +17,33 @@
17 17 #import "CNLivePlayerManager.h"
18 18  
19 19 NS_ASSUME_NONNULL_BEGIN
  20 +typedef NS_ENUM(NSUInteger, CNLivePlayerType) {
  21 + CNLivePlayerVod, //点播
  22 + CNLivePlayerLive //直播
  23 +
  24 +};
20 25  
21 26 @interface CNLivePlayer : NSObject
  27 +/*
  28 + * 播放器类型
  29 + */
  30 +@property (nonatomic, assign) CNLivePlayerType type;
22 31  
  32 +/*
  33 + * 播放器
  34 + */
23 35 @property (nonatomic, strong) KSYMoviePlayerController *player;
  36 +//
  37 +///* 初始化点播播放器 初始化成功后才能对播放器进行设置(如:自动播放、是否开启硬件解码等)和调用准备播放视频方法(prepareToPlay)
  38 +// *
  39 +// * contentId 点播视频Id
  40 +// * authSuccess 初始化成功block
  41 +// * authFailed 初始化失败block 回调一个errorInfo的字典
  42 +// *
  43 +// */
  44 +//- (instancetype)initPlayerWithType:(CNLivePlayerType)type contentId:(NSString *)contentId authSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock;
  45 +//
  46 +//- (void)setPlayerWithType:(CNLivePlayerType)type contentId:(NSString *)contentId;
24 47  
25 48 /* 初始化点播播放器 初始化成功后才能对播放器进行设置(如:自动播放、是否开启硬件解码等)和调用准备播放视频方法(prepareToPlay)
26 49 *
... ...
CNLivePlayer/Classes/Player/CNLivePlayer.m
... ... @@ -8,6 +8,11 @@
8 8  
9 9 #import "CNLivePlayer.h"
10 10 #import "CNLivePlayerManager.h"
  11 +//缓存视频
  12 +#import <KSYHTTPCache/KSYHTTPProxyService.h>
  13 +#import <KSYHTTPCache/HTTPCacheDefines.h>
  14 +
  15 +//缓存url
11 16 #import "CNLivePlayerCache.h"
12 17 #import "CommonCrypto/CommonDigest.h"
13 18 //数据请求
... ... @@ -112,18 +117,42 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
112 117 });
113 118 }
114 119  
  120 +- (void)dealloc {
  121 + [self removeMovieNotificationObservers];
  122 + [self removeRCloudNotificationObservers];
  123 +
  124 +}
  125 +
  126 +- (void)destroyPlayer {
  127 + if (_statTimer) {
  128 + [_statTimer invalidate];
  129 + _statTimer = nil;
  130 + }
  131 +
  132 + if (_player) {
  133 + _player = nil;
  134 + }
  135 +
  136 + [self removeMovieNotificationObservers];
  137 + [self removeRCloudNotificationObservers];
  138 +
  139 +}
  140 +
115 141 #pragma mark - 查找本地是否有缓存url
116 142 - (void)getVideoId:(NSString *)videoId authSuccess:(void (^)(void))authSuccessBlock authFailed:(void (^)(NSDictionary *errorDic))authFailedBlock {
117 143 NSString *key = [NSString stringWithFormat:@"%@:%@",_contentType,videoId];
118 144 id data = [CNLivePlayerCache player_ReadCache:key];
119   - if (data) {
  145 + //1.判断是否存在缓存url
  146 + if (data && [data isKindOfClass:[NSString class]]) {
  147 + __weak typeof(self) weakSelf = self;
120 148 dispatch_async(dispatch_get_main_queue(), ^{
121   - self.videoUrl = (NSString *)data;
122   - self.player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:self.videoUrl]];
123   - [self.view addSubview:self.player.view];
124   - self.player.view.frame = self.view.bounds;
125   - self.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
126   - self.player.shouldEnableKSYStatModule = NO;
  149 + __strong typeof(self) strongSelf = weakSelf;
  150 + strongSelf.videoUrl = (NSString *)data;
  151 + strongSelf.player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:strongSelf.videoUrl]];
  152 + [strongSelf.view addSubview:self.player.view];
  153 + strongSelf.player.view.frame = self.view.bounds;
  154 + strongSelf.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
  155 + strongSelf.player.shouldEnableKSYStatModule = NO;
127 156 if (PLAYER_TestEnvironment) {
128 157 NSLog(@"CNLivePlayer-->缓存数据,播放器初始化成功,可以对播放器进行设置并准备播放");
129 158 }
... ... @@ -131,42 +160,98 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
131 160 });
132 161  
133 162 } else {
  163 + //2.判断是否鉴权
134 164 NSDictionary *privilegeDic = [[NSUserDefaults standardUserDefaults] objectForKey:kCNLivePlayerSDKAuthentication];
135 165 if(privilegeDic&&[privilegeDic[@"resultCode"] isEqualToString:@"0"]){
  166 + //3.存在鉴权成功,直接请求url
136 167 if([_contentType isEqualToString:@"vod"]){
137   - [self getVodVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  168 + [self getVodVideoURLSuccess:authSuccessBlock failure:authFailedBlock];
138 169  
139 170 }else{
140   - [self getLiveVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  171 + [self getLiveVideoURLSuccess:authSuccessBlock failure:authFailedBlock];
141 172  
142 173 }
143 174  
144 175 }else{
145 176 __weak typeof(self) weakSelf = self;
146   - //鉴权
  177 + //4.不存在鉴权成功,先请求鉴权
147 178 [weakSelf authenticateSuccess:^{
  179 + //5.鉴权成功,再请求url
148 180 __strong typeof(self) strongSelf = weakSelf;
149 181 if([strongSelf->_contentType isEqualToString:@"vod"]){
150   - [self getVodVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  182 + [strongSelf getVodVideoURLSuccess:authSuccessBlock failure:authFailedBlock];
151 183  
152 184 }else{
153   - [self getLiveVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  185 + [strongSelf getLiveVideoURLSuccess:authSuccessBlock failure:authFailedBlock];
154 186  
155 187 }
156 188  
157   - } authenticateFailed:authFailedBlock];
  189 + } failure:authFailedBlock];
158 190 }
159 191  
160 192 }
161 193  
162 194 }
163 195  
164   -#pragma mark - 获取点播视频url
165   -- (void)getVodVideoURLSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  196 +#pragma mark - 鉴权
  197 +- (void)authenticateSuccess:(void(^)(void))authSuccessBlock failure:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  198 +
  199 + NSDictionary *parameter = @{@"platform_id": [NSBundle mainBundle].bundleIdentifier,
  200 + @"timestamp": [CNLivePlayerTools getTimestamp],
  201 + @"appId": PLAYER_AppID};
  202 +
  203 + NSString *videoUrl = [CNLivePlayerTools encryptionSignWithUrl:authUrl parameter:parameter];
  204 +
  205 + __weak typeof(self) weakSelf = self;
  206 + [[CNLivePlayerNetworkManager manager] authenticate:videoUrl success:^(NSURLResponse * _Nullable response, id _Nullable responseObject) {
  207 + __strong typeof(self) strongSelf = weakSelf;
  208 + if(!responseObject||![responseObject isKindOfClass:[NSDictionary class]]){
  209 + authFailedBlock ? authFailedBlock(responseObject) : nil;
  210 +
  211 + }
  212 +
  213 + NSDictionary *authErrorDic = @{@"code":responseObject[@"errorCode"],
  214 + @"resultCode":@"0",
  215 + @"errorMessage":responseObject[@"errorMessage"]};
  216 + [[NSUserDefaults standardUserDefaults] setObject:authErrorDic forKey:kCNLivePlayerSDKAuthentication];
  217 + [[NSUserDefaults standardUserDefaults] synchronize];
  218 + if ([responseObject[@"errorCode"] isEqualToString:@"0"]) {
  219 + authSuccessBlock ? authSuccessBlock() : nil;
  220 +
  221 + }
  222 + else {
  223 + if (PLAYER_TestEnvironment) {
  224 + NSLog(@"CNLivePlayer-->播放器初始化失败,失败原因:%@", authErrorDic);
  225 + }
  226 + authFailedBlock ? authFailedBlock(responseObject) : nil;
  227 + [CNLivePlayerTools errorStat:authErrorDic[@"errorMessage"] contentId:strongSelf->_activityId ? strongSelf->_activityId : strongSelf->_contentId idName:strongSelf->_idName];
  228 +
  229 + }
  230 +
  231 + } failure:^(NSURLResponse * _Nullable response, NSError * _Nullable error) {
  232 + __strong typeof(self) strongSelf = weakSelf;
  233 + NSDictionary *authErrorDic = @{@"code":[NSString stringWithFormat:@"%ld", error.code],
  234 + @"resultCode":@"1",
  235 + @"errorMessage":[NSString stringWithFormat:@"%@", error.localizedDescription]};
  236 + [[NSUserDefaults standardUserDefaults] setObject:authErrorDic forKey:kCNLivePlayerSDKAuthentication];
  237 + [[NSUserDefaults standardUserDefaults] synchronize];
  238 +
  239 + if (PLAYER_TestEnvironment) {
  240 + NSLog(@"CNLivePlayer-->播放器初始化失败,失败原因:%@", authErrorDic);
  241 + }
  242 + authFailedBlock ? authFailedBlock(authErrorDic) : nil;
  243 + [CNLivePlayerTools errorStat:authErrorDic[@"errorMessage"] contentId:strongSelf->_activityId ? strongSelf->_activityId : strongSelf->_contentId idName:strongSelf->_idName];
  244 +
  245 + }];
  246 +
  247 +}
166 248  
  249 +#pragma mark - 获取点播视频url
  250 +- (void)getVodVideoURLSuccess:(void(^)(void))authSuccessBlock failure:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  251 + NSString *stamp = [CNLivePlayerTools getTimestamp];
167 252 NSDictionary *parameter = @{@"appId": PLAYER_AppID,
168 253 @"vId": _contentId,
169   - @"timestamp": [CNLivePlayerTools getTimestamp],
  254 + @"timestamp": stamp,
170 255 @"isHLS": @"1",
171 256 @"plat": @"i",
172 257 @"playType": _isAudio ? @"a": @"v",
... ... @@ -175,7 +260,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
175 260 @"tag": PLAYER_Tag,
176 261 @"from": @"apple",
177 262 @"sid": PLAYER_UserId,
178   - @"uid": [CNLivePlayerTools getUidForStat:[NSDate date]]};
  263 + @"uid": [CNLivePlayerTools getUidForStat:stamp]};
179 264  
180 265 NSString *videoUrl = [CNLivePlayerTools encryptionSignWithUrl:vodUrl parameter:parameter];
181 266  
... ... @@ -184,7 +269,9 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
184 269 __strong typeof(self) strongSelf = weakSelf;
185 270 // NSString *key = [NSString stringWithFormat:@"%@:%@",strongSelf->_contentType, strongSelf->_contentId];
186 271 // [CNLivePlayerCache player_SaveDataCache:videoURL forKey:key];
  272 + __weak typeof(self) weakSelf = strongSelf;
187 273 dispatch_async(dispatch_get_main_queue(), ^{
  274 + __strong typeof(self) strongSelf = weakSelf;
188 275 strongSelf.videoUrl = videoUrl;
189 276 strongSelf.player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:videoUrl]];
190 277 [strongSelf.view addSubview:strongSelf.player.view];
... ... @@ -192,7 +279,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
192 279 strongSelf.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
193 280 strongSelf.player.shouldEnableKSYStatModule = NO;
194 281  
195   - [strongSelf statSDK];
  282 + [CNLivePlayerTools statSDKWithContentId:strongSelf->_activityId ? strongSelf->_activityId : strongSelf->_contentId idName:strongSelf->_idName];
196 283  
197 284 if (PLAYER_TestEnvironment) {
198 285 NSLog(@"CNLivePlayer-->请求数据,点播播放器初始化成功,可以对播放器进行设置并准备播放");
... ... @@ -206,7 +293,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
206 293 }
207 294  
208 295 #pragma mark - 获取直播视频url
209   -- (void)getLiveVideoURLSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  296 +- (void)getLiveVideoURLSuccess:(void(^)(void))authSuccessBlock failure:(void(^)(NSDictionary *errorInfo))authFailedBlock {
210 297 NSString *timestamp = [CNLivePlayerTools getTimestamp];
211 298 NSDictionary *parameter = @{@"appId": PLAYER_AppID,
212 299 @"channelId": _contentId,
... ... @@ -220,7 +307,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
220 307 @"tag": PLAYER_Tag,
221 308 @"from": @"apple",
222 309 @"sid": PLAYER_UserId,
223   - @"uid": [CNLivePlayerTools getUidForStat:[NSDate date]]};
  310 + @"uid": [CNLivePlayerTools getUidForStat:timestamp]};
224 311  
225 312 NSString *videoUrl = [CNLivePlayerTools encryptionSignWithUrl:liveUrl parameter:parameter];
226 313  
... ... @@ -229,26 +316,31 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
229 316 [urlRequest setHTTPMethod:@"GET"];
230 317 [urlRequest setTimeoutInterval:30];
231 318  
  319 + __weak typeof(self) weakSelf = self;
232 320 [NSURLConnection sendAsynchronousRequest:urlRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
233   - __weak typeof(self) weakSelf = self;
  321 + __strong typeof(self) strongSelf = weakSelf;
  322 + NSString *url = nil;
  323 + if (connectionError) {
  324 + NSError *error = connectionError.userInfo[NSUnderlyingErrorKey];
  325 + NSString *videoUrl302 = error.userInfo[NSURLErrorFailingURLStringErrorKey];
  326 + if (!videoUrl302 || ![videoUrl302 isKindOfClass:[NSString class]] || videoUrl302.length <= 0) {
  327 + videoUrl302 = nil;
  328 + }
  329 + url = videoUrl302;
  330 +
  331 + } else if (response) {
  332 + url = response.URL.absoluteString;
  333 +
  334 + } else {
  335 + url = videoUrl;
  336 +
  337 + }
  338 + NSString *key = [NSString stringWithFormat:@"%@:%@",strongSelf->_contentType, strongSelf->_contentId];
  339 + [CNLivePlayerCache player_SaveDataCache:url forKey:key];
  340 +
  341 + __weak typeof(self) weakSelf = strongSelf;
234 342 dispatch_async(dispatch_get_main_queue(), ^{
235 343 __strong typeof(self) strongSelf = weakSelf;
236   - NSString *url = nil;
237   - if (connectionError) {
238   - NSError *error = connectionError.userInfo[NSUnderlyingErrorKey];
239   - NSString *videoUrl302 = error.userInfo[NSURLErrorFailingURLStringErrorKey];
240   - if (!videoUrl302 || ![videoUrl302 isKindOfClass:[NSString class]] || videoUrl302.length <= 0) {
241   - videoUrl302 = nil;
242   - }
243   - url = videoUrl302;
244   -
245   - } else if (response) {
246   - url = response.URL.absoluteString;
247   -
248   - } else {
249   - url = videoUrl;
250   -
251   - }
252 344 strongSelf.videoUrl = url;
253 345 strongSelf.player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
254 346 [strongSelf.view addSubview:strongSelf.player.view];
... ... @@ -256,11 +348,8 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
256 348 strongSelf.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
257 349 strongSelf.player.shouldEnableKSYStatModule = NO;
258 350  
259   - NSString *key = [NSString stringWithFormat:@"%@:%@",strongSelf->_contentType, strongSelf->_contentId];
260   - [CNLivePlayerCache player_SaveDataCache:url forKey:key];
261   -
262   - [strongSelf statSDK];
263   -
  351 + [CNLivePlayerTools statSDKWithContentId:strongSelf->_activityId ? strongSelf->_activityId : strongSelf->_contentId idName:strongSelf->_idName];
  352 +
264 353 if (PLAYER_TestEnvironment) {
265 354 NSLog(@"CNLivePlayer-->请求数据,直播播放器初始化成功,可以对播放器进行设置并准备播放");
266 355 }
... ... @@ -272,66 +361,15 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
272 361 }];
273 362 }
274 363  
275   -#pragma mark - 鉴权
276   -- (void)authenticateSuccess:(void(^)(void))authSuccessBlock authenticateFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock {
277   -
278   - NSDictionary *parameter = @{@"platform_id": [NSBundle mainBundle].bundleIdentifier,
279   - @"timestamp": [CNLivePlayerTools getTimestamp],
280   - @"appId": PLAYER_AppID};
281   -
282   - NSString *videoUrl = [CNLivePlayerTools encryptionSignWithUrl:authUrl parameter:parameter];
283   -
284   -
285   - [[CNLivePlayerNetworkManager manager] authenticate:videoUrl success:^(NSURLResponse * _Nullable response, id _Nullable responseObject) {
286   -
287   - if(!responseObject||![responseObject isKindOfClass:[NSDictionary class]]){
288   - authFailedBlock ? authFailedBlock(responseObject) : nil;
289   -
290   - }
291   -
292   - NSDictionary *authErrorDic = @{@"code":responseObject[@"errorCode"],
293   - @"resultCode":@"0",
294   - @"errorMessage":responseObject[@"errorMessage"]};
295   - [[NSUserDefaults standardUserDefaults] setObject:authErrorDic forKey:kCNLivePlayerSDKAuthentication];
296   - [[NSUserDefaults standardUserDefaults] synchronize];
297   -
298   - if ([responseObject[@"errorCode"] isEqualToString:@"0"]) {
299   - authSuccessBlock ? authSuccessBlock() : nil;
300   -
301   - }
302   - else {
303   - if (PLAYER_TestEnvironment) {
304   - NSLog(@"CNLivePlayer-->播放器初始化失败,失败原因:%@", authErrorDic);
305   - }
306   - authFailedBlock ? authFailedBlock(responseObject) : nil;
307   - [self errorStat:authErrorDic[@"errorMessage"]];
308   - }
309   -
310   - } failure:^(NSURLResponse * _Nullable response, NSError * _Nullable error) {
311   -
312   - NSDictionary *authErrorDic = @{@"code":[NSString stringWithFormat:@"%ld", error.code],
313   - @"resultCode":@"1",
314   - @"errorMessage":[NSString stringWithFormat:@"%@", error.localizedDescription]};
315   - [[NSUserDefaults standardUserDefaults] setObject:authErrorDic forKey:kCNLivePlayerSDKAuthentication];
316   - [[NSUserDefaults standardUserDefaults] synchronize];
317   -
318   - if (PLAYER_TestEnvironment) {
319   - NSLog(@"CNLivePlayer-->播放器初始化失败,失败原因:%@", authErrorDic);
320   - }
321   - authFailedBlock ? authFailedBlock(authErrorDic) : nil;
322   - [self errorStat:authErrorDic[@"errorMessage"]];
323   -
324   - }];
325   -
326   -}
327   -
328 364 #pragma mark - 注册通知
329 365 - (void)addMovieNotificationObservers {
  366 + // 视频加载状态
330 367 [[NSNotificationCenter defaultCenter] addObserver:self
331 368 selector:@selector(loadStateDidChange:)
332 369 name:MPMoviePlayerLoadStateDidChangeNotification
333 370 object:nil];
334 371  
  372 + // 视频播放结束
335 373 [[NSNotificationCenter defaultCenter] addObserver:self
336 374 selector:@selector(moviePlayBackDidFinish:)
337 375 name:MPMoviePlayerPlaybackDidFinishNotification
... ... @@ -342,6 +380,18 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
342 380 name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification
343 381 object:nil];
344 382  
  383 + // 缓存状态
  384 + [[NSNotificationCenter defaultCenter] addObserver:self
  385 + selector:@selector(mediaCacheDidChanged:)
  386 + name:CacheStatusNotification
  387 + object:nil];
  388 +
  389 + // 缓存出错
  390 + [[NSNotificationCenter defaultCenter] addObserver:self
  391 + selector:@selector(mediaCacheErrorDidChanged:)
  392 + name:CacheErrorNotification
  393 + object:nil];
  394 +
345 395 }
346 396  
347 397 - (void)addRCloudNotificationObservers {
... ... @@ -351,17 +401,16 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
351 401 }
352 402  
353 403 - (void)removeMovieNotificationObservers {
354   - [[NSNotificationCenter defaultCenter] removeObserver:self
355   - name:MPMoviePlayerLoadStateDidChangeNotification
356   - object:nil];
  404 + [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerLoadStateDidChangeNotification object:nil];
  405 +
  406 + [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:nil];
357 407  
358   - [[NSNotificationCenter defaultCenter] removeObserver:self
359   - name:MPMoviePlayerPlaybackDidFinishNotification
360   - object:nil];
  408 + [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification object:nil];
  409 +
  410 + [[NSNotificationCenter defaultCenter] removeObserver:self name:CacheStatusNotification object:nil];
  411 +
  412 + [[NSNotificationCenter defaultCenter] removeObserver:self name:CacheErrorNotification object:nil];
361 413  
362   - [[NSNotificationCenter defaultCenter] removeObserver:self
363   - name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification
364   - object:nil];
365 414 }
366 415  
367 416 - (void)removeRCloudNotificationObservers {
... ... @@ -391,6 +440,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
391 440 [self mediaIsPreparedToPlayDidChange:nil];
392 441 }
393 442 }
  443 +
394 444 }
395 445  
396 446 - (void)moviePlayBackDidFinish:(NSNotification *)notification {
... ... @@ -418,7 +468,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
418 468  
419 469 case MPMovieFinishReasonPlaybackError://视频异常探针
420 470 {
421   - [self errorStat:notification.userInfo.description];
  471 + [CNLivePlayerTools errorStat:notification.userInfo.description contentId:_activityId ? _activityId : _contentId idName:_idName];
422 472 }
423 473 break;
424 474  
... ... @@ -426,6 +476,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
426 476  
427 477 break;
428 478 }
  479 +
429 480 }
430 481  
431 482 - (void)mediaIsPreparedToPlayDidChange:(NSNotification *)notification {
... ... @@ -441,27 +492,6 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
441 492  
442 493 }
443 494  
444   -- (void)dealloc {
445   - [self removeMovieNotificationObservers];
446   - [self removeRCloudNotificationObservers];
447   -
448   -}
449   -
450   -- (void)destroyPlayer {
451   - if (_statTimer) {
452   - [_statTimer invalidate];
453   - _statTimer = nil;
454   - }
455   -
456   - if (_player) {
457   - _player = nil;
458   - }
459   -
460   - [self removeMovieNotificationObservers];
461   - [self removeRCloudNotificationObservers];
462   -
463   -}
464   -
465 495 #pragma mark - 播放时长计算
466 496 - (void)statTimerAction{
467 497 if (!_contentType || _contentType.length == 0) {
... ... @@ -470,21 +500,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
470 500 _playTime++;
471 501  
472 502 NSString *stamp = [CNLivePlayerTools getTimestamp];
473   - NSString *url = [NSString stringWithFormat:@"%@?sver=%@&uid=%@&tm=%@&from=apple&spid=&appid=%@&version=1001_%@&eventid=1001&uri=%@&sid=&plat=i_%@&objid=%@_%@", StatUrl, StatVersion, [CNLivePlayerTools uidForStat:stamp], stamp, PLAYER_AppID, PlayerSDKVersion, [NSString stringWithFormat:@"%d_30", _playTime], StatAppVersion,_contentId, _idName];
474   - [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:nil];
475   -
476   -}
477   -
478   -#pragma mark - 工具方法
479   -- (void)errorStat:(NSString *)errorString {
480   - NSString *stamp = [CNLivePlayerTools getTimestamp];
481   - NSString *url = [NSString stringWithFormat:@"%@?sver=%@&uid=%@&tm=%@&from=apple&spid=&appid=%@&version=1001_%@&eventid=1000&uri=%@&sid=&plat=i_%@&objid=%@_%@", StatUrl, StatVersion, [CNLivePlayerTools uidForStat:stamp], stamp, PLAYER_AppID, PlayerSDKVersion, errorString, StatAppVersion, _activityId ? _activityId : _contentId, _idName];
482   - [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:nil];
483   -
484   -}
485   -- (void)statSDK {
486   - NSString *stamp = [CNLivePlayerTools getTimestamp];
487   - NSString *url = [NSString stringWithFormat:@"%@?sver=%@&uid=%@&tm=%@&from=apple&spid=&appid=%@&version=1001_%@&eventid=1400&uri=&sid=&plat=i_%@&objid=%@_%@", StatUrl, StatVersion, [CNLivePlayerTools uidForStat:stamp], stamp, PLAYER_AppID, PlayerSDKVersion, StatAppVersion, _activityId ? _activityId : _contentId , _idName];
  503 + NSString *url = [NSString stringWithFormat:@"%@?sver=%@&uid=%@&tm=%@&from=apple&spid=&appid=%@&version=1001_%@&eventid=1001&uri=%@&sid=&plat=i_%@&objid=%@_%@", StatUrl, StatVersion, [CNLivePlayerTools getUidForStat:stamp], stamp, PLAYER_AppID, PlayerSDKVersion, [NSString stringWithFormat:@"%ld_30", (long)_playTime], StatAppVersion,_contentId, _idName];
488 504 [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:nil];
489 505  
490 506 }
... ... @@ -516,6 +532,7 @@ NSString * const CNLiveAnchorStatusChangedNotification = @&quot;CNLiveAnchorStatusCha
516 532 */
517 533 - (void)prepareToPlay {
518 534 [_player prepareToPlay];
  535 +
519 536 }
520 537  
521 538 @end
... ...
CNLivePlayer/Classes/Player/CNLivePlayerConst.h
... ... @@ -10,7 +10,7 @@
10 10 #define CNLivePlayerConst_h
11 11  
12 12 #pragma mark - 版本号
13   -#define PlayerSDKVersion @"0.0.1" //SDK版本
  13 +#define PlayerSDKVersion @"0.0.1" //播放器SDK版本
14 14  
15 15 #pragma mark - 探针
16 16 #define StatUrl [CNLivePlayerManager manager].isTestEnvironment?@"http://app.sta.cnlive.com/app.jpg": @"http://app.sta.cnlive.com/app.jpg"
... ...
CNLivePlayer/Classes/Player/CNLivePlayerManager.m
... ... @@ -58,9 +58,9 @@ static CNLivePlayerManager * _instance = nil;
58 58 }
59 59  
60 60 - (void)setAppId:(NSString *)appId appKey:(NSString *)appKey isTestEnvironment:(BOOL)isTestEnvironment {
61   - self.appId = appId ? [NSString stringWithFormat:@"%@",appId] : @"";
62   - self.appKey = appKey ? [NSString stringWithFormat:@"%@",appKey] : @"";
63   - self.isTestEnvironment = isTestEnvironment;
  61 + [CNLivePlayerManager manager].appId = appId ? [NSString stringWithFormat:@"%@",appId] : @"";
  62 + [CNLivePlayerManager manager].appKey = appKey ? [NSString stringWithFormat:@"%@",appKey] : @"";
  63 + [CNLivePlayerManager manager].isTestEnvironment = isTestEnvironment;
64 64 }
65 65  
66 66 + (NSString *)getVersion {
... ...
CNLivePlayer/Classes/Tools/CNLivePlayerTools.h
... ... @@ -17,10 +17,10 @@
17 17  
18 18 + (NSString *)signvalue:(NSDictionary*)parameter;
19 19  
20   -//获取uuid
21   -+ (NSString *)getUidForStat:(NSDate *)date;
22   -
23   -+ (NSString *)uidForStat:(NSString *)date;
  20 +/**
  21 + * 获取UUID
  22 + */
  23 ++ (NSString *)getUidForStat:(NSString *)date;
24 24  
25 25 //错误信息
26 26 + (NSError *)customErrorWithResponseObject:(id)responseObject errorInfo:(NSString *)errorInfo;
... ... @@ -36,4 +36,9 @@
36 36 + (NSString *)getTimestamp;
37 37  
38 38  
  39 +#pragma mark - 方法
  40 ++ (void)errorStat:(NSString *)errorString contentId:(NSString *)contentId idName:(NSString *)idName;
  41 +
  42 ++ (void)statSDKWithContentId:(NSString *)contentId idName:(NSString *)idName;
  43 +
39 44 @end
... ...
CNLivePlayer/Classes/Tools/CNLivePlayerTools.m
... ... @@ -62,32 +62,7 @@
62 62 }
63 63  
64 64 #pragma mark - UUID
65   -+ (NSString *)getUidForStat:(NSDate *)date {
66   - NSString *uid = @"";
67   -
68   - NSUserDefaults *defauts = [NSUserDefaults standardUserDefaults];
69   -
70   - if ([defauts objectForKey:@"kCNLiveUserDefaultsUIDKey"]) {
71   - uid = [[defauts objectForKey:@"kCNLiveUserDefaultsUIDKey"] copy];
72   - return uid;
73   - }
74   - else {
75   -
76   - NSString *stamp = [NSString stringWithFormat:@"%.3f", [date timeIntervalSince1970]];
77   - stamp = [stamp stringByReplacingOccurrencesOfString:@"." withString:@""];
78   -
79   - NSString *idfv = [[[[UIDevice currentDevice] identifierForVendor] UUIDString] stringByReplacingOccurrencesOfString:@"-" withString:@""];
80   - uid = [NSString stringWithFormat:@"%@_%@", idfv, stamp];
81   -
82   - [defauts setObject:uid forKey:@"kCNLiveUserDefaultsUIDKey"];
83   - [defauts synchronize];
84   - }
85   -
86   - return uid;
87   -
88   -}
89   -
90   -+ (NSString *)uidForStat:(NSString *)date {
  65 ++ (NSString *)getUidForStat:(NSString *)date {
91 66  
92 67 NSString *uid = @"";
93 68  
... ... @@ -127,7 +102,7 @@
127 102 return error;
128 103 }
129 104  
130   -
  105 +#pragma mark - 字符串判空
131 106 + (BOOL)isEmptyString:(NSString *)string {
132 107 if (!string || ![string isKindOfClass:[NSString class]] || string.length == 0 || [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length == 0) {
133 108 return YES;
... ... @@ -135,10 +110,26 @@
135 110 return NO;
136 111 }
137 112  
  113 +#pragma mark - 获取时间戳
138 114 + (NSString *)getTimestamp{
139 115 NSInteger time = [[NSDate date] timeIntervalSince1970];
140 116 NSString *timestamp = [NSString stringWithFormat:@"%ld", (long)time];
141 117 return timestamp;
142 118 }
143 119  
  120 +
  121 +#pragma mark - 方法
  122 ++ (void)errorStat:(NSString *)errorString contentId:(NSString *)contentId idName:(NSString *)idName{
  123 + NSString *stamp = [CNLivePlayerTools getTimestamp];
  124 + NSString *url = [NSString stringWithFormat:@"%@?sver=%@&uid=%@&tm=%@&from=apple&spid=&appid=%@&version=1001_%@&eventid=1000&uri=%@&sid=&plat=i_%@&objid=%@_%@", StatUrl, StatVersion, [CNLivePlayerTools getUidForStat:stamp], stamp, PLAYER_AppID, PlayerSDKVersion, errorString, StatAppVersion, contentId, idName];
  125 + [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:nil];
  126 +
  127 +}
  128 ++ (void)statSDKWithContentId:(NSString *)contentId idName:(NSString *)idName {
  129 + NSString *stamp = [CNLivePlayerTools getTimestamp];
  130 + NSString *url = [NSString stringWithFormat:@"%@?sver=%@&uid=%@&tm=%@&from=apple&spid=&appid=%@&version=1001_%@&eventid=1400&uri=&sid=&plat=i_%@&objid=%@_%@", StatUrl, StatVersion, [CNLivePlayerTools getUidForStat:stamp], stamp, PLAYER_AppID, PlayerSDKVersion, StatAppVersion, contentId , idName];
  131 + [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:nil];
  132 +
  133 +}
  134 +
144 135 @end
... ...
Example/CNLivePlayer.xcodeproj/project.pbxproj
... ... @@ -348,7 +348,8 @@
348 348 );
349 349 inputPaths = (
350 350 "${PODS_ROOT}/Target Support Files/Pods-CNLivePlayer_Example/Pods-CNLivePlayer_Example-frameworks.sh",
351   - "${BUILT_PRODUCTS_DIR}/CNLivePlayer/CNLivePlayer.framework",
  351 + "${BUILT_PRODUCTS_DIR}/CocoaAsyncSocket/CocoaAsyncSocket.framework",
  352 + "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework",
352 353 "${BUILT_PRODUCTS_DIR}/GPUImage/GPUImage.framework",
353 354 "${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework",
354 355 "${BUILT_PRODUCTS_DIR}/libksygpulive/libksygpulive.framework",
... ... @@ -357,7 +358,8 @@
357 358 outputFileListPaths = (
358 359 );
359 360 outputPaths = (
360   - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLivePlayer.framework",
  361 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaAsyncSocket.framework",
  362 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework",
361 363 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GPUImage.framework",
362 364 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework",
363 365 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libksygpulive.framework",
... ... @@ -477,6 +479,7 @@
477 479 GCC_SYMBOLS_PRIVATE_EXTERN = NO;
478 480 GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
479 481 GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  482 + GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
480 483 GCC_WARN_UNDECLARED_SELECTOR = YES;
481 484 GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
482 485 GCC_WARN_UNUSED_FUNCTION = YES;
... ... @@ -485,6 +488,7 @@
485 488 ONLY_ACTIVE_ARCH = YES;
486 489 SDKROOT = iphoneos;
487 490 TARGETED_DEVICE_FAMILY = "1,2";
  491 + WARNING_CFLAGS = "";
488 492 };
489 493 name = Debug;
490 494 };
... ... @@ -510,6 +514,7 @@
510 514 GCC_C_LANGUAGE_STANDARD = gnu99;
511 515 GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
512 516 GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  517 + GCC_WARN_INHIBIT_ALL_WARNINGS = YES;
513 518 GCC_WARN_UNDECLARED_SELECTOR = YES;
514 519 GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
515 520 GCC_WARN_UNUSED_FUNCTION = YES;
... ... @@ -518,6 +523,7 @@
518 523 SDKROOT = iphoneos;
519 524 TARGETED_DEVICE_FAMILY = "1,2";
520 525 VALIDATE_PRODUCT = YES;
  526 + WARNING_CFLAGS = "";
521 527 };
522 528 name = Release;
523 529 };
... ... @@ -534,6 +540,7 @@
534 540 PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.video;
535 541 PRODUCT_NAME = "$(TARGET_NAME)";
536 542 SWIFT_VERSION = 4.0;
  543 + WARNING_CFLAGS = "";
537 544 WRAPPER_EXTENSION = app;
538 545 };
539 546 name = Debug;
... ... @@ -551,6 +558,7 @@
551 558 PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.video;
552 559 PRODUCT_NAME = "$(TARGET_NAME)";
553 560 SWIFT_VERSION = 4.0;
  561 + WARNING_CFLAGS = "";
554 562 WRAPPER_EXTENSION = app;
555 563 };
556 564 name = Release;
... ...