Commit ee67e19b2df235d48d4e9cd3c74e9e3de978a547

Authored by zhangxiaowen
1 parent c39d92e1

no message

Showing 37 changed files with 2857 additions and 1 deletions
CNLivePlayer.podspec 0 → 100644
  1 +#
  2 +# Be sure to run `pod lib lint CNLivePlayer.podspec' to ensure this is a
  3 +# valid spec before submitting.
  4 +#
  5 +# Any lines starting with a # are optional, but their use is encouraged
  6 +# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html
  7 +#
  8 +
  9 +Pod::Spec.new do |s|
  10 + s.name = 'CNLivePlayer'
  11 + s.version = '0.0.1'
  12 + s.summary = '播放器'
  13 +
  14 +# This description is used to generate tags and improve search results.
  15 +# * Think: What does it do? Why did you write it? What is the focus?
  16 +# * Try to keep it short, snappy and to the point.
  17 +# * Write the description between the DESC delimiters below.
  18 +# * Finally, don't worry about the indent, CocoaPods strips it!
  19 +
  20 + s.description = <<-DESC
  21 +TODO: Add long description of the pod here.
  22 + DESC
  23 +
  24 + s.homepage = 'http://bj.gitlab.cnlive.com/ios-team/CNLivePlayer'
  25 + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  26 + s.license = { :type => 'MIT', :file => 'LICENSE' }
  27 + s.author = { '153993236@qq.com' => 'zhangxiaowen@cnlive.com' }
  28 + s.source = { :git => 'http://bj.gitlab.cnlive.com/ios-team/CNLivePlayer.git', :tag => s.version.to_s }
  29 + # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
  30 +
  31 + s.ios.deployment_target = '9.0'
  32 +
  33 + # s.source_files = 'CNLivePlayer/Classes/**/*'
  34 + s.subspec 'Player' do |ss|
  35 + ss.source_files = 'CNLivePlayer/Classes/Player/*.{h,m}'
  36 + end
  37 + s.subspec 'Streamer' do |ss|
  38 + ss.source_files = 'CNLivePlayer/Classes/Streamer/*.{h,m}'
  39 + end
  40 + s.subspec 'DataRequest' do |ss|
  41 + ss.source_files = 'CNLivePlayer/Classes/DataRequest/*.{h,m}'
  42 + end
  43 + s.subspec 'Barrage' do |ss|
  44 + ss.source_files = 'CNLivePlayer/Classes/Barrage/*.{h,m}'
  45 + end
  46 + s.subspec 'Tools' do |ss|
  47 + ss.source_files = 'CNLivePlayer/Classes/Tools/*.{h,m}'
  48 + end
  49 +
  50 + # s.public_header_files = 'Pod/Classes/**/*.h'
  51 + s.frameworks = 'UIKit', 'MediaPlayer'
  52 + s.dependency 'libksygpulive/KSYGPUResource'
  53 + s.dependency 'libksygpulive/libksygpulive'
  54 + s.dependency 'GPUImage'
  55 + s.dependency 'YYCache'
  56 +
  57 +end
... ...
CNLivePlayer/Assets/.gitkeep 0 → 100644
CNLivePlayer/Classes/.gitkeep 0 → 100644
CNLivePlayer/Classes/DataRequest/CNLivePlayerCache.h 0 → 100644
  1 +//
  2 +// CNLivePlayerCache.h
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +
  13 +@interface CNLivePlayerCache : NSObject
  14 +
  15 +/**
  16 + * 存储或者修改数据
  17 + *
  18 + * @param data 保存的数据
  19 + * @param key 保存的key
  20 + */
  21 ++ (void)player_SaveDataCache:(id)data forKey:(NSString *)key;
  22 +
  23 +
  24 +/**
  25 + * 读取数据
  26 + *
  27 + * @param key 保存的key
  28 + *
  29 + * @return 返回id
  30 + */
  31 ++ (id)player_ReadCache:(NSString *)key;
  32 +
  33 +
  34 +/**
  35 + * 读取缓存文件的大小
  36 + *
  37 + * @return 返回NSString
  38 + */
  39 ++ (NSString *)player_GetAllHttpCacheSize;
  40 +
  41 +
  42 +/**
  43 + * 是否缓存过
  44 + *
  45 + * @param key 保存的key
  46 + *
  47 + * @return 返回NSString
  48 + */
  49 ++ (BOOL)player_IsCache:(NSString *)key;
  50 +
  51 +
  52 +/**
  53 + * 删除某个磁盘缓存文件
  54 + *
  55 + * @param key 保存的key(就是请求的url)
  56 + *
  57 + */
  58 ++ (void)player_RemoveChache:(NSString *)key;
  59 +
  60 +
  61 +/**
  62 + * 删除所有的磁盘换存文件
  63 + */
  64 ++ (void)player_RemoveAllCache;
  65 +
  66 +
  67 +/**
  68 + * 磁盘最大缓存开销
  69 + * 默认是30*1024*1024
  70 + */
  71 ++ (void)setCostLimit:(NSInteger)costLimit;
  72 +
  73 +@end
  74 +
  75 +NS_ASSUME_NONNULL_END
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerCache.m 0 → 100644
  1 +//
  2 +// CNLivePlayerCache.m
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLivePlayerCache.h"
  10 +#import "YYCache.h"
  11 +
  12 +@implementation CNLivePlayerCache
  13 +static NSString *const PlayerCache = @"CNLivePlayer_Data_Url_Cache";
  14 +
  15 +static YYCache *_dataCache;
  16 +
  17 ++ (void)initialize {
  18 + [super initialize];
  19 + // 实例化方式一
  20 + _dataCache = [[YYCache alloc] initWithName:PlayerCache];
  21 + [CNLivePlayerCache setCostLimit:1024*1024*20];
  22 +
  23 +}
  24 +
  25 +/**
  26 + * 存储或者修改数据
  27 + *
  28 + * @param data 保存的数据
  29 + * @param key 保存的key
  30 + */
  31 ++ (void)player_SaveDataCache:(id)data forKey:(NSString *)key {
  32 + // [[self sharedManager]setObject:data forKey:key];
  33 + // 默认会开启线程缓存
  34 + [_dataCache setObject:data forKey:key withBlock:nil];
  35 +
  36 +}
  37 +
  38 +/**
  39 + * 读取数据
  40 + *
  41 + * @param key 保存的key
  42 + *
  43 + * @return 返回id
  44 + */
  45 ++ (id)player_ReadCache:(NSString *)key {
  46 + return [_dataCache objectForKey:key];
  47 +
  48 +}
  49 +
  50 +/**
  51 + * 读取缓存文件的大小
  52 + *
  53 + * @return 返回NSString
  54 + */
  55 ++ (NSString *)player_GetAllHttpCacheSize {
  56 + // 总大小
  57 + unsigned long long diskCache = [_dataCache.diskCache totalCost];
  58 +
  59 + NSString *sizeText = nil;
  60 +
  61 + if (diskCache >= pow(10, 9)) {
  62 + // size >= 1GB
  63 + sizeText = [NSString stringWithFormat:@"%.2fGB", diskCache / pow(10, 9)];
  64 + }
  65 + else if (diskCache >= pow(10, 6)) { // 1GB > size >= 1MB
  66 + sizeText = [NSString stringWithFormat:@"%.2fMB", diskCache / pow(10, 6)];
  67 + }
  68 + else if (diskCache >= pow(10, 3)) { // 1MB > size >= 1KB
  69 + sizeText = [NSString stringWithFormat:@"%.2fKB", diskCache / pow(10, 3)];
  70 + }
  71 + else { // 1KB > size
  72 + sizeText = [NSString stringWithFormat:@"%zdB", diskCache];
  73 + }
  74 +
  75 + return sizeText;
  76 +
  77 +}
  78 +
  79 +/**
  80 + * 是否缓存过
  81 + *
  82 + * @param key 保存的key
  83 + *
  84 + * @return 返回NSString
  85 + */
  86 ++ (BOOL)player_IsCache:(NSString *)key {
  87 + return [_dataCache containsObjectForKey:key];
  88 +
  89 +}
  90 +
  91 +/**
  92 + * 删除某个磁盘缓存文件
  93 + *
  94 + * @param key 保存的key
  95 + *
  96 + */
  97 ++ (void)player_RemoveChache:(NSString *)key {
  98 + [_dataCache removeObjectForKey:key withBlock:nil];
  99 +
  100 +}
  101 +
  102 +/**
  103 + * 删除所有的磁盘换存文件
  104 + */
  105 ++ (void)player_RemoveAllCache {
  106 + [_dataCache removeAllObjects];
  107 +
  108 +}
  109 +
  110 +/**
  111 + * 磁盘最大缓存开销
  112 + * 默认是30*1024*1024
  113 + */
  114 ++ (void)setCostLimit:(NSInteger)costLimit {
  115 + [_dataCache.diskCache setCostLimit:costLimit];//磁盘最大缓存开销
  116 +}
  117 +@end
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerNetworkManager.h 0 → 100644
  1 +//
  2 +// CNLivePlayerNetworkManager.h
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +
  13 +@interface CNLivePlayerNetworkManager : NSObject
  14 +/**
  15 + * 设置超时时间
  16 + */
  17 +@property (nonatomic, assign) NSTimeInterval timeoutInterval;
  18 +
  19 +/**
  20 + * 缓存策略
  21 + */
  22 +@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
  23 +
  24 ++ (CNLivePlayerNetworkManager *)manager;
  25 +
  26 +/**
  27 + * GET 请求
  28 + * @param URL url
  29 + * @param parameters 上传参数
  30 + * @param success 请求成功回调
  31 + * @param failure 请求失败回调
  32 + */
  33 ++ (void)GET:(nullable NSString *)URL parameters:(nullable NSDictionary *)parameters success:(nullable void (^)(NSURLResponse *_Nullable response, id _Nullable responseObject))success failure:(nullable void (^)(NSURLResponse *_Nullable response, NSError *_Nullable error))failure;
  34 +
  35 +/**
  36 + * POST 请求
  37 + * @param URL url
  38 + * @param parameters 上传参数
  39 + * @param success 请求成功回调
  40 + * @param failure 请求失败回调
  41 + */
  42 ++ (void)POST:(nullable NSString *)URL parameters:(nullable NSDictionary *)parameters success:(nullable void (^)(NSURLResponse *_Nullable response, id _Nullable responseObject))success failure:(nullable void (^)(NSURLResponse *_Nullable response, NSError *_Nullable error))failure;
  43 +
  44 +
  45 +#pragma mark - 针对具体业务
  46 +/**
  47 + * 鉴权
  48 + */
  49 +- (void)authenticate:(NSString *)URL success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure;
  50 +
  51 +/**
  52 + * 获取视频url
  53 + */
  54 ++ (void)getVideoURL:(nullable NSString *)URL success:(nullable void (^)(NSString *_Nullable videoURL, NSInteger code))success;
  55 +
  56 +
  57 +@end
  58 +
  59 +NS_ASSUME_NONNULL_END
