Commit b3e55654ed14682b3398f258950a6b494a2087a1

Authored by 王军波
1 parent 69c75123

采集

LiveVideoCloud/LiveVideoCloud/Classes/Sections/LiveSections/Controller/LVCLiveViewController.m
... ... @@ -7,13 +7,46 @@
7 7 //
8 8  
9 9 #import "LVCLiveViewController.h"
  10 +#import <CNLivePlayerSDK/CNLiveGPUStreamerKit.h>
  11 +#import <CNLivePlayerSDK/CNLiveWebcastManager.h>
10 12  
11   -@interface LVCLiveViewController ()
  13 +#define KAppId @"60_irn9edco29"
  14 +#define KAppKey @"69fe70bda67e059286ad509d9f5377f815955645b52f94"
  15 +
  16 +@interface LVCLiveViewController () {
  17 + // 开始直播
  18 + UIButton *_startLiveBtn;
  19 + // 缩放因子
  20 + CGFloat _currentPinchZoomFactor;
  21 +}
  22 +
  23 +@property (nonatomic,strong) UIView *captureView;
  24 +
  25 +@property (nonatomic,strong) CNLiveGPUStreamerKit *kitCN;
12 26  
13 27 @end
14 28  
15 29 @implementation LVCLiveViewController
16 30  
  31 +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
  32 +{
  33 + if (_kitCN) {
  34 + return UIInterfaceOrientationMaskAllButUpsideDown;
  35 + } else {
  36 + return UIInterfaceOrientationMaskPortrait;
  37 + }
  38 +}
  39 +
  40 +-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
  41 +
  42 + UIInterfaceOrientation orie = [[UIApplication sharedApplication] statusBarOrientation];
  43 + [_kitCN rotatePreviewTo:orie];
  44 +
  45 + if (_kitCN.streamerBase.isStreaming) {
  46 + [_kitCN rotateStreamTo:orie];
  47 + }
  48 +}
  49 +
