Commit de05ddb643dc8ed460e4cbfdd10f4143bd5f5efc

Authored by zhangxiaowen
1 parent df821378

no message

Showing 79 changed files with 3205 additions and 304 deletions

Too many changes to show.

To preserve performance only 79 of 82 files are displayed.

CNLivePlayer/Classes/Header/CNLivePlayerDefines.h
@@ -326,4 +326,13 @@ typedef NS_ENUM(NSInteger, CNLiveRecordError) { @@ -326,4 +326,13 @@ typedef NS_ENUM(NSInteger, CNLiveRecordError) {
326 }; 326 };
327 327
328 328
  329 +/*
  330 + * 播放器类型
  331 + */
  332 +typedef NS_ENUM(NSUInteger, CNLiveStreamerType) {
  333 + CNLiveStreamerVod, //视频
  334 + CNLiveStreamerAudio //音频
  335 +
  336 +};
  337 +
329 #endif /* CNLivePlayerDefines_h */ 338 #endif /* CNLivePlayerDefines_h */
CNLivePlayer/Classes/Player/CNLivePlayerUrl.h
@@ -8,9 +8,10 @@ @@ -8,9 +8,10 @@
8 8
9 #ifndef CNLivePlayerUrl_h 9 #ifndef CNLivePlayerUrl_h
10 #define CNLivePlayerUrl_h 10 #define CNLivePlayerUrl_h
  11 +#import "CNLivePlayerManager.h"
11 12
12 -#pragma mark - 版本号  
13 -#define PlayerSDKVersion @"0.0.1" //播放器SDK版本 13 +#pragma mark - 播放器版本号
  14 +#define PlayerSDKVersion @"0.0.1"
14 15
15 #pragma mark - 探针 16 #pragma mark - 探针
16 #define StatUrl [CNLivePlayerManager manager].isTestEnvironment?@"http://app.sta.cnlive.com/app.jpg": @"http://app.sta.cnlive.com/app.jpg" 17 #define StatUrl [CNLivePlayerManager manager].isTestEnvironment?@"http://app.sta.cnlive.com/app.jpg": @"http://app.sta.cnlive.com/app.jpg"
CNLivePlayer/Classes/Streamer/CNLiveStreamerKit.h
@@ -20,21 +20,48 @@ NS_ASSUME_NONNULL_BEGIN @@ -20,21 +20,48 @@ NS_ASSUME_NONNULL_BEGIN
20 20
21 21
22 @interface CNLiveStreamerKit : NSObject 22 @interface CNLiveStreamerKit : NSObject
  23 +#pragma mark - 初始化方法
23 /** 24 /**
24 @abstract 初始化(不会打断其他后台的音乐播放) 25 @abstract 初始化(不会打断其他后台的音乐播放)
25 @warning 实例化的对象必须赋值给一个全局变量 26 @warning 实例化的对象必须赋值给一个全局变量
26 - @param mode YES:纯音频推流  
27 @warning 必传参数 27 @warning 必传参数
28 */ 28 */
29 -- (instancetype)initWithDefaultConfigWithPureAudioMode:(BOOL)mode; 29 +- (instancetype)initPureAudioStreamerWithDefaultConfig;
30 30
31 /** 31 /**
32 @abstract 初始化(会打断其他后台的音乐播放) 32 @abstract 初始化(会打断其他后台的音乐播放)
33 @warning 实例化的对象必须赋值给一个全局变量 33 @warning 实例化的对象必须赋值给一个全局变量
34 - @param mode YES:纯音频推流  
35 @warning 必传参数 34 @warning 必传参数
36 */ 35 */
37 -- (instancetype)initWithInterruptConfigWithPureAudioMode:(BOOL)mode; 36 +- (instancetype)initPureAudioStreamerWithInterruptConfig;
  37 +
  38 +/**
  39 + @abstract 初始化(不会打断其他后台的音乐播放)
  40 + @warning 实例化的对象必须赋值给一个全局变量
  41 + @warning 必传参数
  42 + */
  43 +- (instancetype)initVodStreamerWithDefaultConfig;
  44 +
  45 +/**
  46 + @abstract 初始化(会打断其他后台的音乐播放)
  47 + @warning 实例化的对象必须赋值给一个全局变量
  48 + @warning 必传参数
  49 + */
  50 +- (instancetype)initVodStreamerWithInterruptConfig;
  51 +
  52 +/**
  53 + @abstract 普通推流初始化(不会打断其他后台的音乐播放)
  54 + @warning 实例化的对象必须赋值给一个全局变量
  55 + @warning 必传参数
  56 + */
  57 +- (instancetype)initWithDefaultConfig:(BOOL)pureAudioMode;
  58 +
  59 +/**
  60 + @abstract 普通推流初始化(会打断其他后台的音乐播放)
  61 + @warning 实例化的对象必须赋值给一个全局变量
  62 + @warning 必传参数
  63 + */
  64 +- (instancetype)initWithInterruptConfig:(BOOL)pureAudioMode;
38 65
39 /** 66 /**
40 @abstract 活动ID,确保SP下的唯一性 67 @abstract 活动ID,确保SP下的唯一性
@@ -55,7 +82,7 @@ NS_ASSUME_NONNULL_BEGIN @@ -55,7 +82,7 @@ NS_ASSUME_NONNULL_BEGIN
55 @property (nonatomic, assign) BOOL logPrintEnable; 82 @property (nonatomic, assign) BOOL logPrintEnable;
56 83
57 /** 84 /**
58 - @abstract 屏幕方向,0:垂直即竖屏 1:水平即横屏 ,默认为0 85 + @abstract 屏幕方向,0:垂直即竖屏 1:水平即横屏 ,默认为0
59 */ 86 */
60 @property (nonatomic, assign) BOOL isHorizontalScreen; 87 @property (nonatomic, assign) BOOL isHorizontalScreen;
61 88
@@ -65,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN @@ -65,7 +92,7 @@ NS_ASSUME_NONNULL_BEGIN
65 @property (nonatomic, strong) NSString *activityName; 92 @property (nonatomic, strong) NSString *activityName;
66 93
67 /** 94 /**
68 - @abstract 活动状态,0:未开始 /1:已开始 /3:已结束 /4 已下线,默认为0(非必传) 95 + @abstract 活动状态,0:未开始 1:已开始 3:已结束 4:已下线,默认为0(非必传)
69 */ 96 */
70 @property (nonatomic, strong) NSString *activityStatus; 97 @property (nonatomic, strong) NSString *activityStatus;
71 98
@@ -124,22 +151,6 @@ NS_ASSUME_NONNULL_BEGIN @@ -124,22 +151,6 @@ NS_ASSUME_NONNULL_BEGIN
124 */ 151 */
125 FOUNDATION_EXPORT NSString *const CNLiveServiceConnectBreakNotification NS_AVAILABLE_IOS(7_0); 152 FOUNDATION_EXPORT NSString *const CNLiveServiceConnectBreakNotification NS_AVAILABLE_IOS(7_0);
126 153
127 -#pragma mark - 普通推流  
128 -  
129 -/**  
130 - @abstract 初始化(不会打断其他后台的音乐播放)  
131 - @param mode YES:纯音频推流  
132 - @warning 实例化的对象必须赋值给一个全局变量  
133 - */  
134 -- (instancetype)initWithDefaultConfigWithPureAudioMode:(BOOL)mode;  
135 -  
136 -/**  
137 - @abstract 初始化(会打断其他后台的音乐播放)  
138 - @param mode YES:纯音频推流  
139 - @warning 实例化的对象必须赋值给一个全局变量  
140 - */  
141 -- (instancetype)initWithInterruptConfigWithPureAudioMode:(BOOL)mode;  
142 -  
143 /** 154 /**
144 * 预览视图 155 * 预览视图
145 */ 156 */
@@ -213,7 +224,7 @@ FOUNDATION_EXPORT NSString *const CNLiveServiceConnectBreakNotification NS_AVAIL @@ -213,7 +224,7 @@ FOUNDATION_EXPORT NSString *const CNLiveServiceConnectBreakNotification NS_AVAIL
213 @abstract 采集及编码视频帧率 (开始采集前设置有效) 224 @abstract 采集及编码视频帧率 (开始采集前设置有效)
214 @discussion video frame per seconds 有效范围[1~30], 超出范围会取边界有效值 225 @discussion video frame per seconds 有效范围[1~30], 超出范围会取边界有效值
215 @discussion 默认值为15 */ 226 @discussion 默认值为15 */
216 -@property (nonatomic, assign) int videoFPS; 227 +@property (nonatomic, assign) int videoFPS;
217 228
218 /** 229 /**
219 @abstract 摄像头位置 230 @abstract 摄像头位置
@@ -227,7 +238,7 @@ FOUNDATION_EXPORT NSString *const CNLiveServiceConnectBreakNotification NS_AVAIL @@ -227,7 +238,7 @@ FOUNDATION_EXPORT NSString *const CNLiveServiceConnectBreakNotification NS_AVAIL
227 @return AVCaptureDevice* 预览开始前调用返回为nil,开始预览后,返回当前正在使用的摄像头 238 @return AVCaptureDevice* 预览开始前调用返回为nil,开始预览后,返回当前正在使用的摄像头
228 @warning 请勿修改摄像头的像素格式,帧率,分辨率等参数,修改后会导致推流工作异常或崩溃 239 @warning 请勿修改摄像头的像素格式,帧率,分辨率等参数,修改后会导致推流工作异常或崩溃
229 */ 240 */
230 -- (AVCaptureDevice *) getCurrentCameraDevices; 241 +- (AVCaptureDevice *)getCurrentCameraDevices;
231 242
232 /** 243 /**
233 @abstract 采集设备状态 244 @abstract 采集设备状态
@@ -243,7 +254,7 @@ FOUNDATION_EXPORT NSString *const CNLiveCaptureStateDidChangeNotification NS_AVA @@ -243,7 +254,7 @@ FOUNDATION_EXPORT NSString *const CNLiveCaptureStateDidChangeNotification NS_AVA
243 */ 254 */
244 @property (nonatomic, readonly) CNLiveStreamState streamState; 255 @property (nonatomic, readonly) CNLiveStreamState streamState;
245 256
246 -FOUNDATION_EXPORT NSString *const CNLiveStreamStateDidChangeNotification NS_AVAILABLE_IOS(7_0); 257 +FOUNDATION_EXPORT NSString *const CNLiveStreamerStateDidChangeNotification NS_AVAILABLE_IOS(7_0);
247 258
248 /** 259 /**
249 * @abstract 推流错误码,用于指示推流失败的原因 260 * @abstract 推流错误码,用于指示推流失败的原因
@@ -257,7 +268,7 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamStateDidChangeNotification NS_AVAI @@ -257,7 +268,7 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamStateDidChangeNotification NS_AVAI
257 @discussion 若filter 为GPUImageFilter的实例,则使用该滤镜做处理 268 @discussion 若filter 为GPUImageFilter的实例,则使用该滤镜做处理
258 @discussion filter 也可以是GPUImageFilterGroup的实例,可以将多个滤镜组合 269 @discussion filter 也可以是GPUImageFilterGroup的实例,可以将多个滤镜组合
259 */ 270 */
260 -- (void)setupFilter:(GPUImageOutput<GPUImageInput>*) filter; 271 +- (void)setupFilter:(GPUImageOutput<GPUImageInput>*)filter;
261 272
262 #pragma mark - reconnect 273 #pragma mark - reconnect
263 /** 274 /**
@@ -288,7 +299,7 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamStateDidChangeNotification NS_AVAI @@ -288,7 +299,7 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamStateDidChangeNotification NS_AVAI
288 CNLiveStreamErrorCode_CODEC_OPEN_FAILED、 299 CNLiveStreamErrorCode_CODEC_OPEN_FAILED、
289 CNLiveStreamErrorCode_ABNORMAL 时为可重连状态; 300 CNLiveStreamErrorCode_ABNORMAL 时为可重连状态;
290 */ 301 */
291 -FOUNDATION_EXPORT NSString *const CNLiveStreamReconnectStatusChangedNotification NS_AVAILABLE_IOS(7_0); 302 +FOUNDATION_EXPORT NSString *const CNLiveStreamerReconnectStatusChangedNotification NS_AVAILABLE_IOS(7_0);
292 303
293 /** 304 /**
294 @abstract 切换摄像头 305 @abstract 切换摄像头
@@ -327,7 +338,7 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamReconnectStatusChangedNotification @@ -327,7 +338,7 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamReconnectStatusChangedNotification
327 @discussion 需要访问摄像头和麦克风的权限,若授权失败,其他API都会拒绝服务 338 @discussion 需要访问摄像头和麦克风的权限,若授权失败,其他API都会拒绝服务
328 @warning: 开始推流前必须先启动预览 339 @warning: 开始推流前必须先启动预览
329 */ 340 */
330 -- (void)startPreview:(UIView*) view; 341 +- (void)startPreview:(UIView *)view;
331 342
332 /** 343 /**
333 @abstract 停止预览,停止采集设备,并清理会话 344 @abstract 停止预览,停止采集设备,并清理会话
@@ -392,25 +403,25 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamReconnectStatusChangedNotification @@ -392,25 +403,25 @@ FOUNDATION_EXPORT NSString *const CNLiveStreamReconnectStatusChangedNotification
392 @param orie 旋转到目标朝向, 需要从demo中获取UI的朝向传入 403 @param orie 旋转到目标朝向, 需要从demo中获取UI的朝向传入
393 @discussion 采集到的图像的朝向还是和启动时的朝向一致 404 @discussion 采集到的图像的朝向还是和启动时的朝向一致
394 */ 405 */
395 -- (void) rotatePreviewTo: (UIInterfaceOrientation) orie; 406 +- (void)rotatePreviewTo:(UIInterfaceOrientation) orie;
396 407
397 /** 408 /**
398 @abstract 根据UI的朝向旋转推流画面 409 @abstract 根据UI的朝向旋转推流画面
399 @param orie 旋转到目标朝向, 需要从demo中获取UI的朝向传入 410 @param orie 旋转到目标朝向, 需要从demo中获取UI的朝向传入
400 */ 411 */
401 -- (void) rotateStreamTo: (UIInterfaceOrientation) orie; 412 +- (void)rotateStreamTo:(UIInterfaceOrientation) orie;
402 413
403 /** 414 /**
404 @abstract 当前采集设备是否支持自动变焦 415 @abstract 当前采集设备是否支持自动变焦
405 @param point 相机对焦的位置 416 @param point 相机对焦的位置
406 */ 417 */
407 -- (void)focusAtPoint:(CGPoint )point; 418 +- (void)focusAtPoint:(CGPoint)point;
408 419
409 /** 420 /**
410 @abstract 当前采集设备是否支持自动曝光 421 @abstract 当前采集设备是否支持自动曝光
411 @param point 相机曝光的位置 422 @param point 相机曝光的位置
412 */ 423 */
413 -- (void)exposureAtPoint:(CGPoint )point; 424 +- (void)exposureAtPoint:(CGPoint)point;
414 425
415 /** 426 /**
416 @abstract 触摸缩放因子 427 @abstract 触摸缩放因子
CNLivePlayer/Classes/Streamer/CNLiveStreamerKit.m
@@ -18,21 +18,27 @@ @@ -18,21 +18,27 @@
18 #import "CNLiveBgmPlayer.h" 18 #import "CNLiveBgmPlayer.h"
19 #import "CNLivePlayerManager.h" 19 #import "CNLivePlayerManager.h"
20 #import "CNLiveStreamerTools.h" 20 #import "CNLiveStreamerTools.h"
  21 +#import "CNLivePlayerNetworkManager.h"
  22 +
  23 +#import "CNLiveStreamerUrl.h"
  24 +
  25 +#define Host @"bc.cnlive.com"
  26 +#define Port 65432
21 27
22 //采集状态通知 28 //采集状态通知
23 NSString * const CNLiveCaptureStateDidChangeNotification = @"CNLiveCaptureStateDidChangeNotification"; 29 NSString * const CNLiveCaptureStateDidChangeNotification = @"CNLiveCaptureStateDidChangeNotification";
24 30
25 //推流状态通知 31 //推流状态通知
26 -NSString * const CNLiveStreamStateDidChangeNotification = @"CNLiveStreamStateDidChangeNotification"; 32 +NSString * const CNLiveStreamerStateDidChangeNotification = @"CNLiveStreamerStateDidChangeNotification";
27 33
28 //自动重连失败通知 34 //自动重连失败通知
29 -NSString * const CNLiveStreamReconnectStatusChangedNotification = @"CNLiveStreamReconnectStatusChangedNotification"; 35 +NSString * const CNLiveStreamerReconnectStatusChangedNotification = @"CNLiveStreamerReconnectStatusChangedNotification";
30 36
31 //获取直播时长通知 37 //获取直播时长通知
32 -NSString * const CNLiveStreamGetDurationNotification = @"CNLiveStreamGetDurationNotification"; 38 +NSString * const CNLiveStreamerGetDurationNotification = @"CNLiveStreamerGetDurationNotification";
33 39
34 //收到消息通知 40 //收到消息通知
35 -NSString * const MsgToolsStreamReceiveNotification = @"CNLiveMsgToolsPlayerReceiveNotification"; 41 +NSString * const CNLiveStreamerMsgReceiveNotification = @"CNLiveMsgToolsPlayerReceiveNotification";
36 42
37 //由服务端断开 43 //由服务端断开
38 NSString * const CNLiveServiceConnectBreakNotification = @"CNLiveServiceConnectBreakNotification"; 44 NSString * const CNLiveServiceConnectBreakNotification = @"CNLiveServiceConnectBreakNotification";
@@ -42,7 +48,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -42,7 +48,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
42 BOOL _activitySuccess; //活动是否创建成功 48 BOOL _activitySuccess; //活动是否创建成功
43 BOOL _isCNLiveStreaming; //是否为视讯云平台推流 49 BOOL _isCNLiveStreaming; //是否为视讯云平台推流
44 50
45 - BOOL _noti;  
46 BOOL _pureAudioMode; //是否为纯音频推流 51 BOOL _pureAudioMode; //是否为纯音频推流
47 52
48 int _autoRetryCnt; //记录重试次数 53 int _autoRetryCnt; //记录重试次数
@@ -54,6 +59,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -54,6 +59,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
54 NSString *_contentId; 59 NSString *_contentId;
55 NSString *_roomId; 60 NSString *_roomId;
56 int _originalStatus; //原始状态 61 int _originalStatus; //原始状态
  62 +
57 CNLiveStreamerManager *_manager; 63 CNLiveStreamerManager *_manager;
58 64
59 BOOL _enterBackground; 65 BOOL _enterBackground;
@@ -74,66 +80,132 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -74,66 +80,132 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
74 @end 80 @end
75 81
76 @implementation CNLiveStreamerKit 82 @implementation CNLiveStreamerKit
  83 +#pragma mark - 初始化方法
77 /** 84 /**
78 - @abstract 初始化(不会打断其他后台的音乐播放) 85 + @abstract 纯音频推流初始化(不会打断其他后台的音乐播放)
79 @warning 实例化的对象必须赋值给一个全局变量 86 @warning 实例化的对象必须赋值给一个全局变量
80 - @param mode YES:纯音频推流  
81 @warning 必传参数 87 @warning 必传参数
82 */ 88 */
83 -- (instancetype)initWithDefaultConfigWithPureAudioMode:(BOOL)mode{ 89 +- (instancetype)initPureAudioStreamerWithDefaultConfig{
84 if (self = [super init]) { 90 if (self = [super init]) {
85 _logPrintEnable = YES; 91 _logPrintEnable = YES;
86 - _pureAudioMode = mode; 92 + _pureAudioMode = YES;
87 _autoRetryCnt = 0; 93 _autoRetryCnt = 0;
88 _autoRetryDelay = 2.0; 94 _autoRetryDelay = 2.0;
89 95
90 -// _parameter = [[NSMutableDictionary alloc] init];  
91 - [self setStreamerCfgWithInterrupt:NO];  
92 -//  
93 -// //视讯云直播,注册前后台切换通知  
94 -// [self addStatusChangedObservers]; 96 + _parameter = [[NSMutableDictionary alloc] init];
  97 + [self setStreamerWithConfig:NO];
  98 +
  99 + //视讯云直播,注册前后台切换通知
  100 + [self addStatusChangedObservers];
95 101
96 } 102 }
97 return self; 103 return self;
98 } 104 }
99 105
100 /** 106 /**
101 - @abstract 初始化(会打断其他后台的音乐播放) 107 + @abstract 纯音频推流初始化(会打断其他后台的音乐播放)
102 @warning 实例化的对象必须赋值给一个全局变量 108 @warning 实例化的对象必须赋值给一个全局变量
103 - @param mode YES:纯音频推流  
104 @warning 必传参数 109 @warning 必传参数
105 */ 110 */
106 -- (instancetype)initWithInterruptConfigWithPureAudioMode:(BOOL)mode{ 111 +- (instancetype)initPureAudioStreamerWithInterruptConfig{
107 if (self = [super init]) { 112 if (self = [super init]) {
108 _logPrintEnable = YES; 113 _logPrintEnable = YES;
109 - _pureAudioMode = mode; 114 + _pureAudioMode = YES;
110 _autoRetryCnt = 0; 115 _autoRetryCnt = 0;
111 _autoRetryDelay = 2.0; 116 _autoRetryDelay = 2.0;
112 117
113 -// _parameter = [[NSMutableDictionary alloc] init];  
114 - [self setStreamerCfgWithInterrupt:YES];  
115 -//  
116 -// //视讯云直播,注册前后台切换通知  
117 -// [self addStatusChangedObservers]; 118 + _parameter = [[NSMutableDictionary alloc] init];
  119 + [self setStreamerWithConfig:NO];
  120 +
  121 + //视讯云直播,注册前后台切换通知
  122 + [self addStatusChangedObservers];
  123 +
  124 + }
  125 + return self;
  126 +}
  127 +
  128 +/**
  129 + @abstract 音视频推流初始化(不会打断其他后台的音乐播放)
  130 + @warning 实例化的对象必须赋值给一个全局变量
  131 + @warning 必传参数
  132 + */
  133 +- (instancetype)initVodStreamerWithDefaultConfig{
  134 + if (self = [super init]) {
  135 + _logPrintEnable = YES;
  136 + _pureAudioMode = NO;
  137 + _autoRetryCnt = 0;
  138 + _autoRetryDelay = 2.0;
  139 +
  140 + _parameter = [[NSMutableDictionary alloc] init];
  141 + [self setStreamerWithConfig:NO];
  142 +
  143 + //视讯云直播,注册前后台切换通知
  144 + [self addStatusChangedObservers];
118 145
119 } 146 }
120 return self; 147 return self;
121 } 148 }
122 149
123 -#pragma mark - 初始化KSY  
124 -- (void)setStreamerCfgWithInterrupt:(BOOL)interrupt { 150 +/**
  151 + @abstract 音视频推流初始化(会打断其他后台的音乐播放)
  152 + @warning 实例化的对象必须赋值给一个全局变量
  153 + @warning 必传参数
  154 + */
  155 +- (instancetype)initVodStreamerWithInterruptConfig{
  156 + if (self = [super init]) {
  157 + _logPrintEnable = YES;
  158 + _pureAudioMode = NO;
  159 + _autoRetryCnt = 0;
  160 + _autoRetryDelay = 2.0;
  161 +
  162 + _parameter = [[NSMutableDictionary alloc] init];
  163 + [self setStreamerWithConfig:NO];
  164 +
  165 + //视讯云直播,注册前后台切换通知
  166 + [self addStatusChangedObservers];
  167 +
  168 + }
  169 + return self;
  170 +}
  171 +
  172 +//普通推流
  173 +//不会打断其他后台音乐
  174 +- (instancetype)initWithDefaultConfig:(BOOL)pureAudioMode {
  175 + if (self = [super init]) {
  176 + _logPrintEnable = YES;
  177 + _pureAudioMode = pureAudioMode;
  178 + [self setStreamerWithConfig:NO];
  179 + }
  180 + return self;
  181 +}
  182 +
  183 +//会打断其他后台音乐
  184 +- (instancetype)initWithInterruptConfig:(BOOL)pureAudioMode {
  185 + if (self = [super init]) {
  186 + _logPrintEnable = YES;
  187 + _pureAudioMode = pureAudioMode;
  188 + [self setStreamerWithConfig:YES];
  189 + }
  190 + return self;
  191 +}
  192 +
  193 +#pragma mark - 初始化推流器
  194 +- (void)setStreamerWithConfig:(BOOL)interrupt {
125 _manager = [CNLiveStreamerManager manager]; 195 _manager = [CNLiveStreamerManager manager];
126 196
127 [UIApplication sharedApplication].idleTimerDisabled = YES; 197 [UIApplication sharedApplication].idleTimerDisabled = YES;
128 198
129 - if (interrupt) { //初始化金山kit 199 + //初始化金山kit
  200 + if (interrupt) {
130 _manager.kit = [[KSYGPUStreamerKit alloc] initWithInterruptCfg]; 201 _manager.kit = [[KSYGPUStreamerKit alloc] initWithInterruptCfg];
131 } 202 }
132 else { 203 else {
133 _manager.kit = [[KSYGPUStreamerKit alloc] initWithDefaultCfg]; 204 _manager.kit = [[KSYGPUStreamerKit alloc] initWithDefaultCfg];
134 } 205 }
135 206
136 - if (_pureAudioMode) { //是否为纯音频推流 207 + //是否为纯音频推流
  208 + if (_pureAudioMode) {
137 [_manager.kit.aCapDev startCapture]; 209 [_manager.kit.aCapDev startCapture];
138 _manager.kit.streamerBase.bWithVideo = NO; 210 _manager.kit.streamerBase.bWithVideo = NO;
139 211
@@ -158,21 +230,16 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -158,21 +230,16 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
158 }; 230 };
159 231
160 //添加通知 232 //添加通知
161 -// [self addKSYObservers]; 233 + [self addKSYObservers];
162 234
163 } 235 }
164 236
165 #pragma mark - 通知 237 #pragma mark - 通知
166 - (void)addKSYObservers { 238 - (void)addKSYObservers {
167 - if (_noti) return;  
168 - _noti = YES;  
169 -  
170 //采集状态通知 239 //采集状态通知
171 - [[NSNotificationCenter defaultCenter] addObserver:self  
172 - selector:@selector(onCaptureStateChange) 240 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onCaptureStateChange)
173 name:KSYCaptureStateDidChangeNotification 241 name:KSYCaptureStateDidChangeNotification
174 object:nil]; 242 object:nil];
175 -  
176 //推流状态通知 243 //推流状态通知
177 [[NSNotificationCenter defaultCenter] addObserver:self 244 [[NSNotificationCenter defaultCenter] addObserver:self
178 selector:@selector(onStreamStateChange) 245 selector:@selector(onStreamStateChange)
@@ -219,7 +286,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -219,7 +286,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
219 } 286 }
220 _streamState = (CNLiveStreamState)_manager.kit.streamerBase.streamState; 287 _streamState = (CNLiveStreamState)_manager.kit.streamerBase.streamState;
221 288
222 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamStateDidChangeNotification 289 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
223 object:nil 290 object:nil
224 userInfo:nil]; 291 userInfo:nil];
225 292
@@ -227,7 +294,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -227,7 +294,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
227 294
228 if (_autoRetryCnt < 3) { 295 if (_autoRetryCnt < 3) {
229 _reconnectStatus = CNLiveReconnectStatusSuccess; 296 _reconnectStatus = CNLiveReconnectStatusSuccess;
230 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamReconnectStatusChangedNotification 297 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
231 object:nil 298 object:nil
232 userInfo:nil]; 299 userInfo:nil];
233 [self recoverReconnectConfig]; 300 [self recoverReconnectConfig];
@@ -240,7 +307,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -240,7 +307,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
240 _isRecording = NO; 307 _isRecording = NO;
241 308
242 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 309 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
243 -// [self requestStopStreamerWithInfo:[NSString stringWithFormat:@"KSY error:%@",[_manager.kit.streamerBase getKSYStreamErrorCodeName:_manager.kit.streamerBase.streamErrorCode]] timeString:timeString]; 310 + [self requestStopStreamerWithInfo:[NSString stringWithFormat:@"KSY error:%@",[_manager.kit.streamerBase getKSYStreamErrorCodeName:_manager.kit.streamerBase.streamErrorCode]] timeString:timeString];
244 }]; 311 }];
245 312
246 [CNLiveStreamerTools errorStat:@"推流出错" activityId:_activityId]; 313 [CNLiveStreamerTools errorStat:@"推流出错" activityId:_activityId];
@@ -249,7 +316,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -249,7 +316,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
249 if (_retryFailed && _isCNLiveStreaming) { 316 if (_retryFailed && _isCNLiveStreaming) {
250 317
251 _reconnectStatus = CNLiveReconnectStatusFailed; 318 _reconnectStatus = CNLiveReconnectStatusFailed;
252 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamReconnectStatusChangedNotification 319 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
253 object:nil 320 object:nil
254 userInfo:nil]; 321 userInfo:nil];
255 [self recoverReconnectConfig]; 322 [self recoverReconnectConfig];
@@ -263,11 +330,8 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -263,11 +330,8 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
263 _manager.kit.streamerBase.streamErrorCode == KSYStreamErrorCode_DNS_Parse_failed || 330 _manager.kit.streamerBase.streamErrorCode == KSYStreamErrorCode_DNS_Parse_failed ||
264 _manager.kit.streamerBase.streamErrorCode == KSYStreamErrorCode_CODEC_OPEN_FAILED) { 331 _manager.kit.streamerBase.streamErrorCode == KSYStreamErrorCode_CODEC_OPEN_FAILED) {
265 332
266 - // NSLog(@"ksyError---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");  
267 -  
268 if (_autoRetryCnt>0 && !_initiativeRetry) { 333 if (_autoRetryCnt>0 && !_initiativeRetry) {
269 [self tryReconnect]; 334 [self tryReconnect];
270 - // NSLog(@"CNLiveGPUStreamerKit-->reconnect ----- 金山ERROR");  
271 335
272 } 336 }
273 } 337 }
@@ -283,12 +347,12 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -283,12 +347,12 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
283 if (![CNLiveStreamerTools isEmptyString:PLAYER_AppID] && _enterBackground == NO && _isRecording) { 347 if (![CNLiveStreamerTools isEmptyString:PLAYER_AppID] && _enterBackground == NO && _isRecording) {
284 _streamErrorCode = CNLiveStreamErrorCode_ABNORMAL; 348 _streamErrorCode = CNLiveStreamErrorCode_ABNORMAL;
285 _streamState = CNLiveStreamStateError; 349 _streamState = CNLiveStreamStateError;
286 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamStateDidChangeNotification 350 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
287 object:nil 351 object:nil
288 userInfo:nil]; 352 userInfo:nil];
289 353
290 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 354 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
291 -// [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_ABNORMAL_2" timeString:timeString]; 355 + [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_ABNORMAL_2" timeString:timeString];
292 }]; 356 }];
293 357
294 _isRecording = NO; 358 _isRecording = NO;
@@ -297,6 +361,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -297,6 +361,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
297 } 361 }
298 } 362 }
299 } else { 363 } else {
  364 +
300 } 365 }
301 366
302 NSLog(@"CNLiveGPUStreamerKit-->推流工作状态发生变化CNLiveStreamState:%ld", (unsigned long)self.streamState); 367 NSLog(@"CNLiveGPUStreamerKit-->推流工作状态发生变化CNLiveStreamState:%ld", (unsigned long)self.streamState);
@@ -304,9 +369,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -304,9 +369,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
304 } 369 }
305 370
306 - (void)enterBackground { 371 - (void)enterBackground {
307 - // [_manager.kit.aCapDev stopCapture];  
308 - // NSLog(@"CNLiveGPUStreamerKit-->关闭音频采集状态");  
309 -  
310 /** 372 /**
311 * 视讯云平台:推流过程中退到后台或者锁屏情况下,需将活动状态改为“-2”,以便观众端收到主播离开的消息 373 * 视讯云平台:推流过程中退到后台或者锁屏情况下,需将活动状态改为“-2”,以便观众端收到主播离开的消息
312 */ 374 */
@@ -320,7 +382,8 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -320,7 +382,8 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
320 }]; 382 }];
321 383
322 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 384 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
323 -// [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_EnterBackground" timeString:timeString]; 385 + [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_EnterBackground" timeString:timeString];
  386 +