... ...
CNLivePlayer/Classes/DataRequest/CNLivePlayerNetworkManager.m 0 → 100644
  1 +//
  2 +// CNLivePlayerNetworkManager.m
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLivePlayerNetworkManager.h"
  10 +#import "CNLiveURLRequestSerialization.h"
  11 +
  12 +/**
  13 + * 网络超时时间 默认 60
  14 + */
  15 +static NSTimeInterval TimeoutInterval = 30.0 ;
  16 +
  17 +/**
  18 + * 缓存策略
  19 + * NSURLRequestUseProtocolCachePolicy // 默认的缓存策略(取决于协议)
  20 + * NSURLRequestReloadIgnoringLocalCacheData // 忽略缓存,重新请求
  21 + * NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未实现
  22 + * NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略缓存,重新请求
  23 + * NSURLRequestReturnCacheDataElseLoad// 有缓存就用缓存,忽略过期时间!没有缓存就重新请求
  24 + * NSURLRequestReturnCacheDataDontLoad// 有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式)
  25 + * NSURLRequestReloadRevalidatingCacheData // 未实现
  26 + */
  27 +static NSURLRequestCachePolicy CachePolicy = NSURLRequestUseProtocolCachePolicy;
  28 +
  29 +typedef void(^GetVideoURLSuccessBlock)(NSString * _Nullable videoURL, NSInteger code);
  30 +
  31 +@interface CNLivePlayerNetworkManager()<NSURLSessionDelegate>
  32 +@property (nonatomic, assign) BOOL result;
  33 +@property (nonatomic, copy) GetVideoURLSuccessBlock successBlock;
  34 +
  35 +@end
  36 +
  37 +@implementation CNLivePlayerNetworkManager
  38 +static CNLivePlayerNetworkManager *_manager = nil;
  39 +
  40 ++ (CNLivePlayerNetworkManager *)manager {
  41 + static dispatch_once_t predicate;
  42 + dispatch_once(&predicate, ^{
  43 + _manager = [[CNLivePlayerNetworkManager alloc] init];
  44 +
  45 + });
  46 + return _manager;
  47 +
  48 +}
  49 +
  50 +- (instancetype)init {
  51 + self = [super init];
  52 + if (self) {
  53 + self.cachePolicy = CachePolicy;
  54 + self.timeoutInterval = TimeoutInterval;
  55 + }
  56 + return self;
  57 +}
  58 +
  59 ++ (void)GET:(NSString *)URL parameters:(NSDictionary *)parameters success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  60 + [[CNLivePlayerNetworkManager manager] GET:URL parameters:parameters success:success failure:failure];
  61 +
  62 +}
  63 +
  64 +- (void)GET:(NSString *)URL parameters:(NSDictionary *)parameters success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  65 + NSURLSessionDataTask *task = [self dataTaskWithRequestMethod:@"GET" URLString:URL parameters:parameters success:success failure:failure];
  66 + [task resume];
  67 +}
  68 +
  69 ++ (void)POST:(NSString *)URL parameters:(NSDictionary *)parameters success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  70 + [[CNLivePlayerNetworkManager manager] POST:URL parameters:parameters success:success failure:failure];
  71 +
  72 +}
  73 +
  74 +- (void)POST:(NSString *)URL parameters:(NSDictionary *)parameters success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  75 + NSURLSessionDataTask *task = [self dataTaskWithRequestMethod:@"POST" URLString:URL parameters:parameters success:success failure:failure];
  76 + [task resume];
  77 +
  78 +}
  79 +
  80 +- (NSURLSessionDataTask *)dataTaskWithRequestMethod:(NSString *)method URLString:(NSString *)URLString parameters:(NSDictionary *)parameters success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  81 +
  82 + if (![URLString isKindOfClass:[NSString class]]) {
  83 + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"please enter a valid url"}];
  84 + failure(nil, error);
  85 + return nil;
  86 + }
  87 +
  88 + NSString *newURLString;
  89 + if ([method isEqualToString:@"GET"]) {
  90 + if (parameters) {
  91 + newURLString = [[URLString stringByAppendingString:@"?"] stringByAppendingString:[CNLiveURLRequestSerialization cn_QueryStringFromParameters:parameters]];
  92 + }else{
  93 + newURLString = URLString;
  94 + }
  95 +
  96 + }else{
  97 + newURLString = URLString;
  98 + }
  99 +
  100 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:newURLString] cachePolicy:self.cachePolicy timeoutInterval:self.timeoutInterval];
  101 +
  102 + request.HTTPMethod = method;
  103 +
  104 + if([method isEqual:@"POST"]){
  105 + [request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  106 + request.HTTPBody =[[CNLiveURLRequestSerialization cn_QueryStringFromParameters:parameters] dataUsingEncoding:NSUTF8StringEncoding];
  107 + }
  108 +
  109 + NSURLSessionDataTask *task = [self dataTaskWithRequest:request success:success failure:failure];
  110 +
  111 + return task;
  112 +
  113 +}
  114 +
  115 +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  116 + NSURLSession *session = [NSURLSession sharedSession];
  117 + NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  118 +
  119 + dispatch_async(dispatch_get_main_queue(), ^{
  120 + if (error) {
  121 + failure(response,error);
  122 + }else{
  123 + if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
  124 + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
  125 + if (httpResponse.statusCode < 400) {
  126 + id jsonObj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
  127 + success(httpResponse, jsonObj);
  128 + } else {
  129 + NSError *failureError = [NSError errorWithDomain:NSURLErrorDomain code:httpResponse.statusCode userInfo:httpResponse.allHeaderFields];
  130 + failure(httpResponse, failureError);
  131 + }
  132 + } else {
  133 + failure(response, error);
  134 + }
  135 + }
  136 + });
  137 + }];
  138 +
  139 + return task;
  140 +
  141 +}
  142 +
  143 +#pragma mark - NSURLSessionDelegate
  144 +// 1.接收到服务器的响应
  145 +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
  146 + // 允许处理服务器的响应,才会继续接收服务器返回的数据
  147 + completionHandler(NSURLSessionResponseCancel);
  148 + _manager.result = YES;
  149 + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
  150 + [CNLivePlayerNetworkManager manager].successBlock([response.URL absoluteString], httpResponse.statusCode);
  151 +
  152 +}
  153 +
  154 +// 3.请求成功或者失败(如果失败,error有值)
  155 +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
  156 + // 请求完成,成功或者失败的处理
  157 + if (_manager.result) return;
  158 +
  159 + NSString *videoUrl302 = error.userInfo[@"NSErrorFailingURLStringKey"];
  160 + if (!videoUrl302 || ![videoUrl302 isKindOfClass:[NSString class]] || videoUrl302.length <= 0) {
  161 + videoUrl302 = nil;
  162 + }
  163 + [CNLivePlayerNetworkManager manager].successBlock(videoUrl302, error.code);
  164 +
  165 +}
  166 +
  167 +#pragma mark - 针对具体业务
  168 +/**
  169 + * 鉴权
  170 + */
  171 +- (void)authenticate:(NSString *)URL success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure {
  172 + NSURLSessionDataTask *task = [self dataTaskWithRequestMethod:@"GET" URLString:URL parameters:nil success:success failure:failure];
  173 + [task resume];
  174 +}
  175 +
  176 +/**
  177 + * 获取视频url
  178 + */
  179 ++ (void)getVideoURL:(NSString *)URL success:(void (^)(NSString * _Nullable, NSInteger))success {
  180 + [CNLivePlayerNetworkManager manager].successBlock = success;
  181 + _manager.result = NO;
  182 +
  183 + NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  184 + NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:_manager delegateQueue:[[NSOperationQueue alloc] init]];
  185 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URL] cachePolicy:_manager.cachePolicy timeoutInterval:_manager.timeoutInterval];
  186 +
  187 + NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
  188 + // 启动任务
  189 + [task resume];
  190 +
  191 +}
  192 +
  193 +
  194 +@end
... ...
CNLivePlayer/Classes/DataRequest/CNLiveURLRequestSerialization.h 0 → 100644
  1 +//
  2 +// CNLiveURLRequestSerialization.h
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +
  13 +@interface CNLiveURLRequestSerialization : NSObject
  14 ++ (nullable NSString *)cn_QueryStringFromParameters:(nullable NSDictionary *)parameters;
  15 +
  16 +@end
  17 +
  18 +NS_ASSUME_NONNULL_END
... ...
CNLivePlayer/Classes/DataRequest/CNLiveURLRequestSerialization.m 0 → 100644
  1 +//
  2 +// CNLiveURLRequestSerialization.m
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveURLRequestSerialization.h"
  10 +
  11 +@interface CNLiveURLRequestSerialization ()
  12 +@property (readwrite, nonatomic, strong) id value;
  13 +@property (readwrite, nonatomic, strong) id field;
  14 +
  15 +@end
  16 +
  17 +@implementation CNLiveURLRequestSerialization
  18 +
  19 +- (id)initWithField:(id)field value:(id)value {
  20 + self = [super init];
  21 + if (self) {
  22 + self.field = field;
  23 + self.value = value;
  24 + }
  25 +
  26 + return self;
  27 +
  28 +}
  29 +
  30 +FOUNDATION_EXPORT NSArray * CNKSYQueryStringPairsFromDictionary(NSDictionary *dictionary);
  31 +FOUNDATION_EXPORT NSArray * CNKSYQueryStringPairsFromKeyAndValue(NSString *key, id value);
  32 +
  33 ++ (NSString *)cn_QueryStringFromParameters:(NSDictionary *)parameters {
  34 + NSMutableArray *mutablePairs = [NSMutableArray array];
  35 + for (CNLiveURLRequestSerialization *pair in CNKSYQueryStringPairsFromDictionary(parameters)) {
  36 + [mutablePairs addObject:[pair URLEncodedStringValue]];
  37 + }
  38 + return [mutablePairs componentsJoinedByString:@"&"];
  39 +}
  40 +
  41 +NSArray * CNKSYQueryStringPairsFromDictionary(NSDictionary *dictionary) {
  42 + return CNKSYQueryStringPairsFromKeyAndValue(nil, dictionary);
  43 +}
  44 +
  45 +/**
  46 + * 处理上传参数
  47 + */
  48 +NSArray * CNKSYQueryStringPairsFromKeyAndValue(NSString *key, id value) {
  49 + NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
  50 + //排序方式
  51 + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
  52 +
  53 + if ([value isKindOfClass:[NSDictionary class]]) { //字典
  54 + NSDictionary *dictionary = value;
  55 + for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]]) {
  56 + id nestedValue = dictionary[nestedKey];
  57 + if (nestedKey) {
  58 + [mutableQueryStringComponents addObjectsFromArray:CNKSYQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
  59 + }
  60 + }
  61 + }
  62 + else if ([value isKindOfClass:[NSArray class]]){ //数组
  63 + NSArray *array = value;
  64 + for (id nestedValue in array) {
  65 + [mutableQueryStringComponents addObjectsFromArray:CNKSYQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
  66 + }
  67 + }
  68 + else if ([value isKindOfClass:[NSSet class]]){ //集合
  69 + NSSet *set = value;
  70 + for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
  71 + [mutableQueryStringComponents addObjectsFromArray:CNKSYQueryStringPairsFromKeyAndValue(key, obj)];
  72 + }
  73 + }
  74 + else{ //其他类型
  75 + [mutableQueryStringComponents addObject:[[CNLiveURLRequestSerialization alloc] initWithField:key value:value]];
  76 + }
  77 +
  78 + return mutableQueryStringComponents;
  79 +}
  80 +
  81 +static NSString * CNPercentEscapedStringFromString(NSString *string) {
  82 + static NSString * const kCNCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
  83 + static NSString * const kCNCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
  84 +
  85 + NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
  86 + [allowedCharacterSet removeCharactersInString:[kCNCharactersGeneralDelimitersToEncode stringByAppendingString:kCNCharactersSubDelimitersToEncode]];
  87 +
  88 + static NSUInteger const batchSize = 50;
  89 +
  90 + NSUInteger index = 0;
  91 + NSMutableString *escaped = @"".mutableCopy;
  92 +
  93 + while (index < string.length) {
  94 +#pragma GCC diagnostic push
  95 +#pragma GCC diagnostic ignored "-Wgnu"
  96 + NSUInteger length = MIN(string.length - index, batchSize);
  97 +#pragma GCC diagnostic pop
  98 + NSRange range = NSMakeRange(index, length);
  99 +
  100 + range = [string rangeOfComposedCharacterSequencesForRange:range];
  101 +
  102 + NSString *substring = [string substringWithRange:range];
  103 + NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
  104 + [escaped appendString:encoded];
  105 +
  106 + index += range.length;
  107 +
  108 + }
  109 +
  110 + return escaped;
  111 +}
  112 +
  113 +- (NSString *)URLEncodedStringValue {
  114 + if (!self.value || [self.value isEqual:[NSNull null]]) {
  115 + return CNPercentEscapedStringFromString([self.field description]);
  116 + } else {
  117 + return [NSString stringWithFormat:@"%@=%@", CNPercentEscapedStringFromString([self.field description]), CNPercentEscapedStringFromString([self.value description])];
  118 + }
  119 +}
  120 +
  121 +@end
... ...
CNLivePlayer/Classes/Player/CNLivePlayer.h 0 → 100644
  1 +//
  2 +// CNLivePlayer.h
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +#import <libksygpulive/KSYMoviePlayerController.h>
  11 +#import "KSYMediaPlayback.h"
  12 +#import "KSYQosInfo.h"
  13 +#import "KSYMoviePlayerDefines.h"
  14 +#import "KSYReachability.h"
  15 +
  16 +//播放器管理类
  17 +#import "CNLivePlayerManager.h"
  18 +
  19 +NS_ASSUME_NONNULL_BEGIN
  20 +
  21 +@interface CNLivePlayer : NSObject
  22 +
  23 +@property (nonatomic, strong) KSYMoviePlayerController *player;
  24 +
  25 +/* 初始化点播播放器 初始化成功后才能对播放器进行设置(如:自动播放、是否开启硬件解码等)和调用准备播放视频方法(prepareToPlay)
  26 + *
  27 + * videoId 点播视频Id
  28 + * authSuccess 初始化成功block
  29 + * authFailed 初始化失败block 回调一个errorInfo的字典
  30 + *
  31 + */
  32 +- (instancetype)initVodPlayerWithVideoId:(NSString *)videoId authSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock;
  33 +
  34 +
  35 +/* 初始化直播播放器(* 以channelId播放) 初始化成功后才能对播放器进行设置(如:自动播放、是否开启硬件解码等)和调用准备播放视频方法(prepareToPlay)
  36 + *
  37 + * channelId 直播视频Id (注* 若agree为YES时,必传,用于获取主播状态; 若agree为NO,可不传)
  38 + * activityId 活动Id
  39 + * agree 是否允许获取主播状态 YES:获取 NO:不获取
  40 + * authSuccess 初始化成功block
  41 + * authFailed 初始化失败block 回调一个errorInfo的字典
  42 + *
  43 + * result 获取主播状态 YES:获取状态成功
  44 + * NO:获取失败,不影响视频播放,但是获取不到主播离开、回来、直播结束等通知。可通过
  45 + * - (void)retryToGetAnchorStatusResult:(void(^)(BOOL result))result;方法重新获取
  46 + */
  47 +- (instancetype)initLivePlayerWithChannelId:(NSString *)channelId activityId:(NSString *)activityId anchorStatus:(BOOL)agree authSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock getAnchorStatusResult:(void(^)(BOOL result))result;
  48 +
  49 +
  50 +/**
  51 + @abstract 包含视频播放内容的VIEW(只读)。
  52 + @discussion view的使用逻辑:
  53 +
  54 + * 可以通过frame设置view大大小
  55 + * 使用[scalingMode]([KSYMoviePlayerController scalingMode]) 可以更改视频内容在VIEW中的显示情况
  56 +
  57 + @see scalingMode
  58 + */
  59 +// The view in which the media and playback controls are displayed.
  60 +@property (nonatomic, strong, readonly) UIView *view;
  61 +
  62 +/* 准备视频播放
  63 + *
  64 + * MPMediaPlaybackIsPreparedToPlayDidChangeNotification 播放器完成对视频文件的初始化时发送通知
  65 + *
  66 + */
  67 +- (void)prepareToPlay;
  68 +
  69 +
  70 +@end
  71 +
  72 +NS_ASSUME_NONNULL_END
