Index: webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m |
diff --git a/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m |
new file mode 100644 |
index 0000000000000000000000000000000000000000..aa9ea2113d3ceaaba2b776495eb38cff23f4fcd5 |
--- /dev/null |
+++ b/webrtc/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m |
@@ -0,0 +1,222 @@ |
+/* |
+ * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#import "ARDVideoCallViewController.h" |
+ |
+#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" |
+ |
+#import "WebRTC/RTCAVFoundationVideoSource.h" |
+#import "WebRTC/RTCDispatcher.h" |
+#import "WebRTC/RTCLogging.h" |
+ |
+#import "ARDAppClient.h" |
+#import "ARDVideoCallView.h" |
+ |
+@interface ARDVideoCallViewController () <ARDAppClientDelegate, |
+ ARDVideoCallViewDelegate> |
+@property(nonatomic, strong) RTCVideoTrack *localVideoTrack; |
+@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack; |
+@property(nonatomic, readonly) ARDVideoCallView *videoCallView; |
+@end |
+ |
+@implementation ARDVideoCallViewController { |
+ ARDAppClient *_client; |
+ RTCVideoTrack *_remoteVideoTrack; |
+ RTCVideoTrack *_localVideoTrack; |
+ AVAudioSessionPortOverride _portOverride; |
+} |
+ |
+@synthesize videoCallView = _videoCallView; |
+@synthesize delegate = _delegate; |
+ |
+- (instancetype)initForRoom:(NSString *)room |
+ isLoopback:(BOOL)isLoopback |
+ isAudioOnly:(BOOL)isAudioOnly |
+ shouldMakeAecDump:(BOOL)shouldMakeAecDump |
+ shouldUseLevelControl:(BOOL)shouldUseLevelControl |
+ delegate:(id<ARDVideoCallViewControllerDelegate>)delegate { |
+ if (self = [super init]) { |
+ _delegate = delegate; |
+ _client = [[ARDAppClient alloc] initWithDelegate:self]; |
+ [_client connectToRoomWithId:room |
+ isLoopback:isLoopback |
+ isAudioOnly:isAudioOnly |
+ shouldMakeAecDump:shouldMakeAecDump |
+ shouldUseLevelControl:shouldUseLevelControl]; |
+ } |
+ return self; |
+} |
+ |
+- (void)loadView { |
+ _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero]; |
+ _videoCallView.delegate = self; |
+ _videoCallView.statusLabel.text = |
+ [self statusTextForState:RTCIceConnectionStateNew]; |
+ self.view = _videoCallView; |
+} |
+ |
+#pragma mark - ARDAppClientDelegate |
+ |
+- (void)appClient:(ARDAppClient *)client |
+ didChangeState:(ARDAppClientState)state { |
+ switch (state) { |
+ case kARDAppClientStateConnected: |
+ RTCLog(@"Client connected."); |
+ break; |
+ case kARDAppClientStateConnecting: |
+ RTCLog(@"Client connecting."); |
+ break; |
+ case kARDAppClientStateDisconnected: |
+ RTCLog(@"Client disconnected."); |
+ [self hangup]; |
+ break; |
+ } |
+} |
+ |
+- (void)appClient:(ARDAppClient *)client |
+ didChangeConnectionState:(RTCIceConnectionState)state { |
+ RTCLog(@"ICE state changed: %ld", (long)state); |
+ __weak ARDVideoCallViewController *weakSelf = self; |
+ dispatch_async(dispatch_get_main_queue(), ^{ |
+ ARDVideoCallViewController *strongSelf = weakSelf; |
+ strongSelf.videoCallView.statusLabel.text = |
+ [strongSelf statusTextForState:state]; |
+ }); |
+} |
+ |
+- (void)appClient:(ARDAppClient *)client |
+ didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { |
+ self.localVideoTrack = localVideoTrack; |
+} |
+ |
+- (void)appClient:(ARDAppClient *)client |
+ didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { |
+ self.remoteVideoTrack = remoteVideoTrack; |
+ _videoCallView.statusLabel.hidden = YES; |
+} |
+ |
+- (void)appClient:(ARDAppClient *)client |
+ didGetStats:(NSArray *)stats { |
+ _videoCallView.statsView.stats = stats; |
+ [_videoCallView setNeedsLayout]; |
+} |
+ |
+- (void)appClient:(ARDAppClient *)client |
+ didError:(NSError *)error { |
+ NSString *message = |
+ [NSString stringWithFormat:@"%@", error.localizedDescription]; |
+ [self showAlertWithMessage:message]; |
+ [self hangup]; |
+} |
+ |
+#pragma mark - ARDVideoCallViewDelegate |
+ |
+- (void)videoCallViewDidHangup:(ARDVideoCallView *)view { |
+ [self hangup]; |
+} |
+ |
+- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view { |
+ // TODO(tkchin): Rate limit this so you can't tap continously on it. |
+ // Probably through an animation. |
+ [self switchCamera]; |
+} |
+ |
+- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view { |
+ AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone; |
+ if (_portOverride == AVAudioSessionPortOverrideNone) { |
+ override = AVAudioSessionPortOverrideSpeaker; |
+ } |
+ [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession |
+ block:^{ |
+ RTCAudioSession *session = [RTCAudioSession sharedInstance]; |
+ [session lockForConfiguration]; |
+ NSError *error = nil; |
+ if ([session overrideOutputAudioPort:override error:&error]) { |
+ _portOverride = override; |
+ } else { |
+ RTCLogError(@"Error overriding output port: %@", |
+ error.localizedDescription); |
+ } |
+ [session unlockForConfiguration]; |
+ }]; |
+} |
+ |
+- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view { |
+ _client.shouldGetStats = YES; |
+ _videoCallView.statsView.hidden = NO; |
+} |
+ |
+#pragma mark - Private |
+ |
+- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { |
+ if (_localVideoTrack == localVideoTrack) { |
+ return; |
+ } |
+ _localVideoTrack = nil; |
+ _localVideoTrack = localVideoTrack; |
+ RTCAVFoundationVideoSource *source = nil; |
+ if ([localVideoTrack.source |
+ isKindOfClass:[RTCAVFoundationVideoSource class]]) { |
+ source = (RTCAVFoundationVideoSource*)localVideoTrack.source; |
+ } |
+ _videoCallView.localVideoView.captureSession = source.captureSession; |
+} |
+ |
+- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { |
+ if (_remoteVideoTrack == remoteVideoTrack) { |
+ return; |
+ } |
+ [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView]; |
+ _remoteVideoTrack = nil; |
+ [_videoCallView.remoteVideoView renderFrame:nil]; |
+ _remoteVideoTrack = remoteVideoTrack; |
+ [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView]; |
+} |
+ |
+- (void)hangup { |
+ self.remoteVideoTrack = nil; |
+ self.localVideoTrack = nil; |
+ [_client disconnect]; |
+ [_delegate viewControllerDidFinish:self]; |
+} |
+ |
+- (void)switchCamera { |
+ RTCVideoSource* source = self.localVideoTrack.source; |
+ if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) { |
+ RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source; |
+ avSource.useBackCamera = !avSource.useBackCamera; |
+ } |
+} |
+ |
+- (NSString *)statusTextForState:(RTCIceConnectionState)state { |
+ switch (state) { |
+ case RTCIceConnectionStateNew: |
+ case RTCIceConnectionStateChecking: |
+ return @"Connecting..."; |
+ case RTCIceConnectionStateConnected: |
+ case RTCIceConnectionStateCompleted: |
+ case RTCIceConnectionStateFailed: |
+ case RTCIceConnectionStateDisconnected: |
+ case RTCIceConnectionStateClosed: |
+ case RTCIceConnectionStateCount: |
+ return nil; |
+ } |
+} |
+ |
+- (void)showAlertWithMessage:(NSString*)message { |
+ UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil |
+ message:message |
+ delegate:nil |
+ cancelButtonTitle:@"OK" |
+ otherButtonTitles:nil]; |
+ [alertView show]; |
+} |
+ |
+@end |