324 }]; 387 }];
325 } 388 }
326 389
@@ -336,15 +399,15 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -336,15 +399,15 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
336 * 视讯云平台:APP返回前台重新将活动状态改为“1”,若失败将推流状态改为error,并通知开发者 399 * 视讯云平台:APP返回前台重新将活动状态改为“1”,若失败将推流状态改为error,并通知开发者
337 */ 400 */
338 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 401 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
339 -// [self requestStartStreamer:NULL failure:^(NSDictionary *errorDic) {  
340 -//  
341 -// _streamErrorCode = CNLiveStreamErrorCode_ABNORMAL;  
342 -// _streamState = CNLiveStreamStateError;  
343 -//  
344 -// [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamStateDidChangeNotification  
345 -// object:nil  
346 -// userInfo:nil];  
347 -// } timeString:timeString]; 402 + [self requestStartStreamer:NULL failure:^(NSDictionary *errorDic) {
  403 +
  404 + _streamErrorCode = CNLiveStreamErrorCode_ABNORMAL;
  405 + _streamState = CNLiveStreamStateError;
  406 +
  407 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
  408 + object:nil
  409 + userInfo:nil];
  410 + } timeString:timeString];
348 }]; 411 }];
349 } 412 }
350 413
@@ -416,9 +479,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -416,9 +479,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
416 _manager.kit.videoOrientation = uiOrien; 479 _manager.kit.videoOrientation = uiOrien;
417 } 480 }
418 481
419 -#pragma mark -  
420 #pragma mark - mirror & rotate 482 #pragma mark - mirror & rotate
421 -  
422 //预览设置成镜像模式 483 //预览设置成镜像模式
423 - (void)setPreviewMirrored:(BOOL)previewMirrored { 484 - (void)setPreviewMirrored:(BOOL)previewMirrored {
424 _manager.kit.previewMirrored = previewMirrored; 485 _manager.kit.previewMirrored = previewMirrored;
@@ -432,8 +493,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -432,8 +493,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
432 } 493 }
433 494
434 //旋转预览视图 495 //旋转预览视图
435 -- (void)rotatePreviewTo:(UIInterfaceOrientation)orie  
436 -{ 496 +- (void)rotatePreviewTo:(UIInterfaceOrientation)orie {
437 [_manager.kit rotatePreviewTo:orie]; 497 [_manager.kit rotatePreviewTo:orie];
438 } 498 }
439 499
@@ -442,9 +502,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -442,9 +502,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
442 [_manager.kit rotateStreamTo:orie]; 502 [_manager.kit rotateStreamTo:orie];
443 } 503 }
444 504
445 -#pragma mark -  
446 #pragma mark - camera operation 505 #pragma mark - camera operation
447 -  
448 - (BOOL)switchCamera { 506 - (BOOL)switchCamera {
449 return [_manager.kit switchCamera]; 507 return [_manager.kit switchCamera];
450 } 508 }
@@ -467,7 +525,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -467,7 +525,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
467 [_manager.kit toggleTorch]; 525 [_manager.kit toggleTorch];
468 } 526 }
469 527
470 -#pragma mark -  
471 #pragma mark - reconnect(由于开启会暴露推流地址,暂不开放) 528 #pragma mark - reconnect(由于开启会暴露推流地址,暂不开放)
472 @synthesize maxAutoRetry = _maxAutoRetry; 529 @synthesize maxAutoRetry = _maxAutoRetry;
473 - (void)setMaxAutoRetry:(int)maxAutoRetry { 530 - (void)setMaxAutoRetry:(int)maxAutoRetry {
@@ -491,9 +548,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -491,9 +548,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
491 548
492 - (void)tryReconnect { 549 - (void)tryReconnect {
493 550
494 - // NSLog(@"tryReconnect---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");  
495 -  
496 -  
497 if (_autoRetryCnt < 1) { 551 if (_autoRetryCnt < 1) {
498 return; 552 return;
499 } 553 }
@@ -504,12 +558,9 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -504,12 +558,9 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
504 558
505 _reteying = YES; 559 _reteying = YES;
506 560
507 - // NSLog(@"tryReconnect---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");  
508 -  
509 -  
510 if (_autoRetryCnt == _maxAutoRetry) { 561 if (_autoRetryCnt == _maxAutoRetry) {
511 _reconnectStatus = CNLiveReconnectStatusStart; 562 _reconnectStatus = CNLiveReconnectStatusStart;
512 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamReconnectStatusChangedNotification 563 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
513 object:nil 564 object:nil
514 userInfo:nil]; 565 userInfo:nil];
515 } 566 }
@@ -519,13 +570,12 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -519,13 +570,12 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
519 dispatch_after(delay, dispatch_get_main_queue(), ^{ 570 dispatch_after(delay, dispatch_get_main_queue(), ^{
520 571
521 if (!_manager.kit.streamerBase.isStreaming) { 572 if (!_manager.kit.streamerBase.isStreaming) {
522 - // if (!_streamerBase.isStreaming) {  
523 573
524 if (_logPrintEnable) { 574 if (_logPrintEnable) {
525 NSLog(@"CNLiveGPUStreamerKit-->第(%d)次重连/(%d)", (_maxAutoRetry-_autoRetryCnt+1),_maxAutoRetry); 575 NSLog(@"CNLiveGPUStreamerKit-->第(%d)次重连/(%d)", (_maxAutoRetry-_autoRetryCnt+1),_maxAutoRetry);
526 } 576 }
527 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 577 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
528 -// [self requestStartStreamer:NULL failure:NULL timeString:timeString]; 578 + [self requestStartStreamer:NULL failure:NULL timeString:timeString];
529 }]; 579 }];
530 580
531 _autoRetryCnt--; 581 _autoRetryCnt--;
@@ -540,7 +590,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -540,7 +590,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
540 _retryFailed = NO; 590 _retryFailed = NO;
541 } 591 }
542 592
543 -#pragma mark -  
544 #pragma mark - KSYMethod 593 #pragma mark - KSYMethod
545 - (UIView *)preview { 594 - (UIView *)preview {
546 return (UIView *)_manager.kit.preview; 595 return (UIView *)_manager.kit.preview;
@@ -569,13 +618,13 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -569,13 +618,13 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
569 _retryFailed = NO; 618 _retryFailed = NO;
570 619
571 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 620 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
572 -// [self requestStartStreamer:successBlock failure:failureBlock timeString:timeString]; 621 + [self requestStartStreamer:successBlock failure:failureBlock timeString:timeString];
573 }]; 622 }];
574 623
575 } else { 624 } else {
576 625
577 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 626 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
578 -// [self createActivityWithSuccess:successBlock failure:failureBlock timeString:timeString]; 627 + [self createActivityWithSuccess:successBlock failure:failureBlock timeString:timeString];
579 }]; 628 }];
580 629
581 } 630 }
@@ -595,7 +644,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -595,7 +644,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
595 _hostURL = [NSURL URLWithString:url]; //推流地址 644 _hostURL = [NSURL URLWithString:url]; //推流地址
596 645
597 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 646 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
598 -// [self requestStartStreamer:successBlock failure:failureBlock timeString:timeString]; 647 + [self requestStartStreamer:successBlock failure:failureBlock timeString:timeString];
599 }]; 648 }];
600 } 649 }
601 650
@@ -603,7 +652,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -603,7 +652,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
603 [_manager.kit.streamerBase stopStream]; 652 [_manager.kit.streamerBase stopStream];
604 _isRecording = NO; 653 _isRecording = NO;
605 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 654 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
606 -// [self requestStopStreamerWithInfo:@"User Pause" timeString:timeString]; 655 + [self requestStopStreamerWithInfo:@"User Pause" timeString:timeString];
607 }]; 656 }];
608 } 657 }
609 658
@@ -616,7 +665,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -616,7 +665,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
616 - (void)stopStream { 665 - (void)stopStream {
617 if (_activitySuccess) { 666 if (_activitySuccess) {
618 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 667 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
619 -// [self requestStopStreamerWithInfo:@"" timeString:timeString]; 668 + [self requestStopStreamerWithInfo:@"" timeString:timeString];
620 }]; 669 }];
621 _isRecording = NO; 670 _isRecording = NO;
622 [self.socket disconnect]; 671 [self.socket disconnect];
@@ -640,8 +689,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -640,8 +689,6 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
640 - (void)appEnterBackground { 689 - (void)appEnterBackground {
641 [_manager.kit appEnterBackground]; 690 [_manager.kit appEnterBackground];
642 691
643 - // //进入后台停止采集,避免占用资源  
644 - // [_manager.kit.streamerBase stopStream];  
645 } 692 }
646 693
647 //回到前台 694 //回到前台
@@ -672,13 +719,11 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -672,13 +719,11 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
672 _manager.kit.stabilizationMode = stabilizationMode; 719 _manager.kit.stabilizationMode = stabilizationMode;
673 } 720 }
674 721
675 -#pragma mark -  
676 #pragma mark - filters 722 #pragma mark - filters
677 - (void)setupFilter:(GPUImageOutput<GPUImageInput> *)filter { 723 - (void)setupFilter:(GPUImageOutput<GPUImageInput> *)filter {
678 [_manager.kit setupFilter:filter]; 724 [_manager.kit setupFilter:filter];
679 } 725 }
680 726
681 -#pragma mark -  
682 #pragma mark - 设置接口参数 727 #pragma mark - 设置接口参数
683 - (void)setActivityId:(NSString *)activityId { 728 - (void)setActivityId:(NSString *)activityId {
684 _activityId = [NSString stringWithFormat:@"%@", activityId]; 729 _activityId = [NSString stringWithFormat:@"%@", activityId];
@@ -736,11 +781,10 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -736,11 +781,10 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
736 } 781 }
737 782
738 #pragma mark - GCDAsyncSocketDelegate 783 #pragma mark - GCDAsyncSocketDelegate
739 -  
740 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { 784 - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
741 self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES]; 785 self.heartTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(checkLongConnectByServe) userInfo:nil repeats:YES];
742 [self checkLongConnectByServe]; 786 [self checkLongConnectByServe];
743 - // NSLog(@"socket -------- 已连接"); 787 +
744 } 788 }
745 789
746 - (void)checkLongConnectByServe { 790 - (void)checkLongConnectByServe {
@@ -751,32 +795,27 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -751,32 +795,27 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
751 longConnect = [NSString stringWithFormat:@"%@#%@#",PLAYER_AppID,_activityId]; 795 longConnect = [NSString stringWithFormat:@"%@#%@#",PLAYER_AppID,_activityId];
752 } 796 }
753 NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding]; 797 NSData *data = [longConnect dataUsingEncoding:NSUTF8StringEncoding];
754 - // NSLog(@"socket-socket--socket---%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);  
755 [self.socket writeData:data withTimeout:-1 tag:1]; 798 [self.socket writeData:data withTimeout:-1 tag:1];
  799 +
756 } 800 }
757 801
758 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag { 802 - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
759 - // NSLog(@"socket:%p didWriteDataWithTag:%ld", sock, tag); 803 +
760 } 804 }
761 805
762 - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { 806 - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
763 - // NSLog(@"socket:%p didReadData:withTag:%ld", sock, tag);  
764 -  
765 - // NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];  
766 807
767 - // NSLog(@"HTTP Response:\n%@", httpResponse);  
768 808
769 } 809 }
770 810
771 - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { 811 - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
772 - // NSLog(@"socket-------- 断开连接 %@", err);  
773 812
774 if (_isRecording) { 813 if (_isRecording) {
775 814
776 _isRecording = NO; 815 _isRecording = NO;
777 816
778 if (self.logPrintEnable) { 817 if (self.logPrintEnable) {
779 - NSLog(@"CNLiveGPUStreamerKit-->由于监听心跳未能正常运作而暂时断开推流,reason:%@",err?err.localizedDescription:@"nil"); 818 + NSLog(@"CNLiveStreamerKit-->由于监听心跳未能正常运作而暂时断开推流,reason:%@",err?err.localizedDescription:@"nil");
780 } 819 }
781 820
782 [_manager.kit.streamerBase stopStream]; 821 [_manager.kit.streamerBase stopStream];
@@ -784,29 +823,27 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -784,29 +823,27 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
784 //如果socket异常断开,发送异常通知 823 //如果socket异常断开,发送异常通知
785 _streamErrorCode = CNLiveStreamErrorCode_ABNORMAL; 824 _streamErrorCode = CNLiveStreamErrorCode_ABNORMAL;
786 _streamState = CNLiveStreamStateError; 825 _streamState = CNLiveStreamStateError;
787 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamStateDidChangeNotification 826 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
788 object:nil 827 object:nil
789 userInfo:nil]; 828 userInfo:nil];
790 829
791 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 830 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
792 -// [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_ABNORMAL_1" timeString:timeString]; 831 + [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_ABNORMAL_1" timeString:timeString];
793 }]; 832 }];
794 833
795 834
796 //重连失败通知开发者 835 //重连失败通知开发者
797 if (_retryFailed && _isCNLiveStreaming) { 836 if (_retryFailed && _isCNLiveStreaming) {
798 _reconnectStatus = CNLiveReconnectStatusFailed; 837 _reconnectStatus = CNLiveReconnectStatusFailed;
799 - [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamReconnectStatusChangedNotification 838 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
800 object:nil 839 object:nil
801 userInfo:nil]; 840 userInfo:nil];
802 [self recoverReconnectConfig]; 841 [self recoverReconnectConfig];
803 } 842 }
804 843
805 - // NSLog(@"socketBreak---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");  
806 -  
807 if (_autoRetryCnt>0 && !_initiativeRetry) { 844 if (_autoRetryCnt>0 && !_initiativeRetry) {
808 [self tryReconnect]; 845 [self tryReconnect];
809 - //NSLog(@"CNLiveStreamerKit-->reconnect ----- socketERROR"); 846 +
810 } 847 }
811 848
812 } 849 }
@@ -848,25 +885,20 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -848,25 +885,20 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
848 885
849 _roomId = [NSString stringWithFormat:@"CNLiveAnchorStatus_%@",contentId]; 886 _roomId = [NSString stringWithFormat:@"CNLiveAnchorStatus_%@",contentId];
850 887
851 - // NSLog(@"**********************----roomid %@",_roomId);  
852 -  
853 //加入聊天室 888 //加入聊天室
854 - [[CNLiveMsgManager sharedCNLiveMsgManager] gatherIfNullCreate:_roomId  
855 - messageCount:1  
856 - success:^(NSString *targetId) {  
857 -  
858 - if (result) {  
859 - result(YES);  
860 - }  
861 -  
862 - } error:^(NSInteger errors, NSString *targetId) {  
863 -  
864 - // NSLog(@"***********--加入聊天室失败 ----errors %ld",(long)errors);  
865 -  
866 - if (result) {  
867 - result(NO);  
868 - }  
869 - }]; 889 + [[CNLiveMsgManager sharedCNLiveMsgManager] gatherIfNullCreate:_roomId messageCount:1 success:^(NSString *targetId) {
  890 + if (result) {
  891 + result(YES);
  892 +
  893 + }
  894 +
  895 + } error:^(NSInteger errors, NSString *targetId) {
  896 + if (result) {
  897 + result(NO);
  898 +
  899 + }
  900 +
  901 + }];