... ...
CNLivePlayer/Classes/Player/CNLivePlayer.m 0 → 100644
  1 +//
  2 +// CNLivePlayer.m
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLivePlayer.h"
  10 +#import "CNLivePlayerManager.h"
  11 +#import "CNLivePlayerCache.h"
  12 +#import "CommonCrypto/CommonDigest.h"
  13 +//数据请求
  14 +#import "CNLivePlayerNetworkManager.h"
  15 +//常量
  16 +#import "CNLivePlayerConst.h"
  17 +//工具
  18 +#import "CNLivePlayerTools.h"
  19 +
  20 +#pragma mark - 通知
  21 +//收到消息通知
  22 +NSString * const CNLivePlayerMsgReceiveNotification = @"CNLivePlayerMsgReceiveNotification";
  23 +//获取主播状态通知
  24 +NSString * const CNLiveAnchorStatusChangedNotification = @"CNLiveAnchorStatusChangedNotification";
  25 +
  26 +@interface CNLivePlayer () {
  27 + NSString *_idName;
  28 + NSString *_contentType;
  29 + NSString *_contentId;
  30 +
  31 + //直播
  32 + NSString *_activityId;
  33 +
  34 + //音频标识
  35 + BOOL _isAudio;
  36 +
  37 + //探针
  38 + NSTimer *_statTimer;
  39 + BOOL _preparedToPlay;
  40 + NSInteger _playTime;
  41 +
  42 +}
  43 +@property (nonatomic, strong, readwrite) UIView *view;
  44 +@property (nonatomic, copy) NSString *videoUrl;
  45 +
  46 +@end
  47 +@implementation CNLivePlayer
  48 +#pragma mark - 初始化方法
  49 +/* 初始化点播播放器 初始化成功后才能对播放器进行设置(如:自动播放、是否开启硬件解码等)和调用准备播放视频方法(prepareToPlay)
  50 + *
  51 + * videoId 点播视频Id
  52 + * authSuccess 初始化成功block
  53 + * authFailed 初始化失败block 回调一个errorInfo的字典
  54 + *
  55 + */
  56 +- (instancetype)initVodPlayerWithVideoId:(NSString *)videoId authSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  57 + if (self = [super init]) {
  58 + if (![videoId isKindOfClass:[NSString class]] || !videoId) {
  59 + videoId = videoId ? [NSString stringWithFormat:@"%@",videoId] : @"";
  60 +
  61 + }
  62 + _idName = @"vid";
  63 + _contentType = @"vod";
  64 + _contentId = videoId;
  65 +
  66 + [self createPlayerWithContentId:videoId authSuccess:authSuccessBlock authFailed:authFailedBlock];
  67 +
  68 + }
  69 + return self;
  70 +
  71 +}
  72 +
  73 +/* 初始化直播播放器(* 以channelId播放) 初始化成功后才能对播放器进行设置(如:自动播放、是否开启硬件解码等)和调用准备播放视频方法(prepareToPlay)
  74 + *
  75 + * channelId 直播视频Id (注* 若agree为YES时,必传,用于获取主播状态; 若agree为NO,可不传)
  76 + * activityId 活动Id
  77 + * agree 是否允许获取主播状态 YES:获取 NO:不获取
  78 + * authSuccess 初始化成功block
  79 + * authFailed 初始化失败block 回调一个errorInfo的字典
  80 + *
  81 + * result 获取主播状态 YES:获取状态成功
  82 + * NO:获取失败,不影响视频播放,但是获取不到主播离开、回来、直播结束等通知。可通过
  83 + * - (void)retryToGetAnchorStatusResult:(void(^)(BOOL result))result;方法重新获取
  84 + */
  85 +- (instancetype)initLivePlayerWithChannelId:(NSString *)channelId activityId:(NSString *)activityId anchorStatus:(BOOL)agree authSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock getAnchorStatusResult:(void(^)(BOOL result))result{
  86 + if (self = [super init]) {
  87 + if (![channelId isKindOfClass:[NSString class]] || !channelId) {
  88 + channelId = channelId ? [NSString stringWithFormat:@"%@",channelId] : @"";
  89 + }
  90 +
  91 + _idName = @"cid";
  92 + _contentType = @"live";
  93 + _contentId = channelId;
  94 + _activityId = [NSString stringWithFormat:@"%@",activityId];
  95 +
  96 + [self createPlayerWithContentId:channelId authSuccess:authSuccessBlock authFailed:authFailedBlock];
  97 +
  98 + }
  99 + return self;
  100 +
  101 +}
  102 +
  103 +- (void)createPlayerWithContentId:(NSString *)contentId authSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock{
  104 + [UIApplication sharedApplication].idleTimerDisabled = YES;
  105 +
  106 + _isAudio = NO;
  107 + [self addMovieNotificationObservers];
  108 +
  109 + dispatch_async(dispatch_get_global_queue(0, 0), ^{
  110 + [self getVideoId:contentId authSuccess:authSuccessBlock authFailed:authFailedBlock];
  111 +
  112 + });
  113 +}
  114 +
  115 +#pragma mark - 查找本地是否有缓存url
  116 +- (void)getVideoId:(NSString *)videoId authSuccess:(void (^)(void))authSuccessBlock authFailed:(void (^)(NSDictionary *errorDic))authFailedBlock {
  117 + NSString *key = [NSString stringWithFormat:@"%@:%@",_contentType,videoId];
  118 + id data = [CNLivePlayerCache player_ReadCache:key];
  119 + if (data) {
  120 + 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;
  127 + if (PLAYER_TestEnvironment) {
  128 + NSLog(@"CNLivePlayer-->缓存数据,播放器初始化成功,可以对播放器进行设置并准备播放");
  129 + }
  130 + authSuccessBlock ? authSuccessBlock() : nil;
  131 + });
  132 +
  133 + } else {
  134 + NSDictionary *privilegeDic = [[NSUserDefaults standardUserDefaults] objectForKey:kCNLivePlayerSDKAuthentication];
  135 + if(privilegeDic&&[privilegeDic[@"resultCode"] isEqualToString:@"0"]){
  136 + if([_contentType isEqualToString:@"vod"]){
  137 + [self getVodVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  138 +
  139 + }else{
  140 + [self getLiveVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  141 +
  142 + }
  143 +
  144 + }else{
  145 + __weak typeof(self) weakSelf = self;
  146 + //鉴权
  147 + [weakSelf authenticateSuccess:^{
  148 + __strong typeof(self) strongSelf = weakSelf;
  149 + if([strongSelf->_contentType isEqualToString:@"vod"]){
  150 + [self getVodVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  151 +
  152 + }else{
  153 + [self getLiveVideoURLSuccess:authSuccessBlock authFailed:authFailedBlock];
  154 +
  155 + }
  156 +
  157 + } authenticateFailed:authFailedBlock];
  158 + }
  159 +
  160 + }
  161 +
  162 +}
  163 +
  164 +#pragma mark - 获取点播视频url
  165 +- (void)getVodVideoURLSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  166 +
  167 + NSDictionary *parameter = @{@"appId": PLAYER_AppID,
  168 + @"vId": _contentId,
  169 + @"timestamp": [CNLivePlayerTools getTimestamp],
  170 + @"isHLS": @"1",
  171 + @"plat": @"i",
  172 + @"playType": _isAudio ? @"a": @"v",
  173 + @"platform_id": [NSBundle mainBundle].bundleIdentifier,
  174 + @"channelName": PLAYER_ChannelName,
  175 + @"tag": PLAYER_Tag,
  176 + @"from": @"apple",
  177 + @"sid": PLAYER_UserId,
  178 + @"uid": [CNLivePlayerTools getUidForStat:[NSDate date]]};
  179 +
  180 + NSString *videoUrl = [CNLivePlayerTools encryptionSignWithUrl:vodUrl parameter:parameter];
  181 +
  182 + __weak typeof(self) weakSelf = self;
  183 + [CNLivePlayerNetworkManager getVideoURL:videoUrl success:^(NSString * _Nullable videoURL, NSInteger code) {
  184 + __strong typeof(self) strongSelf = weakSelf;
  185 +// NSString *key = [NSString stringWithFormat:@"%@:%@",strongSelf->_contentType, strongSelf->_contentId];
  186 +// [CNLivePlayerCache player_SaveDataCache:videoURL forKey:key];
  187 + dispatch_async(dispatch_get_main_queue(), ^{
  188 + strongSelf.videoUrl = videoUrl;
  189 + strongSelf.player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:videoUrl]];
  190 + [strongSelf.view addSubview:strongSelf.player.view];
  191 + strongSelf.player.view.frame = strongSelf.view.bounds;
  192 + strongSelf.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
  193 + strongSelf.player.shouldEnableKSYStatModule = NO;
  194 +
  195 + [strongSelf statSDK];
  196 +
  197 + if (PLAYER_TestEnvironment) {
  198 + NSLog(@"CNLivePlayer-->请求数据,点播播放器初始化成功,可以对播放器进行设置并准备播放");
  199 + }
  200 + if (authSuccessBlock) {
  201 + authSuccessBlock();
  202 + }
  203 +
  204 + });
  205 + }];
  206 +}
  207 +
  208 +#pragma mark - 获取直播视频url
  209 +- (void)getLiveVideoURLSuccess:(void(^)(void))authSuccessBlock authFailed:(void(^)(NSDictionary *errorInfo))authFailedBlock {
  210 + NSString *timestamp = [CNLivePlayerTools getTimestamp];
  211 + NSDictionary *parameter = @{@"appId": PLAYER_AppID,
  212 + @"channelId": _contentId,
  213 + @"activityId": _activityId ? _activityId : @"",
  214 + @"timestamp": timestamp,
  215 + @"isHLS": @"0",
  216 + @"plat": @"i",
  217 + @"playType": _isAudio ? @"a": @"v",
  218 + @"platform_id": [NSBundle mainBundle].bundleIdentifier,
  219 + @"channelName": PLAYER_ChannelName,
  220 + @"tag": PLAYER_Tag,
  221 + @"from": @"apple",
  222 + @"sid": PLAYER_UserId,
  223 + @"uid": [CNLivePlayerTools getUidForStat:[NSDate date]]};
  224 +
  225 + NSString *videoUrl = [CNLivePlayerTools encryptionSignWithUrl:liveUrl parameter:parameter];
  226 +
  227 + // 拿到302跳转后的播放地址
  228 + NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:videoUrl]];
  229 + [urlRequest setHTTPMethod:@"GET"];
  230 + [urlRequest setTimeoutInterval:30];
  231 +
  232 + [NSURLConnection sendAsynchronousRequest:urlRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
  233 + __weak typeof(self) weakSelf = self;
  234 + dispatch_async(dispatch_get_main_queue(), ^{
  235 + __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 + strongSelf.videoUrl = url;
  253 + strongSelf.player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:url]];
  254 + [strongSelf.view addSubview:strongSelf.player.view];
  255 + strongSelf.player.view.frame = strongSelf.view.bounds;
  256 + strongSelf.player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
  257 + strongSelf.player.shouldEnableKSYStatModule = NO;
  258 +
  259 + NSString *key = [NSString stringWithFormat:@"%@:%@",strongSelf->_contentType, strongSelf->_contentId];
  260 + [CNLivePlayerCache player_SaveDataCache:url forKey:key];
  261 +
  262 + [strongSelf statSDK];
  263 +
  264 + if (PLAYER_TestEnvironment) {
  265 + NSLog(@"CNLivePlayer-->请求数据,直播播放器初始化成功,可以对播放器进行设置并准备播放");
  266 + }
  267 + if (authSuccessBlock) {
  268 + authSuccessBlock();
  269 + }
  270 +
  271 + });
  272 + }];
  273 +}
  274 +
  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 +#pragma mark - 注册通知
  329 +- (void)addMovieNotificationObservers {
  330 + [[NSNotificationCenter defaultCenter] addObserver:self
  331 + selector:@selector(loadStateDidChange:)
  332 + name:MPMoviePlayerLoadStateDidChangeNotification
  333 + object:nil];
  334 +
  335 + [[NSNotificationCenter defaultCenter] addObserver:self
  336 + selector:@selector(moviePlayBackDidFinish:)
  337 + name:MPMoviePlayerPlaybackDidFinishNotification
  338 + object:nil];
  339 +
  340 + [[NSNotificationCenter defaultCenter] addObserver:self
  341 + selector:@selector(mediaIsPreparedToPlayDidChange:)
  342 + name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification
  343 + object:nil];
  344 +
  345 +}
  346 +
  347 +- (void)addRCloudNotificationObservers {
  348 + //接收消息通知
  349 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveMessage:) name:CNLivePlayerMsgReceiveNotification object:nil];
  350 +
  351 +}
  352 +
  353 +- (void)removeMovieNotificationObservers {
  354 + [[NSNotificationCenter defaultCenter] removeObserver:self
  355 + name:MPMoviePlayerLoadStateDidChangeNotification
  356 + object:nil];
  357 +
  358 + [[NSNotificationCenter defaultCenter] removeObserver:self
  359 + name:MPMoviePlayerPlaybackDidFinishNotification
  360 + object:nil];
  361 +
  362 + [[NSNotificationCenter defaultCenter] removeObserver:self
  363 + name:MPMediaPlaybackIsPreparedToPlayDidChangeNotification
  364 + object:nil];
  365 +}
  366 +
  367 +- (void)removeRCloudNotificationObservers {
  368 +
  369 + [[NSNotificationCenter defaultCenter] removeObserver:self name:CNLivePlayerMsgReceiveNotification object:nil];
  370 +
  371 +// if ([CNLivePlayerTools isEmptyString:_roomId]) {
  372 +// return;
  373 +// }
  374 +
  375 +// [[CNLiveMsgManager sharedCNLiveMsgManager] disperse:_roomId success:^(NSString *targetId) {
  376 +//
  377 +// } error:^(NSInteger errors, NSString *targetId) {
  378 +//
  379 +// }];
  380 +
  381 +}
  382 +
  383 +#pragma mark - 通知响应方法
  384 +- (void)loadStateDidChange:(NSNotification *)notification {
  385 + MPMovieLoadState loadState = _player.loadState;
  386 + if (PLAYER_TestEnvironment) {
  387 + NSLog(@"CNLivePlayer-->播放器加载状态改变MPMovieLoadState:%ld", (unsigned long)loadState);
  388 + }
  389 + if ((loadState & MPMovieLoadStatePlaythroughOK) != 0) {
  390 + if (!_preparedToPlay && !_statTimer) {
  391 + [self mediaIsPreparedToPlayDidChange:nil];
  392 + }
  393 + }
  394 +}
  395 +
  396 +- (void)moviePlayBackDidFinish:(NSNotification *)notification {
  397 + [UIApplication sharedApplication].idleTimerDisabled = NO;
  398 + int reason = [[[notification userInfo] valueForKey:MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] intValue];
  399 + if (PLAYER_TestEnvironment) {
  400 + NSLog(@"CNLivePlayer-->播放器播放结束原因MPMovieFinishReason:%d", reason);
  401 + }
  402 + switch (reason) {
  403 + case MPMovieFinishReasonPlaybackEnded:
  404 + {
  405 + [_statTimer invalidate];
  406 + _statTimer = nil;
  407 + _playTime = 0;
  408 + }
  409 + break;
  410 +
  411 + case MPMovieFinishReasonUserExited:
  412 + {
  413 + [_statTimer invalidate];
  414 + _statTimer = nil;
  415 + _playTime = 0;
  416 + }
  417 + break;
  418 +
  419 + case MPMovieFinishReasonPlaybackError://视频异常探针
  420 + {
  421 + [self errorStat:notification.userInfo.description];
  422 + }
  423 + break;
  424 +
  425 + default:
  426 +
  427 + break;
  428 + }
  429 +}
  430 +
  431 +- (void)mediaIsPreparedToPlayDidChange:(NSNotification *)notification {
  432 + if (PLAYER_TestEnvironment) {
  433 + NSLog(@"CNLivePlayer-->播放器缓冲至可播放状态");
  434 +
  435 + }
  436 + _preparedToPlay = YES;
  437 + if (!_contentType || _contentType.length == 0) {
  438 + return;
  439 + }
  440 + _statTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(statTimerAction) userInfo:nil repeats:YES];
  441 +
  442 +}
  443 +
  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 +#pragma mark - 播放时长计算
  466 +- (void)statTimerAction{
  467 + if (!_contentType || _contentType.length == 0) {
  468 + return;
  469 + }
  470 + _playTime++;
  471 +
  472 + 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];
  488 + [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]] delegate:nil];
  489 +
  490 +}
  491 +
  492 +#pragma mark - 属性
  493 +/**
  494 + @abstract 包含视频播放内容的VIEW(只读)。
  495 + @discussion view的使用逻辑:
  496 +
  497 + * 可以通过frame设置view大大小
  498 + * 使用[scalingMode]([KSYMoviePlayerController scalingMode]) 可以更改视频内容在VIEW中的显示情况
  499 +
  500 + @see scalingMode
  501 + */
  502 +// The view in which the media and playback controls are displayed.
  503 +- (UIView *)view {
  504 + if (!_view) {
  505 + _view = [[UIView alloc] init];
  506 + _view.backgroundColor = [UIColor blackColor];
  507 + }
  508 + return _view;
  509 +
  510 +}
  511 +
  512 +/* 准备视频播放
  513 + *
  514 + * MPMediaPlaybackIsPreparedToPlayDidChangeNotification, 播放器完成对视频文件的初始化时发送通知
  515 + *
  516 + */
  517 +- (void)prepareToPlay {
  518 + [_player prepareToPlay];
  519 +}
  520 +
  521 +@end
