From d272d1f5cbfced9b63a581838702a36551722dfc Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Mon, 24 Aug 2015 13:38:54 +0300 Subject: [PATCH 1/9] Fixed rotation issue Added needed handlers for reinit video session --- AppRTC/ARTCVideoChatViewController.m | 49 +- Lib/ARDAppClient.h | 20 +- Lib/ARDAppClient.m | 948 +++++++++++++++------------ 3 files changed, 579 insertions(+), 438 deletions(-) diff --git a/AppRTC/ARTCVideoChatViewController.m b/AppRTC/ARTCVideoChatViewController.m index fff4a47..c44bac7 100644 --- a/AppRTC/ARTCVideoChatViewController.m +++ b/AppRTC/ARTCVideoChatViewController.m @@ -8,6 +8,7 @@ #import "ARTCVideoChatViewController.h" #import +#import "RTCI420Frame.h" #define SERVER_HOST_URL @"https://apprtc.appspot.com" @@ -34,14 +35,19 @@ - (void)viewDidLoad { //RTCEAGLVideoViewDelegate provides notifications on video frame dimensions [self.remoteView setDelegate:self]; [self.localView setDelegate:self]; - + //Getting Orientation change [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:@"UIDeviceOrientationDidChangeNotification" object:nil]; - - + // + // + // //AVCaptureSessionRuntimeErrorNotification + // [[NSNotificationCenter defaultCenter] addObserver:self + // selector:@selector(didChangeVideoSizes) + // name:AVCaptureSessionRuntimeErrorNotification + // object:nil]; } - (void)viewWillAppear:(BOOL)animated { @@ -79,7 +85,7 @@ - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } -- (void)orientationChanged:(NSNotification *)notification{ +- (void)orientationChanged:(NSNotification *)notification { [self videoView:self.localView didChangeVideoSize:self.localVideoSize]; [self videoView:self.remoteView didChangeVideoSize:self.remoteVideoSize]; } @@ -146,6 +152,12 @@ - (IBAction)hangupButtonPressed:(id)sender { [self.navigationController popToRootViewControllerAnimated:YES]; } +-(void)didChangeVideoSizes +{ + [self videoView:self.localView didChangeVideoSize:self.localVideoSize]; + [self videoView:self.remoteView didChangeVideoSize:self.remoteVideoSize]; +} + #pragma mark - ARDAppClientDelegate @@ -176,6 +188,10 @@ - (void)appClient:(ARDAppClient *)client didReceiveLocalVideoTrack:(RTCVideoTrac - (void)appClient:(ARDAppClient *)client didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { self.remoteVideoTrack = remoteVideoTrack; + // [self.remoteView setFrame:CGRectMake(0, 0, 100, 100)]; + // RTCI420Frame* fram = [RTCI420Frame new]; + + // [self.remoteView renderFrame:fram]; [self.remoteVideoTrack addRenderer:self.remoteView]; [UIView animateWithDuration:0.4f animations:^{ @@ -188,6 +204,15 @@ - (void)appClient:(ARDAppClient *)client didReceiveRemoteVideoTrack:(RTCVideoTra }]; } +-(void)didRemoveLocalVideoTrack:(RTCVideoTrack *)remoteVideoTrack +{ + if (self.localVideoTrack == remoteVideoTrack) { + [remoteVideoTrack removeRenderer:self.localView]; + self.localVideoTrack = remoteVideoTrack = nil; + [self.localView renderFrame:nil]; + } +} + - (void)appClient:(ARDAppClient *)client didError:(NSError *)error { UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil message:[NSString stringWithFormat:@"%@", error] @@ -201,8 +226,9 @@ - (void)appClient:(ARDAppClient *)client didError:(NSError *)error { #pragma mark - RTCEAGLVideoViewDelegate - (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size { - UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; - [UIView animateWithDuration:0.4f animations:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + // [UIView animateWithDuration:0.4f animations:^{ CGFloat containerWidth = self.view.frame.size.width; CGFloat containerHeight = self.view.frame.size.height; CGSize defaultAspectRatio = CGSizeMake(4, 3); @@ -213,12 +239,12 @@ - (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size CGRect videoRect = self.view.bounds; if (self.remoteVideoTrack) { videoRect = CGRectMake(0.0f, 0.0f, self.view.frame.size.width/4.0f, self.view.frame.size.height/4.0f); - if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) { + if ( orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) { videoRect = CGRectMake(0.0f, 0.0f, self.view.frame.size.height/4.0f, self.view.frame.size.width/4.0f); } } CGRect videoFrame = AVMakeRectWithAspectRatioInsideRect(aspectRatio, videoRect); - + //Resize the localView accordingly [self.localViewWidthConstraint setConstant:videoFrame.size.width]; [self.localViewHeightConstraint setConstant:videoFrame.size.height]; @@ -229,7 +255,7 @@ - (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size [self.localViewBottomConstraint setConstant:containerHeight/2.0f - videoFrame.size.height/2.0f]; //center [self.localViewRightConstraint setConstant:containerWidth/2.0f - videoFrame.size.width/2.0f]; //center } - } else if (videoView == self.remoteView) { + } else if ( videoView == self.remoteView ) { //Resize Remote View self.remoteVideoSize = size; CGSize aspectRatio = CGSizeEqualToSize(size, CGSizeZero) ? defaultAspectRatio : size; @@ -245,11 +271,8 @@ - (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size [self.remoteViewBottomConstraint setConstant:containerHeight/2.0f - videoFrame.size.height/2.0f]; [self.remoteViewLeftConstraint setConstant:containerWidth/2.0f - videoFrame.size.width/2.0f]; //center [self.remoteViewRightConstraint setConstant:containerWidth/2.0f - videoFrame.size.width/2.0f]; //center - } - [self.view layoutIfNeeded]; - }]; - + }); } diff --git a/Lib/ARDAppClient.h b/Lib/ARDAppClient.h index bc1f099..17e2436 100755 --- a/Lib/ARDAppClient.h +++ b/Lib/ARDAppClient.h @@ -30,25 +30,27 @@ #import "RTCVideoTrack.h" typedef NS_ENUM(NSInteger, ARDAppClientState) { - // Disconnected from servers. - kARDAppClientStateDisconnected, - // Connecting to servers. - kARDAppClientStateConnecting, - // Connected to servers. - kARDAppClientStateConnected, + // Disconnected from servers. + kARDAppClientStateDisconnected, + // Connecting to servers. + kARDAppClientStateConnecting, + // Connected to servers. + kARDAppClientStateConnected, }; @class ARDAppClient; @protocol ARDAppClientDelegate - (void)appClient:(ARDAppClient *)client - didChangeState:(ARDAppClientState)state; + didChangeState:(ARDAppClientState)state; - (void)appClient:(ARDAppClient *)client - didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack; +didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack; - (void)appClient:(ARDAppClient *)client - didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack; +didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack; + +- (void)didRemoveLocalVideoTrack:(RTCVideoTrack *)remoteVideoTrack; - (void)appClient:(ARDAppClient *)client didError:(NSError *)error; diff --git a/Lib/ARDAppClient.m b/Lib/ARDAppClient.m index 7df08a1..a9a5df5 100755 --- a/Lib/ARDAppClient.m +++ b/Lib/ARDAppClient.m @@ -47,22 +47,23 @@ #import "RTCVideoCapturer.h" #import "RTCVideoTrack.h" + // TODO(tkchin): move these to a configuration object. static NSString *kARDRoomServerHostUrl = - @"https://apprtc.appspot.com"; +@"https://apprtc.appspot.com"; static NSString *kARDRoomServerRegisterFormat = - @"%@/join/%@"; +@"%@/join/%@"; static NSString *kARDRoomServerMessageFormat = - @"%@/message/%@/%@"; +@"%@/message/%@/%@"; static NSString *kARDRoomServerByeFormat = - @"%@/leave/%@/%@"; +@"%@/leave/%@/%@"; static NSString *kARDDefaultSTUNServerUrl = - @"stun:stun.l.google.com:19302"; +@"stun:stun.l.google.com:19302"; // TODO(tkchin): figure out a better username for CEOD statistics. static NSString *kARDTurnRequestUrl = - @"https://computeengineondemand.appspot.com" - @"/turn?username=iapprtc&key=4080218913"; +@"https://computeengineondemand.appspot.com" +@"/turn?username=iapprtc&key=4080218913"; static NSString *kARDAppClientErrorDomain = @"ARDAppClient"; static NSInteger kARDAppClientErrorUnknown = -1; @@ -74,7 +75,7 @@ static NSInteger kARDAppClientErrorInvalidRoom = -7; @interface ARDAppClient () +RTCPeerConnectionDelegate, RTCSessionDescriptionDelegate> @property(nonatomic, strong) ARDWebSocketChannel *channel; @property(nonatomic, strong) RTCPeerConnection *peerConnection; @property(nonatomic, strong) RTCPeerConnectionFactory *factory; @@ -111,216 +112,314 @@ @implementation ARDAppClient @synthesize webSocketRestURL = _websocketRestURL; - (instancetype)initWithDelegate:(id)delegate { - if (self = [super init]) { - _delegate = delegate; - _factory = [[RTCPeerConnectionFactory alloc] init]; - _messageQueue = [NSMutableArray array]; - _iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]]; - _serverHostUrl = kARDRoomServerHostUrl; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(orientationChanged:) - name:@"UIDeviceOrientationDidChangeNotification" - object:nil]; - } - return self; + if (self = [super init]) { + _delegate = delegate; + _factory = [[RTCPeerConnectionFactory alloc] init]; + _messageQueue = [NSMutableArray array]; + _iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]]; + _serverHostUrl = kARDRoomServerHostUrl; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(orientationChanged:) + name:@"UIDeviceOrientationDidChangeNotification" + object:nil]; + + + //AVCaptureSessionRuntimeErrorNotification + // [[NSNotificationCenter defaultCenter] addObserver:self + // selector:@selector(handleErrorNotificationVideoCapture:) + // name:AVCaptureSessionRuntimeErrorNotification + // object:nil]; + + + // [[NSNotificationCenter defaultCenter] addObserver:self + // selector:@selector(handleCaptureSessionEnded:) + // name:AVCaptureSessionInterruptionEndedNotification + // object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleCaptureSessionStopRunning:) + name: + AVCaptureSessionDidStopRunningNotification + object:nil]; + + // [[NSNotificationCenter defaultCenter] addObserver:self + // selector:@selector(handleCaptureSessionStartRunning:) + // name: AVCaptureSessionDidStartRunningNotification + // object:nil]; + + } + return self; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceOrientationDidChangeNotification" object:nil]; - [self disconnect]; + [ [NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceOrientationDidChangeNotification" object:nil ]; + [ [NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureSessionDidStopRunningNotification object:nil ]; + [self disconnect]; } +- (void)handleErrorNotificationVideoCapture:(NSNotification *)notification { + NSDictionary *userInfo = notification.userInfo; + NSError* error = userInfo[AVCaptureSessionErrorKey]; + NSLog(@"\n handle video error method: %@", error); + if (error.code == -11819) { + [self orientationChanged:nil]; + } + +} + +//- (void)handleCaptureSessionStartRunning:(NSNotification *)notification +//{ +// +//} + +- (void)handleCaptureSessionStopRunning:(NSNotification *)notification +{ + dispatch_async(dispatch_get_main_queue(), ^{ + RTCMediaStream* localStream = [self createLocalMediaStream]; + [_peerConnection addStream:localStream]; + }); +} + +//- (void)handleCaptureSessionEnded:(NSNotification *)notification +//{ +// +//} + - (void)orientationChanged:(NSNotification *)notification { + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; if (UIDeviceOrientationIsLandscape(orientation) || UIDeviceOrientationIsPortrait(orientation)) { //Remove current video track RTCMediaStream *localStream = _peerConnection.localStreams[0]; - [localStream removeVideoTrack:localStream.videoTracks[0]]; - RTCVideoTrack *localVideoTrack = [self createLocalVideoTrack]; - if (localVideoTrack) { - [localStream addVideoTrack:localVideoTrack]; - [_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack]; - } + RTCVideoTrack* formerVideoTrack = localStream.videoTracks[0]; + [ localStream removeVideoTrack:formerVideoTrack ]; [_peerConnection removeStream:localStream]; - [_peerConnection addStream:localStream]; + [_delegate didRemoveLocalVideoTrack:formerVideoTrack]; } } - - (void)setState:(ARDAppClientState)state { - if (_state == state) { - return; - } - _state = state; - [_delegate appClient:self didChangeState:_state]; + if (_state == state) { + return; + } + _state = state; + [_delegate appClient:self didChangeState:_state]; } - (void)connectToRoomWithId:(NSString *)roomId options:(NSDictionary *)options { - NSParameterAssert(roomId.length); - NSParameterAssert(_state == kARDAppClientStateDisconnected); - self.state = kARDAppClientStateConnecting; - - // Request TURN. - __weak ARDAppClient *weakSelf = self; - NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl]; - [self requestTURNServersWithURL:turnRequestURL - completionHandler:^(NSArray *turnServers) { - ARDAppClient *strongSelf = weakSelf; - [strongSelf.iceServers addObjectsFromArray:turnServers]; - strongSelf.isTurnComplete = YES; - [strongSelf startSignalingIfReady]; - }]; - - // Register with room server. - [self registerWithRoomServerForRoomId:roomId - completionHandler:^(ARDRegisterResponse *response) { - ARDAppClient *strongSelf = weakSelf; - if (!response || response.result != kARDRegisterResultTypeSuccess) { - NSLog(@"Failed to register with room server. Result:%d", - (int)response.result); - [strongSelf disconnect]; - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: @"Room is full.", - }; - NSError *error = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorRoomFull - userInfo:userInfo]; - [strongSelf.delegate appClient:strongSelf didError:error]; - return; - } - NSLog(@"Registered with room server."); - strongSelf.roomId = response.roomId; - strongSelf.clientId = response.clientId; - strongSelf.isInitiator = response.isInitiator; - for (ARDSignalingMessage *message in response.messages) { - if (message.type == kARDSignalingMessageTypeOffer || - message.type == kARDSignalingMessageTypeAnswer) { - strongSelf.hasReceivedSdp = YES; - [strongSelf.messageQueue insertObject:message atIndex:0]; - } else { - [strongSelf.messageQueue addObject:message]; - } - } - strongSelf.webSocketURL = response.webSocketURL; - strongSelf.webSocketRestURL = response.webSocketRestURL; - [strongSelf registerWithColliderIfReady]; - [strongSelf startSignalingIfReady]; - }]; + NSParameterAssert(roomId.length); + NSParameterAssert(_state == kARDAppClientStateDisconnected); + self.state = kARDAppClientStateConnecting; + + // Request TURN. + __weak ARDAppClient *weakSelf = self; + NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl]; + [self requestTURNServersWithURL:turnRequestURL + completionHandler:^(NSArray *turnServers) { + ARDAppClient *strongSelf = weakSelf; + [strongSelf.iceServers addObjectsFromArray:turnServers]; + strongSelf.isTurnComplete = YES; + [strongSelf startSignalingIfReady]; + }]; + + // Register with room server. + [self registerWithRoomServerForRoomId:roomId + completionHandler:^(ARDRegisterResponse *response) { + ARDAppClient *strongSelf = weakSelf; + if (!response || response.result != kARDRegisterResultTypeSuccess) { + NSLog(@"Failed to register with room server. Result:%d", + (int)response.result); + [strongSelf disconnect]; + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: @"Room is full.", + }; + NSError *error = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorRoomFull + userInfo:userInfo]; + [strongSelf.delegate appClient:strongSelf didError:error]; + return; + } + NSLog(@"Registered with room server."); + strongSelf.roomId = response.roomId; + strongSelf.clientId = response.clientId; + strongSelf.isInitiator = response.isInitiator; + for (ARDSignalingMessage *message in response.messages) { + if (message.type == kARDSignalingMessageTypeOffer || + message.type == kARDSignalingMessageTypeAnswer) { + strongSelf.hasReceivedSdp = YES; + [strongSelf.messageQueue insertObject:message atIndex:0]; + } else { + [strongSelf.messageQueue addObject:message]; + } + } + strongSelf.webSocketURL = response.webSocketURL; + strongSelf.webSocketRestURL = response.webSocketRestURL; + [strongSelf registerWithColliderIfReady]; + [strongSelf startSignalingIfReady]; + }]; } - (void)disconnect { - if (_state == kARDAppClientStateDisconnected) { - return; - } - if (self.isRegisteredWithRoomServer) { - [self unregisterWithRoomServer]; - } - if (_channel) { - if (_channel.state == kARDWebSocketChannelStateRegistered) { - // Tell the other client we're hanging up. - ARDByeMessage *byeMessage = [[ARDByeMessage alloc] init]; - NSData *byeData = [byeMessage JSONData]; - [_channel sendData:byeData]; + if (_state == kARDAppClientStateDisconnected) { + return; } - // Disconnect from collider. - _channel = nil; - } - _clientId = nil; - _roomId = nil; - _isInitiator = NO; - _hasReceivedSdp = NO; - _messageQueue = [NSMutableArray array]; - _peerConnection = nil; - self.state = kARDAppClientStateDisconnected; + if ( self.isRegisteredWithRoomServer ) { + [self unregisterWithRoomServer]; + } + if (_channel) { + if (_channel.state == kARDWebSocketChannelStateRegistered) { + // Tell the other client we're hanging up. + ARDByeMessage *byeMessage = [[ARDByeMessage alloc] init]; + NSData *byeData = [byeMessage JSONData]; + [_channel sendData:byeData]; + } + // Disconnect from collider. + _channel = nil; + } + _clientId = nil; + _roomId = nil; + _isInitiator = NO; + _hasReceivedSdp = NO; + _messageQueue = [NSMutableArray array]; + _peerConnection = nil; + self.state = kARDAppClientStateDisconnected; } #pragma mark - ARDWebSocketChannelDelegate - (void)channel:(ARDWebSocketChannel *)channel - didReceiveMessage:(ARDSignalingMessage *)message { - switch (message.type) { - case kARDSignalingMessageTypeOffer: - case kARDSignalingMessageTypeAnswer: - _hasReceivedSdp = YES; - [_messageQueue insertObject:message atIndex:0]; - break; - case kARDSignalingMessageTypeCandidate: - [_messageQueue addObject:message]; - break; - case kARDSignalingMessageTypeBye: - [self processSignalingMessage:message]; - return; - } - [self drainMessageQueueIfReady]; +didReceiveMessage:(ARDSignalingMessage *)message { + switch (message.type) { + case kARDSignalingMessageTypeOffer: + case kARDSignalingMessageTypeAnswer: + _hasReceivedSdp = YES; + [_messageQueue insertObject:message atIndex:0]; + break; + case kARDSignalingMessageTypeCandidate: + [_messageQueue addObject:message]; + break; + case kARDSignalingMessageTypeBye: + [self processSignalingMessage:message]; + return; + } + [self drainMessageQueueIfReady]; } - (void)channel:(ARDWebSocketChannel *)channel - didChangeState:(ARDWebSocketChannelState)state { - switch (state) { - case kARDWebSocketChannelStateOpen: - break; - case kARDWebSocketChannelStateRegistered: - break; - case kARDWebSocketChannelStateClosed: - case kARDWebSocketChannelStateError: - // TODO(tkchin): reconnection scenarios. Right now we just disconnect - // completely if the websocket connection fails. - [self disconnect]; - break; - } + didChangeState:(ARDWebSocketChannelState)state { + switch (state) { + case kARDWebSocketChannelStateOpen: + break; + case kARDWebSocketChannelStateRegistered: + break; + case kARDWebSocketChannelStateClosed: + case kARDWebSocketChannelStateError: + // TODO(tkchin): reconnection scenarios. Right now we just disconnect + // completely if the websocket connection fails. + [self disconnect]; + break; + } } #pragma mark - RTCPeerConnectionDelegate - (void)peerConnection:(RTCPeerConnection *)peerConnection - signalingStateChanged:(RTCSignalingState)stateChanged { - NSLog(@"Signaling state changed: %d", stateChanged); + signalingStateChanged:(RTCSignalingState)stateChanged { + + switch (stateChanged) { + case RTCSignalingStable: + NSLog(@"Signaling state changed: RTCSignalingStable"); + break; + case RTCSignalingHaveLocalOffer: + NSLog(@"Signaling state changed: RTCSignalingHaveLocalOffer"); + break; + case RTCSignalingHaveRemoteOffer: + NSLog(@"Signaling state changed: RTCSignalingHaveRemoteOffer"); + break; + case RTCSignalingHaveLocalPrAnswer: + NSLog(@"Signaling state changed: RTCSignalingHaveLocalPrAnswer"); + break; + case RTCSignalingHaveRemotePrAnswer: + NSLog(@"Signaling state changed: RTCSignalingHaveRemotePrAnswer"); + break; + default: + NSLog(@"Signaling state changed: %d", stateChanged); + break; + } } -- (void)peerConnection:(RTCPeerConnection *)peerConnection - addedStream:(RTCMediaStream *)stream { - dispatch_async(dispatch_get_main_queue(), ^{ - NSLog(@"Received %lu video tracks and %lu audio tracks", - (unsigned long)stream.videoTracks.count, - (unsigned long)stream.audioTracks.count); - if (stream.videoTracks.count) { - RTCVideoTrack *videoTrack = stream.videoTracks[0]; - [_delegate appClient:self didReceiveRemoteVideoTrack:videoTrack]; - } - }); +- (void)peerConnection:(RTCPeerConnection *)peerConnection addedStream:(RTCMediaStream *)stream { + dispatch_async(dispatch_get_main_queue(), ^{ + NSLog(@"Received %lu video tracks and %lu audio tracks", + (unsigned long)stream.videoTracks.count, + (unsigned long)stream.audioTracks.count); + if (stream.videoTracks.count) { + RTCVideoTrack *videoTrack = stream.videoTracks[0]; + [_delegate appClient:self didReceiveRemoteVideoTrack:videoTrack]; + } + }); } - (void)peerConnection:(RTCPeerConnection *)peerConnection - removedStream:(RTCMediaStream *)stream { - NSLog(@"Stream was removed."); + removedStream:(RTCMediaStream *)stream { + NSLog(@"Stream was removed."); } -- (void)peerConnectionOnRenegotiationNeeded: - (RTCPeerConnection *)peerConnection { - NSLog(@"WARNING: Renegotiation needed but unimplemented."); +- (void)peerConnectionOnRenegotiationNeeded:(RTCPeerConnection *)peerConnection { + NSLog(@"WARNING: Renegotiation needed but unimplemented."); + } - (void)peerConnection:(RTCPeerConnection *)peerConnection - iceConnectionChanged:(RTCICEConnectionState)newState { - NSLog(@"ICE state changed: %d", newState); + iceConnectionChanged:(RTCICEConnectionState)newState { + switch (newState) { + case RTCICEConnectionNew: + NSLog(@"ICE state changed: RTCICEConnectionNew"); + break; + case RTCICEConnectionChecking: + NSLog(@"ICE state changed: RTCICEConnectionChecking"); + break; + case RTCICEConnectionConnected: + NSLog(@"ICE state changed: RTCICEConnectionConnected"); + break; + case RTCICEConnectionCompleted: + NSLog(@"ICE state changed: RTCICEConnectionCompleted"); + break; + case RTCICEConnectionFailed: + NSLog(@"ICE state changed: RTCICEConnectionFailed"); + break; + + default: + NSLog(@"ICE state changed: %d", newState); + break; + } } - (void)peerConnection:(RTCPeerConnection *)peerConnection - iceGatheringChanged:(RTCICEGatheringState)newState { - NSLog(@"ICE gathering state changed: %d", newState); + iceGatheringChanged:(RTCICEGatheringState)newState { + switch (newState) { + case RTCICEGatheringGathering: + NSLog(@"ICE gathering state changed: RTCICEGatheringGathering"); + break; + case RTCICEGatheringComplete: + NSLog(@"ICE gathering state changed: RTCICEGatheringComplete"); + break; + default: + NSLog(@"ICE gathering state changed: %d", newState); + break; + } } - (void)peerConnection:(RTCPeerConnection *)peerConnection gotICECandidate:(RTCICECandidate *)candidate { - dispatch_async(dispatch_get_main_queue(), ^{ - ARDICECandidateMessage *message = - [[ARDICECandidateMessage alloc] initWithCandidate:candidate]; - [self sendSignalingMessage:message]; - }); + dispatch_async(dispatch_get_main_queue(), ^{ + ARDICECandidateMessage *message = [[ARDICECandidateMessage alloc] initWithCandidate:candidate]; + [self sendSignalingMessage:message]; + }); } - (void)peerConnection:(RTCPeerConnection*)peerConnection @@ -330,149 +429,148 @@ - (void)peerConnection:(RTCPeerConnection*)peerConnection #pragma mark - RTCSessionDescriptionDelegate - (void)peerConnection:(RTCPeerConnection *)peerConnection - didCreateSessionDescription:(RTCSessionDescription *)sdp - error:(NSError *)error { - dispatch_async(dispatch_get_main_queue(), ^{ - if (error) { - NSLog(@"Failed to create session description. Error: %@", error); - [self disconnect]; - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: @"Failed to create session description.", - }; - NSError *sdpError = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorCreateSDP - userInfo:userInfo]; - [_delegate appClient:self didError:sdpError]; - return; - } - [_peerConnection setLocalDescriptionWithDelegate:self - sessionDescription:sdp]; - ARDSessionDescriptionMessage *message = +didCreateSessionDescription:(RTCSessionDescription *)sdp + error:(NSError *)error { + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + NSLog(@"Failed to create session description. Error: %@", error); + [self disconnect]; + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: @"Failed to create session description.", + }; + NSError *sdpError = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorCreateSDP + userInfo:userInfo]; + [_delegate appClient:self didError:sdpError]; + return; + } + [_peerConnection setLocalDescriptionWithDelegate:self + sessionDescription:sdp]; + ARDSessionDescriptionMessage *message = [[ARDSessionDescriptionMessage alloc] initWithDescription:sdp]; - [self sendSignalingMessage:message]; - }); + [self sendSignalingMessage:message]; + }); } - (void)peerConnection:(RTCPeerConnection *)peerConnection - didSetSessionDescriptionWithError:(NSError *)error { - dispatch_async(dispatch_get_main_queue(), ^{ - if (error) { - NSLog(@"Failed to set session description. Error: %@", error); - [self disconnect]; - NSDictionary *userInfo = @{ - NSLocalizedDescriptionKey: @"Failed to set session description.", - }; - NSError *sdpError = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorSetSDP - userInfo:userInfo]; - [_delegate appClient:self didError:sdpError]; - return; - } - // If we're answering and we've just set the remote offer we need to create - // an answer and set the local description. - if (!_isInitiator && !_peerConnection.localDescription) { - RTCMediaConstraints *constraints = [self defaultAnswerConstraints]; - [_peerConnection createAnswerWithDelegate:self - constraints:constraints]; - - } - }); +didSetSessionDescriptionWithError:(NSError *)error { + dispatch_async(dispatch_get_main_queue(), ^{ + if (error) { + NSLog(@"Failed to set session description. Error: %@", error); + [self disconnect]; + NSDictionary *userInfo = @{ + NSLocalizedDescriptionKey: @"Failed to set session description.", + }; + NSError *sdpError = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorSetSDP + userInfo:userInfo]; + [_delegate appClient:self didError:sdpError]; + return; + } + // If we're answering and we've just set the remote offer we need to create + // an answer and set the local description. + if (!_isInitiator && !_peerConnection.localDescription) { + RTCMediaConstraints *constraints = [self defaultAnswerConstraints]; + [_peerConnection createAnswerWithDelegate:self + constraints:constraints]; + + } + }); } #pragma mark - Private - (BOOL)isRegisteredWithRoomServer { - return _clientId.length; + return _clientId.length; } - (void)startSignalingIfReady { - if (!_isTurnComplete || !self.isRegisteredWithRoomServer) { - return; - } - self.state = kARDAppClientStateConnected; - - // Create peer connection. - RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints]; - _peerConnection = [_factory peerConnectionWithICEServers:_iceServers - constraints:constraints - delegate:self]; - RTCMediaStream *localStream = [self createLocalMediaStream]; - [_peerConnection addStream:localStream]; - if (_isInitiator) { - [self sendOffer]; - } else { - [self waitForAnswer]; - } + if (!_isTurnComplete || !self.isRegisteredWithRoomServer) { + return; + } + self.state = kARDAppClientStateConnected; + + // Create peer connection. + RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints]; + _peerConnection = [_factory peerConnectionWithICEServers:_iceServers + constraints:constraints + delegate:self]; + RTCMediaStream *localStream = [self createLocalMediaStream]; + [_peerConnection addStream:localStream]; + if (_isInitiator) { + [self sendOffer]; + } else { + [self waitForAnswer]; + } } - (void)sendOffer { - [_peerConnection createOfferWithDelegate:self - constraints:[self defaultOfferConstraints]]; + [_peerConnection createOfferWithDelegate:self + constraints:[self defaultOfferConstraints]]; } - (void)waitForAnswer { - [self drainMessageQueueIfReady]; + [self drainMessageQueueIfReady]; } - (void)drainMessageQueueIfReady { - if (!_peerConnection || !_hasReceivedSdp) { - return; - } - for (ARDSignalingMessage *message in _messageQueue) { - [self processSignalingMessage:message]; - } - [_messageQueue removeAllObjects]; + if (!_peerConnection || !_hasReceivedSdp) { + return; + } + for (ARDSignalingMessage *message in _messageQueue) { + [self processSignalingMessage:message]; + } + [_messageQueue removeAllObjects]; } - (void)processSignalingMessage:(ARDSignalingMessage *)message { - NSParameterAssert(_peerConnection || - message.type == kARDSignalingMessageTypeBye); - switch (message.type) { - case kARDSignalingMessageTypeOffer: - case kARDSignalingMessageTypeAnswer: { - ARDSessionDescriptionMessage *sdpMessage = - (ARDSessionDescriptionMessage *)message; - RTCSessionDescription *description = sdpMessage.sessionDescription; - [_peerConnection setRemoteDescriptionWithDelegate:self - sessionDescription:description]; - break; - } - case kARDSignalingMessageTypeCandidate: { - ARDICECandidateMessage *candidateMessage = - (ARDICECandidateMessage *)message; - [_peerConnection addICECandidate:candidateMessage.candidate]; - break; + NSParameterAssert(_peerConnection || + message.type == kARDSignalingMessageTypeBye); + switch (message.type) { + case kARDSignalingMessageTypeOffer: + case kARDSignalingMessageTypeAnswer: { + ARDSessionDescriptionMessage *sdpMessage = + (ARDSessionDescriptionMessage *)message; + RTCSessionDescription *description = sdpMessage.sessionDescription; + [_peerConnection setRemoteDescriptionWithDelegate:self + sessionDescription:description]; + break; + } + case kARDSignalingMessageTypeCandidate: { + ARDICECandidateMessage *candidateMessage = + (ARDICECandidateMessage *)message; + [_peerConnection addICECandidate:candidateMessage.candidate]; + break; + } + case kARDSignalingMessageTypeBye: + // Other client disconnected. + // TODO(tkchin): support waiting in room for next client. For now just + // disconnect. + [self disconnect]; + break; } - case kARDSignalingMessageTypeBye: - // Other client disconnected. - // TODO(tkchin): support waiting in room for next client. For now just - // disconnect. - [self disconnect]; - break; - } } - (void)sendSignalingMessage:(ARDSignalingMessage *)message { - if (_isInitiator) { - [self sendSignalingMessageToRoomServer:message completionHandler:nil]; - } else { - [self sendSignalingMessageToCollider:message]; - } + if (_isInitiator) { + [self sendSignalingMessageToRoomServer:message completionHandler:nil]; + } else { + [self sendSignalingMessageToCollider:message]; + } } - - (RTCVideoTrack *)createLocalVideoTrack { // The iOS simulator doesn't provide any sort of camera capture // support or emulation (http://goo.gl/rHAnC1) so don't bother // trying to open a local stream. // TODO(tkchin): local video capture for OSX. See // https://code.google.com/p/webrtc/issues/detail?id=3417. - + RTCVideoTrack *localVideoTrack = nil; #if !TARGET_IPHONE_SIMULATOR && TARGET_OS_IPHONE - + NSString *cameraID = nil; for (AVCaptureDevice *captureDevice in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { @@ -493,129 +591,129 @@ - (RTCVideoTrack *)createLocalVideoTrack { - (RTCMediaStream *)createLocalMediaStream { RTCMediaStream* localStream = [_factory mediaStreamWithLabel:@"ARDAMS"]; - + RTCVideoTrack *localVideoTrack = [self createLocalVideoTrack]; if (localVideoTrack) { [localStream addVideoTrack:localVideoTrack]; [_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack]; } - + [localStream addAudioTrack:[_factory audioTrackWithID:@"ARDAMSa0"]]; return localStream; } - (void)requestTURNServersWithURL:(NSURL *)requestURL - completionHandler:(void (^)(NSArray *turnServers))completionHandler { - NSParameterAssert([requestURL absoluteString].length); - NSMutableURLRequest *request = - [NSMutableURLRequest requestWithURL:requestURL]; - // We need to set origin because TURN provider whitelists requests based on - // origin. - [request addValue:@"Mozilla/5.0" forHTTPHeaderField:@"user-agent"]; - [request addValue:self.serverHostUrl forHTTPHeaderField:@"origin"]; - [NSURLConnection sendAsyncRequest:request - completionHandler:^(NSURLResponse *response, - NSData *data, - NSError *error) { - NSArray *turnServers = [NSArray array]; - if (error) { - NSLog(@"Unable to get TURN server."); - completionHandler(turnServers); - return; - } - NSDictionary *dict = [NSDictionary dictionaryWithJSONData:data]; - turnServers = [RTCICEServer serversFromCEODJSONDictionary:dict]; - completionHandler(turnServers); - }]; + completionHandler:(void (^)(NSArray *turnServers))completionHandler { + NSParameterAssert([requestURL absoluteString].length); + NSMutableURLRequest *request = + [NSMutableURLRequest requestWithURL:requestURL]; + // We need to set origin because TURN provider whitelists requests based on + // origin. + [request addValue:@"Mozilla/5.0" forHTTPHeaderField:@"user-agent"]; + [request addValue:self.serverHostUrl forHTTPHeaderField:@"origin"]; + [NSURLConnection sendAsyncRequest:request + completionHandler:^(NSURLResponse *response, + NSData *data, + NSError *error) { + NSArray *turnServers = [NSArray array]; + if (error) { + NSLog(@"Unable to get TURN server."); + completionHandler(turnServers); + return; + } + NSDictionary *dict = [NSDictionary dictionaryWithJSONData:data]; + turnServers = [RTCICEServer serversFromCEODJSONDictionary:dict]; + completionHandler(turnServers); + }]; } #pragma mark - Room server methods - (void)registerWithRoomServerForRoomId:(NSString *)roomId - completionHandler:(void (^)(ARDRegisterResponse *))completionHandler { - NSString *urlString = - [NSString stringWithFormat:kARDRoomServerRegisterFormat, self.serverHostUrl, roomId]; - NSURL *roomURL = [NSURL URLWithString:urlString]; - NSLog(@"Registering with room server."); - __weak ARDAppClient *weakSelf = self; - [NSURLConnection sendAsyncPostToURL:roomURL - withData:nil - completionHandler:^(BOOL succeeded, NSData *data) { - ARDAppClient *strongSelf = weakSelf; - if (!succeeded) { - NSError *error = [self roomServerNetworkError]; - [strongSelf.delegate appClient:strongSelf didError:error]; - completionHandler(nil); - return; - } - ARDRegisterResponse *response = - [ARDRegisterResponse responseFromJSONData:data]; - completionHandler(response); - }]; + completionHandler:(void (^)(ARDRegisterResponse *))completionHandler { + NSString *urlString = + [NSString stringWithFormat:kARDRoomServerRegisterFormat, self.serverHostUrl, roomId]; + NSURL *roomURL = [NSURL URLWithString:urlString]; + NSLog(@"Registering with room server."); + __weak ARDAppClient *weakSelf = self; + [NSURLConnection sendAsyncPostToURL:roomURL + withData:nil + completionHandler:^(BOOL succeeded, NSData *data) { + ARDAppClient *strongSelf = weakSelf; + if (!succeeded) { + NSError *error = [self roomServerNetworkError]; + [strongSelf.delegate appClient:strongSelf didError:error]; + completionHandler(nil); + return; + } + ARDRegisterResponse *response = + [ARDRegisterResponse responseFromJSONData:data]; + completionHandler(response); + }]; } - (void)sendSignalingMessageToRoomServer:(ARDSignalingMessage *)message - completionHandler:(void (^)(ARDMessageResponse *))completionHandler { - NSData *data = [message JSONData]; - NSString *urlString = - [NSString stringWithFormat: - kARDRoomServerMessageFormat, self.serverHostUrl, _roomId, _clientId]; - NSURL *url = [NSURL URLWithString:urlString]; - NSLog(@"C->RS POST: %@", message); - __weak ARDAppClient *weakSelf = self; - [NSURLConnection sendAsyncPostToURL:url - withData:data - completionHandler:^(BOOL succeeded, NSData *data) { - ARDAppClient *strongSelf = weakSelf; - if (!succeeded) { - NSError *error = [self roomServerNetworkError]; - [strongSelf.delegate appClient:strongSelf didError:error]; - return; - } - ARDMessageResponse *response = - [ARDMessageResponse responseFromJSONData:data]; - NSError *error = nil; - switch (response.result) { - case kARDMessageResultTypeSuccess: - break; - case kARDMessageResultTypeUnknown: - error = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorUnknown - userInfo:@{ - NSLocalizedDescriptionKey: @"Unknown error.", - }]; - case kARDMessageResultTypeInvalidClient: - error = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorInvalidClient - userInfo:@{ - NSLocalizedDescriptionKey: @"Invalid client.", - }]; - break; - case kARDMessageResultTypeInvalidRoom: - error = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorInvalidRoom - userInfo:@{ - NSLocalizedDescriptionKey: @"Invalid room.", - }]; - break; - }; - if (error) { - [strongSelf.delegate appClient:strongSelf didError:error]; - } - if (completionHandler) { - completionHandler(response); - } - }]; + completionHandler:(void (^)(ARDMessageResponse *))completionHandler { + NSData *data = [message JSONData]; + NSString *urlString = + [NSString stringWithFormat: + kARDRoomServerMessageFormat, self.serverHostUrl, _roomId, _clientId]; + NSURL *url = [NSURL URLWithString:urlString]; + NSLog(@"C->RS POST: %@", message); + __weak ARDAppClient *weakSelf = self; + [NSURLConnection sendAsyncPostToURL:url + withData:data + completionHandler:^(BOOL succeeded, NSData *data) { + ARDAppClient *strongSelf = weakSelf; + if (!succeeded) { + NSError *error = [self roomServerNetworkError]; + [strongSelf.delegate appClient:strongSelf didError:error]; + return; + } + ARDMessageResponse *response = + [ARDMessageResponse responseFromJSONData:data]; + NSError *error = nil; + switch (response.result) { + case kARDMessageResultTypeSuccess: + break; + case kARDMessageResultTypeUnknown: + error = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorUnknown + userInfo:@{ + NSLocalizedDescriptionKey: @"Unknown error.", + }]; + case kARDMessageResultTypeInvalidClient: + error = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorInvalidClient + userInfo:@{ + NSLocalizedDescriptionKey: @"Invalid client.", + }]; + break; + case kARDMessageResultTypeInvalidRoom: + error = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorInvalidRoom + userInfo:@{ + NSLocalizedDescriptionKey: @"Invalid room.", + }]; + break; + }; + if (error) { + [strongSelf.delegate appClient:strongSelf didError:error]; + } + if (completionHandler) { + completionHandler(response); + } + }]; } - (void)unregisterWithRoomServer { - NSString *urlString = - [NSString stringWithFormat:kARDRoomServerByeFormat, self.serverHostUrl, _roomId, _clientId]; - NSURL *url = [NSURL URLWithString:urlString]; - NSLog(@"C->RS: BYE"); + NSString *urlString = + [NSString stringWithFormat:kARDRoomServerByeFormat, self.serverHostUrl, _roomId, _clientId]; + NSURL *url = [NSURL URLWithString:urlString]; + NSLog(@"C->RS: BYE"); //Make sure to do a POST [NSURLConnection sendAsyncPostToURL:url withData:nil completionHandler:^(BOOL succeeded, NSData *data) { if (succeeded) { @@ -627,76 +725,94 @@ - (void)unregisterWithRoomServer { } - (NSError *)roomServerNetworkError { - NSError *error = - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain - code:kARDAppClientErrorNetwork - userInfo:@{ - NSLocalizedDescriptionKey: @"Room server network error", - }]; - return error; + NSError *error = + [[NSError alloc] initWithDomain:kARDAppClientErrorDomain + code:kARDAppClientErrorNetwork + userInfo:@{ + NSLocalizedDescriptionKey: @"Room server network error", + }]; + return error; } #pragma mark - Collider methods - (void)registerWithColliderIfReady { - if (!self.isRegisteredWithRoomServer) { - return; - } - // Open WebSocket connection. - _channel = - [[ARDWebSocketChannel alloc] initWithURL:_websocketURL - restURL:_websocketRestURL - delegate:self]; - [_channel registerForRoomId:_roomId clientId:_clientId]; + if (!self.isRegisteredWithRoomServer) { + return; + } + // Open WebSocket connection. + _channel = + [[ARDWebSocketChannel alloc] initWithURL:_websocketURL + restURL:_websocketRestURL + delegate:self]; + [_channel registerForRoomId:_roomId clientId:_clientId]; } - (void)sendSignalingMessageToCollider:(ARDSignalingMessage *)message { - NSData *data = [message JSONData]; - [_channel sendData:data]; + NSData *data = [message JSONData]; + [_channel sendData:data]; } #pragma mark - Defaults - (RTCMediaConstraints *)defaultMediaStreamConstraints { - RTCMediaConstraints* constraints = - [[RTCMediaConstraints alloc] - initWithMandatoryConstraints:nil - optionalConstraints:nil]; - return constraints; + // + RTCPair *localVideoMaxWidth = [[RTCPair alloc] initWithKey:@"maxWidth" value:@"320"]; + + RTCPair *localVideoMinWidth = [[RTCPair alloc] initWithKey:@"minWidth" value:@"320"]; + + RTCPair *localVideoMaxHeight = [[RTCPair alloc] initWithKey:@"maxHeight" value:@"240"]; + + RTCPair *localVideoMinHeight = [[RTCPair alloc] initWithKey:@"minHeight" value:@"240"]; + + // RTCPair *localVideoMaxFrameRate = [[RTCPair alloc] initWithKey:@"maxFrameRate" value:@"30"]; + // + // RTCPair *localVideoMinFrameRate = [[RTCPair alloc] initWithKey:@"minFrameRate" value:@"5"]; + // + // RTCPair *localVideoGoogLeakyBucket = [[RTCPair alloc] initWithKey:@"googLeakyBucket" value:@"true"]; + + RTCMediaConstraints *videoSourceConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@[localVideoMaxHeight, localVideoMaxWidth, localVideoMinHeight, localVideoMinWidth, /*localVideoMinFrameRate, localVideoMaxFrameRate, localVideoGoogLeakyBucket*/] optionalConstraints:nil]; + + // + // RTCMediaConstraints* constraints = + // [[RTCMediaConstraints alloc] + // initWithMandatoryConstraints:nil + // optionalConstraints:nil]; + return videoSourceConstraints; } - (RTCMediaConstraints *)defaultAnswerConstraints { - return [self defaultOfferConstraints]; + return [self defaultOfferConstraints]; } - (RTCMediaConstraints *)defaultOfferConstraints { - NSArray *mandatoryConstraints = @[ - [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"], - [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"] - ]; - RTCMediaConstraints* constraints = - [[RTCMediaConstraints alloc] - initWithMandatoryConstraints:mandatoryConstraints - optionalConstraints:nil]; - return constraints; + NSArray *mandatoryConstraints = @[ + [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"], + [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"] + ]; + RTCMediaConstraints* constraints = + [[RTCMediaConstraints alloc] + initWithMandatoryConstraints:mandatoryConstraints + optionalConstraints:nil]; + return constraints; } - (RTCMediaConstraints *)defaultPeerConnectionConstraints { - NSArray *optionalConstraints = @[ - [[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"] - ]; - RTCMediaConstraints* constraints = - [[RTCMediaConstraints alloc] - initWithMandatoryConstraints:nil - optionalConstraints:optionalConstraints]; - return constraints; + NSArray *optionalConstraints = @[ + [[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"] + ]; + RTCMediaConstraints* constraints = + [[RTCMediaConstraints alloc] + initWithMandatoryConstraints:nil + optionalConstraints:optionalConstraints]; + return constraints; } - (RTCICEServer *)defaultSTUNServer { - NSURL *defaultSTUNServerURL = [NSURL URLWithString:kARDDefaultSTUNServerUrl]; - return [[RTCICEServer alloc] initWithURI:defaultSTUNServerURL - username:@"" - password:@""]; + NSURL *defaultSTUNServerURL = [NSURL URLWithString:kARDDefaultSTUNServerUrl]; + return [[RTCICEServer alloc] initWithURI:defaultSTUNServerURL + username:@"" + password:@""]; } @end From 61c53fd295dcf0e281cbf72fae60e4d6982b2e94 Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Fri, 16 Oct 2015 17:44:21 +0300 Subject: [PATCH 2/9] Handling any modes to removed and restore media streams TODO: Look into freezing with updated library --- AppRTC/ARTCVideoChatViewController.m | 3 - Lib/ARDAppClient.m | 229 ++++++++++----------------- 2 files changed, 88 insertions(+), 144 deletions(-) diff --git a/AppRTC/ARTCVideoChatViewController.m b/AppRTC/ARTCVideoChatViewController.m index c44bac7..3f9801e 100644 --- a/AppRTC/ARTCVideoChatViewController.m +++ b/AppRTC/ARTCVideoChatViewController.m @@ -188,10 +188,7 @@ - (void)appClient:(ARDAppClient *)client didReceiveLocalVideoTrack:(RTCVideoTrac - (void)appClient:(ARDAppClient *)client didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { self.remoteVideoTrack = remoteVideoTrack; - // [self.remoteView setFrame:CGRectMake(0, 0, 100, 100)]; - // RTCI420Frame* fram = [RTCI420Frame new]; - // [self.remoteView renderFrame:fram]; [self.remoteVideoTrack addRenderer:self.remoteView]; [UIView animateWithDuration:0.4f animations:^{ diff --git a/Lib/ARDAppClient.m b/Lib/ARDAppClient.m index a9a5df5..287f2c5 100755 --- a/Lib/ARDAppClient.m +++ b/Lib/ARDAppClient.m @@ -47,7 +47,6 @@ #import "RTCVideoCapturer.h" #import "RTCVideoTrack.h" - // TODO(tkchin): move these to a configuration object. static NSString *kARDRoomServerHostUrl = @"https://apprtc.appspot.com"; @@ -76,6 +75,10 @@ @interface ARDAppClient () +{ + UIDeviceOrientation currentOrientation; + BOOL isForeGround; +} @property(nonatomic, strong) ARDWebSocketChannel *channel; @property(nonatomic, strong) RTCPeerConnection *peerConnection; @property(nonatomic, strong) RTCPeerConnectionFactory *factory; @@ -118,88 +121,97 @@ - (instancetype)initWithDelegate:(id)delegate { _messageQueue = [NSMutableArray array]; _iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]]; _serverHostUrl = kARDRoomServerHostUrl; + currentOrientation = [[UIDevice currentDevice] orientation]; + isForeGround = YES; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(orientationChanged:) - name:@"UIDeviceOrientationDidChangeNotification" - object:nil]; - - - //AVCaptureSessionRuntimeErrorNotification - // [[NSNotificationCenter defaultCenter] addObserver:self - // selector:@selector(handleErrorNotificationVideoCapture:) - // name:AVCaptureSessionRuntimeErrorNotification - // object:nil]; - - - // [[NSNotificationCenter defaultCenter] addObserver:self - // selector:@selector(handleCaptureSessionEnded:) - // name:AVCaptureSessionInterruptionEndedNotification - // object:nil]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(handleCaptureSessionStopRunning:) - name: - AVCaptureSessionDidStopRunningNotification - object:nil]; - - // [[NSNotificationCenter defaultCenter] addObserver:self - // selector:@selector(handleCaptureSessionStartRunning:) - // name: AVCaptureSessionDidStartRunningNotification - // object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCaptureSessionStopRunning:) name:AVCaptureSessionDidStopRunningNotification object:nil]; + // Init observers to handle going into fore- and back- ground + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackgroundVideo) name:UIApplicationWillResignActiveNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterForegroundVideo) name:UIApplicationDidBecomeActiveNotification object:nil]; } return self; } - (void)dealloc { - [ [NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceOrientationDidChangeNotification" object:nil ]; +#ifdef DEBUG + NSLog(@"\n\n ===== ARDAppClient dealloc ======== \n\n "); +#endif + [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; [ [NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureSessionDidStopRunningNotification object:nil ]; + + [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; + [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil ]; + [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil ]; + [self disconnect]; } -- (void)handleErrorNotificationVideoCapture:(NSNotification *)notification { - NSDictionary *userInfo = notification.userInfo; - NSError* error = userInfo[AVCaptureSessionErrorKey]; - NSLog(@"\n handle video error method: %@", error); - if (error.code == -11819) { - [self orientationChanged:nil]; +#pragma mark - + +- (void)handleCaptureSessionStopRunning:(NSNotification *)notification +{ +// dispatch_async(dispatch_get_main_queue(), ^{ + if (isForeGround) { + [self restoreAllMediaStreams]; } +// }); +} + +- (void)orientationChanged:(NSNotification *)notification { + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationPortrait) { + if (currentOrientation == orientation) { + return; + } + currentOrientation = orientation; + [self cleanUpAllMediaStreams]; + } } -//- (void)handleCaptureSessionStartRunning:(NSNotification *)notification -//{ -// -//} +- (void)didEnterForegroundVideo { + isForeGround = YES; + [self restoreAllMediaStreams]; +} -- (void)handleCaptureSessionStopRunning:(NSNotification *)notification -{ - dispatch_async(dispatch_get_main_queue(), ^{ - RTCMediaStream* localStream = [self createLocalMediaStream]; - [_peerConnection addStream:localStream]; - }); +- (void)didEnterBackgroundVideo { + isForeGround = NO; + [self cleanUpAllMediaStreams]; } -//- (void)handleCaptureSessionEnded:(NSNotification *)notification -//{ -// -//} -- (void)orientationChanged:(NSNotification *)notification { +- (void)restoreAllMediaStreams { + if (self.peerConnection && _peerConnection.localStreams.count == 0){ + RTCMediaStream* localStream = [self createLocalMediaStream]; + [self.peerConnection addStream:localStream]; + } +} + +-(void)cleanUpAllMediaStreams +{ + //Remove current video track + if (_peerConnection.localStreams.count == 0) { + return; + } + RTCMediaStream *localStream = _peerConnection.localStreams[0]; + if (localStream.videoTracks.count == 0) { + return; + } + RTCVideoTrack* formerVideoTrack = localStream.videoTracks[0]; + [ localStream removeVideoTrack:formerVideoTrack ]; + [_delegate didRemoveLocalVideoTrack:formerVideoTrack]; - UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; - if (UIDeviceOrientationIsLandscape(orientation) || UIDeviceOrientationIsPortrait(orientation)) { - //Remove current video track - RTCMediaStream *localStream = _peerConnection.localStreams[0]; - - RTCVideoTrack* formerVideoTrack = localStream.videoTracks[0]; - [ localStream removeVideoTrack:formerVideoTrack ]; - [_peerConnection removeStream:localStream]; - [_delegate didRemoveLocalVideoTrack:formerVideoTrack]; + if (localStream.audioTracks.count > 0) { + RTCAudioTrack* formerAudioTrack = localStream.audioTracks[0]; + [localStream removeAudioTrack:formerAudioTrack]; } + + [_peerConnection removeStream:localStream]; } + - (void)setState:(ARDAppClientState)state { if (_state == state) { return; @@ -267,7 +279,7 @@ - (void)disconnect { if (_state == kARDAppClientStateDisconnected) { return; } - if ( self.isRegisteredWithRoomServer ) { + if (self.isRegisteredWithRoomServer) { [self unregisterWithRoomServer]; } if (_channel) { @@ -329,30 +341,11 @@ - (void)channel:(ARDWebSocketChannel *)channel - (void)peerConnection:(RTCPeerConnection *)peerConnection signalingStateChanged:(RTCSignalingState)stateChanged { - - switch (stateChanged) { - case RTCSignalingStable: - NSLog(@"Signaling state changed: RTCSignalingStable"); - break; - case RTCSignalingHaveLocalOffer: - NSLog(@"Signaling state changed: RTCSignalingHaveLocalOffer"); - break; - case RTCSignalingHaveRemoteOffer: - NSLog(@"Signaling state changed: RTCSignalingHaveRemoteOffer"); - break; - case RTCSignalingHaveLocalPrAnswer: - NSLog(@"Signaling state changed: RTCSignalingHaveLocalPrAnswer"); - break; - case RTCSignalingHaveRemotePrAnswer: - NSLog(@"Signaling state changed: RTCSignalingHaveRemotePrAnswer"); - break; - default: - NSLog(@"Signaling state changed: %d", stateChanged); - break; - } + NSLog(@"Signaling state changed: %d", stateChanged); } -- (void)peerConnection:(RTCPeerConnection *)peerConnection addedStream:(RTCMediaStream *)stream { +- (void)peerConnection:(RTCPeerConnection *)peerConnection + addedStream:(RTCMediaStream *)stream { dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"Received %lu video tracks and %lu audio tracks", (unsigned long)stream.videoTracks.count, @@ -369,55 +362,26 @@ - (void)peerConnection:(RTCPeerConnection *)peerConnection NSLog(@"Stream was removed."); } -- (void)peerConnectionOnRenegotiationNeeded:(RTCPeerConnection *)peerConnection { +- (void)peerConnectionOnRenegotiationNeeded: +(RTCPeerConnection *)peerConnection { NSLog(@"WARNING: Renegotiation needed but unimplemented."); - } - (void)peerConnection:(RTCPeerConnection *)peerConnection iceConnectionChanged:(RTCICEConnectionState)newState { - switch (newState) { - case RTCICEConnectionNew: - NSLog(@"ICE state changed: RTCICEConnectionNew"); - break; - case RTCICEConnectionChecking: - NSLog(@"ICE state changed: RTCICEConnectionChecking"); - break; - case RTCICEConnectionConnected: - NSLog(@"ICE state changed: RTCICEConnectionConnected"); - break; - case RTCICEConnectionCompleted: - NSLog(@"ICE state changed: RTCICEConnectionCompleted"); - break; - case RTCICEConnectionFailed: - NSLog(@"ICE state changed: RTCICEConnectionFailed"); - break; - - default: - NSLog(@"ICE state changed: %d", newState); - break; - } + NSLog(@"ICE state changed: %d", newState); } - (void)peerConnection:(RTCPeerConnection *)peerConnection iceGatheringChanged:(RTCICEGatheringState)newState { - switch (newState) { - case RTCICEGatheringGathering: - NSLog(@"ICE gathering state changed: RTCICEGatheringGathering"); - break; - case RTCICEGatheringComplete: - NSLog(@"ICE gathering state changed: RTCICEGatheringComplete"); - break; - default: - NSLog(@"ICE gathering state changed: %d", newState); - break; - } + NSLog(@"ICE gathering state changed: %d", newState); } - (void)peerConnection:(RTCPeerConnection *)peerConnection gotICECandidate:(RTCICECandidate *)candidate { dispatch_async(dispatch_get_main_queue(), ^{ - ARDICECandidateMessage *message = [[ARDICECandidateMessage alloc] initWithCandidate:candidate]; + ARDICECandidateMessage *message = + [[ARDICECandidateMessage alloc] initWithCandidate:candidate]; [self sendSignalingMessage:message]; }); } @@ -561,6 +525,7 @@ - (void)sendSignalingMessage:(ARDSignalingMessage *)message { } } + - (RTCVideoTrack *)createLocalVideoTrack { // The iOS simulator doesn't provide any sort of camera capture // support or emulation (http://goo.gl/rHAnC1) so don't bother @@ -756,29 +721,11 @@ - (void)sendSignalingMessageToCollider:(ARDSignalingMessage *)message { #pragma mark - Defaults - (RTCMediaConstraints *)defaultMediaStreamConstraints { - // - RTCPair *localVideoMaxWidth = [[RTCPair alloc] initWithKey:@"maxWidth" value:@"320"]; - - RTCPair *localVideoMinWidth = [[RTCPair alloc] initWithKey:@"minWidth" value:@"320"]; - - RTCPair *localVideoMaxHeight = [[RTCPair alloc] initWithKey:@"maxHeight" value:@"240"]; - - RTCPair *localVideoMinHeight = [[RTCPair alloc] initWithKey:@"minHeight" value:@"240"]; - - // RTCPair *localVideoMaxFrameRate = [[RTCPair alloc] initWithKey:@"maxFrameRate" value:@"30"]; - // - // RTCPair *localVideoMinFrameRate = [[RTCPair alloc] initWithKey:@"minFrameRate" value:@"5"]; - // - // RTCPair *localVideoGoogLeakyBucket = [[RTCPair alloc] initWithKey:@"googLeakyBucket" value:@"true"]; - - RTCMediaConstraints *videoSourceConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:@[localVideoMaxHeight, localVideoMaxWidth, localVideoMinHeight, localVideoMinWidth, /*localVideoMinFrameRate, localVideoMaxFrameRate, localVideoGoogLeakyBucket*/] optionalConstraints:nil]; - - // - // RTCMediaConstraints* constraints = - // [[RTCMediaConstraints alloc] - // initWithMandatoryConstraints:nil - // optionalConstraints:nil]; - return videoSourceConstraints; + RTCMediaConstraints* constraints = + [[RTCMediaConstraints alloc] + initWithMandatoryConstraints:nil + optionalConstraints:nil]; + return constraints; } - (RTCMediaConstraints *)defaultAnswerConstraints { From 0ae80d798bd37bd882f4401f260b1494536428c7 Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Fri, 30 Oct 2015 15:18:25 +0300 Subject: [PATCH 3/9] Changes regarding a device rotation --- AppRTC/ARTCVideoChatViewController.m | 37 +++++++--------------------- Lib/ARDAppClient.h | 2 -- Lib/ARDAppClient.m | 36 +++++++++++++++++---------- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/AppRTC/ARTCVideoChatViewController.m b/AppRTC/ARTCVideoChatViewController.m index 3f9801e..381b5c7 100644 --- a/AppRTC/ARTCVideoChatViewController.m +++ b/AppRTC/ARTCVideoChatViewController.m @@ -39,15 +39,10 @@ - (void)viewDidLoad { //Getting Orientation change [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) - name:@"UIDeviceOrientationDidChangeNotification" + name:UIDeviceOrientationDidChangeNotification object:nil]; - // - // - // //AVCaptureSessionRuntimeErrorNotification - // [[NSNotificationCenter defaultCenter] addObserver:self - // selector:@selector(didChangeVideoSizes) - // name:AVCaptureSessionRuntimeErrorNotification - // object:nil]; + + } - (void)viewWillAppear:(BOOL)animated { @@ -73,7 +68,7 @@ - (void)viewWillAppear:(BOOL)animated { - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceOrientationDidChangeNotification" object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; [self disconnect]; } @@ -152,12 +147,6 @@ - (IBAction)hangupButtonPressed:(id)sender { [self.navigationController popToRootViewControllerAnimated:YES]; } --(void)didChangeVideoSizes -{ - [self videoView:self.localView didChangeVideoSize:self.localVideoSize]; - [self videoView:self.remoteView didChangeVideoSize:self.remoteVideoSize]; -} - #pragma mark - ARDAppClientDelegate @@ -201,15 +190,6 @@ - (void)appClient:(ARDAppClient *)client didReceiveRemoteVideoTrack:(RTCVideoTra }]; } --(void)didRemoveLocalVideoTrack:(RTCVideoTrack *)remoteVideoTrack -{ - if (self.localVideoTrack == remoteVideoTrack) { - [remoteVideoTrack removeRenderer:self.localView]; - self.localVideoTrack = remoteVideoTrack = nil; - [self.localView renderFrame:nil]; - } -} - - (void)appClient:(ARDAppClient *)client didError:(NSError *)error { UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil message:[NSString stringWithFormat:@"%@", error] @@ -223,9 +203,8 @@ - (void)appClient:(ARDAppClient *)client didError:(NSError *)error { #pragma mark - RTCEAGLVideoViewDelegate - (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size { - dispatch_async(dispatch_get_main_queue(), ^{ - UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; - // [UIView animateWithDuration:0.4f animations:^{ + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + [UIView animateWithDuration:0.4f animations:^{ CGFloat containerWidth = self.view.frame.size.width; CGFloat containerHeight = self.view.frame.size.height; CGSize defaultAspectRatio = CGSizeMake(4, 3); @@ -269,7 +248,9 @@ - (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size [self.remoteViewLeftConstraint setConstant:containerWidth/2.0f - videoFrame.size.width/2.0f]; //center [self.remoteViewRightConstraint setConstant:containerWidth/2.0f - videoFrame.size.width/2.0f]; //center } - }); + [self.view layoutIfNeeded]; + }]; + } diff --git a/Lib/ARDAppClient.h b/Lib/ARDAppClient.h index 17e2436..f16f9bc 100755 --- a/Lib/ARDAppClient.h +++ b/Lib/ARDAppClient.h @@ -50,8 +50,6 @@ didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack; - (void)appClient:(ARDAppClient *)client didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack; -- (void)didRemoveLocalVideoTrack:(RTCVideoTrack *)remoteVideoTrack; - - (void)appClient:(ARDAppClient *)client didError:(NSError *)error; diff --git a/Lib/ARDAppClient.m b/Lib/ARDAppClient.m index 287f2c5..6e38562 100755 --- a/Lib/ARDAppClient.m +++ b/Lib/ARDAppClient.m @@ -78,6 +78,7 @@ @interface ARDAppClient () )delegate { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCaptureSessionStopRunning:) name:AVCaptureSessionDidStopRunningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleStartCaptureSession:) name:AVCaptureSessionDidStartRunningNotification object:nil]; // Init observers to handle going into fore- and back- ground [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackgroundVideo) name:UIApplicationWillResignActiveNotification object:nil]; @@ -140,9 +142,9 @@ - (void)dealloc { #endif [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; [ [NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureSessionDidStopRunningNotification object:nil ]; + [ [NSNotificationCenter defaultCenter] removeObserver:self name:AVCaptureSessionDidStartRunningNotification object:nil ]; [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil]; - [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil ]; [ [NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil ]; [self disconnect]; @@ -150,18 +152,26 @@ - (void)dealloc { #pragma mark - -- (void)handleCaptureSessionStopRunning:(NSNotification *)notification -{ -// dispatch_async(dispatch_get_main_queue(), ^{ - if (isForeGround) { - [self restoreAllMediaStreams]; +- (void)handleCaptureSessionStopRunning:(NSNotification *)notification { + if ([NSThread isMainThread]) { + if (isForeGround) { + [self restoreAllMediaStreams]; + } + } else { + dispatch_async(dispatch_get_main_queue(), ^{ + if (isForeGround) { + [self restoreAllMediaStreams]; + } + }); } -// }); +} + +- (void)handleStartCaptureSession:(NSNotification *)notification { + sessionCurrent = notification.object; } - (void)orientationChanged:(NSNotification *)notification { UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; - if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationPortrait) { if (currentOrientation == orientation) { return; @@ -189,8 +199,7 @@ - (void)restoreAllMediaStreams { } } --(void)cleanUpAllMediaStreams -{ +-(void)cleanUpAllMediaStreams { //Remove current video track if (_peerConnection.localStreams.count == 0) { return; @@ -199,9 +208,7 @@ -(void)cleanUpAllMediaStreams if (localStream.videoTracks.count == 0) { return; } - RTCVideoTrack* formerVideoTrack = localStream.videoTracks[0]; - [ localStream removeVideoTrack:formerVideoTrack ]; - [_delegate didRemoveLocalVideoTrack:formerVideoTrack]; + [localStream removeVideoTrack:localStream.videoTracks[0]]; if (localStream.audioTracks.count > 0) { RTCAudioTrack* formerAudioTrack = localStream.audioTracks[0]; @@ -209,6 +216,9 @@ -(void)cleanUpAllMediaStreams } [_peerConnection removeStream:localStream]; + if (sessionCurrent) { + [sessionCurrent stopRunning]; + } } From beaaf206d099edce621db540f2b5245834ba686a Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Tue, 17 Nov 2015 11:55:04 +0300 Subject: [PATCH 4/9] Added going into back-fore ground feature --- .idea/.name | 1 + .idea/apprtc-ios.iml | 277 +++++++++++ .idea/encodings.xml | 6 + .idea/misc.xml | 13 + .idea/modules.xml | 8 + .idea/runConfigurations/AppRTC.xml | 9 + .idea/vcs.xml | 6 + .idea/workspace.xml | 470 ++++++++++++++++++ .idea/xcode.xml | 4 + AppRTC/Base.lproj/Main.storyboard | 25 +- Lib/ARDAppClient.m | 32 +- .../xcshareddata/xcschemes/AppRTC.xcscheme | 63 +-- 12 files changed, 862 insertions(+), 52 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/apprtc-ios.iml create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations/AppRTC.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 .idea/xcode.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..2631b8c --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +AppRTC \ No newline at end of file diff --git a/.idea/apprtc-ios.iml b/.idea/apprtc-ios.iml new file mode 100644 index 0000000..fb39c02 --- /dev/null +++ b/.idea/apprtc-ios.iml @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..72abef0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a1d1151 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/AppRTC.xml b/.idea/runConfigurations/AppRTC.xml new file mode 100644 index 0000000..49d6050 --- /dev/null +++ b/.idea/runConfigurations/AppRTC.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..3d7b50e --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,470 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1447683782158 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + file://$PROJECT_DIR$/Lib/ARDAppClient.m + 390 + + + file://$PROJECT_DIR$/Lib/ARDAppClient.m + 498 + + + file://$PROJECT_DIR$/Lib/ARDAppClient.m + 555 + + + file://$PROJECT_DIR$/Lib/ARDAppClient.m + 387 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/xcode.xml b/.idea/xcode.xml new file mode 100644 index 0000000..d4d699b --- /dev/null +++ b/.idea/xcode.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/AppRTC/Base.lproj/Main.storyboard b/AppRTC/Base.lproj/Main.storyboard index 02194e6..06aa969 100644 --- a/AppRTC/Base.lproj/Main.storyboard +++ b/AppRTC/Base.lproj/Main.storyboard @@ -1,7 +1,7 @@ - + - + @@ -12,15 +12,19 @@ + + + + @@ -41,6 +46,7 @@ + @@ -48,6 +54,7 @@ + @@ -97,6 +106,7 @@ + @@ -135,10 +145,12 @@ + + @@ -150,6 +162,7 @@ + @@ -183,6 +198,7 @@ + @@ -219,6 +238,7 @@ + @@ -268,6 +288,7 @@ + diff --git a/Lib/ARDAppClient.m b/Lib/ARDAppClient.m index 6e38562..112ccdf 100755 --- a/Lib/ARDAppClient.m +++ b/Lib/ARDAppClient.m @@ -79,6 +79,9 @@ @interface ARDAppClient () )delegate { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleCaptureSessionStopRunning:) name:AVCaptureSessionDidStopRunningNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleStartCaptureSession:) name:AVCaptureSessionDidStartRunningNotification object:nil]; - + // Init observers to handle going into fore- and back- ground [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackgroundVideo) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterForegroundVideo) name:UIApplicationDidBecomeActiveNotification object:nil]; @@ -380,19 +383,41 @@ - (void)peerConnectionOnRenegotiationNeeded: - (void)peerConnection:(RTCPeerConnection *)peerConnection iceConnectionChanged:(RTCICEConnectionState)newState { NSLog(@"ICE state changed: %d", newState); + switch (newState) { + case RTCICEConnectionCompleted: + NSLog(@"RTCICEConnectionCompleted"); + break; + case RTCICEConnectionConnected: + NSLog(@"RTCICEConnectionConnected"); + break; + default: + break; + } } - (void)peerConnection:(RTCPeerConnection *)peerConnection iceGatheringChanged:(RTCICEGatheringState)newState { NSLog(@"ICE gathering state changed: %d", newState); + switch (newState) { + case RTCICEGatheringComplete: + for (ARDICECandidateMessage *message in arrayCondidates) { + [self sendSignalingMessage:message]; + } + break; + } } + - (void)peerConnection:(RTCPeerConnection *)peerConnection gotICECandidate:(RTCICECandidate *)candidate { dispatch_async(dispatch_get_main_queue(), ^{ + if (!arrayCondidates) { + arrayCondidates = [NSMutableArray array]; + } ARDICECandidateMessage *message = [[ARDICECandidateMessage alloc] initWithCandidate:candidate]; - [self sendSignalingMessage:message]; + [arrayCondidates addObject:message]; +// [self sendSignalingMessage:message]; }); } @@ -481,8 +506,7 @@ - (void)startSignalingIfReady { } - (void)sendOffer { - [_peerConnection createOfferWithDelegate:self - constraints:[self defaultOfferConstraints]]; + [_peerConnection createOfferWithDelegate:self constraints:[self defaultOfferConstraints]]; } - (void)waitForAnswer { diff --git a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/AppRTC.xcscheme b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/AppRTC.xcscheme index 4358193..f8e9b03 100644 --- a/Pods/Pods.xcodeproj/xcshareddata/xcschemes/AppRTC.xcscheme +++ b/Pods/Pods.xcodeproj/xcshareddata/xcschemes/AppRTC.xcscheme @@ -1,60 +1,31 @@ - + + buildForRunning = "YES"> + BuildableIdentifier = "primary" + BlueprintIdentifier = "5C80AA751AAB5DF300F21FFA" + BuildableName = "AppRTC.app" + BlueprintName = "AppRTC" + ReferencedContainer = "container:../AppRTC.xcodeproj"> - - - - - - - - - - - - - + + + + + From eac1d819a72597f94af0bf235bf252855c7e148b Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Tue, 17 Nov 2015 16:02:53 +0300 Subject: [PATCH 5/9] the small fix --- .idea/workspace.xml | 43 +++++++++++-------------------------------- Lib/ARDAppClient.m | 1 - 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index fe1e079..a63a355 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,24 +5,7 @@ - - - - - - - - - - - - - - - - - @@ -126,8 +109,8 @@ - - + + @@ -140,7 +123,7 @@ - + @@ -348,11 +331,11 @@ - + - - + + @@ -375,14 +358,9 @@ file://$PROJECT_DIR$/Lib/ARDAppClient.m - 458 + 457 - - file://$PROJECT_DIR$/Lib/ARDAppClient.m - 515 - @@ -557,7 +536,7 @@ - + @@ -566,8 +545,8 @@ - - + + diff --git a/Lib/ARDAppClient.m b/Lib/ARDAppClient.m index eed69cd..cf0fc2f 100755 --- a/Lib/ARDAppClient.m +++ b/Lib/ARDAppClient.m @@ -199,7 +199,6 @@ - (void)didEnterBackgroundVideo { [self cleanUpAllMediaStreams]; } - - (void)restoreAllMediaStreams { if (self.peerConnection && _peerConnection.localStreams.count == 0){ RTCMediaStream* localStream = [self createLocalMediaStream]; From c4d367a3018546337b4f333ee47574e3da6864c9 Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Wed, 18 Nov 2015 18:34:36 +0300 Subject: [PATCH 6/9] modified a muteVideoin mthod added a isMuteVideoIn ivar indicating muted and undeted videoIn --- .idea/workspace.xml | 73 ++++++++++++++++++++++----------------------- Lib/ARDAppClient.m | 9 +++++- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index a63a355..4a7dc11 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -20,7 +20,7 @@ - + @@ -89,8 +89,8 @@ - - + + @@ -109,11 +109,11 @@ - - + + - + @@ -123,7 +123,7 @@ - + @@ -326,7 +326,7 @@ - + @@ -335,8 +335,8 @@ - - + + @@ -358,7 +358,7 @@ file://$PROJECT_DIR$/Lib/ARDAppClient.m - 457 + 459 @@ -375,7 +375,6 @@ - @@ -385,7 +384,7 @@ - + @@ -457,38 +456,36 @@ - - + - - - + + - + - + - + - + - + - + @@ -501,34 +498,34 @@ - + - - + + - + - + - + - + - + - - + + @@ -536,7 +533,7 @@ - + @@ -545,11 +542,11 @@ - - + + - + diff --git a/Lib/ARDAppClient.m b/Lib/ARDAppClient.m index cf0fc2f..fcf9fe1 100755 --- a/Lib/ARDAppClient.m +++ b/Lib/ARDAppClient.m @@ -80,6 +80,7 @@ @interface ARDAppClient () )delegate { currentOrientation = [[UIDevice currentDevice] orientation]; isForeGround = YES; _isSpeakerEnabled = YES; + isMuteVideoIn = NO; cameraPosition = AVCaptureDevicePositionFront; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; @@ -200,7 +202,7 @@ - (void)didEnterBackgroundVideo { } - (void)restoreAllMediaStreams { - if (self.peerConnection && _peerConnection.localStreams.count == 0){ + if (self.peerConnection && _peerConnection.localStreams.count == 0 && !isMuteVideoIn) { RTCMediaStream* localStream = [self createLocalMediaStream]; [self.peerConnection addStream:localStream]; } @@ -813,14 +815,19 @@ - (void)unmuteAudioIn { #pragma mark - Video mute/unmute - (void)muteVideoIn { NSLog(@"video muted"); + isMuteVideoIn = YES; RTCMediaStream *localStream = _peerConnection.localStreams[0]; self.defaultVideoTrack = localStream.videoTracks[0]; [localStream removeVideoTrack:localStream.videoTracks[0]]; [_peerConnection removeStream:localStream]; [_peerConnection addStream:localStream]; + if (sessionCurrent) { + [sessionCurrent stopRunning]; + } } - (void)unmuteVideoIn { NSLog(@"video unmuted"); + isMuteVideoIn = NO; RTCMediaStream* localStream = _peerConnection.localStreams[0]; [localStream addVideoTrack:self.defaultVideoTrack]; [_peerConnection removeStream:localStream]; From ac10b2ac2d90e14d566f613f2b48eeebe08f065e Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Wed, 18 Nov 2015 18:52:45 +0300 Subject: [PATCH 7/9] .idea was ignored --- .gitignore | 2 + .idea/workspace.xml | 555 -------------------------------------------- 2 files changed, 2 insertions(+), 555 deletions(-) delete mode 100644 .idea/workspace.xml diff --git a/.gitignore b/.gitignore index 7a1b541..9c9fd44 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ xcuserdata # Misc .DS_Store #*.lock + +.idea/workspace.xml diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 4a7dc11..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,555 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1447683782158 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file://$PROJECT_DIR$/Lib/ARDAppClient.m - 459 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 3ffdf608ebfd457a2796bf58f767465a0e3da8e9 Mon Sep 17 00:00:00 2001 From: Kos Date: Wed, 18 Nov 2015 19:20:02 +0300 Subject: [PATCH 8/9] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9c9fd44..f357ad6 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,4 @@ xcuserdata .DS_Store #*.lock -.idea/workspace.xml +.idea/ From 2632c8086587c9bfef7fde5e1ff63dd960194d57 Mon Sep 17 00:00:00 2001 From: Konstantine Kus Date: Wed, 18 Nov 2015 19:42:38 +0300 Subject: [PATCH 9/9] removed .idea --- .idea/.name | 1 - .idea/apprtc-ios.iml | 277 ------------------------------------------- .idea/encodings.xml | 6 - .idea/misc.xml | 13 -- .idea/modules.xml | 8 -- .idea/vcs.xml | 6 - .idea/xcode.xml | 4 - 7 files changed, 315 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/apprtc-ios.iml delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/xcode.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index 2631b8c..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -AppRTC \ No newline at end of file diff --git a/.idea/apprtc-ios.iml b/.idea/apprtc-ios.iml deleted file mode 100644 index fb39c02..0000000 --- a/.idea/apprtc-ios.iml +++ /dev/null @@ -1,277 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 72abef0..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index a1d1151..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/xcode.xml b/.idea/xcode.xml deleted file mode 100644 index d4d699b..0000000 --- a/.idea/xcode.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file