870 } 902 }
871 903
872 - (void)initRCloudNotificationObservers { 904 - (void)initRCloudNotificationObservers {
@@ -874,7 +906,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -874,7 +906,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
874 if (_registerChatNoti) return; 906 if (_registerChatNoti) return;
875 907
876 //接收消息通知 908 //接收消息通知
877 - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveMessage:) name:MsgToolsStreamReceiveNotification object:nil]; 909 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveMessage:) name:CNLiveStreamerMsgReceiveNotification object:nil];
878 910
879 _registerChatNoti = YES; 911 _registerChatNoti = YES;
880 912
@@ -887,6 +919,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -887,6 +919,7 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
887 int newValue = [noti.userInfo[@"message"] intValue]; 919 int newValue = [noti.userInfo[@"message"] intValue];
888 920
889 if (_originalStatus == newValue) return; //如果新收到的状态与上一次状态一样不作处理 921 if (_originalStatus == newValue) return; //如果新收到的状态与上一次状态一样不作处理
  922 +
890 if (!_originalStatus && newValue == 2) { 923 if (!_originalStatus && newValue == 2) {
891 return; 924 return;
892 } 925 }
@@ -907,20 +940,16 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -907,20 +940,16 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
907 940
908 _registerChatNoti = NO; 941 _registerChatNoti = NO;
909 942
910 - [[NSNotificationCenter defaultCenter] removeObserver:self  
911 - name:MsgToolsStreamReceiveNotification  
912 - object:nil]; 943 + [[NSNotificationCenter defaultCenter] removeObserver:self name:CNLiveStreamerMsgReceiveNotification object:nil];
913 944
914 - if ([CNLiveStreamerTools isEmptyString:_roomId]) {  
915 - return; 945 + if (![CNLiveStreamerTools isEmptyString:_roomId]) {
  946 + [[CNLiveMsgManager sharedCNLiveMsgManager] disperse:_roomId success:^(NSString *targetId) {
  947 +
  948 + } error:^(NSInteger errors, NSString *targetId) {
  949 +
  950 + }];
916 } 951 }
917 952
918 - [[CNLiveMsgManager sharedCNLiveMsgManager] disperse:_roomId success:^(NSString *targetId) {  
919 -  
920 - } error:^(NSInteger errors, NSString *targetId) {  
921 -  
922 - }];  
923 -  
924 } 953 }
925 954
926 #pragma mark - getter 955 #pragma mark - getter
@@ -961,30 +990,9 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -961,30 +990,9 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
961 990
962 #pragma mark - dealloc 991 #pragma mark - dealloc
963 - (void)dealloc { 992 - (void)dealloc {
964 -  
965 - [[NSNotificationCenter defaultCenter] removeObserver:self  
966 - name:KSYCaptureStateDidChangeNotification  
967 - object:nil];  
968 -  
969 - [[NSNotificationCenter defaultCenter] removeObserver:self  
970 - name:KSYStreamStateDidChangeNotification  
971 - object:nil];  
972 -  
973 - [[NSNotificationCenter defaultCenter] removeObserver:self  
974 - name:UIApplicationDidEnterBackgroundNotification  
975 - object:nil];  
976 -  
977 - [[NSNotificationCenter defaultCenter] removeObserver:self  
978 - name:UIApplicationWillEnterForegroundNotification  
979 - object:nil];  
980 -  
981 - [[NSNotificationCenter defaultCenter] removeObserver:self  
982 - name:MsgToolsStreamReceiveNotification  
983 - object:nil];  
984 - 993 + [[NSNotificationCenter defaultCenter] removeObserver:self];
985 [UIApplication sharedApplication].idleTimerDisabled = NO; 994 [UIApplication sharedApplication].idleTimerDisabled = NO;
986 995
987 -  
988 [_manager destroyStreamerManager]; 996 [_manager destroyStreamerManager];
989 _manager = nil; 997 _manager = nil;
990 } 998 }
@@ -998,4 +1006,375 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB @@ -998,4 +1006,375 @@ NSString * const CNLiveServiceConnectBreakNotification = @&quot;CNLiveServiceConnectB
998 return view; 1006 return view;
999 } 1007 }
1000 1008
  1009 +#pragma mark - data
  1010 +- (void)requestCreateActivityParameter:(NSDictionary *)param success:(void(^)(void))successBlock failure :(void (^)(NSDictionary *errorDic))failureBlock {
  1011 +
  1012 + [CNLivePlayerNetworkManager POST:StreamerURL parameters:param success:^(NSURLResponse * _Nullable response, id _Nullable responseObject) {
  1013 +
  1014 + if (![CNLiveStreamerTools isEmptyString:responseObject[@"errorCode"]] && [responseObject[@"errorCode"] intValue] == 0) {
  1015 +
  1016 + if (self.logPrintEnable) {
  1017 + NSLog(@"CNLiveGPUStreamerKit-->创建活动成功");
  1018 + }
  1019 +
  1020 + //创建活动成功后,连接RM,获取主播状态
  1021 + // [self initRCloudWithAppId:SHARE_APPID appKey:SHARE_APPKEY connectResult:NULL];
  1022 +
  1023 + _activitySuccess = YES;
  1024 +
  1025 + NSString *url = responseObject[@"data"][@"location"];
  1026 + _hostURL = [NSURL URLWithString:url];
  1027 +
  1028 + [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
  1029 + [self requestStartStreamer:successBlock failure:failureBlock timeString:timeString];
  1030 + }];
  1031 +
  1032 + } else {
  1033 +
  1034 + if (self.logPrintEnable) {
  1035 + NSLog(@"CNLiveGPUStreamerKit-->创建活动失败,失败原因:%@", responseObject);
  1036 + }
  1037 +
  1038 + failureBlock ? failureBlock(responseObject) : nil;
  1039 +
  1040 + //用于探针
  1041 +
  1042 + NSError *error = [CNLiveStreamerTools customErrorWithResponseObject:responseObject errorInfo:@"开启推流失败,请重试"];
  1043 +
  1044 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1045 + }
  1046 +
  1047 + } failure:^(NSURLResponse * _Nullable response, NSError * _Nullable error) {
  1048 +
  1049 + NSDictionary *errorDic = @{@"errorCode": [NSString stringWithFormat:@"%ld", error.code],
  1050 + @"errorMessage": error.localizedDescription};
  1051 +
  1052 + failureBlock ? failureBlock(errorDic) : nil;
  1053 +
  1054 + if (self.logPrintEnable) {
  1055 + NSLog(@"CNLiveGPUStreamerKit-->创建活动失败,失败原因:%@", errorDic);
  1056 + }
  1057 +
  1058 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1059 +
  1060 + }];
  1061 +
  1062 +}
  1063 +
  1064 +//启动直播活动
  1065 +- (void)requestStartStreamer:(void (^)(void))successBlock failure:(void (^)(NSDictionary *))failureBlock timeString:(NSString *)timeString {
  1066 +
  1067 + _reteying = NO;
  1068 +
  1069 + // NSDate *date = [NSDate date];
  1070 + // NSInteger time = [date timeIntervalSince1970];
  1071 + // NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time];
  1072 +
  1073 + NSMutableDictionary *parameter = [@{@"appId": PLAYER_AppID,
  1074 + @"activityId": _activityId,
  1075 + @"timestamp":timeString,
  1076 + @"platform_id":[NSBundle mainBundle].bundleIdentifier} copy] ;
  1077 +
  1078 + NSMutableDictionary *para = [CNLiveStreamerTools encryptionSignWithParameter:parameter];
  1079 +
  1080 + [CNLivePlayerNetworkManager GET:StartStreamerURL parameters:para success:^(NSURLResponse * _Nullable response, id _Nullable responseObject) {
  1081 +
  1082 + if (responseObject[@"errorCode"] && [responseObject[@"errorCode"]isEqualToString:@"0"]) { //开始活动success
  1083 +
  1084 + _isRecording = YES;
  1085 + BOOL linkResult;
  1086 +
  1087 + if (_socket.isDisconnected || !_socket) {
  1088 + self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
  1089 + NSError *error;
  1090 + linkResult = [self.socket connectToHost:Host onPort:Port withTimeout:5 error:&error];
  1091 + } else {
  1092 + linkResult = YES;
  1093 + }
  1094 +
  1095 + if (linkResult) { //连接聊天室success
  1096 +
  1097 + if (_manager.kit.streamerBase.isStreaming) {
  1098 + _streamState = CNLiveStreamStateConnected;
  1099 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
  1100 + object:nil
  1101 + userInfo:nil];
  1102 + }
  1103 +
  1104 + if (!_manager.kit.streamerBase.isStreaming) {
  1105 + [_manager.kit.streamerBase startStream:_hostURL];
  1106 + }
  1107 +
  1108 +
  1109 + if (successBlock) {
  1110 + successBlock();
  1111 + }
  1112 +
  1113 + if (self.logPrintEnable) {
  1114 + // D_NSLog(@"CNLiveGPUStreamerKit-->开启活动成功 -----连接状态%@", share.kit.streamerBase.isStreaming ? @"YES" : @"NO");
  1115 + NSLog(@"CNLiveGPUStreamerKit-->开启活动成功");
  1116 + }
  1117 +
  1118 + _initiativeRetry = NO;
  1119 +
  1120 +
  1121 + } else { //连接聊天室fail
  1122 +
  1123 + _isRecording = NO;
  1124 +
  1125 + /**
  1126 + * 开始活动成功但是聊天室连接失败应将活动状态置为“-2”
  1127 + */
  1128 + [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
  1129 + [self requestStopStreamerWithInfo:@"CNLiveStreamErrorCode_JoinRoomFailed" timeString:timeString];
  1130 + }];
  1131 +
  1132 + /**
  1133 + * 若返回前台,流没断,但是连接聊天室失败,需将流断开
  1134 + */
  1135 + if (_manager.kit.streamerBase.isStreaming) {
  1136 + [_manager.kit.streamerBase stopStream];
  1137 + }
  1138 +
  1139 + //用于错误探针
  1140 + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"socket连接失败"}];
  1141 +
  1142 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1143 +
  1144 + //用于回调
  1145 + NSDictionary *errorDic = @{@"errorCode": @"-1",
  1146 + @"errorMessage": @"心跳连接失败,请重试"};
  1147 +
  1148 + if (self.logPrintEnable) {
  1149 + NSLog(@"CNLiveGPUStreamerKit-->开启活动失败,失败原因:%@", errorDic);
  1150 + }
  1151 +
  1152 + //重连失败通知开发者
  1153 + if (_retryFailed && _isCNLiveStreaming) {
  1154 + _reconnectStatus = CNLiveReconnectStatusFailed;
  1155 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
  1156 + object:nil
  1157 + userInfo:nil];
  1158 + [self recoverReconnectConfig];
  1159 + }
  1160 +
  1161 + // NSLog(@"socketConnectFailed---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");
  1162 +
  1163 + if (_autoRetryCnt>0 && !_initiativeRetry) {
  1164 + [self tryReconnect];
  1165 + // D_NSLog(@"CNLiveGPUStreamerKit-->reconnect ----- socket连接失败");
  1166 +
  1167 + }
  1168 +
  1169 + failureBlock ? failureBlock(errorDic) : nil;
  1170 +
  1171 + }
  1172 +
  1173 + } else { //开始活动失败
  1174 +
  1175 + _isRecording = NO;
  1176 +
  1177 + if (_manager.kit.streamerBase.isStreaming) {
  1178 + [_manager.kit.streamerBase stopStream];
  1179 + }
  1180 +
  1181 + //用于探针
  1182 + NSError *error = [CNLiveStreamerTools customErrorWithResponseObject:responseObject errorInfo:@"开启推流失败,请重试"];
  1183 +
  1184 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1185 +
  1186 + if (self.logPrintEnable) {
  1187 + NSLog(@"CNLiveGPUStreamerKit-->开启活动失败,失败原因:%@", responseObject);
  1188 + }
  1189 +
  1190 + //重连失败通知开发者
  1191 + if (_retryFailed && _isCNLiveStreaming) {
  1192 + _reconnectStatus = CNLiveReconnectStatusFailed;
  1193 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
  1194 + object:nil
  1195 + userInfo:nil];
  1196 + [self recoverReconnectConfig];
  1197 + }
  1198 +
  1199 + // NSLog(@"startFailed---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");
  1200 +
  1201 + if (_autoRetryCnt>0 && !_initiativeRetry) {
  1202 + [self tryReconnect];
  1203 + // D_NSLog(@"CNLiveGPUStreamerKit-->reconnect ----- 启动活动失败");
  1204 + }
  1205 +
  1206 + failureBlock ? failureBlock(responseObject) : nil;
  1207 +
  1208 + }
  1209 +
  1210 + } failure:^(NSURLResponse * _Nullable response, NSError * _Nullable error) {
  1211 +
  1212 + _isRecording = NO;
  1213 +
  1214 + if (_manager.kit.streamerBase.isStreaming) {
  1215 + [_manager.kit.streamerBase stopStream];
  1216 + }
  1217 +
  1218 + NSDictionary *errorDic = @{@"errorCode": [NSString stringWithFormat:@"%ld",error.code], @"errorMessage": error.localizedDescription};
  1219 +
  1220 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1221 +
  1222 +
  1223 + if (self.logPrintEnable) {
  1224 + NSLog(@"CNLiveGPUStreamerKit-->开启活动失败,失败原因:%@", errorDic);
  1225 + }
  1226 +
  1227 + //重连失败通知开发者
  1228 + if (_retryFailed && _isCNLiveStreaming) {
  1229 + _reconnectStatus = CNLiveReconnectStatusFailed;
  1230 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerReconnectStatusChangedNotification
  1231 + object:nil
  1232 + userInfo:nil];
  1233 + [self recoverReconnectConfig];
  1234 + }
  1235 +
  1236 + // NSLog(@"no wlan---->autoRetryCnt:%d----initiativeRetry:%@----reteying:%@----retryFailed:%@", _autoRetryCnt, _initiativeRetry ? @"YES" : @"NO", _reteying?@"YES":@"NO", _retryFailed?@"YES":@"NO");
  1237 +
  1238 + if (_autoRetryCnt>0 && !_initiativeRetry) {
  1239 + [self tryReconnect];
  1240 + // D_NSLog(@"CNLiveGPUStreamerKit-->reconnect ----- 启动活动(((请求)))失败");
  1241 + }
  1242 +
  1243 + failureBlock ? failureBlock(errorDic) : nil;
  1244 +
  1245 + }];
  1246 +}
  1247 +
  1248 +//结束直播活动
  1249 +- (void)requestStopStreamerWithInfo:(NSString *)remark timeString:(NSString *)timeString {
  1250 + // NSDate *date = [NSDate date];
  1251 + // NSInteger time = [date timeIntervalSince1970];
  1252 + // NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time];
  1253 +
  1254 + NSMutableDictionary *parameter = [@{@"appId": PLAYER_AppID,
  1255 + @"activityId": _activityId,
  1256 + @"platform_id":[NSBundle mainBundle].bundleIdentifier,
  1257 + @"timestamp":timeString} mutableCopy];
  1258 + if (remark.length > 0) {
  1259 + [parameter setObject:remark forKey:@"remark"];
  1260 + }
  1261 +
  1262 + NSMutableDictionary *para = [CNLiveStreamerTools encryptionSignWithParameter:parameter];
  1263 +
  1264 + [CNLivePlayerNetworkManager GET:StopStreamerURL parameters:para success:^(NSURLResponse * _Nullable response, id _Nullable responseObject) {
  1265 +
  1266 + if ([[NSString stringWithFormat:@"%@", responseObject[@"errorCode"]] isEqualToString:@"0"]) {
  1267 +
  1268 + if (self.logPrintEnable) {
  1269 + if (remark.length > 0) {
  1270 + NSLog(@"CNLiveGPUStreamerKit-->异常结束推流error:%@,并成功通知后台", remark);
  1271 + } else {
  1272 + //结束推流成功通知
  1273 + _streamState = CNLiveStopStreamSuccess;
  1274 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
  1275 + object:nil
  1276 + userInfo:nil];
  1277 +
  1278 + NSLog(@"CNLiveGPUStreamerKit-->正常结束推流并成功通知后台");
  1279 + }
  1280 + }
  1281 +
  1282 +
  1283 + if ([CNLiveStreamerTools isEmptyString:remark]) {
  1284 + NSString *duration = responseObject[@"data"][@"duration"];
  1285 + if ([duration isKindOfClass:[NSString class]] && duration.length > 0) {
  1286 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerGetDurationNotification object:duration ? duration : @"0"];
  1287 + } else {
  1288 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerGetDurationNotification object:@"0"];
  1289 + }
  1290 + }
  1291 +
  1292 +
  1293 + } else {
  1294 +
  1295 + if ([CNLiveStreamerTools isEmptyString:remark]) {
  1296 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerGetDurationNotification object:@"0"];
  1297 +
  1298 + }
  1299 +
  1300 + if (self.logPrintEnable) {
  1301 + if (remark.length > 0) {
  1302 + NSLog(@"CNLiveGPUStreamerKit-->异常结束推流error:%@,未能通知后台 %@", remark,responseObject);
  1303 + } else {
  1304 + NSLog(@"CNLiveGPUStreamerKit-->正常结束推流,未能通知后台 %@",responseObject);
  1305 + //结束推流失败通知
  1306 + _streamState = CNLiveStopStreamFailure;
  1307 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
  1308 + object:nil
  1309 + userInfo:nil];
  1310 + }
  1311 + }
  1312 +
  1313 +
  1314 + NSError *error = [CNLiveStreamerTools customErrorWithResponseObject:responseObject errorInfo:@"结束推流失败"];
  1315 +
  1316 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1317 +
  1318 + }
  1319 +
  1320 + } failure:^(NSURLResponse * _Nullable response, NSError * _Nullable error) {
  1321 +
  1322 + if (self.logPrintEnable) {
  1323 + if (remark.length > 0) {
  1324 + NSLog(@"CNLiveGPUStreamerKit-->异常结束推流error:%@,未能通知后台", remark);
  1325 + } else {
  1326 + NSLog(@"CNLiveGPUStreamerKit-->正常结束推流,未能通知后台");
  1327 + }
  1328 + }
  1329 +
  1330 + //结束推流失败通知
  1331 + _streamState = CNLiveStopStreamFailure;
  1332 + [[NSNotificationCenter defaultCenter] postNotificationName:CNLiveStreamerStateDidChangeNotification
  1333 + object:nil
  1334 + userInfo:nil];
  1335 +
  1336 + [CNLiveStreamerTools errorStat:error.userInfo.description activityId:_activityId];
  1337 +
  1338 + }];
  1339 +}
  1340 +
  1341 +//创建直播活动
  1342 +- (void)createActivityWithSuccess:(void (^)(void))successBlock failure:(void (^)(NSDictionary *))failureBlock timeString:(NSString *)timeString {
  1343 + //如果不是纯音频推流,先判断是否已开启采集状态,若未开启直接返回
  1344 + if (!_pureAudioMode) {
  1345 + if (_manager.kit.captureState != KSYCaptureStateCapturing) {
  1346 +
  1347 + NSDictionary *errorDic = @{@"errorCode": @"-101",
  1348 + @"errorMessage": @"未开启采集状态"};
  1349 +
  1350 + failureBlock ? failureBlock(errorDic) : nil;
  1351 + return;
  1352 + }
  1353 + }
  1354 +
  1355 + NSDate *date = [NSDate date];
  1356 +// NSInteger time = [date timeIntervalSince1970];
  1357 +// NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time];
  1358 +
  1359 + NSDictionary *params=@{@"platform_id":[NSBundle mainBundle].bundleIdentifier,
  1360 + @"timestamp": timeString,
  1361 + @"appId": PLAYER_AppID,
  1362 + @"isHorizontalScreen":[NSString stringWithFormat:@"%d",_isHorizontalScreen],
  1363 + @"uuid":[CNLiveStreamerTools getUidForStat:date]};
  1364 +
  1365 + [_parameter addEntriesFromDictionary:params];
  1366 +
  1367 + //避免创建活动失败,再次创建时字典中包含已加密sign
  1368 + [_parameter removeObjectForKey:@"sign"];
  1369 +
  1370 + //加密参数
  1371 + NSMutableDictionary *para = [CNLiveStreamerTools encryptionSignWithParameter:_parameter];
  1372 +
  1373 + [self requestCreateActivityParameter:para success:successBlock failure:failureBlock];
  1374 +
  1375 + [CNLiveStreamerTools statSDKWithDate:date activityId:_activityId];
  1376 +
  1377 +}
  1378 +
  1379 +