... ...
CNLivePlayer/Classes/Player/CNLivePlayerConst.h 0 → 100644
  1 +//
  2 +// CNLivePlayerConst.h
  3 +// CNLivePlayer
  4 +//
  5 +// Created by CNLive-zxw on 2019/8/14.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#ifndef CNLivePlayerConst_h
  10 +#define CNLivePlayerConst_h
  11 +
  12 +#pragma mark - 版本号
  13 +#define PlayerSDKVersion @"0.0.1" //SDK版本
  14 +
  15 +#pragma mark - 探针
  16 +#define StatUrl [CNLivePlayerManager manager].isTestEnvironment?@"http://app.sta.cnlive.com/app.jpg": @"http://app.sta.cnlive.com/app.jpg"
  17 +#define StatVersion @"4.0" //探针版本
  18 +#define StatAppVersion ([[[NSBundle mainBundle] infoDictionary] objectForKey: @"CFBundleShortVersionString"])
  19 +
  20 +#pragma mark - 鉴权
  21 +#define authUrl [NSString stringWithFormat:@"%@/platform/valid", [CNLivePlayerManager manager].isTestEnvironment ? @"http://test.open.cnlive.com/openapi/api2" : @"http://api.cnlive.com/open/api2"]
  22 +
  23 +#pragma mark - 点播
  24 +#define vodUrl [CNLivePlayerManager manager].isTestEnvironment?@"http://test.open.cnlive.com/openapi/api2/vod_ips/vodplayByAPP":@"http://api.cnlive.com/open/api2/vod_ips/vodplayByAPP"
  25 +
  26 +#pragma mark - 直播
  27 +#define liveUrl [CNLivePlayerManager manager].isTestEnvironment?@"http://test.open.cnlive.com/openapi/api2/live_ips/liveplayByAPP":@"http://api.cnlive.com/open/api2/live_ips/liveplayByAPP"
  28 +
  29 +// 存储鉴权
  30 +#define kCNLivePlayerSDKAuthentication @"kCNLivePlayerSDKAuthentication"
  31 +
  32 +#endif /* CNLivePlayerConst_h */
... ...
CNLivePlayer/Classes/Player/CNLivePlayerManager.h 0 → 100644
  1 +//
  2 +// CNLivePlayerManager.h
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +#define PLAYER_AppID [CNLivePlayerManager manager].appId?[CNLivePlayerManager manager].appId:@""
  12 +#define PLAYER_AppKey [CNLivePlayerManager manager].appKey?[CNLivePlayerManager manager].appKey:@""
  13 +#define PLAYER_UserId [CNLivePlayerManager manager].userId?[CNLivePlayerManager manager].userId:@""
  14 +#define PLAYER_ChannelName [CNLivePlayerManager manager].channelName?[CNLivePlayerManager manager].channelName:@""
  15 +#define PLAYER_Tag [CNLivePlayerManager manager].tag?[CNLivePlayerManager manager].tag:@""
  16 +#define PLAYER_TestEnvironment [CNLivePlayerManager manager].isTestEnvironment
  17 +
  18 +NS_ASSUME_NONNULL_BEGIN
  19 +
  20 +@interface CNLivePlayerManager : NSObject
  21 ++ (CNLivePlayerManager *)manager;
  22 +
  23 +/**
  24 + * 应用ID(只读)
  25 + */
  26 +@property (nonatomic, copy, readonly) NSString *appId;
  27 +
  28 +/**
  29 + * 应用KEY(只读)
  30 + */
  31 +@property (nonatomic, copy, readonly) NSString *appKey;
  32 +
  33 +/**
  34 + * 是否是测试环境
  35 + */
  36 +@property (nonatomic, assign, readonly) BOOL isTestEnvironment;
  37 +
  38 +/**
  39 + * 用户ID
  40 + */
  41 +@property (nonatomic, copy) NSString *userId;
  42 +
  43 +/**
  44 + * ChannelName 网++定制
  45 + */
  46 +@property (nonatomic, copy) NSString *channelName;
  47 +
  48 +/**
  49 + * tag 网++定制
  50 + */
  51 +@property (nonatomic, copy) NSString *tag;
  52 +
  53 +/**
  54 + * from 网++定制
  55 + */
  56 +@property (nonatomic, copy) NSString *from;
  57 +
  58 +/**
  59 + @abstract 初始化直播云SDK(该方法默认正式环境)
  60 + @param appId 在open.cnlive.com网站申请得到的appId
  61 + @param appKey 在open.cnlive.com网站申请得到的appKey
  62 + @warning 必传参数
  63 + */
  64 ++ (void)setAppId:(NSString *)appId appKey:(NSString *)appKey;
  65 +
  66 +/**
  67 + @abstract 初始化直播云SDK
  68 + @param appId 在open.cnlive.com网站申请得到的appId
  69 + @param appKey 在open.cnlive.com网站申请得到的appKey
  70 + @param isTestEnvironment YES:测试环境 NO:正式环境
  71 + @warning 必传参数
  72 + */
  73 ++ (void)setAppId:(NSString *)appId appKey:(NSString *)appKey isTestEnvironment:(BOOL)isTestEnvironment;
  74 +
  75 +/**
  76 + @abstract 获取版本号
  77 + */
  78 ++ (NSString *)getVersion;
  79 +
  80 +
  81 +@end
  82 +
  83 +NS_ASSUME_NONNULL_END
... ...
CNLivePlayer/Classes/Player/CNLivePlayerManager.m 0 → 100644
  1 +//
  2 +// CNLivePlayerManager.m
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLivePlayerManager.h"
  10 +#import <libksygpulive/KSYGPUStreamerKit.h>
  11 +#import "CNLivePlayerConst.h"
  12 +
  13 +@interface CNLivePlayerManager()
  14 +/**
  15 + * 应用ID(只读)
  16 + */
  17 +@property (nonatomic, copy, readwrite) NSString *appId;
  18 +
  19 +/**
  20 + * 应用KEY(只读)
  21 + */
  22 +@property (nonatomic, copy, readwrite) NSString *appKey;
  23 +
  24 +/**
  25 + * 是否是测试环境
  26 + */
  27 +@property (nonatomic, assign, readwrite) BOOL isTestEnvironment;
  28 +
  29 +@end
  30 +
  31 +@implementation CNLivePlayerManager
  32 +static CNLivePlayerManager * _instance = nil;
  33 ++ (CNLivePlayerManager *)manager {
  34 + static dispatch_once_t onceToken;
  35 + dispatch_once(&onceToken, ^{
  36 + _instance = [[self alloc] init];
  37 + //清除播放器鉴权缓存
  38 + [CNLivePlayerManager clearAuthentication];
  39 +
  40 + });
  41 +
  42 + return _instance;
  43 +}
  44 +
  45 ++ (void)setAppId:(NSString *)appId appKey:(NSString *)appKey {
  46 + [CNLivePlayerManager setAppId:appId appKey:appKey isTestEnvironment:NO];
  47 +
  48 +}
  49 +
  50 ++ (void)setAppId:(NSString *)appId appKey:(NSString *)appKey isTestEnvironment:(BOOL)isTestEnvironment{
  51 + [[CNLivePlayerManager manager] setAppId:appId appKey:appKey isTestEnvironment:isTestEnvironment];
  52 +
  53 +}
  54 +
  55 +#pragma mark - 私有方法
  56 +- (void)setAppId:(NSString *)appId appKey:(NSString *)appKey {
  57 + [self setAppId:appId appKey:appKey isTestEnvironment:NO];
  58 +}
  59 +
  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;
  64 +}
  65 +
  66 ++ (NSString *)getVersion {
  67 + KSYGPUStreamerKit *kit = [[KSYGPUStreamerKit alloc] init];
  68 + NSString *str = [[[kit.streamerBase getKSYVersion] componentsSeparatedByString:@"-"] lastObject];
  69 + return [NSString stringWithFormat:@"%@_%@", PlayerSDKVersion,str];
  70 +}
  71 +
  72 ++ (void)clearAuthentication {
  73 + NSDictionary *authenticationDic = [[NSUserDefaults standardUserDefaults] objectForKey:kCNLivePlayerSDKAuthentication];
  74 + if (authenticationDic) {
  75 + [[NSUserDefaults standardUserDefaults] removeObjectForKey:kCNLivePlayerSDKAuthentication];
  76 + }
  77 +}
  78 +
  79 +@end
... ...
CNLivePlayer/Classes/Tools/CNLivePlayerTools.h 0 → 100644
  1 +//
  2 +// CNLivePlayerTools.h
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface CNLivePlayerTools : NSObject
  12 +
  13 +//SHA加密
  14 ++ (NSString *)encryptionSignWithUrl:(NSString *)url parameter:(NSDictionary *)parameter;
  15 +
  16 ++ (NSString *)sha1:(NSString *)string;
  17 +
  18 ++ (NSString *)signvalue:(NSDictionary*)parameter;
  19 +
  20 +//获取uuid
  21 ++ (NSString *)getUidForStat:(NSDate *)date;
  22 +
  23 ++ (NSString *)uidForStat:(NSString *)date;
  24 +
  25 +//错误信息
  26 ++ (NSError *)customErrorWithResponseObject:(id)responseObject errorInfo:(NSString *)errorInfo;
  27 +
  28 +/**
  29 + * 验证是是否为是空字符串
  30 + */
  31 ++ (BOOL)isEmptyString:(NSString *)string;
  32 +
  33 +/**
  34 + * 获取时间戳
  35 + */
  36 ++ (NSString *)getTimestamp;
  37 +
  38 +
  39 +@end
