481 lines
15 KiB
Objective-C
Executable File
481 lines
15 KiB
Objective-C
Executable File
//
|
|
// NTESVideoChatViewController.m
|
|
// NIM
|
|
//
|
|
// Created by chris on 15/5/5.
|
|
// Copyright (c) 2015年 Netease. All rights reserved.
|
|
//
|
|
|
|
#import "NTESVideoChatViewController.h"
|
|
#import "Toast+UIView.h"
|
|
#import "NTESTimerHolder.h"
|
|
#import "NTESAudioChatViewController.h"
|
|
#import "NetCallChatInfo.h"
|
|
#import "NTESSessionUtil.h"
|
|
#import "NTESVideoChatNetStatusView.h"
|
|
#import "NTESGLView.h"
|
|
#import "NTESBundleSetting.h"
|
|
#import "NTESRecordSelectView.h"
|
|
#import "UIView+NTES.h"
|
|
|
|
#define NTESUseGLView
|
|
|
|
@interface NTESVideoChatViewController ()
|
|
@property (nonatomic,assign) NIMNetCallCamera cameraType;
|
|
|
|
@property (nonatomic,strong) CALayer *localVideoLayer;
|
|
|
|
@property (nonatomic,assign) BOOL oppositeCloseVideo;
|
|
|
|
#if defined (NTESUseGLView)
|
|
@property (nonatomic, strong) NTESGLView *remoteGLView;
|
|
#endif
|
|
|
|
@property (nonatomic,weak) UIView *localView;
|
|
|
|
@end
|
|
|
|
@implementation NTESVideoChatViewController
|
|
|
|
- (instancetype)initWithCallInfo:(NetCallChatInfo *)callInfo
|
|
{
|
|
self = [self initWithNibName:nil bundle:nil];
|
|
if (self) {
|
|
self.callInfo = callInfo;
|
|
self.callInfo.isMute = NO;
|
|
self.callInfo.useSpeaker = NO;
|
|
self.callInfo.disableCammera = NO;
|
|
if (!self.localVideoLayer) {
|
|
//没有的话,尝试去取一把预览层(从视频切到语音再切回来的情况下是会有的)
|
|
self.localVideoLayer = [NIMAVChatSDK sharedSDK].netCallManager.localPreviewLayer;
|
|
}
|
|
[[NIMAVChatSDK sharedSDK].netCallManager switchType:NIMNetCallMediaTypeVideo];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
|
|
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
|
|
if (self) {
|
|
self.callInfo.callType = NIMNetCallTypeVideo;
|
|
_cameraType = [[NTESBundleSetting sharedConfig] startWithBackCamera] ? NIMNetCallCameraBack :NIMNetCallCameraFront;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
self.localView = self.smallVideoView;
|
|
[super viewDidLoad];
|
|
if (self.localVideoLayer) {
|
|
[self.localView.layer addSublayer:self.localVideoLayer];
|
|
}
|
|
[self initUI];
|
|
}
|
|
|
|
- (void)initUI
|
|
{
|
|
self.localRecordingView.layer.cornerRadius = 10.0;
|
|
self.localRecordingRedPoint.layer.cornerRadius = 4.0;
|
|
self.lowMemoryView.layer.cornerRadius = 10.0;
|
|
self.lowMemoryRedPoint.layer.cornerRadius = 4.0;
|
|
self.refuseBtn.exclusiveTouch = YES;
|
|
self.acceptBtn.exclusiveTouch = YES;
|
|
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) {
|
|
[self initRemoteGLView];
|
|
}
|
|
}
|
|
|
|
- (void)initRemoteGLView {
|
|
#if defined (NTESUseGLView)
|
|
_remoteGLView = [[NTESGLView alloc] initWithFrame:_bigVideoView.bounds];
|
|
[_remoteGLView setContentMode:UIViewContentModeScaleAspectFit];
|
|
[_remoteGLView setBackgroundColor:[UIColor clearColor]];
|
|
_remoteGLView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
[_bigVideoView addSubview:_remoteGLView];
|
|
#endif
|
|
}
|
|
|
|
|
|
#pragma mark - Call Life
|
|
- (void)startByCaller{
|
|
[super startByCaller];
|
|
[self startInterface];
|
|
}
|
|
|
|
- (void)startByCallee{
|
|
[super startByCallee];
|
|
[self waitToCallInterface];
|
|
}
|
|
- (void)onCalling{
|
|
[super onCalling];
|
|
[self videoCallingInterface];
|
|
}
|
|
|
|
- (void)waitForConnectiong{
|
|
[super waitForConnectiong];
|
|
[self connectingInterface];
|
|
}
|
|
|
|
#pragma mark - Interface
|
|
//正在接听中界面
|
|
- (void)startInterface{
|
|
self.acceptBtn.hidden = YES;
|
|
self.refuseBtn.hidden = YES;
|
|
self.hungUpBtn.hidden = NO;
|
|
self.connectingLabel.hidden = NO;
|
|
self.connectingLabel.text = @"正在呼叫,请稍候...";
|
|
self.switchModelBtn.hidden = YES;
|
|
self.switchCameraBtn.hidden = NO;
|
|
self.muteBtn.hidden = NO;
|
|
self.disableCameraBtn.hidden = NO;
|
|
self.localRecordBtn.hidden = NO;
|
|
self.muteBtn.enabled = NO;
|
|
self.disableCameraBtn.enabled = NO;
|
|
self.localRecordBtn.enabled = NO;
|
|
|
|
self.localRecordingView.hidden = YES;
|
|
self.lowMemoryView.hidden = YES;
|
|
[self.hungUpBtn removeTarget:self action:NULL forControlEvents:UIControlEventTouchUpInside];
|
|
[self.hungUpBtn addTarget:self action:@selector(hangup) forControlEvents:UIControlEventTouchUpInside];
|
|
self.localView = self.bigVideoView;
|
|
}
|
|
|
|
//选择是否接听界面
|
|
- (void)waitToCallInterface{
|
|
self.acceptBtn.hidden = NO;
|
|
self.refuseBtn.hidden = NO;
|
|
self.hungUpBtn.hidden = YES;
|
|
NSString *nick = [NTESSessionUtil showNick:self.callInfo.caller inSession:nil];
|
|
self.connectingLabel.text = [nick stringByAppendingString:@"的来电"];
|
|
self.muteBtn.hidden = YES;
|
|
self.switchCameraBtn.hidden = YES;
|
|
self.disableCameraBtn.hidden = YES;
|
|
self.localRecordBtn.hidden = YES;
|
|
self.localRecordingView.hidden = YES;
|
|
self.lowMemoryView.hidden = YES;
|
|
self.switchModelBtn.hidden = YES;
|
|
}
|
|
|
|
//连接对方界面
|
|
- (void)connectingInterface{
|
|
self.acceptBtn.hidden = YES;
|
|
self.refuseBtn.hidden = YES;
|
|
self.hungUpBtn.hidden = NO;
|
|
self.connectingLabel.hidden = NO;
|
|
self.connectingLabel.text = @"正在连接对方...请稍后...";
|
|
self.switchModelBtn.hidden = YES;
|
|
self.switchCameraBtn.hidden = YES;
|
|
self.muteBtn.hidden = YES;
|
|
self.disableCameraBtn.hidden = YES;
|
|
self.localRecordBtn.hidden = YES;
|
|
self.localRecordingView.hidden = YES;
|
|
self.lowMemoryView.hidden = YES;
|
|
[self.hungUpBtn removeTarget:self action:NULL forControlEvents:UIControlEventTouchUpInside];
|
|
[self.hungUpBtn addTarget:self action:@selector(hangup) forControlEvents:UIControlEventTouchUpInside];
|
|
}
|
|
|
|
//接听中界面(视频)
|
|
- (void)videoCallingInterface{
|
|
|
|
NIMNetCallNetStatus status = [[NIMAVChatSDK sharedSDK].netCallManager netStatus:self.peerUid];
|
|
[self.netStatusView refreshWithNetState:status];
|
|
self.acceptBtn.hidden = YES;
|
|
self.refuseBtn.hidden = YES;
|
|
self.hungUpBtn.hidden = NO;
|
|
self.connectingLabel.hidden = YES;
|
|
self.muteBtn.hidden = NO;
|
|
self.switchCameraBtn.hidden = NO;
|
|
self.disableCameraBtn.hidden = NO;
|
|
self.localRecordBtn.hidden = NO;
|
|
self.switchModelBtn.hidden = NO;
|
|
|
|
self.muteBtn.enabled = YES;
|
|
self.disableCameraBtn.enabled = YES;
|
|
self.localRecordBtn.enabled = YES;
|
|
|
|
self.muteBtn.selected = self.callInfo.isMute;
|
|
self.disableCameraBtn.selected = self.callInfo.disableCammera;
|
|
self.localRecordBtn.selected = ![self allRecordsStopped];
|
|
;
|
|
self.localRecordingView.hidden = [self allRecordsStopped];
|
|
;
|
|
self.lowMemoryView.hidden = YES;
|
|
[self.switchModelBtn setTitle:@"语音模式" forState:UIControlStateNormal];
|
|
[self.hungUpBtn removeTarget:self action:NULL forControlEvents:UIControlEventTouchUpInside];
|
|
[self.hungUpBtn addTarget:self action:@selector(hangup) forControlEvents:UIControlEventTouchUpInside];
|
|
self.localVideoLayer.hidden = NO;
|
|
}
|
|
|
|
//切换接听中界面(语音)
|
|
- (void)audioCallingInterface{
|
|
|
|
NTESAudioChatViewController *vc = [[NTESAudioChatViewController alloc] initWithCallInfo:self.callInfo];
|
|
[UIView beginAnimations:nil context:NULL];
|
|
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
|
|
[UIView setAnimationDuration:0.75];
|
|
[self.navigationController pushViewController:vc animated:NO];
|
|
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
|
|
[UIView commitAnimations];
|
|
NSMutableArray * vcs = [self.navigationController.viewControllers mutableCopy];
|
|
[vcs removeObject:self];
|
|
self.navigationController.viewControllers = vcs;
|
|
}
|
|
|
|
- (void)udpateLowSpaceWarning:(BOOL)show {
|
|
self.lowMemoryView.hidden = !show;
|
|
self.localRecordingView.hidden = show;
|
|
}
|
|
|
|
|
|
#pragma mark - IBAction
|
|
|
|
- (IBAction)acceptToCall:(id)sender{
|
|
BOOL accept = (sender == self.acceptBtn);
|
|
//防止用户在点了接收后又点拒绝的情况
|
|
[self response:accept];
|
|
}
|
|
|
|
- (IBAction)mute:(BOOL)sender{
|
|
self.callInfo.isMute = !self.callInfo.isMute;
|
|
self.player.volume = !self.callInfo.isMute;
|
|
[[NIMAVChatSDK sharedSDK].netCallManager setMute:self.callInfo.isMute];
|
|
self.muteBtn.selected = self.callInfo.isMute;
|
|
}
|
|
|
|
- (IBAction)switchCamera:(id)sender{
|
|
if (self.cameraType == NIMNetCallCameraFront) {
|
|
self.cameraType = NIMNetCallCameraBack;
|
|
}else{
|
|
self.cameraType = NIMNetCallCameraFront;
|
|
}
|
|
[[NIMAVChatSDK sharedSDK].netCallManager switchCamera:self.cameraType];
|
|
self.switchCameraBtn.selected = (self.cameraType == NIMNetCallCameraBack);
|
|
}
|
|
|
|
|
|
- (IBAction)disableCammera:(id)sender{
|
|
self.callInfo.disableCammera = !self.callInfo.disableCammera;
|
|
[[NIMAVChatSDK sharedSDK].netCallManager setCameraDisable:self.callInfo.disableCammera];
|
|
self.disableCameraBtn.selected = self.callInfo.disableCammera;
|
|
if (self.callInfo.disableCammera) {
|
|
[self.localVideoLayer removeFromSuperlayer];
|
|
[[NIMAVChatSDK sharedSDK].netCallManager control:self.callInfo.callID type:NIMNetCallControlTypeCloseVideo];
|
|
}else{
|
|
[self.localView.layer addSublayer:self.localVideoLayer];
|
|
[[NIMAVChatSDK sharedSDK].netCallManager control:self.callInfo.callID type:NIMNetCallControlTypeOpenVideo];
|
|
}
|
|
}
|
|
|
|
- (IBAction)localRecord:(id)sender {
|
|
//出现录制选择框
|
|
if ([self allRecordsStopped]) {
|
|
[self showRecordSelectView:YES];
|
|
}
|
|
//同时停止所有录制
|
|
else
|
|
{
|
|
//结束语音对话
|
|
if (self.callInfo.audioConversation) {
|
|
[self stopAudioRecording];
|
|
if([self allRecordsStopped])
|
|
{
|
|
self.localRecordBtn.selected = NO;
|
|
self.localRecordingView.hidden = YES;
|
|
self.lowMemoryView.hidden = YES;
|
|
}
|
|
}
|
|
[self stopRecordTaskWithVideo:YES];
|
|
}
|
|
|
|
}
|
|
|
|
|
|
- (IBAction)switchCallingModel:(id)sender{
|
|
[[NIMAVChatSDK sharedSDK].netCallManager control:self.callInfo.callID type:NIMNetCallControlTypeToAudio];
|
|
[self switchToAudio];
|
|
}
|
|
|
|
|
|
#pragma mark - NTESRecordSelectViewDelegate
|
|
|
|
-(void)onRecordWithAudioConversation:(BOOL)audioConversationOn myMedia:(BOOL)myMediaOn otherSideMedia:(BOOL)otherSideMediaOn
|
|
{
|
|
if (audioConversationOn) {
|
|
//开始语音对话
|
|
if ([self startAudioRecording]) {
|
|
self.callInfo.audioConversation = YES;
|
|
self.localRecordBtn.selected = YES;
|
|
self.localRecordingView.hidden = NO;
|
|
self.lowMemoryView.hidden = YES;
|
|
}
|
|
}
|
|
[self recordWithAudioConversation:audioConversationOn myMedia:myMediaOn otherSideMedia:otherSideMediaOn video:YES];
|
|
}
|
|
|
|
|
|
#pragma mark - NIMNetCallManagerDelegate
|
|
|
|
- (void)setLocalVideoLayer:(CALayer *)localVideoLayer{
|
|
_localVideoLayer = localVideoLayer;
|
|
}
|
|
|
|
- (void)onLocalPreviewReady:(CALayer *)layer{
|
|
if (self.localVideoLayer) {
|
|
[self.localVideoLayer removeFromSuperlayer];
|
|
}
|
|
self.localVideoLayer = layer;
|
|
layer.frame = self.localView.bounds;
|
|
[self.localView.layer addSublayer:layer];
|
|
}
|
|
|
|
#if defined(NTESUseGLView)
|
|
- (void)onRemoteYUVReady:(NSData *)yuvData
|
|
width:(NSUInteger)width
|
|
height:(NSUInteger)height
|
|
from:(NSString *)user
|
|
{
|
|
if (([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive) && !self.oppositeCloseVideo) {
|
|
|
|
if (!_remoteGLView) {
|
|
[self initRemoteGLView];
|
|
}
|
|
[_remoteGLView render:yuvData width:width height:height];
|
|
}
|
|
}
|
|
#else
|
|
- (void)onRemoteImageReady:(CGImageRef)image{
|
|
if (self.oppositeCloseVideo) {
|
|
return;
|
|
}
|
|
self.bigVideoView.contentMode = UIViewContentModeScaleAspectFill;
|
|
self.bigVideoView.image = [UIImage imageWithCGImage:image];
|
|
}
|
|
#endif
|
|
|
|
- (void)onControl:(UInt64)callID
|
|
from:(NSString *)user
|
|
type:(NIMNetCallControlType)control{
|
|
[super onControl:callID from:user type:control];
|
|
switch (control) {
|
|
case NIMNetCallControlTypeToAudio:
|
|
[self switchToAudio];
|
|
break;
|
|
case NIMNetCallControlTypeCloseVideo:
|
|
[self resetRemoteImage];
|
|
self.oppositeCloseVideo = YES;
|
|
[self.view makeToast:@"对方关闭了摄像头"
|
|
];
|
|
break;
|
|
case NIMNetCallControlTypeOpenVideo:
|
|
self.oppositeCloseVideo = NO;
|
|
[self.view makeToast:@"对方开启了摄像头"
|
|
];
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
-(void)onCallEstablished:(UInt64)callID
|
|
{
|
|
if (self.callInfo.callID == callID) {
|
|
[super onCallEstablished:callID];
|
|
|
|
self.durationLabel.hidden = NO;
|
|
self.durationLabel.text = self.durationDesc;
|
|
|
|
if (self.localView == self.bigVideoView) {
|
|
self.localView = self.smallVideoView;
|
|
|
|
if (self.localVideoLayer) {
|
|
[self onLocalPreviewReady:self.localVideoLayer];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)onNetStatus:(NIMNetCallNetStatus)status user:(NSString *)user
|
|
{
|
|
if ([user isEqualToString:self.peerUid]) {
|
|
[self.netStatusView refreshWithNetState:status];
|
|
}
|
|
}
|
|
|
|
|
|
- (void)onRecordStarted:(UInt64)callID fileURL:(NSURL *)fileURL uid:(NSString *)userId
|
|
{
|
|
[super onRecordStarted:callID fileURL:fileURL uid:userId];
|
|
if (self.callInfo.callID == callID) {
|
|
self.localRecordBtn.selected = YES;
|
|
self.localRecordingView.hidden = NO;
|
|
self.lowMemoryView.hidden = YES;
|
|
}
|
|
}
|
|
|
|
|
|
- (void)onRecordError:(NSError *)error
|
|
callID:(UInt64)callID
|
|
uid:(NSString *)userId;
|
|
|
|
{
|
|
[super onRecordError:error callID:callID uid:userId];
|
|
if (self.callInfo.callID == callID) {
|
|
//判断是否全部结束
|
|
if([self allRecordsStopped])
|
|
{
|
|
self.localRecordBtn.selected = NO;
|
|
self.localRecordingView.hidden = YES;
|
|
self.lowMemoryView.hidden = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void) onRecordStopped:(UInt64)callID
|
|
fileURL:(NSURL *)fileURL
|
|
uid:(NSString *)userId;
|
|
|
|
{
|
|
[super onRecordStopped:callID fileURL:fileURL uid:userId];
|
|
if (self.callInfo.callID == callID) {
|
|
if([self allRecordsStopped])
|
|
{
|
|
self.localRecordBtn.selected = NO;
|
|
self.localRecordingView.hidden = YES;
|
|
self.lowMemoryView.hidden = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark - M80TimerHolderDelegate
|
|
|
|
- (void)onNTESTimerFired:(NTESTimerHolder *)holder{
|
|
[super onNTESTimerFired:holder];
|
|
self.durationLabel.text = self.durationDesc;
|
|
}
|
|
|
|
#pragma mark - Misc
|
|
- (void)switchToAudio{
|
|
[self audioCallingInterface];
|
|
}
|
|
|
|
- (NSString*)durationDesc{
|
|
if (!self.callInfo.startTime) {
|
|
return @"";
|
|
}
|
|
NSTimeInterval time = [NSDate date].timeIntervalSince1970;
|
|
NSTimeInterval duration = time - self.callInfo.startTime;
|
|
return [NSString stringWithFormat:@"%02d:%02d",(int)duration/60,(int)duration%60];
|
|
}
|
|
|
|
- (void)resetRemoteImage{
|
|
#if defined (NTESUseGLView)
|
|
[self.remoteGLView render:nil width:0 height:0];
|
|
#endif
|
|
|
|
self.bigVideoView.image = [UIImage imageNamed:@"netcall_bkg.png"];
|
|
}
|
|
|
|
@end
|