1001 @end 1380 @end
CNLivePlayer/Classes/Streamer/CNLiveStreamerTools.m
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 #import "CNLivePlayerUrl.h" 13 #import "CNLivePlayerUrl.h"
14 14
15 @implementation CNLiveStreamerTools 15 @implementation CNLiveStreamerTools
16 - 16 +#pragma mark - 加密
17 + (NSMutableDictionary *)encryptionSignWithParameter:(NSMutableDictionary *)parameter { 17 + (NSMutableDictionary *)encryptionSignWithParameter:(NSMutableDictionary *)parameter {
18 NSString *string = [NSString stringWithFormat:@"%@&key=%@",[self signvalue:parameter],PLAYER_AppKey]; 18 NSString *string = [NSString stringWithFormat:@"%@&key=%@",[self signvalue:parameter],PLAYER_AppKey];
19 NSString *signString = [[self sha1:string] uppercaseString]; 19 NSString *signString = [[self sha1:string] uppercaseString];
@@ -22,10 +22,7 @@ @@ -22,10 +22,7 @@
22 return startPara; 22 return startPara;
23 } 23 }
24 24
25 -#pragma mark -  
26 -#pragma mark - 加密  
27 -+ (NSString*)sha1:(NSString *)string  
28 -{ 25 ++ (NSString*)sha1:(NSString *)string {
29 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 26 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
30 27
31 uint8_t digest[CC_SHA1_DIGEST_LENGTH]; 28 uint8_t digest[CC_SHA1_DIGEST_LENGTH];
@@ -44,8 +41,7 @@ @@ -44,8 +41,7 @@
44 return output; 41 return output;
45 } 42 }
46 43
47 -+ (NSString *)signvalue:(NSDictionary*)parameter  
48 -{ 44 ++ (NSString *)signvalue:(NSDictionary*)parameter {
49 //对所有传入参数按照字段名的 ASCII 码从小到大排序 45 //对所有传入参数按照字段名的 ASCII 码从小到大排序
50 NSArray *keyArr=[parameter allKeys]; 46 NSArray *keyArr=[parameter allKeys];
51 NSArray *arr = [keyArr sortedArrayUsingSelector:@selector(compare:)]; 47 NSArray *arr = [keyArr sortedArrayUsingSelector:@selector(compare:)];
@@ -66,10 +62,8 @@ @@ -66,10 +62,8 @@
66 return string1; 62 return string1;
67 } 63 }
68 64
69 -#pragma mark -  
70 #pragma mark - 探针 65 #pragma mark - 探针
71 -+ (void)statSDKWithDate:(NSDate *)date activityId:(NSString *)activityId  
72 -{ 66 ++ (void)statSDKWithDate:(NSDate *)date activityId:(NSString *)activityId {
73 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 67 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
74 NSString *stamp = [NSString stringWithFormat:@"%.3f", [timeString floatValue]]; 68 NSString *stamp = [NSString stringWithFormat:@"%.3f", [timeString floatValue]];
75 stamp = [stamp stringByReplacingOccurrencesOfString:@"." withString:@""]; 69 stamp = [stamp stringByReplacingOccurrencesOfString:@"." withString:@""];
@@ -79,8 +73,7 @@ @@ -79,8 +73,7 @@
79 73
80 } 74 }
81 75
82 -+ (void)errorStat:(NSString *)errorString activityId:(NSString *)activityId  
83 -{ 76 ++ (void)errorStat:(NSString *)errorString activityId:(NSString *)activityId {
84 __block NSString *errorStr; 77 __block NSString *errorStr;
85 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) { 78 [CNLiveStreamerTools getRealTimeString:^(NSString *timeString) {
86 errorStr = [self urlEncodeUsingEncodingString:errorString]; 79 errorStr = [self urlEncodeUsingEncodingString:errorString];
@@ -101,7 +94,6 @@ @@ -101,7 +94,6 @@
101 CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)); 94 CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
102 } 95 }
103 96
104 -#pragma mark -  
105 #pragma mark - uuid 97 #pragma mark - uuid
106 + (NSString *)getUidForStat:(NSDate *)date { 98 + (NSString *)getUidForStat:(NSDate *)date {
107 NSString *uid = @""; 99 NSString *uid = @"";
@@ -138,10 +130,7 @@ @@ -138,10 +130,7 @@
138 uid = [[defauts objectForKey:@"kCNLiveUserDefaultsUIDKey"] copy]; 130 uid = [[defauts objectForKey:@"kCNLiveUserDefaultsUIDKey"] copy];
139 return uid; 131 return uid;
140 } else { 132 } else {
141 -  
142 - // NSString *stamp = [NSString stringWithFormat:@"%.3f", [date timeIntervalSince1970]];  
143 - // stamp = [stamp stringByReplacingOccurrencesOfString:@"." withString:@""];  
144 - 133 +
145 NSString *idfv = [[[[UIDevice currentDevice] identifierForVendor] UUIDString] stringByReplacingOccurrencesOfString:@"-" withString:@""]; 134 NSString *idfv = [[[[UIDevice currentDevice] identifierForVendor] UUIDString] stringByReplacingOccurrencesOfString:@"-" withString:@""];
146 uid = [NSString stringWithFormat:@"%@_%@", idfv, date]; 135 uid = [NSString stringWithFormat:@"%@_%@", idfv, date];
147 136
@@ -153,8 +142,7 @@ @@ -153,8 +142,7 @@
153 } 142 }
154 143
155 //错误信息 144 //错误信息
156 -+ (NSError *)customErrorWithResponseObject:(id)responseObject errorInfo:(NSString *) errorInfo  
157 -{ 145 ++ (NSError *)customErrorWithResponseObject:(id)responseObject errorInfo:(NSString *) errorInfo {
158 //用于探针 146 //用于探针
159 NSString *defaultErrorInfo; 147 NSString *defaultErrorInfo;
160 NSInteger errorCode = -1; 148 NSInteger errorCode = -1;
@@ -170,50 +158,18 @@ @@ -170,50 +158,18 @@
170 } 158 }
171 159
172 160
173 -+ (BOOL)isEmptyString:(NSString *)string  
174 -{ 161 ++ (BOOL)isEmptyString:(NSString *)string {
175 if (!string || ![string isKindOfClass:[NSString class]] || string.length == 0 || [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length == 0) { 162 if (!string || ![string isKindOfClass:[NSString class]] || string.length == 0 || [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length == 0) {
176 return YES; 163 return YES;
177 } 164 }
178 return NO; 165 return NO;
179 } 166 }
180 167
181 -#pragma mark -  
182 #pragma mark - 真时时间 168 #pragma mark - 真时时间
183 -+ (void)getRealTimeString:(void (^)(NSString * __nullable))realTime  
184 -{ 169 ++ (void)getRealTimeString:(void (^)(NSString * __nullable))realTime {
185 NSInteger time = [[NSDate date] timeIntervalSince1970]; 170 NSInteger time = [[NSDate date] timeIntervalSince1970];
186 NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time]; 171 NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time];
187 realTime(timeString); 172 realTime(timeString);
188 -  
189 - // [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:HTTPorHTTPs@"api.cnlive.com/open/api2/timestamp"]] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {// https://m.baidu.com  
190 - //  
191 - // if (!response) {  
192 - // NSInteger time = [[NSDate date] timeIntervalSince1970];  
193 - // NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time];  
194 - // dispatch_sync(dispatch_get_main_queue(), ^{  
195 - // realTime(timeString);  
196 - // });  
197 - // return ;  
198 - // }  
199 - //  
200 - // NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;  
201 - // NSString *timestamp = [[httpResponse allHeaderFields] objectForKey:@"Date"];  
202 - //  
203 - // NSString *timeStr = [timestamp substringWithRange:NSMakeRange(5, 20)];  
204 - // NSDateFormatter *formatter = [[NSDateFormatter alloc] init];  
205 - // NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"GMT"];  
206 - // NSLocale *local = [[NSLocale alloc]initWithLocaleIdentifier:@"en_US_POSIX"];  
207 - // [formatter setLocale:local];//需要配置区域,不然会造成模拟器正常,真机日期为null的情况  
208 - // [formatter setTimeZone:timeZone];  
209 - // [formatter setDateFormat:@"dd MMM yyyy HH:mm:ss"];//设置源时间字符串的格式  
210 - // NSDate *date = [formatter dateFromString:timeStr];//将源时间字符串转化为NSDate  
211 - //  
212 - // NSString *timeString = [NSString stringWithFormat:@"%.0f", [date timeIntervalSince1970]];  
213 - // dispatch_sync(dispatch_get_main_queue(), ^{  
214 - // realTime(timeString);  
215 - // });  
216 - // }];  
217 } 173 }
218 174
219 @end 175 @end
CNLivePlayer/Classes/Streamer/CNLiveStreamerUrl.h 0 → 100644
  1 +//
  2 +// CNLiveStreamerUrl.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 CNLiveStreamerUrl_h
  10 +#define CNLiveStreamerUrl_h
  11 +
  12 +#import "CNLivePlayerManager.h"
  13 +
  14 +#pragma mark - 推流器版本号
  15 +#define StreamerSDKVersion @"0.0.1"
  16 +
  17 +#pragma mark - 推流
  18 +//创建直播活动
  19 +#define StreamerURL [NSString stringWithFormat:@"%@/live_epg/createActivity", [CNLivePlayerManager manager].isTestEnvironment ? @"http://test.open.cnlive.com/openapi/api2" : @"http://api.cnlive.com/open/api2"]
  20 +
  21 +//启动直播活动
  22 +#define StartStreamerURL [NSString stringWithFormat:@"%@/live_epg/startActivity", [CNLivePlayerManager manager].isTestEnvironment ? @"http://test.open.cnlive.com/openapi/api2" : @"http://api.cnlive.com/open/api2"]
  23 +
  24 +//停止直播活动
  25 +#define StopStreamerURL [NSString stringWithFormat:@"%@/live_epg/stopActivity", [CNLivePlayerManager manager].isTestEnvironment ? @"http://test.open.cnlive.com/openapi/api2" : @"http://api.cnlive.com/open/api2"]
  26 +
  27 +#endif /* CNLiveStreamerUrl_h */
Example/CNLivePlayer.xcodeproj/project.pbxproj
@@ -7,13 +7,23 @@ @@ -7,13 +7,23 @@
7 objects = { 7 objects = {
8 8
9 /* Begin PBXBuildFile section */ 9 /* Begin PBXBuildFile section */
10 - 0807DF0E230799E000F409AC /* CNLivePlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0807DF0D230799E000F409AC /* CNLivePlayerController.m */; };  
11 - 085FA988230D34890072B936 /* CNLiveStreamerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 085FA987230D34890072B936 /* CNLiveStreamerController.m */; };  
12 086413BC22EAE229008713D3 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BB22EAE229008713D3 /* VideoToolbox.framework */; }; 10 086413BC22EAE229008713D3 /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BB22EAE229008713D3 /* VideoToolbox.framework */; };
13 086413BE22EAE23E008713D3 /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BD22EAE23E008713D3 /* libbz2.tbd */; }; 11 086413BE22EAE23E008713D3 /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BD22EAE23E008713D3 /* libbz2.tbd */; };
14 086413C022EAE24F008713D3 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BF22EAE24F008713D3 /* libz.tbd */; }; 12 086413C022EAE24F008713D3 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413BF22EAE24F008713D3 /* libz.tbd */; };
15 086413C222EAE591008713D3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413C122EAE591008713D3 /* OpenGLES.framework */; }; 13 086413C222EAE591008713D3 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413C122EAE591008713D3 /* OpenGLES.framework */; };
16 086413C422EAEC11008713D3 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413C322EAEC11008713D3 /* libstdc++.tbd */; }; 14 086413C422EAEC11008713D3 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 086413C322EAEC11008713D3 /* libstdc++.tbd */; };
  15 + 08740E51230E7DFB00B5D28D /* CNLiveStreamerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E3F230E7DFA00B5D28D /* CNLiveStreamerController.m */; };
  16 + 08740E52230E7DFB00B5D28D /* StreamerDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E40230E7DFA00B5D28D /* StreamerDetailViewController.m */; };
  17 + 08740E53230E7DFB00B5D28D /* FilterFunctionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E41230E7DFA00B5D28D /* FilterFunctionView.m */; };
  18 + 08740E54230E7DFB00B5D28D /* SliderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E44230E7DFA00B5D28D /* SliderView.m */; };
  19 + 08740E55230E7DFB00B5D28D /* FloatingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E45230E7DFA00B5D28D /* FloatingViewController.m */; };
  20 + 08740E56230E7DFB00B5D28D /* AudioStreamingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E46230E7DFA00B5D28D /* AudioStreamingViewController.m */; };
  21 + 08740E57230E7DFB00B5D28D /* MoreFunctionsView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E47230E7DFA00B5D28D /* MoreFunctionsView.m */; };
  22 + 08740E58230E7DFB00B5D28D /* AudioCfgView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E48230E7DFA00B5D28D /* AudioCfgView.m */; };
  23 + 08740E59230E7DFB00B5D28D /* BgmPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E4D230E7DFA00B5D28D /* BgmPlayerView.m */; };
  24 + 08740E5C230E83B100B5D28D /* LoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E5B230E83B100B5D28D /* LoadingView.m */; };
  25 + 08740E5E230E8A0700B5D28D /* house.gif in Resources */ = {isa = PBXBuildFile; fileRef = 08740E5D230E8A0700B5D28D /* house.gif */; };
  26 + 08740E62230E8C6500B5D28D /* CNLivePlayerController.m in Sources */ = {isa = PBXBuildFile; fileRef = 08740E60230E8C6500B5D28D /* CNLivePlayerController.m */; };
17 1D258610626B544AFEEFD2F9 /* Pods_CNLivePlayer_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E14DC7AF4B1116AA5BC01855 /* Pods_CNLivePlayer_Example.framework */; }; 27 1D258610626B544AFEEFD2F9 /* Pods_CNLivePlayer_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E14DC7AF4B1116AA5BC01855 /* Pods_CNLivePlayer_Example.framework */; };
18 2A57832D4B5A8EF9638641C3 /* Pods_CNLivePlayer_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDD4ACEE076815DE64A1FE2E /* Pods_CNLivePlayer_Tests.framework */; }; 28 2A57832D4B5A8EF9638641C3 /* Pods_CNLivePlayer_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDD4ACEE076815DE64A1FE2E /* Pods_CNLivePlayer_Tests.framework */; };
19 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 29 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
@@ -44,15 +54,34 @@ @@ -44,15 +54,34 @@
44 /* End PBXContainerItemProxy section */ 54 /* End PBXContainerItemProxy section */
45 55
46 /* Begin PBXFileReference section */ 56 /* Begin PBXFileReference section */
47 - 0807DF0C230799E000F409AC /* CNLivePlayerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLivePlayerController.h; sourceTree = "<group>"; };  
48 - 0807DF0D230799E000F409AC /* CNLivePlayerController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLivePlayerController.m; sourceTree = "<group>"; };  
49 - 085FA986230D34890072B936 /* CNLiveStreamerController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveStreamerController.h; sourceTree = "<group>"; };  
50 - 085FA987230D34890072B936 /* CNLiveStreamerController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveStreamerController.m; sourceTree = "<group>"; };  
51 086413BB22EAE229008713D3 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; }; 57 086413BB22EAE229008713D3 /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
52 086413BD22EAE23E008713D3 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; 58 086413BD22EAE23E008713D3 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; };
53 086413BF22EAE24F008713D3 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 59 086413BF22EAE24F008713D3 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
54 086413C122EAE591008713D3 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 60 086413C122EAE591008713D3 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
55 086413C322EAEC11008713D3 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; }; 61 086413C322EAEC11008713D3 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
  62 + 08740E3F230E7DFA00B5D28D /* CNLiveStreamerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNLiveStreamerController.m; sourceTree = "<group>"; };
  63 + 08740E40230E7DFA00B5D28D /* StreamerDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamerDetailViewController.m; sourceTree = "<group>"; };
  64 + 08740E41230E7DFA00B5D28D /* FilterFunctionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FilterFunctionView.m; sourceTree = "<group>"; };
  65 + 08740E42230E7DFA00B5D28D /* AudioCfgView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioCfgView.h; sourceTree = "<group>"; };
  66 + 08740E43230E7DFA00B5D28D /* BgmPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BgmPlayerView.h; sourceTree = "<group>"; };
  67 + 08740E44230E7DFA00B5D28D /* SliderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SliderView.m; sourceTree = "<group>"; };
  68 + 08740E45230E7DFA00B5D28D /* FloatingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FloatingViewController.m; sourceTree = "<group>"; };
  69 + 08740E46230E7DFA00B5D28D /* AudioStreamingViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioStreamingViewController.m; sourceTree = "<group>"; };
  70 + 08740E47230E7DFA00B5D28D /* MoreFunctionsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MoreFunctionsView.m; sourceTree = "<group>"; };
  71 + 08740E48230E7DFA00B5D28D /* AudioCfgView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AudioCfgView.m; sourceTree = "<group>"; };
  72 + 08740E49230E7DFA00B5D28D /* FilterFunctionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterFunctionView.h; sourceTree = "<group>"; };
  73 + 08740E4A230E7DFA00B5D28D /* StreamerDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamerDetailViewController.h; sourceTree = "<group>"; };
  74 + 08740E4B230E7DFA00B5D28D /* CNLiveStreamerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNLiveStreamerController.h; sourceTree = "<group>"; };
  75 + 08740E4C230E7DFA00B5D28D /* SliderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SliderView.h; sourceTree = "<group>"; };
  76 + 08740E4D230E7DFA00B5D28D /* BgmPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BgmPlayerView.m; sourceTree = "<group>"; };
  77 + 08740E4E230E7DFA00B5D28D /* FloatingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatingViewController.h; sourceTree = "<group>"; };
  78 + 08740E4F230E7DFA00B5D28D /* MoreFunctionsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MoreFunctionsView.h; sourceTree = "<group>"; };
  79 + 08740E50230E7DFA00B5D28D /* AudioStreamingViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioStreamingViewController.h; sourceTree = "<group>"; };
  80 + 08740E5A230E83B100B5D28D /* LoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadingView.h; sourceTree = "<group>"; };
  81 + 08740E5B230E83B100B5D28D /* LoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoadingView.m; sourceTree = "<group>"; };
  82 + 08740E5D230E8A0700B5D28D /* house.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = house.gif; sourceTree = "<group>"; };
  83 + 08740E60230E8C6500B5D28D /* CNLivePlayerController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CNLivePlayerController.m; sourceTree = "<group>"; };
  84 + 08740E61230E8C6500B5D28D /* CNLivePlayerController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CNLivePlayerController.h; sourceTree = "<group>"; };
56 17E088CE7F3FDB52D35B374B /* CNLivePlayer.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = CNLivePlayer.podspec; path = ../CNLivePlayer.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 85 17E088CE7F3FDB52D35B374B /* CNLivePlayer.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = CNLivePlayer.podspec; path = ../CNLivePlayer.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
57 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>"; }; 86 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>"; };
58 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>"; }; 87 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>"; };
@@ -127,6 +156,43 @@ @@ -127,6 +156,43 @@
127 path = Pods; 156 path = Pods;
128 sourceTree = "<group>"; 157 sourceTree = "<group>";
129 }; 158 };
  159 + 08740E3E230E7DFA00B5D28D /* Streamer */ = {
  160 + isa = PBXGroup;
  161 + children = (
  162 + 08740E5D230E8A0700B5D28D /* house.gif */,
  163 + 08740E4B230E7DFA00B5D28D /* CNLiveStreamerController.h */,
  164 + 08740E3F230E7DFA00B5D28D /* CNLiveStreamerController.m */,
  165 + 08740E4A230E7DFA00B5D28D /* StreamerDetailViewController.h */,
  166 + 08740E40230E7DFA00B5D28D /* StreamerDetailViewController.m */,
  167 + 08740E5A230E83B100B5D28D /* LoadingView.h */,
  168 + 08740E5B230E83B100B5D28D /* LoadingView.m */,
  169 + 08740E50230E7DFA00B5D28D /* AudioStreamingViewController.h */,
  170 + 08740E46230E7DFA00B5D28D /* AudioStreamingViewController.m */,
  171 + 08740E4E230E7DFA00B5D28D /* FloatingViewController.h */,
  172 + 08740E45230E7DFA00B5D28D /* FloatingViewController.m */,
  173 + 08740E49230E7DFA00B5D28D /* FilterFunctionView.h */,
  174 + 08740E41230E7DFA00B5D28D /* FilterFunctionView.m */,
  175 + 08740E42230E7DFA00B5D28D /* AudioCfgView.h */,
  176 + 08740E48230E7DFA00B5D28D /* AudioCfgView.m */,
  177 + 08740E43230E7DFA00B5D28D /* BgmPlayerView.h */,
  178 + 08740E4D230E7DFA00B5D28D /* BgmPlayerView.m */,
  179 + 08740E4C230E7DFA00B5D28D /* SliderView.h */,
  180 + 08740E44230E7DFA00B5D28D /* SliderView.m */,
  181 + 08740E4F230E7DFA00B5D28D /* MoreFunctionsView.h */,
  182 + 08740E47230E7DFA00B5D28D /* MoreFunctionsView.m */,
  183 + );
  184 + path = Streamer;
  185 + sourceTree = "<group>";
  186 + };
  187 + 08740E5F230E8C6500B5D28D /* Player */ = {
  188 + isa = PBXGroup;
  189 + children = (
  190 + 08740E60230E8C6500B5D28D /* CNLivePlayerController.m */,
  191 + 08740E61230E8C6500B5D28D /* CNLivePlayerController.h */,
  192 + );
  193 + path = Player;
  194 + sourceTree = "<group>";
  195 + };