... ...
CNLivePlayer/Classes/Tools/CNLivePlayerTools.m 0 → 100644
  1 +//
  2 +// CNLivePlayerTools.m
  3 +// CNLivePlayer_Example
  4 +//
  5 +// Created by CNLive-zxw on 2019/7/26.
  6 +// Copyright © 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLivePlayerTools.h"
  10 +#import "CommonCrypto/CommonDigest.h"
  11 +#import "CNLivePlayerManager.h"
  12 +#import "CNLivePlayerConst.h"
  13 +
  14 +@implementation CNLivePlayerTools
  15 +#pragma mark - 加密
  16 ++ (NSString *)encryptionSignWithUrl:(NSString *)url parameter:(NSDictionary *)parameter {
  17 + NSString *string1 = [NSString stringWithFormat:@"%@&key=%@", [CNLivePlayerTools signvalue:parameter], PLAYER_AppKey];
  18 + NSString *signString1 = [[CNLivePlayerTools sha1:string1] uppercaseString];
  19 + return [NSString stringWithFormat:@"%@?%@&sign=%@", url, [CNLivePlayerTools signvalue:parameter], signString1];
  20 +
  21 +}
  22 +
  23 ++ (NSString*)sha1:(NSString *)string {
  24 + NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  25 +
  26 + uint8_t digest[CC_SHA1_DIGEST_LENGTH];
  27 +
  28 + CC_SHA1(data.bytes, data.length, digest);
  29 +
  30 + NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
  31 +
  32 + for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
  33 + [output appendFormat:@"%02x", digest[i]];
  34 +
  35 + while ([[output substringToIndex:1] isEqualToString:@"0"]) {
  36 + output = [[NSMutableString alloc] initWithString:[output substringFromIndex:1]];
  37 + }
  38 +
  39 + return output;
  40 +
  41 +}
  42 +
  43 ++ (NSString *)signvalue:(NSDictionary*)parameter {
  44 + //对所有传入参数按照字段名的 ASCII 码从小到大排序
  45 + NSArray *keyArr=[parameter allKeys];
  46 + NSArray *arr = [keyArr sortedArrayUsingSelector:@selector(compare:)];
  47 +
  48 + NSMutableString *str = [[NSMutableString alloc]init];
  49 + for (int i=0; i < arr.count; i++) {
  50 +
  51 + NSString *parameterString = parameter[[arr objectAtIndex:i]];
  52 + if (parameterString.length > 0) {
  53 + [str appendString:[NSString stringWithFormat:@"%@=%@&",[arr objectAtIndex:i],parameter[[arr objectAtIndex:i]]]];
  54 + }
  55 + }
  56 +
  57 + if (str.length > 0) {
  58 + [str deleteCharactersInRange:NSMakeRange(str.length-1, 1)];
  59 + }
  60 +
  61 + return str;
  62 +}
  63 +
  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 {
  91 +
  92 + NSString *uid = @"";
  93 +
  94 + NSUserDefaults *defauts = [NSUserDefaults standardUserDefaults];
  95 +
  96 + if ([defauts objectForKey:@"kCNLiveUserDefaultsUIDKey"]) {
  97 + uid = [[defauts objectForKey:@"kCNLiveUserDefaultsUIDKey"] copy];
  98 + return uid;
  99 + }
  100 + else {
  101 + NSString *stamp = [NSString stringWithFormat:@"%.3f", [date floatValue]];
  102 + stamp = [stamp stringByReplacingOccurrencesOfString:@"." withString:@""];
  103 +
  104 + NSString *idfv = [[[[UIDevice currentDevice] identifierForVendor] UUIDString] stringByReplacingOccurrencesOfString:@"-" withString:@""];
  105 + uid = [NSString stringWithFormat:@"%@_%@", idfv, stamp];
  106 +
  107 + [defauts setObject:uid forKey:@"kCNLiveUserDefaultsUIDKey"];
  108 + [defauts synchronize];
  109 +
  110 + }
  111 + return uid;
  112 +}
  113 +
  114 +//错误信息
  115 ++ (NSError *)customErrorWithResponseObject:(id)responseObject errorInfo:(NSString *)errorInfo {
  116 + //用于探针
  117 + NSString *defaultErrorInfo;
  118 + NSInteger errorCode = -1;
  119 + if (!responseObject[@"errorMessage"] || [self isEmptyString:responseObject[@"errorMessage"]]) {
  120 + defaultErrorInfo = errorInfo;
  121 + } else {
  122 + defaultErrorInfo = responseObject[@"errorMessage"];
  123 + errorCode = [responseObject[@"errorCode"] integerValue];
  124 + }
  125 +
  126 + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:errorCode userInfo:@{NSLocalizedDescriptionKey : defaultErrorInfo}];
  127 + return error;
  128 +}
  129 +
  130 +
  131 ++ (BOOL)isEmptyString:(NSString *)string {
  132 + if (!string || ![string isKindOfClass:[NSString class]] || string.length == 0 || [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length == 0) {
  133 + return YES;
  134 + }
  135 + return NO;
  136 +}
  137 +
  138 ++ (NSString *)getTimestamp{
  139 + NSInteger time = [[NSDate date] timeIntervalSince1970];
  140 + NSString *timestamp = [NSString stringWithFormat:@"%ld", (long)time];
  141 + return timestamp;
  142 +}
  143 +
  144 +@end
... ...
Example/CNLivePlayer.xcodeproj/project.pbxproj 0 → 100644
  1 +// !$*UTF8*$!
  2 +{
  3 + archiveVersion = 1;
  4 + classes = {
  5 + };
  6 + objectVersion = 46;
  7 + objects = {
  8 +
  9 +/* Begin PBXBuildFile section */
  10 + 086413BC22EAE229008713D3 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BB22EAE229008713D3 /* VideoToolbox.framework */; };
  11 + 086413BE22EAE23E008713D3 /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BD22EAE23E008713D3 /* libbz2.tbd */; };
  12 + 086413C022EAE24F008713D3 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BF22EAE24F008713D3 /* libz.tbd */; };
  13 + 086413C222EAE591008713D3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413C122EAE591008713D3 /* OpenGLES.framework */; };
  14 + 086413C422EAEC11008713D3 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413C322EAEC11008713D3 /* libstdc++.tbd */; };
  15 + 1D258610626B544AFEEFD2F9 /* Pods_CNLivePlayer_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E14DC7AF4B1116AA5BC01855 /* Pods_CNLivePlayer_Example.framework */; };
  16 + 2A57832D4B5A8EF9638641C3 /* Pods_CNLivePlayer_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDD4ACEE076815DE64A1FE2E /* Pods_CNLivePlayer_Tests.framework */; };
  17 + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
  18 + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
  19 + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
  20 + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; };
  21 + 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; };
  22 + 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */; };
  23 + 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* CNLiveViewController.m */; };
  24 + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; };
  25 + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
  26 + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
  27 + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
  28 + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
  29 + 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; };
  30 + 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; };
  31 + 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
  32 +/* End PBXBuildFile section */
  33 +
  34 +/* Begin PBXContainerItemProxy section */
  35 + 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = {
  36 + isa = PBXContainerItemProxy;
  37 + containerPortal = 6003F582195388D10070C39A /* Project object */;
  38 + proxyType = 1;
  39 + remoteGlobalIDString = 6003F589195388D20070C39A;
  40 + remoteInfo = CNLivePlayer;
  41 + };
  42 +/* End PBXContainerItemProxy section */
  43 +
  44 +/* Begin PBXFileReference section */
  45 + 086413BB22EAE229008713D3 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
  46 + 086413BD22EAE23E008713D3 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; };
  47 + 086413BF22EAE24F008713D3 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
  48 + 086413C122EAE591008713D3 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
  49 + 086413C322EAEC11008713D3 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
  50 + 17E088CE7F3FDB52D35B374B /* CNLivePlayer.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = CNLivePlayer.podspec; path = ../CNLivePlayer.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
  51 + 26B97BD3DF7A4A551798F5CA /* Pods-CNLivePlayer_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLivePlayer_Tests.release.xcconfig"; path = "Target Support Files/Pods-CNLivePlayer_Tests/Pods-CNLivePlayer_Tests.release.xcconfig"; sourceTree = "<group>"; };
  52 + 32AFD179FF73966F488CAFA0 /* Pods-CNLivePlayer_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLivePlayer_Example.debug.xcconfig"; path = "Target Support Files/Pods-CNLivePlayer_Example/Pods-CNLivePlayer_Example.debug.xcconfig"; sourceTree = "<group>"; };
  53 + 37981DDF2819BA9A67F2E1B6 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
  54 + 6003F58A195388D20070C39A /* CNLivePlayer_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CNLivePlayer_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
  55 + 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
  56 + 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
  57 + 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
  58 + 6003F595195388D20070C39A /* CNLivePlayer-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CNLivePlayer-Info.plist"; sourceTree = "<group>"; };
  59 + 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
  60 + 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
  61 + 6003F59B195388D20070C39A /* CNLivePlayer-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CNLivePlayer-Prefix.pch"; sourceTree = "<group>"; };
  62 + 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveAppDelegate.h; sourceTree = "<group>"; };
  63 + 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveAppDelegate.m; sourceTree = "<group>"; };
  64 + 6003F5A5195388D20070C39A /* CNLiveViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveViewController.h; sourceTree = "<group>"; };
  65 + 6003F5A6195388D20070C39A /* CNLiveViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveViewController.m; sourceTree = "<group>"; };
  66 + 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
  67 + 6003F5AE195388D20070C39A /* CNLivePlayer_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CNLivePlayer_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
  68 + 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
  69 + 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = "<group>"; };
  70 + 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
  71 + 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
  72 + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = "<group>"; };
  73 + 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
  74 + 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
  75 + 989389CB217D6D9AA21297F3 /* Pods-CNLivePlayer_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLivePlayer_Tests.debug.xcconfig"; path = "Target Support Files/Pods-CNLivePlayer_Tests/Pods-CNLivePlayer_Tests.debug.xcconfig"; sourceTree = "<group>"; };
  76 + A4C9006063170899C5349EDB /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
  77 + DDD4ACEE076815DE64A1FE2E /* Pods_CNLivePlayer_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLivePlayer_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  78 + E14DC7AF4B1116AA5BC01855 /* Pods_CNLivePlayer_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLivePlayer_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  79 + F70645D16D3AB5A2FC1ACE4F /* Pods-CNLivePlayer_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLivePlayer_Example.release.xcconfig"; path = "Target Support Files/Pods-CNLivePlayer_Example/Pods-CNLivePlayer_Example.release.xcconfig"; sourceTree = "<group>"; };
  80 +/* End PBXFileReference section */
  81 +
  82 +/* Begin PBXFrameworksBuildPhase section */
  83 + 6003F587195388D20070C39A /* Frameworks */ = {
  84 + isa = PBXFrameworksBuildPhase;
  85 + buildActionMask = 2147483647;
  86 + files = (
  87 + 086413C422EAEC11008713D3 /* libstdc++.tbd in Frameworks */,
  88 + 086413C222EAE591008713D3 /* OpenGLES.framework in Frameworks */,
  89 + 086413C022EAE24F008713D3 /* libz.tbd in Frameworks */,
  90 + 086413BE22EAE23E008713D3 /* libbz2.tbd in Frameworks */,
  91 + 086413BC22EAE229008713D3 /* VideoToolbox.framework in Frameworks */,
  92 + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */,
  93 + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */,
  94 + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */,
  95 + 1D258610626B544AFEEFD2F9 /* Pods_CNLivePlayer_Example.framework in Frameworks */,
  96 + );
  97 + runOnlyForDeploymentPostprocessing = 0;
  98 + };
  99 + 6003F5AB195388D20070C39A /* Frameworks */ = {
  100 + isa = PBXFrameworksBuildPhase;
  101 + buildActionMask = 2147483647;
  102 + files = (
  103 + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
  104 + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
  105 + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
  106 + 2A57832D4B5A8EF9638641C3 /* Pods_CNLivePlayer_Tests.framework in Frameworks */,
  107 + );
  108 + runOnlyForDeploymentPostprocessing = 0;
  109 + };
  110 +/* End PBXFrameworksBuildPhase section */
  111 +
  112 +/* Begin PBXGroup section */
  113 + 01F40873EC5EF29DDD824E4B /* Pods */ = {
  114 + isa = PBXGroup;
  115 + children = (
  116 + 32AFD179FF73966F488CAFA0 /* Pods-CNLivePlayer_Example.debug.xcconfig */,
  117 + F70645D16D3AB5A2FC1ACE4F /* Pods-CNLivePlayer_Example.release.xcconfig */,
  118 + 989389CB217D6D9AA21297F3 /* Pods-CNLivePlayer_Tests.debug.xcconfig */,
  119 + 26B97BD3DF7A4A551798F5CA /* Pods-CNLivePlayer_Tests.release.xcconfig */,
  120 + );
  121 + path = Pods;
  122 + sourceTree = "<group>";
  123 + };
  124 + 6003F581195388D10070C39A = {
  125 + isa = PBXGroup;
  126 + children = (
  127 + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
  128 + 6003F593195388D20070C39A /* Example for CNLivePlayer */,
  129 + 6003F5B5195388D20070C39A /* Tests */,
  130 + 6003F58C195388D20070C39A /* Frameworks */,
  131 + 6003F58B195388D20070C39A /* Products */,
  132 + 01F40873EC5EF29DDD824E4B /* Pods */,
  133 + );
  134 + sourceTree = "<group>";
  135 + };
  136 + 6003F58B195388D20070C39A /* Products */ = {
  137 + isa = PBXGroup;
  138 + children = (
  139 + 6003F58A195388D20070C39A /* CNLivePlayer_Example.app */,
  140 + 6003F5AE195388D20070C39A /* CNLivePlayer_Tests.xctest */,
  141 + );
  142 + name = Products;
  143 + sourceTree = "<group>";
  144 + };
  145 + 6003F58C195388D20070C39A /* Frameworks */ = {
  146 + isa = PBXGroup;
  147 + children = (
  148 + 086413C322EAEC11008713D3 /* libstdc++.tbd */,
  149 + 086413C122EAE591008713D3 /* OpenGLES.framework */,
  150 + 086413BF22EAE24F008713D3 /* libz.tbd */,
  151 + 086413BD22EAE23E008713D3 /* libbz2.tbd */,
  152 + 086413BB22EAE229008713D3 /* VideoToolbox.framework */,
  153 + 6003F58D195388D20070C39A /* Foundation.framework */,
  154 + 6003F58F195388D20070C39A /* CoreGraphics.framework */,
  155 + 6003F591195388D20070C39A /* UIKit.framework */,
  156 + 6003F5AF195388D20070C39A /* XCTest.framework */,
  157 + E14DC7AF4B1116AA5BC01855 /* Pods_CNLivePlayer_Example.framework */,
  158 + DDD4ACEE076815DE64A1FE2E /* Pods_CNLivePlayer_Tests.framework */,
  159 + );
  160 + name = Frameworks;
  161 + sourceTree = "<group>";
  162 + };
  163 + 6003F593195388D20070C39A /* Example for CNLivePlayer */ = {
  164 + isa = PBXGroup;
  165 + children = (
  166 + 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */,
  167 + 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */,
  168 + 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */,
  169 + 6003F5A5195388D20070C39A /* CNLiveViewController.h */,
  170 + 6003F5A6195388D20070C39A /* CNLiveViewController.m */,
  171 + 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */,
  172 + 6003F5A8195388D20070C39A /* Images.xcassets */,
  173 + 6003F594195388D20070C39A /* Supporting Files */,
  174 + );
  175 + name = "Example for CNLivePlayer";
  176 + path = CNLivePlayer;
  177 + sourceTree = "<group>";
  178 + };
  179 + 6003F594195388D20070C39A /* Supporting Files */ = {
  180 + isa = PBXGroup;
  181 + children = (
  182 + 6003F595195388D20070C39A /* CNLivePlayer-Info.plist */,
  183 + 6003F596195388D20070C39A /* InfoPlist.strings */,
  184 + 6003F599195388D20070C39A /* main.m */,
  185 + 6003F59B195388D20070C39A /* CNLivePlayer-Prefix.pch */,
  186 + );
  187 + name = "Supporting Files";
  188 + sourceTree = "<group>";
  189 + };
  190 + 6003F5B5195388D20070C39A /* Tests */ = {
  191 + isa = PBXGroup;
  192 + children = (
  193 + 6003F5BB195388D20070C39A /* Tests.m */,
  194 + 6003F5B6195388D20070C39A /* Supporting Files */,
  195 + );
  196 + path = Tests;
  197 + sourceTree = "<group>";
  198 + };
  199 + 6003F5B6195388D20070C39A /* Supporting Files */ = {
  200 + isa = PBXGroup;
  201 + children = (
  202 + 6003F5B7195388D20070C39A /* Tests-Info.plist */,
  203 + 6003F5B8195388D20070C39A /* InfoPlist.strings */,
  204 + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
  205 + );
  206 + name = "Supporting Files";
  207 + sourceTree = "<group>";
  208 + };
  209 + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
  210 + isa = PBXGroup;
  211 + children = (
  212 + 17E088CE7F3FDB52D35B374B /* CNLivePlayer.podspec */,
  213 + A4C9006063170899C5349EDB /* README.md */,
  214 + 37981DDF2819BA9A67F2E1B6 /* LICENSE */,
  215 + );
  216 + name = "Podspec Metadata";
  217 + sourceTree = "<group>";
  218 + };
  219 +/* End PBXGroup section */
  220 +
  221 +/* Begin PBXNativeTarget section */
  222 + 6003F589195388D20070C39A /* CNLivePlayer_Example */ = {
  223 + isa = PBXNativeTarget;
  224 + buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLivePlayer_Example" */;
  225 + buildPhases = (
  226 + 5113AD1A1A6CE60F5F11067D /* [CP] Check Pods Manifest.lock */,
  227 + 6003F586195388D20070C39A /* Sources */,
  228 + 6003F587195388D20070C39A /* Frameworks */,
  229 + 6003F588195388D20070C39A /* Resources */,
  230 + A3F196DAAD60775729A3E44B /* [CP] Embed Pods Frameworks */,
  231 + );
  232 + buildRules = (
  233 + );
  234 + dependencies = (
  235 + );
  236 + name = CNLivePlayer_Example;
  237 + productName = CNLivePlayer;
  238 + productReference = 6003F58A195388D20070C39A /* CNLivePlayer_Example.app */;
  239 + productType = "com.apple.product-type.application";
  240 + };
  241 + 6003F5AD195388D20070C39A /* CNLivePlayer_Tests */ = {
  242 + isa = PBXNativeTarget;
  243 + buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLivePlayer_Tests" */;
  244 + buildPhases = (
  245 + F2F7E26A364E397E51274BD5 /* [CP] Check Pods Manifest.lock */,
  246 + 6003F5AA195388D20070C39A /* Sources */,
  247 + 6003F5AB195388D20070C39A /* Frameworks */,
  248 + 6003F5AC195388D20070C39A /* Resources */,
  249 + );
  250 + buildRules = (
  251 + );
  252 + dependencies = (
  253 + 6003F5B4195388D20070C39A /* PBXTargetDependency */,
  254 + );
  255 + name = CNLivePlayer_Tests;
  256 + productName = CNLivePlayerTests;
  257 + productReference = 6003F5AE195388D20070C39A /* CNLivePlayer_Tests.xctest */;
  258 + productType = "com.apple.product-type.bundle.unit-test";
  259 + };
  260 +/* End PBXNativeTarget section */
  261 +
  262 +/* Begin PBXProject section */
  263 + 6003F582195388D10070C39A /* Project object */ = {
  264 + isa = PBXProject;
  265 + attributes = {
  266 + CLASSPREFIX = CNLive;
  267 + LastUpgradeCheck = 0720;
  268 + ORGANIZATIONNAME = "153993236@qq.com";
  269 + TargetAttributes = {
  270 + 6003F589195388D20070C39A = {
  271 + DevelopmentTeam = 94X49GG3ZW;
  272 + };
  273 + 6003F5AD195388D20070C39A = {
  274 + TestTargetID = 6003F589195388D20070C39A;
  275 + };
  276 + };
  277 + };
  278 + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "CNLivePlayer" */;
  279 + compatibilityVersion = "Xcode 3.2";
  280 + developmentRegion = English;
  281 + hasScannedForEncodings = 0;
  282 + knownRegions = (
  283 + en,
  284 + Base,
  285 + );
  286 + mainGroup = 6003F581195388D10070C39A;
  287 + productRefGroup = 6003F58B195388D20070C39A /* Products */;
  288 + projectDirPath = "";
  289 + projectRoot = "";
  290 + targets = (
  291 + 6003F589195388D20070C39A /* CNLivePlayer_Example */,
  292 + 6003F5AD195388D20070C39A /* CNLivePlayer_Tests */,
  293 + );
  294 + };
  295 +/* End PBXProject section */
  296 +
  297 +/* Begin PBXResourcesBuildPhase section */
  298 + 6003F588195388D20070C39A /* Resources */ = {
  299 + isa = PBXResourcesBuildPhase;
  300 + buildActionMask = 2147483647;
  301 + files = (
  302 + 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */,
  303 + 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
  304 + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
  305 + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
  306 + );
  307 + runOnlyForDeploymentPostprocessing = 0;
  308 + };
  309 + 6003F5AC195388D20070C39A /* Resources */ = {
  310 + isa = PBXResourcesBuildPhase;
  311 + buildActionMask = 2147483647;
  312 + files = (
  313 + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
  314 + );
  315 + runOnlyForDeploymentPostprocessing = 0;
  316 + };
  317 +/* End PBXResourcesBuildPhase section */
  318 +
  319 +/* Begin PBXShellScriptBuildPhase section */
  320 + 5113AD1A1A6CE60F5F11067D /* [CP] Check Pods Manifest.lock */ = {
  321 + isa = PBXShellScriptBuildPhase;
  322 + buildActionMask = 2147483647;
  323 + files = (
  324 + );
  325 + inputFileListPaths = (
  326 + );
  327 + inputPaths = (
  328 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  329 + "${PODS_ROOT}/Manifest.lock",
  330 + );
  331 + name = "[CP] Check Pods Manifest.lock";
  332 + outputFileListPaths = (
  333 + );
  334 + outputPaths = (
  335 + "$(DERIVED_FILE_DIR)/Pods-CNLivePlayer_Example-checkManifestLockResult.txt",
  336 + );
  337 + runOnlyForDeploymentPostprocessing = 0;
  338 + shellPath = /bin/sh;
  339 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  340 + showEnvVarsInLog = 0;
  341 + };
  342 + A3F196DAAD60775729A3E44B /* [CP] Embed Pods Frameworks */ = {
  343 + isa = PBXShellScriptBuildPhase;
  344 + buildActionMask = 2147483647;
  345 + files = (
  346 + );
  347 + inputFileListPaths = (
  348 + );
  349 + inputPaths = (
  350 + "${PODS_ROOT}/Target Support Files/Pods-CNLivePlayer_Example/Pods-CNLivePlayer_Example-frameworks.sh",
  351 + "${BUILT_PRODUCTS_DIR}/CNLivePlayer/CNLivePlayer.framework",
  352 + "${BUILT_PRODUCTS_DIR}/GPUImage/GPUImage.framework",
  353 + "${BUILT_PRODUCTS_DIR}/YYCache/YYCache.framework",
  354 + "${BUILT_PRODUCTS_DIR}/libksygpulive/libksygpulive.framework",
  355 + );
  356 + name = "[CP] Embed Pods Frameworks";
  357 + outputFileListPaths = (
  358 + );
  359 + outputPaths = (
  360 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLivePlayer.framework",
  361 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GPUImage.framework",
  362 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYCache.framework",
  363 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libksygpulive.framework",
  364 + );
  365 + runOnlyForDeploymentPostprocessing = 0;
  366 + shellPath = /bin/sh;
  367 + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-CNLivePlayer_Example/Pods-CNLivePlayer_Example-frameworks.sh\"\n";
  368 + showEnvVarsInLog = 0;
  369 + };
  370 + F2F7E26A364E397E51274BD5 /* [CP] Check Pods Manifest.lock */ = {
  371 + isa = PBXShellScriptBuildPhase;
  372 + buildActionMask = 2147483647;
  373 + files = (
  374 + );
  375 + inputFileListPaths = (
  376 + );
  377 + inputPaths = (
  378 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  379 + "${PODS_ROOT}/Manifest.lock",
  380 + );
  381 + name = "[CP] Check Pods Manifest.lock";
  382 + outputFileListPaths = (
  383 + );
  384 + outputPaths = (
  385 + "$(DERIVED_FILE_DIR)/Pods-CNLivePlayer_Tests-checkManifestLockResult.txt",
  386 + );
  387 + runOnlyForDeploymentPostprocessing = 0;
  388 + shellPath = /bin/sh;
  389 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  390 + showEnvVarsInLog = 0;
  391 + };
  392 +/* End PBXShellScriptBuildPhase section */
  393 +
  394 +/* Begin PBXSourcesBuildPhase section */
  395 + 6003F586195388D20070C39A /* Sources */ = {
  396 + isa = PBXSourcesBuildPhase;
  397 + buildActionMask = 2147483647;
  398 + files = (
  399 + 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */,
  400 + 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */,
  401 + 6003F59A195388D20070C39A /* main.m in Sources */,
  402 + );
  403 + runOnlyForDeploymentPostprocessing = 0;
  404 + };
  405 + 6003F5AA195388D20070C39A /* Sources */ = {
  406 + isa = PBXSourcesBuildPhase;
  407 + buildActionMask = 2147483647;
  408 + files = (
  409 + 6003F5BC195388D20070C39A /* Tests.m in Sources */,
  410 + );
  411 + runOnlyForDeploymentPostprocessing = 0;
  412 + };
  413 +/* End PBXSourcesBuildPhase section */
  414 +
  415 +/* Begin PBXTargetDependency section */
  416 + 6003F5B4195388D20070C39A /* PBXTargetDependency */ = {
  417 + isa = PBXTargetDependency;
  418 + target = 6003F589195388D20070C39A /* CNLivePlayer_Example */;
  419 + targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */;
  420 + };
  421 +/* End PBXTargetDependency section */
  422 +
  423 +/* Begin PBXVariantGroup section */
  424 + 6003F596195388D20070C39A /* InfoPlist.strings */ = {
  425 + isa = PBXVariantGroup;
  426 + children = (
  427 + 6003F597195388D20070C39A /* en */,
  428 + );
  429 + name = InfoPlist.strings;
  430 + sourceTree = "<group>";
  431 + };
  432 + 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
  433 + isa = PBXVariantGroup;
  434 + children = (
  435 + 6003F5B9195388D20070C39A /* en */,
  436 + );
  437 + name = InfoPlist.strings;
  438 + sourceTree = "<group>";
  439 + };
  440 + 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = {
  441 + isa = PBXVariantGroup;
  442 + children = (
  443 + 71719F9E1E33DC2100824A3D /* Base */,
  444 + );
  445 + name = LaunchScreen.storyboard;
  446 + sourceTree = "<group>";
  447 + };
  448 +/* End PBXVariantGroup section */
  449 +
  450 +/* Begin XCBuildConfiguration section */
  451 + 6003F5BD195388D20070C39A /* Debug */ = {
  452 + isa = XCBuildConfiguration;
  453 + buildSettings = {
  454 + ALWAYS_SEARCH_USER_PATHS = NO;
  455 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  456 + CLANG_CXX_LIBRARY = "libc++";
  457 + CLANG_ENABLE_MODULES = YES;
  458 + CLANG_ENABLE_OBJC_ARC = YES;
  459 + CLANG_WARN_BOOL_CONVERSION = YES;
  460 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  461 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  462 + CLANG_WARN_EMPTY_BODY = YES;
  463 + CLANG_WARN_ENUM_CONVERSION = YES;
  464 + CLANG_WARN_INT_CONVERSION = YES;
  465 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  466 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  467 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  468 + COPY_PHASE_STRIP = NO;
  469 + ENABLE_TESTABILITY = YES;
  470 + GCC_C_LANGUAGE_STANDARD = gnu99;
  471 + GCC_DYNAMIC_NO_PIC = NO;
  472 + GCC_OPTIMIZATION_LEVEL = 0;
  473 + GCC_PREPROCESSOR_DEFINITIONS = (
  474 + "DEBUG=1",
  475 + "$(inherited)",
  476 + );
  477 + GCC_SYMBOLS_PRIVATE_EXTERN = NO;
  478 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  479 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  480 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  481 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  482 + GCC_WARN_UNUSED_FUNCTION = YES;
  483 + GCC_WARN_UNUSED_VARIABLE = YES;
  484 + IPHONEOS_DEPLOYMENT_TARGET = 9.3;
  485 + ONLY_ACTIVE_ARCH = YES;
  486 + SDKROOT = iphoneos;
  487 + TARGETED_DEVICE_FAMILY = "1,2";
  488 + };
  489 + name = Debug;
  490 + };
  491 + 6003F5BE195388D20070C39A /* Release */ = {
  492 + isa = XCBuildConfiguration;
  493 + buildSettings = {
  494 + ALWAYS_SEARCH_USER_PATHS = NO;
  495 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  496 + CLANG_CXX_LIBRARY = "libc++";
  497 + CLANG_ENABLE_MODULES = YES;
  498 + CLANG_ENABLE_OBJC_ARC = YES;
  499 + CLANG_WARN_BOOL_CONVERSION = YES;
  500 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  501 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  502 + CLANG_WARN_EMPTY_BODY = YES;
  503 + CLANG_WARN_ENUM_CONVERSION = YES;
  504 + CLANG_WARN_INT_CONVERSION = YES;
  505 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  506 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  507 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  508 + COPY_PHASE_STRIP = YES;
  509 + ENABLE_NS_ASSERTIONS = NO;
  510 + GCC_C_LANGUAGE_STANDARD = gnu99;
  511 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  512 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  513 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  514 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  515 + GCC_WARN_UNUSED_FUNCTION = YES;
  516 + GCC_WARN_UNUSED_VARIABLE = YES;
  517 + IPHONEOS_DEPLOYMENT_TARGET = 9.3;
  518 + SDKROOT = iphoneos;
  519 + TARGETED_DEVICE_FAMILY = "1,2";
  520 + VALIDATE_PRODUCT = YES;
  521 + };
  522 + name = Release;
  523 + };
  524 + 6003F5C0195388D20070C39A /* Debug */ = {
  525 + isa = XCBuildConfiguration;
  526 + baseConfigurationReference = 32AFD179FF73966F488CAFA0 /* Pods-CNLivePlayer_Example.debug.xcconfig */;
  527 + buildSettings = {
  528 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  529 + DEVELOPMENT_TEAM = 94X49GG3ZW;
  530 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  531 + GCC_PREFIX_HEADER = "CNLivePlayer/CNLivePlayer-Prefix.pch";
  532 + INFOPLIST_FILE = "CNLivePlayer/CNLivePlayer-Info.plist";
  533 + MODULE_NAME = ExampleApp;
  534 + PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.video;
  535 + PRODUCT_NAME = "$(TARGET_NAME)";
  536 + SWIFT_VERSION = 4.0;
  537 + WRAPPER_EXTENSION = app;
  538 + };
  539 + name = Debug;
  540 + };
  541 + 6003F5C1195388D20070C39A /* Release */ = {
  542 + isa = XCBuildConfiguration;
  543 + baseConfigurationReference = F70645D16D3AB5A2FC1ACE4F /* Pods-CNLivePlayer_Example.release.xcconfig */;
  544 + buildSettings = {
  545 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  546 + DEVELOPMENT_TEAM = 94X49GG3ZW;
  547 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  548 + GCC_PREFIX_HEADER = "CNLivePlayer/CNLivePlayer-Prefix.pch";
  549 + INFOPLIST_FILE = "CNLivePlayer/CNLivePlayer-Info.plist";
  550 + MODULE_NAME = ExampleApp;
  551 + PRODUCT_BUNDLE_IDENTIFIER = com.cnlive.video;
  552 + PRODUCT_NAME = "$(TARGET_NAME)";
  553 + SWIFT_VERSION = 4.0;
  554 + WRAPPER_EXTENSION = app;
  555 + };
  556 + name = Release;
  557 + };
  558 + 6003F5C3195388D20070C39A /* Debug */ = {
  559 + isa = XCBuildConfiguration;
  560 + baseConfigurationReference = 989389CB217D6D9AA21297F3 /* Pods-CNLivePlayer_Tests.debug.xcconfig */;
  561 + buildSettings = {
  562 + BUNDLE_LOADER = "$(TEST_HOST)";
  563 + FRAMEWORK_SEARCH_PATHS = (
  564 + "$(PLATFORM_DIR)/Developer/Library/Frameworks",
  565 + "$(inherited)",
  566 + "$(DEVELOPER_FRAMEWORKS_DIR)",
  567 + );
  568 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  569 + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
  570 + GCC_PREPROCESSOR_DEFINITIONS = (
  571 + "DEBUG=1",
  572 + "$(inherited)",
  573 + );
  574 + INFOPLIST_FILE = "Tests/Tests-Info.plist";
  575 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  576 + PRODUCT_NAME = "$(TARGET_NAME)";
  577 + SWIFT_VERSION = 4.0;
  578 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CNLivePlayer_Example.app/CNLivePlayer_Example";
  579 + WRAPPER_EXTENSION = xctest;
  580 + };
  581 + name = Debug;
  582 + };
  583 + 6003F5C4195388D20070C39A /* Release */ = {
  584 + isa = XCBuildConfiguration;
  585 + baseConfigurationReference = 26B97BD3DF7A4A551798F5CA /* Pods-CNLivePlayer_Tests.release.xcconfig */;
  586 + buildSettings = {
  587 + BUNDLE_LOADER = "$(TEST_HOST)";
  588 + FRAMEWORK_SEARCH_PATHS = (
  589 + "$(PLATFORM_DIR)/Developer/Library/Frameworks",
  590 + "$(inherited)",
  591 + "$(DEVELOPER_FRAMEWORKS_DIR)",
  592 + );
  593 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  594 + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
  595 + INFOPLIST_FILE = "Tests/Tests-Info.plist";
  596 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  597 + PRODUCT_NAME = "$(TARGET_NAME)";
  598 + SWIFT_VERSION = 4.0;
  599 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CNLivePlayer_Example.app/CNLivePlayer_Example";
  600 + WRAPPER_EXTENSION = xctest;
  601 + };
  602 + name = Release;
  603 + };
  604 +/* End XCBuildConfiguration section */
  605 +
  606 +/* Begin XCConfigurationList section */
  607 + 6003F585195388D10070C39A /* Build configuration list for PBXProject "CNLivePlayer" */ = {
  608 + isa = XCConfigurationList;
  609 + buildConfigurations = (
  610 + 6003F5BD195388D20070C39A /* Debug */,
  611 + 6003F5BE195388D20070C39A /* Release */,
  612 + );
  613 + defaultConfigurationIsVisible = 0;
  614 + defaultConfigurationName = Release;
  615 + };
  616 + 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLivePlayer_Example" */ = {
  617 + isa = XCConfigurationList;
  618 + buildConfigurations = (
  619 + 6003F5C0195388D20070C39A /* Debug */,
  620 + 6003F5C1195388D20070C39A /* Release */,
  621 + );
  622 + defaultConfigurationIsVisible = 0;
  623 + defaultConfigurationName = Release;
  624 + };
  625 + 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLivePlayer_Tests" */ = {
  626 + isa = XCConfigurationList;
  627 + buildConfigurations = (
  628 + 6003F5C3195388D20070C39A /* Debug */,
  629 + 6003F5C4195388D20070C39A /* Release */,
  630 + );
  631 + defaultConfigurationIsVisible = 0;
  632 + defaultConfigurationName = Release;
  633 + };
  634 +/* End XCConfigurationList section */
  635 + };
  636 + rootObject = 6003F582195388D10070C39A /* Project object */;
  637 +}