17 50 - (void)viewDidLoad {
18 51 [super viewDidLoad];
19 52 // Do any additional setup after loading the view.
... ... @@ -23,26 +56,303 @@
23 56 [closeBtn setTitle:@"关闭" forState:UIControlStateNormal];
24 57 [closeBtn addTarget:self action:@selector(closeBtnClivk) forControlEvents:UIControlEventTouchUpInside];
25 58 [self.view addSubview:closeBtn];
  59 +
  60 + // 活动Id
  61 + NSString *activityId = [NSString stringWithFormat:@"%d%d%d%d%d",arc4random()%9,arc4random()%9,arc4random()%9,arc4random()%9,arc4random()%9];
  62 + // 初始化直播云
  63 + [[CNLiveWebcastManager manager] initWithAppId:KAppId appKey:KAppKey];
  64 + // 初始化推流
  65 + _kitCN = [[CNLiveGPUStreamerKit alloc] initWithDefaultConfigWithActivityId:activityId channelId:@"iOStest" isHorizontalScreen:@"0"];
  66 +
  67 + // _kitCN.activityName = @"iOS test";
  68 + // _kitCN.coverImgUrl = @"djfiwooa";
  69 +
  70 + [self setStreamerCfg];
  71 + [self addObservers];
26 72 }
27 73  
28   -- (void)closeBtnClivk
29   -{
  74 +#pragma mark - initialization Streamer
  75 +- (void)setStreamerCfg {
  76 + //采集配置
  77 + _kitCN.capPreset = AVCaptureSessionPreset640x480;
  78 + _kitCN.previewDimension = CGSizeMake(360, 640);
  79 + _kitCN.streamDimension = CGSizeMake(360, 640);
  80 + _kitCN.videoFPS = 15;
  81 + _kitCN.cameraPosition = AVCaptureDevicePositionFront;
  82 +
  83 + //推流配置
  84 + _kitCN.streamerBase.videoCodec = CNLiveVideoCodec_AUTO;
  85 + _kitCN.streamerBase.videoInitBitrate = 900;
  86 + _kitCN.streamerBase.videoMaxBitrate = 900;
  87 + _kitCN.streamerBase.videoMinBitrate = 300;
  88 + _kitCN.streamerBase.maxKeyInterval = 2;
  89 + _kitCN.streamerBase.audiokBPS = 48;
  90 +
  91 + // 如果有耳机,麦克风
  92 + if ([CNLiveAudioCapture isHeadsetPluggedIn]) {
  93 + // 音频采集器 自动播放采集声音
  94 + [_kitCN.audioCapture setBPlayCapturedAudio:YES];
  95 + }
  96 +
  97 + //设置画面朝向
  98 + [_kitCN setVideoOrientationBy:[[UIApplication sharedApplication] statusBarOrientation]];
  99 +
  100 + // 启动预览
  101 + [_kitCN startPreview:self.captureView];
  102 +
  103 + //水印图片
  104 + _kitCN.watermark.logoPic = [UIImage imageNamed:@"互动电视180x180"];
  105 + _kitCN.watermark.logoRect = CGRectMake(0.8, 0.8, 50, 50);
  106 + _kitCN.watermark.logoAlpha = 0.6;
  107 +
  108 + //水印文字
  109 + _kitCN.watermark.textLabel = [[UILabel alloc] init];
  110 + _kitCN.watermark.textLabel.text = [NSString stringWithFormat:@"cnlive"];
  111 + _kitCN.watermark.textLabel.font = [UIFont systemFontOfSize:8];
  112 + _kitCN.watermark.textRect = CGRectMake(0.78, 0.88, 0.2, 0.04);
  113 + [_kitCN.watermark updateTextLabel];
  114 +
  115 +}
  116 +
  117 +#pragma mark - Action !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  118 +
  119 +- (void)addObservers {
  120 +
  121 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(captureStateChange) name:CNLiveCaptureStateDidChangeNotification object:nil];
  122 +
  123 + [[NSNotificationCenter defaultCenter] addObserver:self
  124 + selector:@selector(streamStateChange)
  125 + name:CNLiveStreamStateDidChangeNotification
  126 + object:nil];
  127 +
  128 + [[NSNotificationCenter defaultCenter] addObserver:self
  129 + selector:@selector(enterBg)
  130 + name:UIApplicationDidEnterBackgroundNotification
  131 + object:nil];
  132 +
  133 + [[NSNotificationCenter defaultCenter] addObserver:self
  134 + selector:@selector(becameActive)
  135 + name:UIApplicationDidBecomeActiveNotification
  136 + object:nil];
  137 +}
  138 +
  139 +// 退出
  140 +- (void)closeBtnClivk {
  141 +
30 142 [self dismissViewControllerAnimated:YES completion:nil];
31 143 }
32 144  
33   -- (void)didReceiveMemoryWarning {
34   - [super didReceiveMemoryWarning];
35   - // Dispose of any resources that can be recreated.
  145 +#pragma mark - notification
  146 +
  147 +- (void)enterBg {
  148 +
  149 + [_kitCN appEnterBackground];
  150 +}
  151 +
  152 +- (void)becameActive {
  153 +
  154 + [_kitCN appBecomeActive];
  155 +}
  156 +
  157 +- (void)captureStateChange {
  158 +
  159 + if ( _kitCN.captureState == CNLiveCaptureStateIdle){
  160 + //初始化时状态为空闲
  161 +// _stateLab.text = @"CNLiveCaptureStateIdle";
  162 +
  163 + return;
  164 + }
  165 + else if (_kitCN.captureState == CNLiveCaptureStateCapturing ) {
  166 + //设备工作中
  167 +// _stateLab.text = @"CNLiveCaptureStateCapturing";
  168 +
  169 + return;
  170 + }
  171 + else if (_kitCN.captureState == CNLiveCaptureStateClosingCapture ) {
  172 + //关闭采集设备中
  173 +// _stateLab.text = @"CNLiveCaptureStateClosingCapture";
  174 +
  175 + return;
  176 + }
  177 + else if (_kitCN.captureState == CNLiveCaptureStateDevAuthDenied ) {
  178 + //设备授权被拒绝
  179 + NSLog(@"---------CNLiveCaptureStateDevAuthDenied");
  180 +// _stateLab.text = @"camera/mic Authorization Denied";
  181 +
  182 + return;
  183 + }
  184 + else if (_kitCN.captureState == CNLiveCaptureStateParameterError ) {
  185 + // 参数错误,无法打开
  186 + NSLog(@"---------CNLiveCaptureStateParameterError");
  187 +// _stateLab.text = @"capture devices ParameterError";
  188 +
  189 + return;
  190 + }
  191 + else if (_kitCN.captureState == CNLiveCaptureStateDevBusy ) {
  192 + //设备正忙,请稍后尝试
  193 + NSLog(@"---------CNLiveCaptureStateDevBusy");
  194 +// _stateLab.text = @"device busy, try later";
  195 +
  196 + }
  197 +}
  198 +
  199 +- (void)streamStateChange {
  200 +
  201 + if (_kitCN.streamState == CNLiveStreamStateIdle) {
  202 +
  203 + NSLog(@"---------CNLiveStreamStateIdle");
  204 +// _stateLab.text = @"CNLiveStreamStateIdle";
  205 + }
  206 +
  207 + if (_kitCN.streamState == CNLiveStreamStateConnected) {
  208 +
  209 + NSLog(@"---------CNLiveStreamStateConnected");
  210 +// _stateLab.text = [NSString stringWithFormat:@"CNLiveStreamStateConnected------%@",_hostURL];
  211 + }
  212 +
  213 + if (_kitCN.streamState == CNLiveStreamStateConnecting) {
  214 +
  215 + NSLog(@"---------CNLiveStreamStateConnecting");
  216 +// _stateLab.text = @"CNLiveStreamStateConnecting";
  217 + }
  218 +
  219 + //推流出错
  220 + if (_kitCN.streamState == CNLiveStreamStateError) {
  221 +
  222 + NSLog(@"---------CNLiveStreamStateError");
  223 + [self onStreamError];
  224 + }
  225 +
  226 + //断开推流
  227 + if ( _kitCN.streamState == CNLiveStreamStateDisconnecting) {
  228 +
  229 + NSLog(@"---------CNLiveStreamStateDisconnecting");
  230 +// _stateLab.text = @"CNLiveStreamStateDisconnecting";
  231 + }
  232 +
  233 + //结束推流成功
  234 + if ( _kitCN.streamState == CNLiveStopStreamSuccess) {
  235 +
  236 + NSLog(@"---------CNLiveStopStreamSuccess");
  237 +// _stateLab.text = @"CNLiveStopStreamSuccess";
  238 + }
  239 +}
  240 +
  241 +- (void)onStreamError {
  242 +
  243 + CNLiveStreamErrorCode err = _kitCN.streamErrorCode;
  244 +
  245 + NSLog(@"onErr: %lu ", (unsigned long) err);
  246 +
  247 + if ( CNLiveStreamErrorCode_CNLiveAUTHFAILED == err ) {
  248 +// _stateLab.text = @"SDK auth failed, \npls check ak/sk";
  249 + }
  250 + else if ( CNLiveStreamErrorCode_CODEC_OPEN_FAILED == err) {
  251 +// _stateLab.text = @"Selected Codec not supported \n in this version";
  252 + }
  253 + else if ( CNLiveStreamErrorCode_CONNECT_FAILED == err) {
  254 +// _stateLab.text = @"Connecting error, pls check host url \nor network";
  255 + }
  256 + else if ( CNLiveStreamErrorCode_CONNECT_BREAK == err) {
  257 +// _stateLab.text = @"Connection break";
  258 + }
  259 + else if ( CNLiveStreamErrorCode_ABNORMAL == err) {
  260 +// _stateLab.text = @"CNLiveStreamErrorCode_ABNORMAL";
  261 + [self toast:@"推流异常中断~~"];
  262 + _startLiveBtn.selected = NO;
  263 +
  264 + } else if (err == CNLiveStreamErrorCode_CODEC_OPEN_FAILED) {
  265 + NSLog(@"video codec open failed, try software codec");
  266 + _kitCN.streamerBase.videoCodec = CNLiveVideoCodec_VT264;
  267 + [self tryReconnect];
  268 + }
  269 + else {
  270 +
  271 + }
  272 +
  273 + // 断网重连
  274 + if (err == CNLiveStreamErrorCode_CONNECT_BREAK || err == CNLiveStreamErrorCode_AV_SYNC_ERROR) {
  275 + [self tryReconnect];
  276 + }
  277 +
  278 +}
  279 +
  280 +- (void) tryReconnect {
  281 +
  282 + dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC));
  283 + dispatch_after(delay, dispatch_get_main_queue(), ^{
  284 +
  285 + NSLog(@"try again");
  286 +
  287 + [_kitCN stopStream];
  288 +
  289 + [_kitCN startStream:^{
  290 + NSLog(@"开启推流成功 ------- success");
  291 + _startLiveBtn.selected = YES;
  292 +
  293 + } failure:^(NSDictionary *errorDic) {
  294 + [self toast:errorDic[@"errorMessage"]];
  295 + _startLiveBtn.selected = NO;
  296 + }];
  297 +
  298 + });
  299 +}
  300 +
  301 +//
  302 +- (void)toast:(NSString*)message
  303 +{
  304 +
  305 + UIAlertView *toast = [[UIAlertView alloc] initWithTitle:nil
  306 + message:message
  307 + delegate:nil
  308 + cancelButtonTitle:nil
  309 + otherButtonTitles:nil, nil];
  310 + [toast show];
  311 + double duration = 2.5;
  312 + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  313 + [toast dismissWithClickedButtonIndex:0 animated:NO];
  314 + });