130 6003F581195388D10070C39A = { 196 6003F581195388D10070C39A = {
131 isa = PBXGroup; 197 isa = PBXGroup;
132 children = ( 198 children = (
@@ -171,10 +237,8 @@ @@ -171,10 +237,8 @@
171 children = ( 237 children = (
172 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */, 238 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */,
173 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */, 239 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */,
174 - 0807DF0C230799E000F409AC /* CNLivePlayerController.h */,  
175 - 0807DF0D230799E000F409AC /* CNLivePlayerController.m */,  
176 - 085FA986230D34890072B936 /* CNLiveStreamerController.h */,  
177 - 085FA987230D34890072B936 /* CNLiveStreamerController.m */, 240 + 08740E5F230E8C6500B5D28D /* Player */,
  241 + 08740E3E230E7DFA00B5D28D /* Streamer */,
178 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */, 242 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */,
179 6003F5A5195388D20070C39A /* CNLiveViewController.h */, 243 6003F5A5195388D20070C39A /* CNLiveViewController.h */,
180 6003F5A6195388D20070C39A /* CNLiveViewController.m */, 244 6003F5A6195388D20070C39A /* CNLiveViewController.m */,
@@ -311,6 +375,7 @@ @@ -311,6 +375,7 @@
311 buildActionMask = 2147483647; 375 buildActionMask = 2147483647;
312 files = ( 376 files = (
313 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */, 377 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */,
  378 + 08740E5E230E8A0700B5D28D /* house.gif in Resources */,
314 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */, 379 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
315 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 380 6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
316 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 381 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
@@ -381,6 +446,7 @@ @@ -381,6 +446,7 @@
381 "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework", 446 "${BUILT_PRODUCTS_DIR}/CocoaLumberjack/CocoaLumberjack.framework",
382 "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework", 447 "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
383 "${BUILT_PRODUCTS_DIR}/GPUImage/GPUImage.framework", 448 "${BUILT_PRODUCTS_DIR}/GPUImage/GPUImage.framework",
  449 + "${BUILT_PRODUCTS_DIR}/YYImage/YYImage.framework",
384 "${BUILT_PRODUCTS_DIR}/libksygpulive/libksygpulive.framework", 450 "${BUILT_PRODUCTS_DIR}/libksygpulive/libksygpulive.framework",
385 ); 451 );
386 name = "[CP] Embed Pods Frameworks"; 452 name = "[CP] Embed Pods Frameworks";
@@ -392,6 +458,7 @@ @@ -392,6 +458,7 @@
392 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework", 458 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CocoaLumberjack.framework",
393 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework", 459 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
394 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GPUImage.framework", 460 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GPUImage.framework",
  461 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYImage.framework",
395 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libksygpulive.framework", 462 "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libksygpulive.framework",
396 ); 463 );
397 runOnlyForDeploymentPostprocessing = 0; 464 runOnlyForDeploymentPostprocessing = 0;
@@ -428,11 +495,20 @@ @@ -428,11 +495,20 @@
428 isa = PBXSourcesBuildPhase; 495 isa = PBXSourcesBuildPhase;
429 buildActionMask = 2147483647; 496 buildActionMask = 2147483647;
430 files = ( 497 files = (
  498 + 08740E58230E7DFB00B5D28D /* AudioCfgView.m in Sources */,
  499 + 08740E5C230E83B100B5D28D /* LoadingView.m in Sources */,
  500 + 08740E55230E7DFB00B5D28D /* FloatingViewController.m in Sources */,
431 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */, 501 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */,
432 - 0807DF0E230799E000F409AC /* CNLivePlayerController.m in Sources */, 502 + 08740E52230E7DFB00B5D28D /* StreamerDetailViewController.m in Sources */,
433 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */, 503 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */,
  504 + 08740E56230E7DFB00B5D28D /* AudioStreamingViewController.m in Sources */,
  505 + 08740E62230E8C6500B5D28D /* CNLivePlayerController.m in Sources */,
  506 + 08740E54230E7DFB00B5D28D /* SliderView.m in Sources */,
434 6003F59A195388D20070C39A /* main.m in Sources */, 507 6003F59A195388D20070C39A /* main.m in Sources */,
435 - 085FA988230D34890072B936 /* CNLiveStreamerController.m in Sources */, 508 + 08740E59230E7DFB00B5D28D /* BgmPlayerView.m in Sources */,
  509 + 08740E57230E7DFB00B5D28D /* MoreFunctionsView.m in Sources */,
  510 + 08740E53230E7DFB00B5D28D /* FilterFunctionView.m in Sources */,
  511 + 08740E51230E7DFB00B5D28D /* CNLiveStreamerController.m in Sources */,
436 ); 512 );
437 runOnlyForDeploymentPostprocessing = 0; 513 runOnlyForDeploymentPostprocessing = 0;
438 }; 514 };
Example/CNLivePlayer/CNLiveStreamerController.m deleted 100644 → 0
1 -//  
2 -// CNLiveStreamerController.m  
3 -// CNLivePlayer_Example  
4 -//  
5 -// Created by CNLive-zxw on 2019/8/21.  
6 -// Copyright © 2019 153993236@qq.com. All rights reserved.  
7 -//  
8 -  
9 -#import "CNLiveStreamerController.h"  
10 -  
11 -@interface CNLiveStreamerController ()  
12 -  
13 -@end  
14 -  
15 -@implementation CNLiveStreamerController  
16 -  
17 -- (void)viewDidLoad {  
18 - [super viewDidLoad];  
19 - // Do any additional setup after loading the view.  
20 - self.view.backgroundColor = [UIColor whiteColor];  
21 - UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];  
22 - btn2.frame = CGRectMake(0, 0, 100, 50);  
23 - btn2.center = CGPointMake(self.view.center.x, self.view.center.y+50);  
24 - btn2.backgroundColor = [UIColor redColor];  
25 - [btn2 setTitle:@"返回" forState:UIControlStateNormal];  
26 - [btn2 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];  
27 - [btn2 addTarget:self action:@selector(btnDidClicked2) forControlEvents:UIControlEventTouchUpInside];  
28 - [self.view addSubview:btn2];  
29 -}  
30 -  
31 -  
32 -- (void)btnDidClicked2{  
33 - [self dismissViewControllerAnimated:YES completion:nil];  
34 -  
35 -}  
36 -  
37 -/*  
38 -#pragma mark - Navigation  
39 -  
40 -// In a storyboard-based application, you will often want to do a little preparation before navigation  
41 -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {  
42 - // Get the new view controller using [segue destinationViewController].  
43 - // Pass the selected object to the new view controller.  
44 -}  
45 -*/  
46 -  
47 -@end  
Example/CNLivePlayer/Images.xcassets/Contents.json 0 → 100644
  1 +{
  2 + "info" : {
  3 + "version" : 1,
  4 + "author" : "xcode"
  5 + }
  6 +}
0 \ No newline at end of file 7 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/Contents.json 0 → 100644
  1 +{
  2 + "info" : {
  3 + "version" : 1,
  4 + "author" : "xcode"
  5 + }
  6 +}
0 \ No newline at end of file 7 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/back.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "back.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/back.imageset/back.png 0 → 100644

1.16 KB

Example/CNLivePlayer/Images.xcassets/Streamer/big_pause_button.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "big_pause_button.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/big_pause_button.imageset/big_pause_button.png 0 → 100644

3.7 KB

Example/CNLivePlayer/Images.xcassets/Streamer/big_play_button.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "big_play_button.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/big_play_button.imageset/big_play_button.png 0 → 100644

3.68 KB

Example/CNLivePlayer/Images.xcassets/Streamer/btn_dot.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "btn_dot.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/btn_dot.imageset/btn_dot.png 0 → 100644

627 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/cache setting.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "cache setting.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/cache setting.imageset/cache setting.png 0 → 100644

1.26 KB

Example/CNLivePlayer/Images.xcassets/Streamer/camera.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "camera.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/camera.imageset/camera.png 0 → 100644

1.4 KB

Example/CNLivePlayer/Images.xcassets/Streamer/cancel.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "cancel.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/cancel.imageset/cancel.png 0 → 100644

1.14 KB

Example/CNLivePlayer/Images.xcassets/Streamer/fanhui.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "fanhui.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/fanhui.imageset/fanhui.png 0 → 100644

983 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/filter.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "filter.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/filter.imageset/filter.png 0 → 100644

1.18 KB

Example/CNLivePlayer/Images.xcassets/Streamer/flash close.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "flash close.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/flash close.imageset/flash close.png 0 → 100644

1.13 KB

Example/CNLivePlayer/Images.xcassets/Streamer/flash open.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "flash open.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/flash open.imageset/flash open.png 0 → 100644

1.21 KB

Example/CNLivePlayer/Images.xcassets/Streamer/loop_all_icon.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "loop_all_icon.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/loop_all_icon.imageset/loop_all_icon.png 0 → 100644

840 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/loop_single_icon.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "loop_single_icon.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/loop_single_icon.imageset/loop_single_icon.png 0 → 100644

948 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/menu.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "menu.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/menu.imageset/menu.png 0 → 100644

296 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/music_slider_circle.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "music_slider_circle.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/music_slider_circle.imageset/music_slider_circle.png 0 → 100644

1.07 KB

Example/CNLivePlayer/Images.xcassets/Streamer/next_song.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "next_song.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/next_song.imageset/next_song.png 0 → 100644

814 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/pause.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "pause.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/pause.imageset/pause.png 0 → 100644

3.15 KB

Example/CNLivePlayer/Images.xcassets/Streamer/play.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "play.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/play.imageset/play.png 0 → 100644

6.41 KB

Example/CNLivePlayer/Images.xcassets/Streamer/prev_song.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "prev_song.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/prev_song.imageset/prev_song.png 0 → 100644

845 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/shuffle_icon.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "shuffle_icon.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/shuffle_icon.imageset/shuffle_icon.png 0 → 100644

802 Bytes

Example/CNLivePlayer/Images.xcassets/Streamer/voice.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "voice.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/voice.imageset/voice.png 0 → 100644

1.27 KB

Example/CNLivePlayer/Images.xcassets/Streamer/互动电视180x180.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "互动电视180x180.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/互动电视180x180.imageset/互动电视180x180.png 0 → 100644

21.2 KB

Example/CNLivePlayer/Images.xcassets/Streamer/更多.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "更多.png",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/更多.imageset/更多.png 0 → 100644

1.38 KB

Example/CNLivePlayer/Images.xcassets/Streamer/背景.imageset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "universal",
  5 + "filename" : "背景.jpg",
  6 + "scale" : "1x"
  7 + },
  8 + {
  9 + "idiom" : "universal",
  10 + "scale" : "2x"
  11 + },
  12 + {
  13 + "idiom" : "universal",
  14 + "scale" : "3x"
  15 + }
  16 + ],
  17 + "info" : {
  18 + "version" : 1,
  19 + "author" : "xcode"
  20 + }
  21 +}
0 \ No newline at end of file 22 \ No newline at end of file
Example/CNLivePlayer/Images.xcassets/Streamer/背景.imageset/背景.jpg 0 → 100644

17.1 KB

Example/CNLivePlayer/CNLivePlayerController.h renamed to Example/CNLivePlayer/Player/CNLivePlayerController.h
Example/CNLivePlayer/CNLivePlayerController.m renamed to Example/CNLivePlayer/Player/CNLivePlayerController.m
Example/CNLivePlayer/Streamer/AudioCfgView.h 0 → 100644
  1 +//
  2 +// AudioCfgView.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/4/26.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +typedef void(^AudioEffectBlock)(int type); //音效回调
  12 +typedef void(^ReverbTypeBlock)(int type); //混响回调
  13 +typedef void(^BPlayCapturedAudioBlock)(BOOL isOn); //是否开启耳返
  14 +typedef void(^MicVolumeBlock)(float micVolume); //麦克风音量
  15 +typedef void(^BPlayVolumeBlock)(float bPlayVolume); //耳返音量
  16 +
  17 +@interface AudioCfgView : UIView
  18 +
  19 +@property (nonatomic, strong) UISwitch *bPlaySwitch;
  20 +
  21 +@property (nonatomic, copy) AudioEffectBlock audioEffectBlock;
  22 +@property (nonatomic, copy) ReverbTypeBlock reverbTypeBlock;
  23 +@property (nonatomic, copy) BPlayCapturedAudioBlock bPlayCapturedAudio;
  24 +@property (nonatomic, copy) MicVolumeBlock micVolumeBlock;
  25 +@property (nonatomic, copy) BPlayVolumeBlock bPlayVolumeBlock;
  26 +
  27 +@end
Example/CNLivePlayer/Streamer/AudioCfgView.m 0 → 100644
  1 +//
  2 +// AudioCfgView.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/4/26.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "AudioCfgView.h"
  10 +
  11 +@interface AudioCfgView ()
  12 +
  13 +@property (nonatomic, strong) UISegmentedControl *audioEffectType;
  14 +@property (nonatomic, strong) UISegmentedControl *reverbType;
  15 +@property (nonatomic, strong) UISlider *micVolumeSlider;
  16 +@property (nonatomic, strong) UISlider *bPlayVolumeSlider;
  17 +
  18 +@end
  19 +
  20 +@implementation AudioCfgView
  21 +
  22 +- (instancetype)initWithFrame:(CGRect)frame
  23 +{
  24 + self = [super initWithFrame:frame];
  25 + if (self) {
  26 + self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
  27 + [self addSubview:self.audioEffectType];
  28 + [self addSubview:self.reverbType];
  29 + [self addSubview:self.bPlaySwitch];
  30 + [self addSubview:self.micVolumeSlider];
  31 + [self addSubview:self.bPlayVolumeSlider];
  32 + }
  33 + return self;
  34 +}
  35 +
  36 +#pragma mark -
  37 +#pragma mark - action
  38 +- (void)audioEffect:(UISegmentedControl *)sender {
  39 + self.audioEffectBlock ? self.audioEffectBlock((int)sender.selectedSegmentIndex) : nil;
  40 +}
  41 +
  42 +- (void)reverbType:(UISegmentedControl *)sender {
  43 + self.reverbTypeBlock ? self.reverbTypeBlock((int)sender.selectedSegmentIndex) : nil;
  44 +}
  45 +
  46 +-(void)switchAction:(id)sender {
  47 + UISwitch *swi = (UISwitch *)sender;
  48 + self.bPlayCapturedAudio ? self.bPlayCapturedAudio(swi.on) : nil;
  49 +}
  50 +
  51 +- (void)micVolumeChanged:(UISlider *)slider {
  52 + self.micVolumeBlock ? self.micVolumeBlock(slider.value) : nil;
  53 +}
  54 +
  55 +- (void)bPlayVolumeChanged:(UISlider *)slider {
  56 + self.bPlayVolumeBlock ? self.bPlayVolumeBlock(slider.value) : nil;
  57 +}
  58 +
  59 +#pragma mark -
  60 +#pragma mark - getter
  61 +- (UISegmentedControl *)audioEffectType
  62 +{
  63 + if (!_audioEffectType) {
  64 + NSArray *items = @[ @"关闭",
  65 + @"大叔",
  66 + @"萝莉",
  67 + @"庄严",
  68 + @"机器人"];
  69 +
  70 + _audioEffectType = [[UISegmentedControl alloc] initWithItems:items];
  71 + _audioEffectType.frame = CGRectMake(60, 50, self.bounds.size.width-70, 30);
  72 + _audioEffectType.tintColor= [UIColor blackColor];
  73 + _audioEffectType.selectedSegmentIndex = 0;
  74 + _audioEffectType.layer.cornerRadius = 5;
  75 + [_audioEffectType addTarget:self action:@selector(audioEffect:) forControlEvents:UIControlEventValueChanged];
  76 +
  77 + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 55, 40, 20)];
  78 + label.text = @"变声";
  79 + [self addSubview:label];
  80 + }
  81 + return _audioEffectType;
  82 +}
  83 +
  84 +- (UISegmentedControl *)reverbType
  85 +{
  86 + if (!_reverbType) {
  87 + NSArray *items = @[ @"关闭",
  88 + @"录音棚",
  89 + @"演唱会",
  90 + @"KTV",
  91 + @"小舞台"];
  92 +
  93 + _reverbType = [[UISegmentedControl alloc] initWithItems:items];
  94 + _reverbType.frame = CGRectMake(60, 90, self.bounds.size.width-70, 30);
  95 + _reverbType.tintColor= [UIColor blackColor];
  96 + _reverbType.selectedSegmentIndex = 0;
  97 + _reverbType.layer.cornerRadius = 5;
  98 + [_reverbType addTarget:self action:@selector(reverbType:) forControlEvents:UIControlEventValueChanged];
  99 +
  100 + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 95, 40, 20)];
  101 + label.text = @"混响";
  102 + [self addSubview:label];
  103 + }
  104 + return _reverbType;
  105 +}
  106 +
  107 +- (UISwitch *)bPlaySwitch
  108 +{
  109 + if (!_bPlaySwitch) {
  110 + _bPlaySwitch = [[UISwitch alloc] initWithFrame:CGRectMake(60, 10, 100, 30)];
  111 + [_bPlaySwitch addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged];
  112 + UILabel *modeLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 15, 40, 20)];
  113 + modeLab.textColor = [UIColor blackColor];
  114 + modeLab.text = @"耳返";
  115 + [self addSubview:modeLab];
  116 + }
  117 + return _bPlaySwitch;
  118 +}
  119 +
  120 +- (UISlider *)micVolumeSlider
  121 +{
  122 + if (!_micVolumeSlider) {
  123 + _micVolumeSlider = [[UISlider alloc] initWithFrame:CGRectMake(100, 135, self.bounds.size.width-110, 24)];
  124 + [_micVolumeSlider setMinimumTrackTintColor:[UIColor redColor]];
  125 + [_micVolumeSlider setMaximumTrackTintColor:[UIColor whiteColor]];
  126 + _micVolumeSlider.value = 1.0;
  127 + [_micVolumeSlider addTarget:self action:@selector(micVolumeChanged:) forControlEvents:UIControlEventValueChanged];
  128 + [_micVolumeSlider setThumbImage:[UIImage imageNamed:@"btn_dot"] forState:UIControlStateNormal];
  129 +
  130 +
  131 + UILabel *micLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 135, 90, 20)];
  132 + micLab.textColor = [UIColor blackColor];
  133 + micLab.text = @"麦克风音量";
  134 + [self addSubview:micLab];
  135 + }
  136 + return _micVolumeSlider;
  137 +}
  138 +
  139 +- (UISlider *)bPlayVolumeSlider
  140 +{
  141 + if (!_bPlayVolumeSlider) {
  142 + _bPlayVolumeSlider = [[UISlider alloc] initWithFrame:CGRectMake(100, 170, self.bounds.size.width-110, 24)];
  143 + _bPlayVolumeSlider.value = 1.0;
  144 + [_bPlayVolumeSlider setMinimumTrackTintColor:[UIColor redColor]];
  145 + [_bPlayVolumeSlider setMaximumTrackTintColor:[UIColor whiteColor]];
  146 + [_bPlayVolumeSlider addTarget:self action:@selector(bPlayVolumeChanged:) forControlEvents:UIControlEventValueChanged];
  147 + [_bPlayVolumeSlider setThumbImage:[UIImage imageNamed:@"btn_dot"] forState:UIControlStateNormal];
  148 +
  149 + UILabel *micLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 170, 80, 20)];
  150 + micLab.textColor = [UIColor blackColor];
  151 + micLab.text = @"耳返音量";
  152 + [self addSubview:micLab];
  153 + }
  154 + return _bPlayVolumeSlider;
  155 +}
  156 +
  157 +/*
  158 +// Only override drawRect: if you perform custom drawing.
  159 +// An empty implementation adversely affects performance during animation.
  160 +- (void)drawRect:(CGRect)rect {
  161 + // Drawing code
  162 +}
  163 +*/
  164 +
  165 +@end
Example/CNLivePlayer/Streamer/AudioStreamingViewController.h 0 → 100644
  1 +//
  2 +// AudioStreamingViewController.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/4/26.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +@interface AudioStreamingViewController : UIViewController
  12 +
  13 +@property (nonatomic, assign) BOOL isAuthLive;
  14 +
  15 +@property (nonatomic, strong) NSURL *url;
  16 +
  17 +@end