... ...
Example/CNLivePlayer.xcodeproj/xcshareddata/xcschemes/CNLivePlayer-Example.xcscheme 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Scheme
  3 + LastUpgradeVersion = "0720"
  4 + version = "1.3">
  5 + <BuildAction
  6 + parallelizeBuildables = "YES"
  7 + buildImplicitDependencies = "YES">
  8 + <BuildActionEntries>
  9 + <BuildActionEntry
  10 + buildForTesting = "YES"
  11 + buildForRunning = "YES"
  12 + buildForProfiling = "YES"
  13 + buildForArchiving = "YES"
  14 + buildForAnalyzing = "YES">
  15 + <BuildableReference
  16 + BuildableIdentifier = "primary"
  17 + BlueprintIdentifier = "6003F589195388D20070C39A"
  18 + BuildableName = "CNLivePlayer_Example.app"
  19 + BlueprintName = "CNLivePlayer_Example"
  20 + ReferencedContainer = "container:CNLivePlayer.xcodeproj">
  21 + </BuildableReference>
  22 + </BuildActionEntry>
  23 + </BuildActionEntries>
  24 + </BuildAction>
  25 + <TestAction
  26 + buildConfiguration = "Debug"
  27 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  28 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  29 + shouldUseLaunchSchemeArgsEnv = "YES">
  30 + <Testables>
  31 + <TestableReference
  32 + skipped = "NO">
  33 + <BuildableReference
  34 + BuildableIdentifier = "primary"
  35 + BlueprintIdentifier = "6003F5AD195388D20070C39A"
  36 + BuildableName = "CNLivePlayer_Tests.xctest"
  37 + BlueprintName = "CNLivePlayer_Tests"
  38 + ReferencedContainer = "container:CNLivePlayer.xcodeproj">
  39 + </BuildableReference>
  40 + </TestableReference>
  41 + </Testables>
  42 + <MacroExpansion>
  43 + <BuildableReference
  44 + BuildableIdentifier = "primary"
  45 + BlueprintIdentifier = "6003F589195388D20070C39A"
  46 + BuildableName = "CNLivePlayer_Example.app"
  47 + BlueprintName = "CNLivePlayer_Example"
  48 + ReferencedContainer = "container:CNLivePlayer.xcodeproj">
  49 + </BuildableReference>
  50 + </MacroExpansion>
  51 + <AdditionalOptions>
  52 + </AdditionalOptions>
  53 + </TestAction>
  54 + <LaunchAction
  55 + buildConfiguration = "Debug"
  56 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  57 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  58 + launchStyle = "0"
  59 + useCustomWorkingDirectory = "NO"
  60 + ignoresPersistentStateOnLaunch = "NO"
  61 + debugDocumentVersioning = "YES"
  62 + debugServiceExtension = "internal"
  63 + allowLocationSimulation = "YES">
  64 + <BuildableProductRunnable
  65 + runnableDebuggingMode = "0">
  66 + <BuildableReference
  67 + BuildableIdentifier = "primary"
  68 + BlueprintIdentifier = "6003F589195388D20070C39A"
  69 + BuildableName = "CNLivePlayer_Example.app"
  70 + BlueprintName = "CNLivePlayer_Example"
  71 + ReferencedContainer = "container:CNLivePlayer.xcodeproj">
  72 + </BuildableReference>
  73 + </BuildableProductRunnable>
  74 + <AdditionalOptions>
  75 + </AdditionalOptions>
  76 + </LaunchAction>
  77 + <ProfileAction
  78 + buildConfiguration = "Release"
  79 + shouldUseLaunchSchemeArgsEnv = "YES"
  80 + savedToolIdentifier = ""
  81 + useCustomWorkingDirectory = "NO"
  82 + debugDocumentVersioning = "YES">
  83 + <BuildableProductRunnable
  84 + runnableDebuggingMode = "0">
  85 + <BuildableReference
  86 + BuildableIdentifier = "primary"
  87 + BlueprintIdentifier = "6003F589195388D20070C39A"
  88 + BuildableName = "CNLivePlayer_Example.app"
  89 + BlueprintName = "CNLivePlayer_Example"
  90 + ReferencedContainer = "container:CNLivePlayer.xcodeproj">
  91 + </BuildableReference>
  92 + </BuildableProductRunnable>
  93 + </ProfileAction>
  94 + <AnalyzeAction
  95 + buildConfiguration = "Debug">
  96 + </AnalyzeAction>
  97 + <ArchiveAction
  98 + buildConfiguration = "Release"
  99 + revealArchiveInOrganizer = "YES">
  100 + </ArchiveAction>
  101 +</Scheme>