36 315 }
37 316  
38   -/*
39   -#pragma mark - Navigation
40 317  
41   -// In a storyboard-based application, you will often want to do a little preparation before navigation
42   -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
43   - // Get the new view controller using [segue destinationViewController].
44   - // Pass the selected object to the new view controller.
  318 +// 将UI的坐标转换成相机坐标
  319 +- (CGPoint)convertToPointOfInterestFromViewCoordinates:(CGPoint)viewCoordinates
  320 +{
  321 + CGPoint pointOfInterest = CGPointMake(.5f, .5f);
  322 + CGSize frameSize = self.view.frame.size;
  323 + CGSize apertureSize = [_kitCN captureDimension];
  324 + CGPoint point = viewCoordinates;
  325 + CGFloat apertureRatio = apertureSize.height / apertureSize.width;
  326 + CGFloat viewRatio = frameSize.width / frameSize.height;
  327 + CGFloat xc = .5f;
  328 + CGFloat yc = .5f;
  329 +
  330 + if (viewRatio > apertureRatio) {
  331 + CGFloat y2 = frameSize.height;
  332 + CGFloat x2 = frameSize.height * apertureRatio;
  333 + CGFloat x1 = frameSize.width;
  334 + CGFloat blackBar = (x1 - x2) / 2;
  335 + if (point.x >= blackBar && point.x <= blackBar + x2) {
  336 + xc = point.y / y2;
  337 + yc = 1.f - ((point.x - blackBar) / x2);
  338 + }
  339 + }else {
  340 + CGFloat y2 = frameSize.width / apertureRatio;
  341 + CGFloat y1 = frameSize.height;
  342 + CGFloat x2 = frameSize.width;
  343 + CGFloat blackBar = (y1 - y2) / 2;
  344 + if (point.y >= blackBar && point.y <= blackBar + y2) {
  345 + xc = ((point.y - blackBar) / y2);
  346 + yc = 1.f - (point.x / x2);
  347 + }
  348 + }
  349 + pointOfInterest = CGPointMake(xc, yc);
  350 + return pointOfInterest;
  351 +}
  352 +
  353 +- (void)didReceiveMemoryWarning {
  354 + [super didReceiveMemoryWarning];
  355 + // Dispose of any resources that can be recreated.
45 356 }
46   -*/
47 357  
48 358 @end
... ...