Example/CNLivePlayer/Streamer/AudioStreamingViewController.m 0 → 100644
  1 +//
  2 +// AudioStreamingViewController.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/4/26.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "AudioStreamingViewController.h"
  10 +#import "CNLiveStreamerManager.h"
  11 +#import "CNLiveStreamerKit.h"
  12 +#import "AudioCfgView.h"
  13 +#import "BgmPlayerView.h"
  14 +#import "CNLiveStreamerBase.h"
  15 +#import "CNLiveWatermark.h"
  16 +#import "CNLiveAudioCapture.h"
  17 +#import "CNLiveBgmPlayer.h"
  18 +
  19 +#define Width [UIScreen mainScreen].bounds.size.width
  20 +#define Height [UIScreen mainScreen].bounds.size.height
  21 +
  22 +@interface AudioStreamingViewController ()<BgmPlayerViewDelegate>
  23 +{
  24 + UIButton *_startLiveBtn;
  25 + NSArray *_listArr;
  26 + NSInteger _currentIndex;
  27 + NSTimer *_currentTimer;
  28 + BOOL _playMode; //播放模式
  29 +}
  30 +
  31 +@property (nonatomic,strong) CNLiveStreamerKit *kitCN; //直播推流
  32 +@property (nonatomic,strong) UILabel *stateLab;
  33 +@property (nonatomic,strong) AudioCfgView *audioCfgView; //声音相关设置
  34 +@property (nonatomic,strong) BgmPlayerView *bgmPlayerView; //背景音乐
  35 +
  36 +@end
  37 +
  38 +@implementation AudioStreamingViewController
  39 +
  40 +- (void)viewDidLoad {
  41 + [super viewDidLoad];
  42 + // Do any additional setup after loading the view.
  43 + self.view.backgroundColor = [UIColor whiteColor];
  44 + [self.view addSubview:self.stateLab];
  45 + [self.view addSubview:self.audioCfgView];
  46 + [self.view addSubview:self.bgmPlayerView];
  47 +
  48 + _currentTimer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
  49 +
  50 +
  51 + if (_isAuthLive) {
  52 +
  53 + NSDate *date = [NSDate date];
  54 + NSInteger time = [date timeIntervalSince1970];
  55 + NSString *activityId = [NSString stringWithFormat:@"%ld", (long)time];
  56 +
  57 + _kitCN = [[CNLiveStreamerKit alloc] initPureAudioStreamerWithDefaultConfig];
  58 + _kitCN.activityId = activityId;
  59 + _kitCN.channelId = @"iostest";
  60 +
  61 + [self setStreamerCfg];
  62 + [self addObservers];
  63 +
  64 + }else{
  65 +
  66 + _kitCN = [[CNLiveStreamerKit alloc] initWithDefaultConfig:YES];
  67 +
  68 + [self setStreamerCfg];
  69 + [self addObservers];
  70 +
  71 + }
  72 +
  73 + _startLiveBtn = [self addButton:@"开始直播" frame:CGRectMake(10, 40, 80, 40) action:@selector(startStreaming:)];
  74 + [_startLiveBtn setTitle:@"开始直播" forState:UIControlStateNormal];
  75 + [_startLiveBtn setTitle:@"停止直播" forState:UIControlStateSelected];
  76 +
  77 + [self addButton:@"退出" frame:CGRectMake(100, 40, 80, 40) action:@selector(quit)];
  78 + [self addButton:@"背景音乐" frame:CGRectMake(10, 100, 80, 40) action:@selector(bgmPlayerBtnAction:)];
  79 + [self addButton:@"声音" frame:CGRectMake(100, 100, 80, 40) action:@selector(voiceBtnAction:)];
  80 +
  81 + _listArr = @[@" See You Again ",
  82 + @"Idina Menzel - Let It Go",
  83 + @"Morrie - Lullaby",
  84 + @"Zedd,Alessia Cara - Stay"];
  85 +}
  86 +
  87 +- (void)setStreamerCfg {
  88 + _kitCN.streamerBase.audiokBPS = 48;
  89 +
  90 + //声音相关设置
  91 + __weak AudioStreamingViewController *weakself = self;
  92 +
  93 + _audioCfgView.audioEffectBlock = ^(int type) { //音效
  94 + weakself.kitCN.audioCapture.audioEffectType = type;
  95 + };
  96 +
  97 + _audioCfgView.reverbTypeBlock = ^(int type) { //混响
  98 + weakself.kitCN.audioCapture.reverbType = type;
  99 + };
  100 +
  101 + _audioCfgView.bPlayCapturedAudio = ^(BOOL isOn) { //耳返
  102 + if ([CNLiveAudioCapture isHeadsetPluggedIn]) {
  103 + [weakself.kitCN.audioCapture setBPlayCapturedAudio:isOn];
  104 + } else {
  105 + weakself.audioCfgView.bPlaySwitch.on = NO;
  106 + [weakself toast:@"未检测到耳机"];
  107 + }
  108 + };
  109 +
  110 + _audioCfgView.micVolumeBlock = ^(float micVolume) { //麦克风音量
  111 + weakself.kitCN.audioCapture.micVolume = micVolume;
  112 + };
  113 +
  114 + _audioCfgView.bPlayVolumeBlock = ^(float bPlayVolume) { //耳返音量
  115 + weakself.kitCN.audioCapture.bPlayVolume = bPlayVolume;
  116 + };
  117 +
  118 + _kitCN.bgmPlayer.cnBgmFinishBlock = ^{
  119 + if (!_playMode) {
  120 + if (_currentIndex != 3) {
  121 + _currentIndex ++;
  122 + [_kitCN.bgmPlayer stopPlayBgm];
  123 + [_kitCN.bgmPlayer startPlayBgm:[[NSBundle mainBundle] pathForResource:_listArr[_currentIndex] ofType:@"mp3"] isLoop:_playMode];
  124 + _bgmPlayerView.songTitleLab.text = _listArr[_currentIndex];
  125 + }
  126 + }
  127 + };
  128 +
  129 +}
  130 +
  131 +- (UIButton *)addButton:(NSString*)title
  132 + frame:(CGRect)frame
  133 + action:(SEL)action {
  134 + UIButton * button;
  135 + button = [UIButton buttonWithType:UIButtonTypeCustom];
  136 + button.frame = frame;
  137 + [button setTitle: title forState: UIControlStateNormal];
  138 + [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
  139 + button.titleLabel.font = [UIFont systemFontOfSize:15];
  140 + [button setTitleColor:[UIColor colorWithRed:23/255.0 green:110/255.0 blue:254/255.0 alpha:1] forState:UIControlStateNormal];
  141 + button.layer.cornerRadius = 10;
  142 + button.layer.masksToBounds = YES;
  143 + button.layer.borderColor = [UIColor blackColor].CGColor;
  144 + button.layer.borderWidth = 1;
  145 + [self.view addSubview:button];
  146 + return button;
  147 +
  148 +}
  149 +
  150 +#pragma mark -
  151 +#pragma mark - action
  152 +- (void)startStreaming:(UIButton *)button {
  153 + button.selected = !button.selected;
  154 +
  155 + if (button.selected) {
  156 +
  157 + if (_isAuthLive) {
  158 +
  159 + [_kitCN startStream:^{
  160 + NSLog(@"开启推流成功 ------- success");
  161 + } failure:^(NSDictionary *errorDic) {
  162 + [self toast:errorDic[@"errorMessage"]];
  163 + _startLiveBtn.selected = NO;
  164 + }];
  165 +
  166 + }else{
  167 + [_kitCN startStream:self.url];
  168 + }
  169 + }else{
  170 + _stateLab.text = nil;
  171 + [_kitCN stopStream];
  172 + }
  173 +}
  174 +
  175 +- (void)quit {
  176 + if (_kitCN.streamState == CNLiveStreamStateConnected) {
  177 + [_kitCN stopStream];
  178 + }
  179 +
  180 + if (_kitCN.bgmPlayer.isRunning) {
  181 + [_kitCN.bgmPlayer stopPlayBgm];
  182 + }
  183 +
  184 + if (_currentTimer) {
  185 + [_currentTimer invalidate];
  186 + _currentTimer = nil;
  187 + }
  188 +
  189 + [_kitCN quitStreaming];
  190 + self.kitCN = nil;
  191 + [[NSNotificationCenter defaultCenter] removeObserver:self];
  192 +
  193 + [self dismissViewControllerAnimated:YES completion:NULL];
  194 +}
  195 +
  196 +- (void)bgmPlayerBtnAction:(UIButton *)button {
  197 + _audioCfgView.hidden = YES;
  198 + _bgmPlayerView.hidden = button.selected;
  199 + button.selected = !button.selected;
  200 +}
  201 +
  202 +- (void)voiceBtnAction:(UIButton *)button {
  203 + _bgmPlayerView.hidden = YES;
  204 + _audioCfgView.hidden = button.selected;
  205 + button.selected = !button.selected;
  206 +}
  207 +
  208 +- (void)timeChange
  209 +{
  210 + _bgmPlayerView.proSlider.value = _kitCN.bgmPlayer.bgmPlayTime/_kitCN.bgmPlayer.bgmDuration;
  211 + _bgmPlayerView.currentTimeLab.text = [self getMMSSFromSS:[NSString stringWithFormat:@"%f",_kitCN.bgmPlayer.bgmPlayTime]];
  212 + _bgmPlayerView.duraTimeLab.text = [self getMMSSFromSS:[NSString stringWithFormat:@"%f",_kitCN.bgmPlayer.bgmDuration]];
  213 +}
  214 +
  215 +- (NSString *)getMMSSFromSS:(NSString *)totalTime {
  216 + NSInteger seconds = [totalTime integerValue];
  217 + NSString *str_minute = [NSString stringWithFormat:@"%02ld",(seconds%3600)/60];
  218 + NSString *str_second = [NSString stringWithFormat:@"%02ld",seconds%60];
  219 + NSString *format_time = [NSString stringWithFormat:@"%@:%@",str_minute,str_second];
  220 + return format_time;
  221 +}
  222 +
  223 +#pragma mark -
  224 +#pragma mark - BgmPlayerViewDelegate
  225 +- (void)valueType:(BOOL)isVolume value:(float)value {
  226 + if (isVolume) {
  227 + _kitCN.bgmPlayer.bgmVolume = value;
  228 + } else {
  229 + _kitCN.bgmPlayer.bgmPitch = value;
  230 + }
  231 +}
  232 +
  233 +- (void)bgmPlayerPlay:(UIButton *)button {
  234 + if (_kitCN.bgmPlayer.isRunning) {
  235 + [_kitCN.bgmPlayer stopPlayBgm];
  236 + } else {
  237 + NSString *path = [[NSBundle mainBundle] pathForResource:_listArr[_currentIndex] ofType:@"mp3"];
  238 + _bgmPlayerView.songTitleLab.text = _listArr[_currentIndex];
  239 + [_kitCN.bgmPlayer startPlayBgm:path isLoop:_playMode];
  240 + }
  241 +}
  242 +
  243 +- (void)bgmPlayerMode:(UIButton *)button {
  244 + _kitCN.bgmPlayer.bLoop = button.selected;
  245 + _playMode = _kitCN.bgmPlayer.bLoop;
  246 +}
  247 +
  248 +- (void)bgmPlayerPauseOrResume:(UIButton *)button {
  249 + if (button.selected) {
  250 + [_kitCN.bgmPlayer pauseBgm];
  251 + } else {
  252 + [_kitCN.bgmPlayer resumeBgm];
  253 + }
  254 +}
  255 +
  256 +- (void)bgmPlayerLast:(UIButton *)button {
  257 + /*
  258 + if (_currentIndex == 0) {
  259 + [self toast:@"已经是第一首"];
  260 + } else {
  261 + _currentIndex --;
  262 + [_kitCN.bgmPlayer stopPlayBgm];
  263 + [_kitCN.bgmPlayer startPlayBgm:[[NSBundle mainBundle] pathForResource:_listArr[_currentIndex] ofType:@"mp3"] isLoop:_playMode];
  264 + _bgmPlayerView.songTitleLab.text = _listArr[_currentIndex];
  265 + }
  266 + */
  267 +
  268 + [_kitCN.streamerBase muteStream:button.selected];
  269 +}
  270 +
  271 +- (void)bgmPlayerNext:(UIButton *)button; {
  272 + if (_currentIndex == 3) {
  273 + [self toast:@"已经是最后一首"];
  274 + } else {
  275 + _currentIndex ++;
  276 + [_kitCN.bgmPlayer stopPlayBgm];
  277 + [_kitCN.bgmPlayer startPlayBgm:[[NSBundle mainBundle] pathForResource:_listArr[_currentIndex] ofType:@"mp3"] isLoop:_playMode];
  278 + _bgmPlayerView.songTitleLab.text = _listArr[_currentIndex];
  279 + }
  280 +}
  281 +
  282 +- (void)bgmPlayerProgressSlider:(UISlider *)slider {
  283 + [_kitCN.bgmPlayer seekToProgress:slider.value];
  284 +}
  285 +
  286 +#pragma mark -
  287 +#pragma mark - notification
  288 +- (void)addObservers
  289 +{
  290 + [[NSNotificationCenter defaultCenter] addObserver:self
  291 + selector:@selector(streamStateChange)
  292 + name:CNLiveStreamerStateDidChangeNotification
  293 + object:nil];
  294 +}
  295 +
  296 +- (void)streamStateChange
  297 +{
  298 +
  299 + if (_kitCN.streamState == CNLiveStreamStateIdle) {
  300 + NSLog(@"---------CNLiveStreamStateIdle");
  301 + _stateLab.text = @"CNLiveStreamStateIdle";
  302 + }
  303 +
  304 + if (_kitCN.streamState == CNLiveStreamStateConnected) {
  305 + _startLiveBtn.selected = YES;
  306 + NSLog(@"---------CNLiveStreamStateConnected");
  307 + _stateLab.text = [NSString stringWithFormat:@"CNLiveStreamStateConnected------%@",self.url];
  308 + }
  309 +
  310 + if (_kitCN.streamState == CNLiveStreamStateConnecting) {
  311 + NSLog(@"---------CNLiveStreamStateConnecting");
  312 + _stateLab.text = @"CNLiveStreamStateConnecting";
  313 + }
  314 +
  315 + //推流出错
  316 + if (_kitCN.streamState == CNLiveStreamStateError) {
  317 + NSLog(@"---------CNLiveStreamStateError");
  318 + [self onStreamError];
  319 + }
  320 +
  321 + //断开推流
  322 + if ( _kitCN.streamState == CNLiveStreamStateDisconnecting) {
  323 + NSLog(@"---------CNLiveStreamStateDisconnecting");
  324 + _stateLab.text = @"CNLiveStreamStateDisconnecting";
  325 +
  326 + }
  327 +
  328 + //结束推流成功
  329 + if ( _kitCN.streamState == CNLiveStopStreamSuccess) {
  330 + NSLog(@"---------CNLiveStopStreamSuccess");
  331 + _stateLab.text = @"CNLiveStopStreamSuccess";
  332 +
  333 + }
  334 +}
  335 +
  336 +- (void)onStreamError {
  337 +
  338 + _startLiveBtn.selected = NO;
  339 + CNLiveStreamErrorCode err = _kitCN.streamErrorCode;
  340 + [self toast:[NSString stringWithFormat:@"error ------ %lu",(unsigned long)err]];
  341 +
  342 + NSLog(@"onErr: %lu [%@]", (unsigned long) err, _stateLab.text);
  343 +
  344 + if ( CNLiveStreamErrorCode_CNLiveAUTHFAILED == err ) {
  345 + _stateLab.text = @"SDK auth failed, \npls check ak/sk";
  346 + }
  347 + else if ( CNLiveStreamErrorCode_CODEC_OPEN_FAILED == err) {
  348 + _stateLab.text = @"Selected Codec not supported \n in this version";
  349 + }
  350 + else if ( CNLiveStreamErrorCode_CONNECT_FAILED == err) {
  351 + _stateLab.text = @"Connecting error, pls check host url \nor network";
  352 + }
  353 + else if ( CNLiveStreamErrorCode_CONNECT_BREAK == err) {
  354 + _stateLab.text = @"Connection break";
  355 + }
  356 + else if ( CNLiveStreamErrorCode_ABNORMAL == err) {
  357 + _stateLab.text = @"CNLiveStreamErrorCode_ABNORMAL";
  358 + [self toast:@"推流异常中断~~"];
  359 +
  360 + } else if (err == CNLiveStreamErrorCode_CODEC_OPEN_FAILED) {
  361 + NSLog(@"video codec open failed, try software codec");
  362 + _kitCN.streamerBase.videoCodec = CNLiveVideoCodec_VT264;
  363 + [self tryReconnect];
  364 + }
  365 + else {
  366 +
  367 + }
  368 +
  369 + // 断网重连
  370 + if (err == CNLiveStreamErrorCode_CONNECT_BREAK || err == CNLiveStreamErrorCode_AV_SYNC_ERROR) {
  371 + [self tryReconnect];
  372 + }
  373 +
  374 +}
  375 +
  376 +- (void) tryReconnect
  377 +{
  378 + dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC));
  379 + dispatch_after(delay, dispatch_get_main_queue(), ^{
  380 +
  381 + NSLog(@"try again");
  382 +
  383 + [_kitCN stopStream];
  384 +
  385 + if (_isAuthLive) {
  386 +
  387 + [_kitCN startStream:^{
  388 + NSLog(@"开启推流成功 ------- success");
  389 + _startLiveBtn.selected = YES;
  390 +
  391 + } failure:^(NSDictionary *errorDic) {
  392 + [self toast:errorDic[@"errorMessage"]];
  393 + _startLiveBtn.selected = NO;
  394 + }];
  395 +
  396 + }else{
  397 + [_kitCN startStream:self.url];
  398 + }
  399 + });
  400 +}
  401 +
  402 +- (void)toast:(NSString*)message
  403 +{
  404 +
  405 + UIAlertView *toast = [[UIAlertView alloc] initWithTitle:nil
  406 + message:message
  407 + delegate:nil
  408 + cancelButtonTitle:nil
  409 + otherButtonTitles:nil, nil];
  410 + [toast show];
  411 + double duration = 2.5;
  412 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  413 + [toast dismissWithClickedButtonIndex:0 animated:NO];
  414 + });
  415 +}
  416 +
  417 +- (UILabel *)stateLab
  418 +{
  419 + if (!_stateLab) {
  420 + _stateLab = [[UILabel alloc] initWithFrame:CGRectMake(0, Height-100, Width, 100)];
  421 + _stateLab.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
  422 + _stateLab.numberOfLines = 0;
  423 + _stateLab.text = @"message";
  424 + _stateLab.textColor = [UIColor redColor];
  425 + }
  426 + return _stateLab;
  427 +}
  428 +
  429 +- (AudioCfgView *)audioCfgView
  430 +{
  431 + if (!_audioCfgView) {
  432 + _audioCfgView = [[AudioCfgView alloc] initWithFrame:CGRectMake(0, 160, Width, 200)];
  433 + _audioCfgView.hidden = YES;
  434 + }
  435 + return _audioCfgView;
  436 +}
  437 +
  438 +- (BgmPlayerView *)bgmPlayerView
  439 +{
  440 + if (!_bgmPlayerView) {
  441 + _bgmPlayerView = [[BgmPlayerView alloc] initWithFrame:CGRectMake(0, 160, Width, 200)];
  442 + _bgmPlayerView.delegate = self;
  443 + _bgmPlayerView.hidden = YES;
  444 + }
  445 + return _bgmPlayerView;
  446 +}
  447 +
  448 +- (void)dealloc
  449 +{
  450 + if (_currentTimer) {
  451 + [_currentTimer invalidate];
  452 + _currentTimer = nil;
  453 + }
  454 +
  455 + [_kitCN quitStreaming];
  456 + self.kitCN = nil;
  457 + _bgmPlayerView.delegate = nil;
  458 + [[NSNotificationCenter defaultCenter] removeObserver:self];
  459 +}
  460 +
  461 +- (void)didReceiveMemoryWarning {
  462 + [super didReceiveMemoryWarning];
  463 + // Dispose of any resources that can be recreated.
  464 +}
  465 +
  466 +/*
  467 +#pragma mark - Navigation
  468 +
  469 +// In a storyboard-based application, you will often want to do a little preparation before navigation
  470 +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  471 + // Get the new view controller using [segue destinationViewController].
  472 + // Pass the selected object to the new view controller.
  473 +}
  474 +*/
  475 +
  476 +@end
Example/CNLivePlayer/Streamer/BgmPlayerView.h 0 → 100644
  1 +//
  2 +// BgmPlayerView.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/4/19.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +@protocol BgmPlayerViewDelegate <NSObject>
  12 +
  13 +- (void)valueType:(BOOL)isVolume value:(float)value;
  14 +- (void)bgmPlayerPlay:(UIButton *)button;
  15 +- (void)bgmPlayerMode:(UIButton *)button;
  16 +- (void)bgmPlayerPauseOrResume:(UIButton *)button;
  17 +- (void)bgmPlayerLast:(UIButton *)button;
  18 +- (void)bgmPlayerNext:(UIButton *)button;
  19 +- (void)bgmPlayerProgressSlider:(UISlider *)slider;
  20 +
  21 +@end
  22 +
  23 +@interface BgmPlayerView : UIView
  24 +
  25 +@property (nonatomic, strong) UILabel *currentTimeLab;
  26 +@property (nonatomic, strong) UILabel *duraTimeLab;
  27 +@property (nonatomic, strong) UISlider *proSlider;
  28 +@property (nonatomic, strong) UILabel *songTitleLab;
  29 +@property (nonatomic, strong) UIButton *playBtn;
  30 +@property (nonatomic, strong) UIButton *nextBtn;
  31 +@property (nonatomic, strong) UIButton *lastBtn;
  32 +@property (nonatomic, strong) UIButton *pauseBtn;
  33 +@property (nonatomic, strong) UIButton *playModeBtn;
  34 +@property (nonatomic, assign) id<BgmPlayerViewDelegate> delegate;
  35 +
  36 +@end
  37 +
  38 +@interface MusicListView : UIView
  39 +
  40 +@end