... ...
Example/CNLivePlayer/Base.lproj/LaunchScreen.storyboard 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
  3 + <device id="retina4_7" orientation="portrait">
  4 + <adaptation id="fullscreen"/>
  5 + </device>
  6 + <dependencies>
  7 + <deployment identifier="iOS"/>
  8 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
  9 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  10 + </dependencies>
  11 + <scenes>
  12 + <!--View Controller-->
  13 + <scene sceneID="EHf-IW-A2E">
  14 + <objects>
  15 + <viewController id="01J-lp-oVM" sceneMemberID="viewController">
  16 + <layoutGuides>
  17 + <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
  18 + <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
  19 + </layoutGuides>
  20 + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
  21 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  22 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  23 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  24 + </view>
  25 + </viewController>
  26 + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
  27 + </objects>
  28 + <point key="canvasLocation" x="53" y="375"/>
  29 + </scene>
  30 + </scenes>
  31 +</document>
... ...
Example/CNLivePlayer/Base.lproj/Main.storyboard 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="whP-gf-Uak">
  3 + <device id="retina4_7" orientation="portrait">
  4 + <adaptation id="fullscreen"/>
  5 + </device>
  6 + <dependencies>
  7 + <deployment identifier="iOS"/>
  8 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
  9 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  10 + </dependencies>
  11 + <scenes>
  12 + <!--View Controller-->
  13 + <scene sceneID="wQg-tq-qST">
  14 + <objects>
  15 + <viewController id="whP-gf-Uak" customClass="CNLiveViewController" sceneMemberID="viewController">
  16 + <layoutGuides>
  17 + <viewControllerLayoutGuide type="top" id="uEw-UM-LJ8"/>
  18 + <viewControllerLayoutGuide type="bottom" id="Mvr-aV-6Um"/>
  19 + </layoutGuides>
  20 + <view key="view" contentMode="scaleToFill" id="TpU-gO-2f1">
  21 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  22 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  23 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  24 + </view>
  25 + </viewController>
  26 + <placeholder placeholderIdentifier="IBFirstResponder" id="tc2-Qw-aMS" userLabel="First Responder" sceneMemberID="firstResponder"/>
  27 + </objects>
  28 + <point key="canvasLocation" x="305" y="433"/>
  29 + </scene>
  30 + </scenes>
  31 +</document>
... ...
Example/CNLivePlayer/CNLiveAppDelegate.h 0 → 100644
  1 +//
  2 +// CNLiveAppDelegate.h
  3 +// CNLivePlayer
  4 +//
  5 +// Created by 153993236@qq.com on 07/26/2019.
  6 +// Copyright (c) 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +
  11 +@interface CNLiveAppDelegate : UIResponder <UIApplicationDelegate>
  12 +
  13 +@property (strong, nonatomic) UIWindow *window;
  14 +
  15 +@end
... ...
Example/CNLivePlayer/CNLiveAppDelegate.m 0 → 100644
  1 +//
  2 +// CNLiveAppDelegate.m
  3 +// CNLivePlayer
  4 +//
  5 +// Created by 153993236@qq.com on 07/26/2019.
  6 +// Copyright (c) 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveAppDelegate.h"
  10 +#import "CNLivePlayerManager.h"
  11 +
  12 +#define KAppId @"60_irn9edco29"
  13 +#define KAppKey @"69fe70bda67e059286ad509d9f5377f815955645b52f94"
  14 +#define bundleID @"com.cnlive.video"
  15 +
  16 +@implementation CNLiveAppDelegate
  17 +
  18 +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  19 +{
  20 + // Override point for customization after application launch.
  21 + [CNLivePlayerManager setAppId:KAppId appKey:KAppKey isTestEnvironment:YES];
  22 +
  23 + return YES;
  24 +}
  25 +
  26 +- (void)applicationWillResignActive:(UIApplication *)application
  27 +{
  28 + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
  29 + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
  30 +}
  31 +
  32 +- (void)applicationDidEnterBackground:(UIApplication *)application
  33 +{
  34 + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
  35 + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  36 +}
  37 +
  38 +- (void)applicationWillEnterForeground:(UIApplication *)application
  39 +{
  40 + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
  41 +}
  42 +
  43 +- (void)applicationDidBecomeActive:(UIApplication *)application
  44 +{
  45 + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
  46 +}
  47 +
  48 +- (void)applicationWillTerminate:(UIApplication *)application
  49 +{
  50 + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
  51 +}
  52 +
  53 +@end
... ...
Example/CNLivePlayer/CNLivePlayer-Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleDisplayName</key>
  8 + <string>${PRODUCT_NAME}</string>
  9 + <key>CFBundleExecutable</key>
  10 + <string>${EXECUTABLE_NAME}</string>
  11 + <key>CFBundleIdentifier</key>
  12 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  13 + <key>CFBundleInfoDictionaryVersion</key>
  14 + <string>6.0</string>
  15 + <key>CFBundleName</key>
  16 + <string>${PRODUCT_NAME}</string>
  17 + <key>CFBundlePackageType</key>
  18 + <string>APPL</string>
  19 + <key>CFBundleShortVersionString</key>
  20 + <string>1.0</string>
  21 + <key>CFBundleSignature</key>
  22 + <string>????</string>
  23 + <key>CFBundleVersion</key>
  24 + <string>1.0</string>
  25 + <key>LSRequiresIPhoneOS</key>
  26 + <true/>
  27 + <key>NSAppTransportSecurity</key>
  28 + <dict>
  29 + <key>NSAllowsArbitraryLoads</key>
  30 + <true/>
  31 + </dict>
  32 + <key>UILaunchStoryboardName</key>
  33 + <string>LaunchScreen</string>
  34 + <key>UIMainStoryboardFile</key>
  35 + <string>Main</string>
  36 + <key>UIRequiredDeviceCapabilities</key>
  37 + <array>
  38 + <string>armv7</string>
  39 + </array>
  40 + <key>UISupportedInterfaceOrientations</key>
  41 + <array>
  42 + <string>UIInterfaceOrientationPortrait</string>
  43 + <string>UIInterfaceOrientationLandscapeLeft</string>
  44 + <string>UIInterfaceOrientationLandscapeRight</string>
  45 + </array>
  46 + <key>UISupportedInterfaceOrientations~ipad</key>
  47 + <array>
  48 + <string>UIInterfaceOrientationPortrait</string>
  49 + <string>UIInterfaceOrientationPortraitUpsideDown</string>
  50 + <string>UIInterfaceOrientationLandscapeLeft</string>
  51 + <string>UIInterfaceOrientationLandscapeRight</string>
  52 + </array>
  53 +</dict>
  54 +</plist>
... ...
Example/CNLivePlayer/CNLivePlayer-Prefix.pch 0 → 100644
  1 +//
  2 +// Prefix header
  3 +//
  4 +// The contents of this file are implicitly included at the beginning of every source file.
  5 +//
  6 +
  7 +#import <Availability.h>
  8 +
  9 +#ifndef __IPHONE_5_0
  10 +#warning "This project uses features only available in iOS SDK 5.0 and later."
  11 +#endif
  12 +
  13 +#ifdef __OBJC__
  14 + @import UIKit;
  15 + @import Foundation;
  16 +#endif
... ...
Example/CNLivePlayer/CNLiveViewController.h 0 → 100644
  1 +//
  2 +// CNLiveViewController.h
  3 +// CNLivePlayer
  4 +//
  5 +// Created by 153993236@qq.com on 07/26/2019.
  6 +// Copyright (c) 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +
  11 +@interface CNLiveViewController : UIViewController
  12 +
  13 +@end
... ...
Example/CNLivePlayer/CNLiveViewController.m 0 → 100644
  1 +//
  2 +// CNLiveViewController.m
  3 +// CNLivePlayer
  4 +//
  5 +// Created by 153993236@qq.com on 07/26/2019.
  6 +// Copyright (c) 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveViewController.h"
  10 +#import "CNLivePlayer.h"
  11 +#import <GPUImage/GPUImage.h>
  12 +#import <libksygpulive/KSYGPUStreamerKit.h>
  13 +#import <libksygpulive/KSYMoviePlayerController.h>
  14 +
  15 +@interface CNLiveViewController ()
  16 +@property (nonatomic, strong) CNLivePlayer *player;
  17 +
  18 +@end
  19 +
  20 +@implementation CNLiveViewController
  21 +
  22 +- (void)viewDidLoad
  23 +{
  24 + [super viewDidLoad];
  25 + // Do any additional setup after loading the view, typically from a nib.
  26 + _player = [[CNLivePlayer alloc]initVodPlayerWithVideoId:@"82_c8ff347048414b7295cef882f8361073" authSuccess:^{
  27 + NSLog(@"---------------初始化播放器成功---------------");
  28 + _player.view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width*9/16.0);
  29 + [_player prepareToPlay];
  30 + [self.view addSubview:_player.view];
  31 + } authFailed:^(NSDictionary * _Nonnull errorInfo) {
  32 + NSLog(@"%@", errorInfo);
  33 +
  34 + }];
  35 +
  36 +// KSYMoviePlayerController *player = [[KSYMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:@"http://wideo02.cnlive.com/video/data1/2017/0423/206473/800/c8ff347048414b7295cef882f8361073_206473_800.m3u8"]];
  37 +// player.view.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.width*9/16.0);
  38 +// player.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
  39 +// [player prepareToPlay];
  40 +// [self.view addSubview:player.view];
  41 +
  42 +}
  43 +
  44 +- (void)didReceiveMemoryWarning
  45 +{
  46 + [super didReceiveMemoryWarning];
  47 + // Dispose of any resources that can be recreated.
  48 +}
  49 +
  50 +@end
... ...
Example/CNLivePlayer/Images.xcassets/AppIcon.appiconset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "iphone",
  5 + "size" : "20x20",
  6 + "scale" : "2x"
  7 + },
  8 + {
  9 + "idiom" : "iphone",
  10 + "size" : "20x20",
  11 + "scale" : "3x"
  12 + },
  13 + {
  14 + "idiom" : "iphone",
  15 + "size" : "29x29",
  16 + "scale" : "2x"
  17 + },
  18 + {
  19 + "idiom" : "iphone",
  20 + "size" : "29x29",
  21 + "scale" : "3x"
  22 + },
  23 + {
  24 + "idiom" : "iphone",
  25 + "size" : "40x40",
  26 + "scale" : "2x"
  27 + },
  28 + {
  29 + "idiom" : "iphone",
  30 + "size" : "40x40",
  31 + "scale" : "3x"
  32 + },
  33 + {
  34 + "idiom" : "iphone",
  35 + "size" : "60x60",
  36 + "scale" : "2x"
  37 + },
  38 + {
  39 + "idiom" : "iphone",
  40 + "size" : "60x60",
  41 + "scale" : "3x"
  42 + },
  43 + {
  44 + "idiom" : "ipad",
  45 + "size" : "20x20",
  46 + "scale" : "1x"
  47 + },
  48 + {
  49 + "idiom" : "ipad",
  50 + "size" : "20x20",
  51 + "scale" : "2x"
  52 + },
  53 + {
  54 + "idiom" : "ipad",
  55 + "size" : "29x29",
  56 + "scale" : "1x"
  57 + },
  58 + {
  59 + "idiom" : "ipad",
  60 + "size" : "29x29",
  61 + "scale" : "2x"
  62 + },
  63 + {
  64 + "idiom" : "ipad",
  65 + "size" : "40x40",
  66 + "scale" : "1x"
  67 + },
  68 + {
  69 + "idiom" : "ipad",
  70 + "size" : "40x40",
  71 + "scale" : "2x"
  72 + },
  73 + {
  74 + "idiom" : "ipad",
  75 + "size" : "76x76",
  76 + "scale" : "1x"
  77 + },
  78 + {
  79 + "idiom" : "ipad",
  80 + "size" : "76x76",
  81 + "scale" : "2x"
  82 + },
  83 + {
  84 + "idiom" : "ipad",
  85 + "size" : "83.5x83.5",
  86 + "scale" : "2x"
  87 + },
  88 + {
  89 + "idiom" : "ios-marketing",
  90 + "size" : "1024x1024",
  91 + "scale" : "1x"
  92 + }
  93 + ],
  94 + "info" : {
  95 + "version" : 1,
  96 + "author" : "xcode"
  97 + }
  98 +}
... ...
Example/CNLivePlayer/en.lproj/InfoPlist.strings 0 → 100644
  1 +/* Localized versions of Info.plist keys */
  2 +
... ...
Example/CNLivePlayer/main.m 0 → 100644
  1 +//
  2 +// main.m
  3 +// CNLivePlayer
  4 +//
  5 +// Created by 153993236@qq.com on 07/26/2019.
  6 +// Copyright (c) 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +#import "CNLiveAppDelegate.h"
  11 +
  12 +int main(int argc, char * argv[])
  13 +{
  14 + @autoreleasepool {
  15 + return UIApplicationMain(argc, argv, nil, NSStringFromClass([CNLiveAppDelegate class]));
  16 + }
  17 +}
... ...
Example/Podfile 0 → 100644
  1 +use_frameworks!
  2 +
  3 +platform :ios, '9.0'
  4 +
  5 +target 'CNLivePlayer_Example' do
  6 + pod 'CNLivePlayer', :path => '../'
  7 +
  8 + target 'CNLivePlayer_Tests' do
  9 + inherit! :search_paths
  10 +
  11 +
  12 + end
  13 +end
... ...
Example/Tests/Tests-Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleExecutable</key>
  8 + <string>${EXECUTABLE_NAME}</string>
  9 + <key>CFBundleIdentifier</key>
  10 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  11 + <key>CFBundleInfoDictionaryVersion</key>
  12 + <string>6.0</string>
  13 + <key>CFBundlePackageType</key>
  14 + <string>BNDL</string>
  15 + <key>CFBundleShortVersionString</key>
  16 + <string>1.0</string>
  17 + <key>CFBundleSignature</key>
  18 + <string>????</string>
  19 + <key>CFBundleVersion</key>
  20 + <string>1</string>
  21 +</dict>
  22 +</plist>
... ...
Example/Tests/Tests-Prefix.pch 0 → 100644
  1 +// The contents of this file are implicitly included at the beginning of every test case source file.
  2 +
  3 +#ifdef __OBJC__
  4 +
  5 +
  6 +
  7 +#endif
... ...
Example/Tests/Tests.m 0 → 100644
  1 +//
  2 +// CNLivePlayerTests.m
  3 +// CNLivePlayerTests
  4 +//
  5 +// Created by 153993236@qq.com on 07/26/2019.
  6 +// Copyright (c) 2019 153993236@qq.com. All rights reserved.
  7 +//
  8 +
  9 +@import XCTest;
  10 +
  11 +@interface Tests : XCTestCase
  12 +
  13 +@end
  14 +
  15 +@implementation Tests
  16 +
  17 +- (void)setUp
  18 +{
  19 + [super setUp];
  20 + // Put setup code here. This method is called before the invocation of each test method in the class.
  21 +}
  22 +
  23 +- (void)tearDown
  24 +{
  25 + // Put teardown code here. This method is called after the invocation of each test method in the class.
  26 + [super tearDown];
  27 +}
  28 +
  29 +- (void)testExample
  30 +{
  31 + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
  32 +}
  33 +
  34 +@end
  35 +
... ...
Example/Tests/en.lproj/InfoPlist.strings 0 → 100644
  1 +/* Localized versions of Info.plist keys */
  2 +
... ...
  1 +Copyright (c) 2019 153993236@qq.com <zhangxiaowen@cnlive.com>
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19 +THE SOFTWARE.
... ...
README.md
1   -CNLivePlayer
2 1 \ No newline at end of file
  2 +# CNLivePlayer
  3 +
  4 +[![CI Status](https://img.shields.io/travis/153993236@qq.com/CNLivePlayer.svg?style=flat)](https://travis-ci.org/153993236@qq.com/CNLivePlayer)
  5 +[![Version](https://img.shields.io/cocoapods/v/CNLivePlayer.svg?style=flat)](https://cocoapods.org/pods/CNLivePlayer)
  6 +[![License](https://img.shields.io/cocoapods/l/CNLivePlayer.svg?style=flat)](https://cocoapods.org/pods/CNLivePlayer)
  7 +[![Platform](https://img.shields.io/cocoapods/p/CNLivePlayer.svg?style=flat)](https://cocoapods.org/pods/CNLivePlayer)
  8 +
  9 +## Example
  10 +
  11 +To run the example project, clone the repo, and run `pod install` from the Example directory first.
  12 +
  13 +## Requirements
  14 +
  15 +## Installation
  16 +
  17 +CNLivePlayer is available through [CocoaPods](https://cocoapods.org). To install
  18 +it, simply add the following line to your Podfile:
  19 +
  20 +```ruby
  21 +pod 'CNLivePlayer'
  22 +```
  23 +
  24 +## Author
  25 +
  26 +153993236@qq.com, zhangxiaowen@cnlive.com
  27 +
  28 +## License
  29 +
  30 +CNLivePlayer is available under the MIT license. See the LICENSE file for more info.
... ...
_Pods.xcodeproj 0 → 120000
  1 +Example/Pods/Pods.xcodeproj
0 2 \ No newline at end of file
... ...