Example/CNLivePlayer/Streamer/BgmPlayerView.m 0 → 100644
  1 +//
  2 +// BgmPlayerView.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/4/19.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "BgmPlayerView.h"
  10 +
  11 +#define COLOR(R, G, B, A) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:A]
  12 +#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]
  13 +
  14 +#define BTN_WIDTH (CGRectGetWidth(self.bounds)-SPACE*6)/5
  15 +#define SPACE 7
  16 +
  17 +@interface BgmPlayerView ()
  18 +
  19 +@property (nonatomic, strong) UIView *playFuncView;
  20 +@property (nonatomic, strong) UIView *volumeFuncView;
  21 +@property (nonatomic, strong) UILabel *volumeValLab;
  22 +@property (nonatomic, strong) UILabel *toneValLab;
  23 +
  24 +@end
  25 +
  26 +@implementation BgmPlayerView
  27 +
  28 +- (instancetype)initWithFrame:(CGRect)frame
  29 +{
  30 + self = [super initWithFrame:frame];
  31 + if (self) {
  32 +
  33 + self.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1];
  34 +
  35 + [self addSubview:self.playFuncView];
  36 + [self addSubview:self.volumeFuncView];
  37 + [self addSubview:self.currentTimeLab];
  38 + [self addSubview:self.duraTimeLab];
  39 + [self addSubview:self.proSlider];
  40 + [self addSubview:self.songTitleLab];
  41 +
  42 + _playModeBtn = [self addButton:CGRectMake(SPACE, 0, BTN_WIDTH, 30) action:@selector(playModeBtnAction:) normalTitle:@"顺序播放" selectedTitle:@"循环播放"];
  43 + _lastBtn = [self addButton:CGRectMake(BTN_WIDTH+2*SPACE, 0, BTN_WIDTH, 30) action:@selector(lastBtnAction:) normalTitle:@"上一首" selectedTitle:@"上一首"];
  44 + _playBtn = [self addButton:CGRectMake(BTN_WIDTH*2+3*SPACE, 0, BTN_WIDTH, 30) action:@selector(playBtnAction:) normalTitle:@"播放" selectedTitle:@"停止"];
  45 + _pauseBtn = [self addButton:CGRectMake(BTN_WIDTH*3+4*SPACE, 0, BTN_WIDTH, 30) action:@selector(pauseBtnAction:) normalTitle:@"暂停" selectedTitle:@"继续"];
  46 + _nextBtn = [self addButton:CGRectMake(BTN_WIDTH*4+5*SPACE, 0, BTN_WIDTH, 30) action:@selector(nextBtnAction:) normalTitle:@"下一首" selectedTitle:@"下一首"];
  47 +
  48 + [self.volumeFuncView addSubview:[self addVolumeView:CGRectMake(0, 0, CGRectGetWidth(self.bounds)/2, 40) action:@selector(volumeStepperAction:) type:YES]];
  49 + [self.volumeFuncView addSubview:[self addVolumeView:CGRectMake(CGRectGetWidth(self.bounds)/2, 0, CGRectGetWidth(self.bounds), 40) action:@selector(toneStepperAction:) type:NO]];
  50 +
  51 +
  52 + }
  53 + return self;
  54 +}
  55 +
  56 +#pragma mark -
  57 +#pragma mark - action
  58 +- (void)playModeBtnAction:(UIButton *)button {
  59 + button.selected = !button.selected;
  60 + if (self.delegate && [self.delegate respondsToSelector:@selector(bgmPlayerMode:)]) {
  61 + [self.delegate bgmPlayerMode:button];
  62 + }
  63 +}
  64 +
  65 +- (void)lastBtnAction:(UIButton *)button {
  66 + button.selected = !button.selected;
  67 + if (self.delegate && [self.delegate respondsToSelector:@selector(bgmPlayerLast:)]) {
  68 + [self.delegate bgmPlayerLast:button];
  69 + }
  70 +}
  71 +
  72 +- (void)playBtnAction:(UIButton *)button {
  73 + button.selected = !button.selected;
  74 + if (self.delegate && [self.delegate respondsToSelector:@selector(bgmPlayerPlay:)]) {
  75 + [self.delegate bgmPlayerPlay:button];
  76 + }
  77 +}
  78 +
  79 +- (void)nextBtnAction:(UIButton *)button {
  80 + button.selected = !button.selected;
  81 + if (self.delegate && [self.delegate respondsToSelector:@selector(bgmPlayerNext:)]) {
  82 + [self.delegate bgmPlayerNext:button];
  83 + }
  84 +}
  85 +
  86 +- (void)pauseBtnAction:(UIButton *)button {
  87 + button.selected = !button.selected;
  88 + if (self.delegate && [self.delegate respondsToSelector:@selector(bgmPlayerPauseOrResume:)]) {
  89 + [self.delegate bgmPlayerPauseOrResume:button];
  90 + }
  91 +}
  92 +
  93 +- (void)beginScrubbing {
  94 +}
  95 +
  96 +- (void)endScrubbing:(UISlider *)slider {
  97 + if (self.delegate && [self.delegate respondsToSelector:@selector(bgmPlayerProgressSlider:)]) {
  98 + [self.delegate bgmPlayerProgressSlider:slider];
  99 + }
  100 +}
  101 +
  102 +- (void)volumeStepperAction:(UIStepper *)stepper {
  103 + _volumeValLab.text = [NSString stringWithFormat:@"%.1f",stepper.value];
  104 + if (self.delegate && [self.delegate respondsToSelector:@selector(valueType:value:)]) {
  105 + [self.delegate valueType:YES value:stepper.value];
  106 + }
  107 +}
  108 +
  109 +- (void)toneStepperAction:(UIStepper *)stepper {
  110 + _toneValLab.text = [NSString stringWithFormat:@"%.1f",stepper.value];
  111 + if (self.delegate && [self.delegate respondsToSelector:@selector(valueType:value:)]) {
  112 + [self.delegate valueType:NO value:stepper.value];
  113 + }
  114 +}
  115 +
  116 +#pragma mark -
  117 +#pragma mark -
  118 +- (UIButton *)addButton:(CGRect)rect action:(SEL)action normalTitle:(NSString *)normalTitle selectedTitle:(NSString *)selectedTitle{
  119 + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  120 + button.frame = rect;
  121 + [button addTarget:self action:action forControlEvents:UIControlEventTouchUpInside];
  122 + [button setTitle:normalTitle forState:UIControlStateNormal];
  123 + [button setTitle:selectedTitle forState:UIControlStateSelected];
  124 + [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  125 + button.titleLabel.font = [UIFont systemFontOfSize:14];
  126 + button.layer.cornerRadius = 5;
  127 + button.layer.masksToBounds = YES;
  128 + button.layer.borderColor = [UIColor blackColor].CGColor;
  129 + button.layer.borderWidth = 1;
  130 + [self.playFuncView addSubview:button];
  131 + return button;
  132 +}
  133 +
  134 +- (UIView *)addVolumeView:(CGRect)rect action:(SEL)action type:(BOOL)volume {
  135 + UIView *view = [[UIView alloc] initWithFrame:rect];
  136 + UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(0, 10, 40, 20)];
  137 +
  138 + UILabel *valueLab = [[UILabel alloc] initWithFrame:CGRectMake(45, 10, 30, 20)];
  139 + valueLab.font = [UIFont systemFontOfSize:14];
  140 +
  141 + UIStepper *step = [[UIStepper alloc] initWithFrame:CGRectMake(80, 5, 30, 30)];
  142 + step.tintColor = [UIColor blackColor];
  143 + [step addTarget:self action:action forControlEvents:UIControlEventValueChanged];
  144 +
  145 + if (volume) {
  146 + titleLab.text = @"音量: ";
  147 + valueLab.text = @"1.0";
  148 + _volumeValLab = valueLab;
  149 + step.maximumValue = 1;
  150 + step.minimumValue = 0;
  151 + step.stepValue = 0.1;
  152 + step.value = 1.0;
  153 + } else {
  154 + titleLab.text = @"音调: ";
  155 + valueLab.text = @"0.01";
  156 + _toneValLab = valueLab;
  157 + step.maximumValue = 24.0;
  158 + step.minimumValue = -24.0;
  159 + step.stepValue = 1.0;
  160 + step.value = 0.01;
  161 + }
  162 +
  163 + [view addSubview:titleLab];
  164 + [view addSubview:valueLab];
  165 + [view addSubview:step];
  166 + return view;
  167 +}
  168 +
  169 +#pragma mark -
  170 +#pragma mark - gatter
  171 +- (UIView *)playFuncView {
  172 + if (!_playFuncView) {
  173 + _playFuncView = [[UIView alloc] initWithFrame:CGRectMake(0, 80, CGRectGetWidth(self.bounds), 40)];
  174 + }
  175 + return _playFuncView;
  176 +}
  177 +
  178 +- (UIView *)volumeFuncView {
  179 + if (!_volumeFuncView) {
  180 + _volumeFuncView = [[UIView alloc] initWithFrame:CGRectMake(0, 120, CGRectGetWidth(self.bounds), 40)];
  181 + }
  182 + return _volumeFuncView;
  183 +}
  184 +
  185 +
  186 +- (UILabel *)songTitleLab
  187 +{
  188 + if (!_songTitleLab) {
  189 + _songTitleLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, CGRectGetWidth(self.bounds)-20, 20)];
  190 + _songTitleLab.textColor = [UIColor redColor];
  191 + _songTitleLab.font = [UIFont systemFontOfSize:14];
  192 + _songTitleLab.text = @"xxxx";
  193 + }
  194 + return _songTitleLab;
  195 +}
  196 +
  197 +- (UILabel *)currentTimeLab
  198 +{
  199 + if (!_currentTimeLab) {
  200 + _currentTimeLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 40, 20)];
  201 + _currentTimeLab.font = [UIFont systemFontOfSize:13];
  202 + _currentTimeLab.text = @"00:00";
  203 + }
  204 + return _currentTimeLab;
  205 +}
  206 +
  207 +- (UILabel *)duraTimeLab
  208 +{
  209 + if (!_duraTimeLab) {
  210 + _duraTimeLab = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.bounds)-50, 40, 40, 20)];
  211 + _duraTimeLab.font = [UIFont systemFontOfSize:13];
  212 + _duraTimeLab.text = @"00:00";
  213 + }
  214 + return _duraTimeLab;
  215 +}
  216 +
  217 +- (UISlider *)proSlider
  218 +{
  219 + if (!_proSlider) {
  220 + _proSlider = [[UISlider alloc] initWithFrame:CGRectMake(60, 35, CGRectGetWidth(self.bounds)-120, 30)];
  221 + [_proSlider setThumbImage:[UIImage imageNamed:@"btn_dot"] forState:UIControlStateNormal];
  222 + [_proSlider setMinimumTrackTintColor:[UIColor redColor]];
  223 + [_proSlider setMaximumTrackTintColor:[UIColor whiteColor]];
  224 + [_proSlider addTarget:self action:@selector(beginScrubbing) forControlEvents:UIControlEventTouchDown];
  225 + [_proSlider addTarget:self action:@selector(endScrubbing:) forControlEvents:UIControlEventTouchUpInside];
  226 + [_proSlider addTarget:self action:@selector(endScrubbing:) forControlEvents:UIControlEventTouchUpOutside];
  227 + }
  228 + return _proSlider;
  229 +}
  230 +/*
  231 +// Only override drawRect: if you perform custom drawing.
  232 +// An empty implementation adversely affects performance during animation.
  233 +- (void)drawRect:(CGRect)rect {
  234 + // Drawing code
  235 +}
  236 +*/
  237 +
  238 +@end
  239 +
  240 +#pragma mark - 音乐列表
  241 +
  242 +@interface MusicListView ()<UITableViewDelegate,UITableViewDataSource>
  243 +{
  244 + NSArray *_listArr;
  245 +}
  246 +
  247 +@property (nonatomic, strong) UITableView *tableView;
  248 +
  249 +@end
  250 +
  251 +@implementation MusicListView
  252 +
  253 +- (instancetype)initWithFrame:(CGRect)frame
  254 +{
  255 + self = [super initWithFrame:frame];
  256 + if (self) {
  257 + _listArr = @[@"See You Again .mp3",
  258 + @"Idina Menzel - Let It Go.mp3",
  259 + @"Morrie - Lullaby.mp3",
  260 + @"Zedd,Alessia Cara - Stay.mp3"];
  261 + }
  262 + return self;
  263 +}
  264 +
  265 +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  266 + return _listArr.count;
  267 +}
  268 +
  269 +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  270 + static NSString *cellID = @"MusicListViewIdentify";
  271 + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
  272 + if (!cell) {
  273 + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
  274 + }
  275 + cell.textLabel.text = _listArr[indexPath.row];
  276 + cell.textLabel.textColor = UIColorFromRGB(515151);
  277 + cell.backgroundColor = [UIColor whiteColor];
  278 + return cell;
  279 +}
  280 +
  281 +
  282 +- (UITableView *)tableView
  283 +{
  284 + if (!_tableView) {
  285 + _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 40, CGRectGetWidth(self.bounds), 100) style:UITableViewStylePlain];
  286 + _tableView.delegate = self;
  287 + _tableView.dataSource = self;
  288 + _tableView.backgroundColor = [UIColor whiteColor];
  289 + }
  290 + return _tableView;
  291 +}
  292 +
  293 +
  294 +@end
Example/CNLivePlayer/CNLiveStreamerController.h renamed to Example/CNLivePlayer/Streamer/CNLiveStreamerController.h
1 // 1 //
2 -// CNLiveStreamerController.h  
3 -// CNLivePlayer_Example 2 +// StreamerViewController.h
  3 +// CNLivePlayerSDKTest
4 // 4 //
5 -// Created by CNLive-zxw on 2019/8/21.  
6 -// Copyright © 2019 153993236@qq.com. All rights reserved. 5 +// Created by 雷浩杰 on 16/8/10.
  6 +// Copyright © 2016年 雷浩杰. All rights reserved.
7 // 7 //
8 8
9 #import <UIKit/UIKit.h> 9 #import <UIKit/UIKit.h>
10 10
11 -NS_ASSUME_NONNULL_BEGIN  
12 -  
13 @interface CNLiveStreamerController : UIViewController 11 @interface CNLiveStreamerController : UIViewController
14 12
15 @end 13 @end
16 -  
17 -NS_ASSUME_NONNULL_END  
Example/CNLivePlayer/Streamer/CNLiveStreamerController.m 0 → 100644
  1 +//
  2 +// StreamerViewController.m
  3 +// CNLivePlayerSDKTest
  4 +//
  5 +// Created by 雷浩杰 on 16/8/10.
  6 +// Copyright © 2016年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveStreamerController.h"
  10 +#import "StreamerDetailViewController.h"
  11 +#import "AudioStreamingViewController.h"
  12 +
  13 +#define KScreenWidth [UIScreen mainScreen].bounds.size.width
  14 +#define KScreenHeight [UIScreen mainScreen].bounds.size.height
  15 +
  16 +@interface CNLiveStreamerController ()<UITextFieldDelegate>
  17 +@property (nonatomic, strong) UITextField *urlTextField;
  18 +@property (nonatomic, strong) UISwitch *pureAudioSwitch;
  19 +@property (nonatomic, strong) UISegmentedControl *liveType;
  20 +
  21 +@end
  22 +
  23 +@implementation CNLiveStreamerController
  24 +
  25 +- (void)viewDidLoad {
  26 + [super viewDidLoad];
  27 + self.view.backgroundColor = [UIColor whiteColor];
  28 +
  29 + [self.view addSubview:self.urlTextField];
  30 + [self.view addSubview:self.pureAudioSwitch];
  31 + [self.view addSubview:self.liveType];
  32 +
  33 + UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
  34 + btn.frame = CGRectMake(0, 0, 100, 50);
  35 + btn.center = CGPointMake(self.view.center.x, self.view.center.y);
  36 + btn.backgroundColor = [UIColor redColor];
  37 + [btn setTitle:@"返回" forState:UIControlStateNormal];
  38 + [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
  39 + [btn addTarget:self action:@selector(btnDidClicked) forControlEvents:UIControlEventTouchUpInside];
  40 + [self.view addSubview:btn];
  41 +
  42 +}
  43 +
  44 +- (void)btnDidClicked{
  45 + [self dismissViewControllerAnimated:YES completion:nil];
  46 +
  47 +}
  48 +
  49 +#pragma mark - Actioon
  50 +- (void)onSegmentedControl:(UISegmentedControl *)sender {
  51 + if (sender.selectedSegmentIndex == 0) {
  52 + if (_urlTextField.text.length == 0) {
  53 + [self toast:@"请输入推流地址"];
  54 +
  55 + }
  56 + else{
  57 + if (_pureAudioSwitch.on) {
  58 + AudioStreamingViewController *vc = [[AudioStreamingViewController alloc] init];
  59 + vc.isAuthLive = NO;
  60 + vc.url = [NSURL URLWithString:[NSString stringWithFormat:@"%@",self.urlTextField.text]];
  61 + [self presentViewController:vc animated:YES completion:NULL];
  62 + }
  63 + else {
  64 + StreamerDetailViewController *vc = [[StreamerDetailViewController alloc] init];
  65 + vc.isAuthLive = NO;
  66 + vc.url = [NSURL URLWithString:[NSString stringWithFormat:@"%@",self.urlTextField.text]];
  67 + [self presentViewController:vc animated:YES completion:NULL];
  68 + }
  69 + }
  70 +
  71 + }
  72 + else if (sender.selectedSegmentIndex == 1) {
  73 +
  74 + if (_pureAudioSwitch.on) {
  75 + AudioStreamingViewController *vc = [[AudioStreamingViewController alloc] init];
  76 + vc.isAuthLive = YES;
  77 + [self presentViewController:vc animated:YES completion:NULL];
  78 + }
  79 + else {
  80 + StreamerDetailViewController *vc = [[StreamerDetailViewController alloc] init];
  81 + vc.isAuthLive = YES;
  82 + vc.url = [NSURL URLWithString:[NSString stringWithFormat:@"%@",self.urlTextField.text]];
  83 + [self presentViewController:vc animated:YES completion:NULL];
  84 + }
  85 +
  86 + }
  87 + else if (sender.selectedSegmentIndex == 2) {
  88 + StreamerDetailViewController *vc = [[StreamerDetailViewController alloc] init];
  89 + vc.isRecord = YES;
  90 + [self presentViewController:vc animated:YES completion:NULL];
  91 +
  92 + }
  93 +
  94 + _liveType.selectedSegmentIndex = -1;
  95 +
  96 +}
  97 +
  98 +
  99 +- (void)toast:(NSString*)message {
  100 + UIAlertView *toast = [[UIAlertView alloc] initWithTitle:nil
  101 + message:message
  102 + delegate:nil
  103 + cancelButtonTitle:nil
  104 + otherButtonTitles:nil, nil];
  105 + [toast show];
  106 + double duration = 2.5;
  107 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  108 + [toast dismissWithClickedButtonIndex:0 animated:NO];
  109 + });
  110 +}
  111 +
  112 +- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  113 + if ([_urlTextField isFirstResponder]) {
  114 + [_urlTextField resignFirstResponder];
  115 + }
  116 +}
  117 +
  118 +- (BOOL)textFieldShouldReturn:(UITextField *)textField {
  119 + [textField resignFirstResponder];
  120 + return YES;
  121 +}
  122 +
  123 +#pragma mark - getter
  124 +- (UITextField *)urlTextField {
  125 + if (!_urlTextField) {
  126 + _urlTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 170, KScreenWidth-20, 40)];
  127 + _urlTextField.placeholder = @"请输入推流地址";
  128 + _urlTextField.borderStyle = UITextBorderStyleRoundedRect;
  129 + _urlTextField.returnKeyType = UIReturnKeyDone;
  130 + _urlTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
  131 + _urlTextField.delegate = self;
  132 + _urlTextField.text = @"rtmp://jsrtmp.up.cnlive.com/live/ceshi";
  133 + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, -30, 80, 30)];
  134 + label.text = @"推流地址:";
  135 + label.font = [UIFont systemFontOfSize:15];
  136 + [_urlTextField addSubview:label];
  137 + }
  138 + return _urlTextField;
  139 +}
  140 +
  141 +- (UISwitch *)pureAudioSwitch {
  142 + if (!_pureAudioSwitch) {
  143 + _pureAudioSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(110, 85, 100, 30)];
  144 + UILabel *modeLab = [[UILabel alloc] initWithFrame:CGRectMake(10, 90, 100, 20)];
  145 + modeLab.textColor = [UIColor blackColor];
  146 + modeLab.text = @"纯音频推流";
  147 + [self.view addSubview:modeLab];
  148 + }
  149 + return _pureAudioSwitch;
  150 +}
  151 +
  152 +- (UISegmentedControl *)liveType {
  153 + if (!_liveType) {
  154 + NSArray *items = @[ @"普通直播",
  155 + @"鉴权直播",
  156 + @"本地录制"];
  157 +
  158 + _liveType = [[UISegmentedControl alloc] initWithItems:items];
  159 + _liveType.frame = CGRectMake(10, self.view.bounds.size.height-80, self.view.bounds.size.width-20, 40);
  160 + _liveType.tintColor= [UIColor blackColor];
  161 + _liveType.selectedSegmentIndex = 0;
  162 + _liveType.layer.cornerRadius = 5;
  163 + _liveType.selectedSegmentIndex = -1;
  164 + [_liveType addTarget:self action:@selector(onSegmentedControl:) forControlEvents:UIControlEventValueChanged];
  165 + }
  166 + return _liveType;
  167 +}
  168 +
  169 +
  170 +@end
Example/CNLivePlayer/Streamer/FilterFunctionView.h 0 → 100644
  1 +//
  2 +// FilterFunctionView.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 16/12/21.
  6 +// Copyright © 2016年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +typedef void(^FilterViewBlock)(float grindRatio , float whitenRatio, float intensity);
  12 +typedef void(^FilterCurrentType)(NSInteger currentType);
  13 +typedef void(^FilterCurrentIdx)(NSInteger currentIdx);
  14 +
  15 +@interface FilterFunctionView : UIView
  16 +
  17 +@property (nonatomic, copy) FilterViewBlock filterViewBlock;
  18 +@property (nonatomic, copy) FilterCurrentType currentTypeBlock;
  19 +@property (nonatomic, copy) FilterCurrentIdx currentIdxBlock;
  20 +
  21 +@end
  22 +
Example/CNLivePlayer/Streamer/FilterFunctionView.m 0 → 100644
  1 +//
  2 +// FilterFunctionView.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 16/12/21.
  6 +// Copyright © 2016年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "FilterFunctionView.h"
  10 +#import "SliderView.h"
  11 +
  12 +@interface FilterFunctionView ()<SliderViewDelegate,UIPickerViewDelegate,UIPickerViewDataSource>
  13 +{
  14 + NSArray *_dataArr;
  15 +}
  16 +
  17 +@property (nonatomic, strong) SliderView *slider1;
  18 +@property (nonatomic, strong) SliderView *slider2;
  19 +@property (nonatomic, strong) SliderView *slider3;
  20 +@property (nonatomic, strong) UISegmentedControl * filterGroupType;
  21 +@property (nonatomic, strong) UIPickerView *effectPicker;
  22 +
  23 +@end
  24 +
  25 +@implementation FilterFunctionView
  26 +
  27 +- (instancetype)initWithFrame:(CGRect)frame
  28 +{
  29 + self = [super initWithFrame:frame];
  30 + if (self) {
  31 + [self addSubview:self.slider1];
  32 + [self addSubview:self.slider2];
  33 + [self addSubview:self.slider3];
  34 + [self addSubview:self.effectPicker];
  35 + [self addSubview:self.filterGroupType];
  36 +
  37 + _dataArr = @[@"小清新",@"靓丽",@"甜美可人",@"怀旧",@"蓝调",@"老照片",@"樱花",@"樱花(光线较暗)",@"红润(光线较暗)",@"阳光(光线较暗)",@"红润",@"阳光",@"自然"];
  38 +
  39 + }
  40 + return self;
  41 +}
  42 +
  43 +#pragma mark -
  44 +#pragma mark - SliderViewDelegate
  45 +
  46 +- (void)sliderValueChenged
  47 +{
  48 + if (_filterViewBlock) {
  49 + _filterViewBlock(_slider1.currentValue, _slider2.currentValue, _slider3.currentValue);
  50 + }
  51 +}
  52 +
  53 +- (void)onSegCtrl:(UISegmentedControl *)sender
  54 +{
  55 +
  56 + if (sender.selectedSegmentIndex == 0) {
  57 + _slider1.hidden = YES;
  58 + _slider2.hidden = YES;
  59 + _slider3.hidden = YES;
  60 + _effectPicker.hidden = YES;
  61 +
  62 + } else if (sender.selectedSegmentIndex == 1) {
  63 + _slider1.hidden = NO;
  64 + _slider2.hidden = YES;
  65 + _slider3.hidden = YES;
  66 + _effectPicker.hidden = YES;
  67 + } else if (sender.selectedSegmentIndex == 2) {
  68 + _slider1.hidden = NO;
  69 + _slider2.hidden = NO;
  70 + _slider3.hidden = NO;
  71 + _effectPicker.hidden = YES;
  72 + } else {
  73 + _slider1.hidden = NO;
  74 + _slider2.hidden = NO;
  75 + _slider3.hidden = NO;
  76 + _effectPicker.hidden = NO;
  77 + }
  78 +
  79 + _currentTypeBlock ? _currentTypeBlock(sender.selectedSegmentIndex) : nil;
  80 +
  81 +}
  82 +
  83 +#pragma mark -
  84 +#pragma mark - effectPicker
  85 +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
  86 +{
  87 + return 1;
  88 +}
  89 +
  90 +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
  91 +{
  92 + return _dataArr.count;
  93 +}
  94 +
  95 +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
  96 +{
  97 + return _dataArr[row];
  98 +}
  99 +
  100 +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
  101 +{
  102 + _currentIdxBlock ? _currentIdxBlock(row) : nil;
  103 +}
  104 +
  105 +#pragma mark -
  106 +#pragma mark - getter
  107 +
  108 +- (SliderView *)slider1
  109 +{
  110 + if (!_slider1) {
  111 + _slider1 = [[SliderView alloc] initWithFrame:CGRectMake(8, 50, self.bounds.size.width-16, 24) title:@"磨皮"];
  112 + _slider1.delagate = self;
  113 + }
  114 + return _slider1;
  115 +}
  116 +
  117 +- (SliderView *)slider2
  118 +{
  119 + if (!_slider2) {
  120 + _slider2 = [[SliderView alloc] initWithFrame:CGRectMake(8, 80, self.bounds.size.width-16, 24) title:@"美白"];
  121 + _slider2.delagate = self;
  122 + }
  123 + return _slider2;
  124 +}
  125 +
  126 +- (SliderView *)slider3
  127 +{
  128 + if (!_slider3) {
  129 + _slider3 = [[SliderView alloc] initWithFrame:CGRectMake(8, 110, self.bounds.size.width-16, 24) title:@"特效"];
  130 + _slider3.delagate = self;
  131 + }
  132 + return _slider3;
  133 +}
  134 +
  135 +- (UIPickerView *)effectPicker
  136 +{
  137 + if (!_effectPicker) {
  138 + _effectPicker = [[UIPickerView alloc] initWithFrame:CGRectMake(8, 130, self.bounds.size.width-16, 100)];
  139 + _effectPicker.showsSelectionIndicator=YES;
  140 + _effectPicker.tintColor = [UIColor whiteColor];
  141 + _effectPicker.dataSource = self;
  142 + _effectPicker.delegate = self;
  143 + _effectPicker.hidden = YES;
  144 + }
  145 + return _effectPicker;
  146 +}
  147 +
  148 +- (UISegmentedControl *)filterGroupType
  149 +{
  150 + if (!_filterGroupType) {
  151 + NSArray *items = @[ @"关",
  152 + @"旧美颜",
  153 + @"红润美颜",
  154 + @"美颜特效",
  155 + ];
  156 +
  157 + _filterGroupType = [[UISegmentedControl alloc] initWithItems:items];
  158 + _filterGroupType.frame = CGRectMake(10, 0, self.bounds.size.width-20, 30);
  159 + _filterGroupType.tintColor= [UIColor blackColor];
  160 + _filterGroupType.selectedSegmentIndex = 0;
  161 + _filterGroupType.layer.cornerRadius = 5;
  162 + _filterGroupType.selectedSegmentIndex = 1;
  163 + [_filterGroupType addTarget:self action:@selector(onSegCtrl:) forControlEvents:UIControlEventValueChanged];
  164 + }
  165 + return _filterGroupType;
  166 +}
  167 +@end
Example/CNLivePlayer/Streamer/FloatingViewController.h 0 → 100644
  1 +//
  2 +// FloatingViewController.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 2017/9/20.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +#import "CNLiveStreamerKit.h"
  11 +
  12 +@interface FloatingViewController : UIViewController
  13 +
  14 +@property (nonatomic, strong) CNLiveStreamerKit *kit;
  15 +
  16 +@end
Example/CNLivePlayer/Streamer/FloatingViewController.m 0 → 100644
  1 +//
  2 +// FloatingViewController.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 2017/9/20.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "FloatingViewController.h"
  10 +
  11 +#define Width [UIScreen mainScreen].bounds.size.width
  12 +#define Height [UIScreen mainScreen].bounds.size.height
  13 +
  14 +@interface FloatingViewController ()
  15 +
  16 +@property (nonatomic, strong) UIView *preView;
  17 +@property CGPoint loc_in;
  18 +
  19 +@end
  20 +
  21 +@implementation FloatingViewController
  22 +
  23 +- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
  24 +
  25 + [self.preView removeFromSuperview];
  26 + self.preView = nil;
  27 +
  28 + self.preView = [self.kit floatingWindowFrame:CGRectMake(Width/3*2, Height/3*2, Width/3, Height/3)];
  29 + [self.view addSubview:self.preView];
  30 + UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
  31 + [_preView addGestureRecognizer:panGes];
  32 +
  33 +}
  34 +
  35 +- (void)viewDidLoad {
  36 + [super viewDidLoad];
  37 +
  38 + self.view.backgroundColor = [UIColor whiteColor];
  39 +
  40 + _preView = [self.kit floatingWindowFrame:CGRectMake(Width/3*2, Height/3*2, Width/3, Height/3)];
  41 + [self.view addSubview:self.preView];
  42 + UIPanGestureRecognizer *panGes = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
  43 + [_preView addGestureRecognizer:panGes];
  44 +
  45 + UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  46 + button.frame = CGRectMake(10, 30, 25, 25);
  47 + [button setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
  48 + [button addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
  49 + [self.view addSubview:button];
  50 +
  51 +}
  52 +
  53 +- (void)backAction {
  54 + [self dismissViewControllerAnimated:YES completion:NULL];
  55 +}
  56 +
  57 +- (void)pan:(UIPanGestureRecognizer *)ges{
  58 + CGPoint loc = [ges locationInView:self.view];
  59 + if (ges.state == UIGestureRecognizerStateBegan) {
  60 + _loc_in = [ges locationInView:_preView];
  61 + }
  62 +
  63 + CGFloat x;
  64 + CGFloat y;
  65 + if (_preView.frame.size.width - _loc_in.x + loc.x >= Width){
  66 + x = Width - _preView.frame.size.width * 0.5;
  67 + }else if (loc.x - _loc_in.x <= 0) {
  68 + x = _preView.frame.size.width * 0.5;
  69 + }else {
  70 + x = _preView.frame.size.width * 0.5 - _loc_in.x + loc.x;
  71 + }
  72 +
  73 + if (_preView.frame.size.height - _loc_in.y + loc.y >= Height) {
  74 + y = Height - _preView.frame.size.height * 0.5;
  75 + }else if (loc.y - _loc_in.y <= 0){
  76 + y = _preView.frame.size.height * 0.5;
  77 + }else {
  78 + y = _preView.frame.size.height * 0.5 - _loc_in.y + loc.y;
  79 + }
  80 +
  81 + [UIView animateWithDuration:0 animations:^{
  82 + _preView.center = CGPointMake(x, y);
  83 + }];
  84 +}
  85 +
  86 +
  87 +- (void)didReceiveMemoryWarning {
  88 + [super didReceiveMemoryWarning];
  89 + // Dispose of any resources that can be recreated.
  90 +}
  91 +
  92 +/*
  93 +#pragma mark - Navigation
  94 +
  95 +// In a storyboard-based application, you will often want to do a little preparation before navigation
  96 +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  97 + // Get the new view controller using [segue destinationViewController].
  98 + // Pass the selected object to the new view controller.
  99 +}
  100 +*/
  101 +
  102 +@end
Example/CNLivePlayer/Streamer/LoadingView.h 0 → 100644
  1 +//
  2 +// LoadingView.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/3/8.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +typedef NS_ENUM(NSUInteger, LoadingViewStyle) {
  12 + LoadingViewStyleStartLoading = 0,
  13 + LoadingViewStyleStopLoading,
  14 + LoadingViewStyleRetry,
  15 +};
  16 +
  17 +@class LoadingView;
  18 +
  19 +@protocol LoadingViewDelegate <NSObject>
  20 +
  21 +- (void)loadingView:(LoadingView *)loadingViewRetryAction;
  22 +
  23 +@end
  24 +
  25 +@interface LoadingView : UIView
  26 +
  27 +@property (nonatomic, assign) id<LoadingViewDelegate> delegate;
  28 +
  29 +- (void)setLoadingViewStyle:(LoadingViewStyle)style;
  30 +
  31 +@end
Example/CNLivePlayer/Streamer/LoadingView.m 0 → 100644
  1 +//
  2 +// LoadingView.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 17/3/8.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "LoadingView.h"
  10 +
  11 +@interface LoadingView ()
  12 +
  13 +@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
  14 +@property (nonatomic, strong) UIButton *retryBtn;
  15 +
  16 +@end
  17 +
  18 +@implementation LoadingView
  19 +
  20 +- (instancetype)initWithFrame:(CGRect)frame
  21 +{
  22 + self = [super initWithFrame:frame];
  23 + if (self) {
  24 + [self addSubview:self.activityIndicator];
  25 + [self addSubview:self.retryBtn];
  26 + [self.activityIndicator startAnimating];
  27 +
  28 + }
  29 + return self;
  30 +}
  31 +
  32 +#pragma mark -
  33 +#pragma mark - action
  34 +- (void)retryBtnAction {
  35 + if (self.delegate && [self.delegate respondsToSelector:@selector(loadingView:)]) {
  36 + [self.delegate loadingView:self];
  37 + [self setLoadingViewStyle:LoadingViewStyleStartLoading];
  38 + }
  39 +}
  40 +
  41 +- (void)setLoadingViewStyle:(LoadingViewStyle)style {
  42 + switch (style) {
  43 + case LoadingViewStyleStartLoading:
  44 + [_activityIndicator startAnimating];
  45 + _retryBtn.hidden = YES;
  46 + break;
  47 +
  48 + case LoadingViewStyleStopLoading:
  49 + [_activityIndicator stopAnimating];
  50 + _retryBtn.hidden = YES;
  51 + break;
  52 +
  53 + case LoadingViewStyleRetry:
  54 + [_activityIndicator stopAnimating];
  55 + _retryBtn.hidden = NO;
  56 + break;
  57 +
  58 + default:
  59 + break;
  60 + }
  61 +}
  62 +
  63 +
  64 +
  65 +#pragma mark -
  66 +#pragma mark - getter
  67 +- (UIActivityIndicatorView *)activityIndicator {
  68 + if (!_activityIndicator) {
  69 + _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
  70 + _activityIndicator.center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
  71 + }
  72 + return _activityIndicator;
  73 +}
  74 +
  75 +- (UIButton *)retryBtn {
  76 + if (!_retryBtn) {
  77 + _retryBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  78 + _retryBtn.frame = CGRectMake(self.bounds.size.width/2-30, self.bounds.size.height/2-20, 60, 40);
  79 + [_retryBtn setTitle:@"重试" forState:UIControlStateNormal];
  80 + [_retryBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  81 + _retryBtn.hidden = YES;
  82 + _retryBtn.layer.cornerRadius = 10;
  83 + _retryBtn.layer.masksToBounds = YES;
  84 + _retryBtn.layer.borderColor = [UIColor blackColor].CGColor;
  85 + _retryBtn.layer.borderWidth = 1;
  86 + [_retryBtn addTarget:self action:@selector(retryBtnAction) forControlEvents:UIControlEventTouchUpInside];
  87 +
  88 + }
  89 + return _retryBtn;
  90 +}
  91 +
  92 +@end
Example/CNLivePlayer/Streamer/MoreFunctionsView.h 0 → 100644
  1 +//
  2 +// MoreFunctionsView.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 2017/9/19.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +typedef NS_ENUM(NSUInteger, MoreFuncType) {
  12 + MoreFuncTypeScreenshot = 0,
  13 + MoreFuncTypeLiveScene,
  14 + MoreFuncTypeRecordScene,
  15 + MoreFuncTypeLogo
  16 +};
  17 +
  18 +typedef void(^MoreFuncBlock)(MoreFuncType type, NSInteger idx, UISegmentedControl *seg);
  19 +
  20 +@interface MoreFunctionsView : UIView
  21 +
  22 +@property (nonatomic, copy) MoreFuncBlock moreFuncBlock;
  23 +@property (nonatomic, strong) UISwitch *bypassRecord;
  24 +@property (nonatomic, strong) UIButton *floatingWindowBtn;
  25 +
  26 +@end
Example/CNLivePlayer/Streamer/MoreFunctionsView.m 0 → 100644
  1 +//
  2 +// MoreFunctionsView.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 2017/9/19.
  6 +// Copyright © 2017年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "MoreFunctionsView.h"
  10 +
  11 +@interface MoreFunctionsView ()
  12 +
  13 +@property (nonatomic, strong) UISegmentedControl *screenshotSeg;
  14 +@property (nonatomic, strong) UISegmentedControl *liveSceneSeg;
  15 +@property (nonatomic, strong) UISegmentedControl *recordSceneSeg;
  16 +@property (nonatomic, strong) UISegmentedControl *logoSeg;
  17 +
  18 +@end
  19 +
  20 +@implementation MoreFunctionsView
  21 +
  22 +- (instancetype)initWithFrame:(CGRect)frame
  23 +{
  24 + self = [super initWithFrame:frame];
  25 + if (self) {
  26 +
  27 + [self addSubview:self.screenshotSeg];
  28 + [self addSubview:self.liveSceneSeg];
  29 + [self addSubview:self.recordSceneSeg];
  30 + [self addSubview:self.logoSeg];
  31 + [self addSubview:self.bypassRecord];
  32 + [self addSubview:self.floatingWindowBtn];
  33 +
  34 + }
  35 + return self;
  36 +}
  37 +
  38 +#pragma mark -
  39 +#pragma mark - action
  40 +- (void)onSegCtrl:(UISegmentedControl *)seg {
  41 + if (self.moreFuncBlock) {
  42 + self.moreFuncBlock(seg.tag, seg.selectedSegmentIndex, seg);
  43 + }
  44 +}
  45 +
  46 +#pragma mark -
  47 +#pragma mark - getter
  48 +- (UISegmentedControl *)screenshotSeg
  49 +{
  50 + if (!_screenshotSeg) {
  51 + NSArray *items = @[ @"截图为文件",
  52 + @"截图为UIImage"];
  53 +
  54 + _screenshotSeg = [[UISegmentedControl alloc] initWithItems:items];
  55 + _screenshotSeg.frame = CGRectMake(95, 0, self.bounds.size.width-105, 30);
  56 + _screenshotSeg.tintColor= [UIColor blackColor];
  57 + _screenshotSeg.layer.cornerRadius = 5;
  58 + _screenshotSeg.selectedSegmentIndex = -1;
  59 + _screenshotSeg.tag = MoreFuncTypeScreenshot;
  60 + [_screenshotSeg addTarget:self action:@selector(onSegCtrl:) forControlEvents:UIControlEventValueChanged];
  61 +
  62 + UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(-85, 0, 80, 30)];
  63 + titleLab.text = @"截图";
  64 + titleLab.textColor = [UIColor blackColor];
  65 + titleLab.font = [UIFont systemFontOfSize:15];
  66 + titleLab.textAlignment = NSTextAlignmentCenter;
  67 + titleLab.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.2];
  68 + [_screenshotSeg addSubview:titleLab];
  69 + }
  70 + return _screenshotSeg;
  71 +}
  72 +
  73 +- (UISegmentedControl *)liveSceneSeg
  74 +{
  75 + if (!_liveSceneSeg) {
  76 + NSArray *items = @[ @"默认",
  77 + @"秀场",
  78 + @"游戏",
  79 + ];
  80 +
  81 + _liveSceneSeg = [[UISegmentedControl alloc] initWithItems:items];
  82 + _liveSceneSeg.frame = CGRectMake(95, 40, self.bounds.size.width-105, 30);
  83 + _liveSceneSeg.tintColor= [UIColor blackColor];
  84 + _liveSceneSeg.selectedSegmentIndex = 0;
  85 + _liveSceneSeg.layer.cornerRadius = 5;
  86 + _liveSceneSeg.selectedSegmentIndex = 1;
  87 + _liveSceneSeg.tag = MoreFuncTypeLiveScene;
  88 + [_liveSceneSeg addTarget:self action:@selector(onSegCtrl:) forControlEvents:UIControlEventValueChanged];
  89 +
  90 + UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(-85, 0, 80, 30)];
  91 + titleLab.text = @"直播场景";
  92 + titleLab.textColor = [UIColor blackColor];
  93 + titleLab.font = [UIFont systemFontOfSize:15];
  94 + titleLab.textAlignment = NSTextAlignmentCenter;
  95 + titleLab.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.2];
  96 + [_liveSceneSeg addSubview:titleLab];
  97 + }
  98 + return _liveSceneSeg;
  99 +}
  100 +
  101 +- (UISegmentedControl *)recordSceneSeg
  102 +{
  103 + if (!_recordSceneSeg) {
  104 + NSArray *items = @[ @"恒定码率",
  105 + @"恒定质量",
  106 + ];
  107 +
  108 + _recordSceneSeg = [[UISegmentedControl alloc] initWithItems:items];
  109 + _recordSceneSeg.frame = CGRectMake(95, 80, self.bounds.size.width-105, 30);
  110 + _recordSceneSeg.tintColor= [UIColor blackColor];
  111 + _recordSceneSeg.selectedSegmentIndex = 0;
  112 + _recordSceneSeg.layer.cornerRadius = 5;
  113 + _recordSceneSeg.selectedSegmentIndex = 1;
  114 + _recordSceneSeg.tag = MoreFuncTypeRecordScene;
  115 + [_recordSceneSeg addTarget:self action:@selector(onSegCtrl:) forControlEvents:UIControlEventValueChanged];
  116 +
  117 + UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(-85, 0, 80, 30)];
  118 + titleLab.text = @"录制场景";
  119 + titleLab.textColor = [UIColor blackColor];
  120 + titleLab.font = [UIFont systemFontOfSize:15];
  121 + titleLab.textAlignment = NSTextAlignmentCenter;
  122 + titleLab.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.2];
  123 + [_recordSceneSeg addSubview:titleLab];
  124 + }
  125 + return _recordSceneSeg;
  126 +}
  127 +
  128 +- (UISegmentedControl *)logoSeg
  129 +{
  130 + if (!_logoSeg) {
  131 + NSArray *items = @[ @"清除logo",
  132 + @"图片logo",
  133 + @"动态logo",
  134 + ];
  135 +
  136 + _logoSeg = [[UISegmentedControl alloc] initWithItems:items];
  137 + _logoSeg.frame = CGRectMake(95, 120, self.bounds.size.width-105, 30);
  138 + _logoSeg.tintColor= [UIColor blackColor];
  139 + _logoSeg.selectedSegmentIndex = 0;
  140 + _logoSeg.layer.cornerRadius = 5;
  141 + _logoSeg.selectedSegmentIndex = 1;
  142 + _logoSeg.tag = MoreFuncTypeLogo;
  143 + [_logoSeg addTarget:self action:@selector(onSegCtrl:) forControlEvents:UIControlEventValueChanged];
  144 +
  145 + UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(-85, 0, 80, 30)];
  146 + titleLab.text = @"Logo设置";
  147 + titleLab.textColor = [UIColor blackColor];
  148 + titleLab.font = [UIFont systemFontOfSize:15];
  149 + titleLab.textAlignment = NSTextAlignmentCenter;
  150 + titleLab.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.2];
  151 + [_logoSeg addSubview:titleLab];
  152 + }
  153 + return _logoSeg;
  154 +}
  155 +
  156 +- (UISwitch *)bypassRecord
  157 +{
  158 + if (!_bypassRecord) {
  159 + _bypassRecord = [[UISwitch alloc] initWithFrame:CGRectMake(95, 160, 100, 30)];
  160 +
  161 + UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(-85, 0, 80, 30)];
  162 + titleLab.textColor = [UIColor blackColor];
  163 + titleLab.text = @"旁路录制";
  164 + titleLab.font = [UIFont systemFontOfSize:15];
  165 + titleLab.textAlignment = NSTextAlignmentCenter;
  166 + titleLab.backgroundColor = [UIColor colorWithWhite:0.9 alpha:0.2];
  167 + [_bypassRecord addSubview:titleLab];
  168 + }
  169 + return _bypassRecord;
  170 +}
  171 +
  172 +- (UIButton *)floatingWindowBtn
  173 +{
  174 + if (!_floatingWindowBtn) {
  175 + _floatingWindowBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  176 + _floatingWindowBtn.frame = CGRectMake(220, 160, 80, 30);
  177 + [_floatingWindowBtn setTitle:@"悬浮窗" forState: UIControlStateNormal];
  178 + _floatingWindowBtn.titleLabel.font = [UIFont systemFontOfSize:15];
  179 + [_floatingWindowBtn setTitleColor:[UIColor colorWithRed:23/255.0 green:110/255.0 blue:254/255.0 alpha:1] forState:UIControlStateNormal];
  180 + _floatingWindowBtn.layer.cornerRadius = 3;
  181 + _floatingWindowBtn.layer.masksToBounds = YES;
  182 + _floatingWindowBtn.layer.borderColor = [UIColor blackColor].CGColor;
  183 + _floatingWindowBtn.layer.borderWidth = 1;
  184 +
  185 + }
  186 + return _floatingWindowBtn;
  187 +}
  188 +
  189 +/*
  190 +// Only override drawRect: if you perform custom drawing.
  191 +// An empty implementation adversely affects performance during animation.
  192 +- (void)drawRect:(CGRect)rect {
  193 + // Drawing code
  194 +}
  195 +*/
  196 +
  197 +@end
Example/CNLivePlayer/Streamer/SliderView.h 0 → 100644
  1 +//
  2 +// SliderView.h
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 16/12/21.
  6 +// Copyright © 2016年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +@protocol SliderViewDelegate <NSObject>
  12 +
  13 +- (void)sliderValueChenged;
  14 +
  15 +@end
  16 +
  17 +@interface SliderView : UIView
  18 +
  19 +@property (nonatomic, strong) UILabel* nameL; // 滑块对应参数名称
  20 +@property (nonatomic, strong) UISlider* slider; // 滑块
  21 +@property (nonatomic, strong) UILabel* valueL; // 滑块当前的值
  22 +@property (nonatomic, assign, readonly) float currentValue;
  23 +@property (nonatomic, assign) id<SliderViewDelegate> delagate;
  24 +
  25 +- (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title;
  26 +
  27 +@end
Example/CNLivePlayer/Streamer/SliderView.m 0 → 100644
  1 +//
  2 +// SliderView.m
  3 +// CNLivePlayerSDKDemo
  4 +//
  5 +// Created by iOS on 16/12/21.
  6 +// Copyright © 2016年 雷浩杰. All rights reserved.
  7 +//
  8 +
  9 +#import "SliderView.h"
  10 +
  11 +@implementation SliderView
  12 +{
  13 + NSString *_title;
  14 +}
  15 +
  16 +- (instancetype)initWithFrame:(CGRect)frame title:(NSString *)title{
  17 + self = [super initWithFrame:frame];
  18 + if (self) {
  19 + _title = title;
  20 + [self addSubview:self.nameL];
  21 + [self addSubview:self.valueL];
  22 + [self addSubview:self.slider];
  23 + }
  24 + return self;
  25 +}
  26 +
  27 +- (float)currentValue
  28 +{
  29 + return _slider.value;
  30 +}
  31 +
  32 +#pragma mark -
  33 +#pragma mark - action
  34 +
  35 +- (void)onSlider:(UISlider *)slider
  36 +{
  37 + _valueL.text = [NSString stringWithFormat:@"%d",(int)(slider.value * 100)];
  38 + if (self.delagate && [self.delagate respondsToSelector:@selector(sliderValueChenged)]) {
  39 + [self.delagate sliderValueChenged];
  40 + }
  41 +}
  42 +
  43 +#pragma mark -
  44 +#pragma mark - getter
  45 +
  46 +- (UILabel *)nameL
  47 +{
  48 + if (!_nameL) {
  49 + _nameL = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 24)];
  50 + _nameL.text = _title;
  51 + _nameL.textAlignment = NSTextAlignmentCenter;
  52 + _nameL.textColor = [UIColor blackColor];
  53 + _nameL.backgroundColor = [UIColor colorWithRed:192/255.0 green:192/255.0 blue:192/255.0 alpha:1];
  54 + _nameL.font = [UIFont systemFontOfSize:15];
  55 + _nameL.layer.cornerRadius = 5;
  56 + _nameL.layer.masksToBounds = YES;
  57 + }
  58 + return _nameL;
  59 +}
  60 +
  61 +- (UILabel *)valueL
  62 +{
  63 + if (!_valueL) {
  64 + _valueL = [[UILabel alloc] initWithFrame:CGRectMake(self.bounds.size.width-40, 0, 40, 24)];
  65 + _valueL.text = @"50";
  66 + _valueL.textAlignment = NSTextAlignmentCenter;
  67 + _valueL.textColor = [UIColor blackColor];
  68 + _valueL.backgroundColor = [UIColor colorWithRed:192/255.0 green:192/255.0 blue:192/255.0 alpha:1];
  69 + _valueL.font = [UIFont systemFontOfSize:15];
  70 + _valueL.layer.cornerRadius = 5;
  71 + _valueL.layer.masksToBounds = YES;
  72 +
  73 + }
  74 + return _valueL;
  75 +}
  76 +
  77 +- (UISlider *)slider
  78 +{
  79 + if (!_slider) {
  80 + _slider = [[UISlider alloc] initWithFrame:CGRectMake(40, 0, self.bounds.size.width-80, 24)];
  81 + [_slider setThumbImage:[UIImage imageNamed:@"btn_dot"] forState:UIControlStateNormal];
  82 + [_slider setMinimumTrackTintColor:[UIColor redColor]];
  83 + [_slider setMaximumTrackTintColor:[UIColor whiteColor]];
  84 + _slider.value = 0.5;
  85 +
  86 + [_slider addTarget:self action:@selector(onSlider:) forControlEvents:UIControlEventValueChanged];
  87 + }
  88 + return _slider;
  89 +}
  90 +@end
Example/CNLivePlayer/Streamer/StreamerDetailViewController.h 0 → 100644
  1 +//
  2 +// LiveViewController.h
  3 +// CNLiveLiveDemo
  4 +//
  5 +// Created by Android on 16/8/10.
  6 +// Copyright © 2016年 Android. All rights reserved.
  7 +//
  8 +
  9 +#import <UIKit/UIKit.h>
  10 +
  11 +@interface StreamerDetailViewController : UIViewController
  12 +
  13 +@property (nonatomic, assign) BOOL isAuthLive;
  14 +@property (nonatomic, assign) BOOL isRecord;
  15 +
  16 +@property (nonatomic, strong) NSURL *url;
  17 +
  18 +@end