blob: cd42514a9f930690df6a97deb5e807427250b9ea [file] [log] [blame]
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00009 */
10
11#import "ARDVideoCallViewController.h"
12
tkchin0ce3bf92016-03-12 16:52:04 -080013#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
14
denicijad17d5362016-11-02 02:56:09 -070015#import "ARDAppClient.h"
denicija2256e042016-11-09 06:26:18 -080016#import "ARDSettingsModel.h"
denicijad17d5362016-11-02 02:56:09 -070017#import "ARDVideoCallView.h"
tkchin9eeb6242016-04-27 01:54:20 -070018#import "WebRTC/RTCAVFoundationVideoSource.h"
19#import "WebRTC/RTCDispatcher.h"
20#import "WebRTC/RTCLogging.h"
denicijad17d5362016-11-02 02:56:09 -070021#import "WebRTC/RTCMediaConstraints.h"
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000022
23@interface ARDVideoCallViewController () <ARDAppClientDelegate,
24 ARDVideoCallViewDelegate>
Zeke Chin57cc74e2015-05-05 07:52:31 -070025@property(nonatomic, strong) RTCVideoTrack *localVideoTrack;
26@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000027@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
28@end
29
30@implementation ARDVideoCallViewController {
31 ARDAppClient *_client;
32 RTCVideoTrack *_remoteVideoTrack;
33 RTCVideoTrack *_localVideoTrack;
tkchin0ce3bf92016-03-12 16:52:04 -080034 AVAudioSessionPortOverride _portOverride;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000035}
36
37@synthesize videoCallView = _videoCallView;
kthelgasonb13237b2017-03-30 04:56:05 -070038@synthesize localVideoTrack = _localVideoTrack;
39@synthesize remoteVideoTrack = _remoteVideoTrack;
tkchind2511962016-05-06 18:54:15 -070040@synthesize delegate = _delegate;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000041
haysc913e6452015-10-02 11:44:03 -070042- (instancetype)initForRoom:(NSString *)room
43 isLoopback:(BOOL)isLoopback
tkchind2511962016-05-06 18:54:15 -070044 isAudioOnly:(BOOL)isAudioOnly
peah5085b0c2016-08-25 22:15:14 -070045 shouldMakeAecDump:(BOOL)shouldMakeAecDump
tkchinab1293a2016-08-30 12:35:05 -070046 shouldUseLevelControl:(BOOL)shouldUseLevelControl
tkchind2511962016-05-06 18:54:15 -070047 delegate:(id<ARDVideoCallViewControllerDelegate>)delegate {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000048 if (self = [super init]) {
denicija2256e042016-11-09 06:26:18 -080049 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
sakal68b5df92017-03-17 09:01:59 -070050 _delegate = delegate;
sakalc4adacf2017-03-28 01:22:48 -070051 _client = [[ARDAppClient alloc] initWithDelegate:self];
haysc913e6452015-10-02 11:44:03 -070052 [_client connectToRoomWithId:room
sakalc4adacf2017-03-28 01:22:48 -070053 settings:settingsModel
haysc913e6452015-10-02 11:44:03 -070054 isLoopback:isLoopback
peah5085b0c2016-08-25 22:15:14 -070055 isAudioOnly:isAudioOnly
tkchinab1293a2016-08-30 12:35:05 -070056 shouldMakeAecDump:shouldMakeAecDump
57 shouldUseLevelControl:shouldUseLevelControl];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000058 }
59 return self;
60}
61
62- (void)loadView {
63 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
64 _videoCallView.delegate = self;
65 _videoCallView.statusLabel.text =
hjon79858f82016-03-13 22:08:26 -070066 [self statusTextForState:RTCIceConnectionStateNew];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000067 self.view = _videoCallView;
68}
69
70#pragma mark - ARDAppClientDelegate
71
72- (void)appClient:(ARDAppClient *)client
73 didChangeState:(ARDAppClientState)state {
74 switch (state) {
75 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070076 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000077 break;
78 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070079 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000080 break;
81 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070082 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000083 [self hangup];
84 break;
85 }
86}
87
88- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -070089 didChangeConnectionState:(RTCIceConnectionState)state {
90 RTCLog(@"ICE state changed: %ld", (long)state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000091 __weak ARDVideoCallViewController *weakSelf = self;
92 dispatch_async(dispatch_get_main_queue(), ^{
93 ARDVideoCallViewController *strongSelf = weakSelf;
94 strongSelf.videoCallView.statusLabel.text =
95 [strongSelf statusTextForState:state];
96 });
97}
98
99- (void)appClient:(ARDAppClient *)client
100 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700101 self.localVideoTrack = localVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000102}
103
104- (void)appClient:(ARDAppClient *)client
105 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700106 self.remoteVideoTrack = remoteVideoTrack;
107 _videoCallView.statusLabel.hidden = YES;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000108}
109
110- (void)appClient:(ARDAppClient *)client
Zeke Chind3325802015-08-14 11:00:02 -0700111 didGetStats:(NSArray *)stats {
112 _videoCallView.statsView.stats = stats;
113 [_videoCallView setNeedsLayout];
114}
115
116- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000117 didError:(NSError *)error {
118 NSString *message =
119 [NSString stringWithFormat:@"%@", error.localizedDescription];
120 [self showAlertWithMessage:message];
121 [self hangup];
122}
123
124#pragma mark - ARDVideoCallViewDelegate
125
126- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
127 [self hangup];
128}
129
Zeke Chin57cc74e2015-05-05 07:52:31 -0700130- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
131 // TODO(tkchin): Rate limit this so you can't tap continously on it.
132 // Probably through an animation.
133 [self switchCamera];
134}
135
tkchin0ce3bf92016-03-12 16:52:04 -0800136- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view {
137 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
138 if (_portOverride == AVAudioSessionPortOverrideNone) {
139 override = AVAudioSessionPortOverrideSpeaker;
140 }
141 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession
142 block:^{
143 RTCAudioSession *session = [RTCAudioSession sharedInstance];
144 [session lockForConfiguration];
145 NSError *error = nil;
146 if ([session overrideOutputAudioPort:override error:&error]) {
147 _portOverride = override;
148 } else {
149 RTCLogError(@"Error overriding output port: %@",
150 error.localizedDescription);
151 }
152 [session unlockForConfiguration];
153 }];
154}
155
Zeke Chind3325802015-08-14 11:00:02 -0700156- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
157 _client.shouldGetStats = YES;
158 _videoCallView.statsView.hidden = NO;
159}
160
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000161#pragma mark - Private
162
Zeke Chin57cc74e2015-05-05 07:52:31 -0700163- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
164 if (_localVideoTrack == localVideoTrack) {
165 return;
166 }
Zeke Chin57cc74e2015-05-05 07:52:31 -0700167 _localVideoTrack = nil;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700168 _localVideoTrack = localVideoTrack;
hayscedd8fef2015-12-08 11:08:39 -0800169 RTCAVFoundationVideoSource *source = nil;
170 if ([localVideoTrack.source
171 isKindOfClass:[RTCAVFoundationVideoSource class]]) {
172 source = (RTCAVFoundationVideoSource*)localVideoTrack.source;
173 }
174 _videoCallView.localVideoView.captureSession = source.captureSession;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700175}
176
177- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
178 if (_remoteVideoTrack == remoteVideoTrack) {
179 return;
180 }
hayscedd8fef2015-12-08 11:08:39 -0800181 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700182 _remoteVideoTrack = nil;
183 [_videoCallView.remoteVideoView renderFrame:nil];
184 _remoteVideoTrack = remoteVideoTrack;
185 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
186}
187
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000188- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700189 self.remoteVideoTrack = nil;
190 self.localVideoTrack = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000191 [_client disconnect];
tkchind2511962016-05-06 18:54:15 -0700192 [_delegate viewControllerDidFinish:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000193}
194
Zeke Chin57cc74e2015-05-05 07:52:31 -0700195- (void)switchCamera {
196 RTCVideoSource* source = self.localVideoTrack.source;
197 if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
198 RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
199 avSource.useBackCamera = !avSource.useBackCamera;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700200 }
201}
202
hjon79858f82016-03-13 22:08:26 -0700203- (NSString *)statusTextForState:(RTCIceConnectionState)state {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000204 switch (state) {
hjon79858f82016-03-13 22:08:26 -0700205 case RTCIceConnectionStateNew:
206 case RTCIceConnectionStateChecking:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000207 return @"Connecting...";
hjon79858f82016-03-13 22:08:26 -0700208 case RTCIceConnectionStateConnected:
209 case RTCIceConnectionStateCompleted:
210 case RTCIceConnectionStateFailed:
211 case RTCIceConnectionStateDisconnected:
212 case RTCIceConnectionStateClosed:
hjon8bbbf2c2016-03-14 13:15:44 -0700213 case RTCIceConnectionStateCount:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000214 return nil;
215 }
216}
217
218- (void)showAlertWithMessage:(NSString*)message {
kthelgasonb13237b2017-03-30 04:56:05 -0700219 UIAlertController *alert =
220 [UIAlertController alertControllerWithTitle:nil
221 message:message
222 preferredStyle:UIAlertControllerStyleAlert];
223
224 UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK"
225 style:UIAlertActionStyleDefault
226 handler:^(UIAlertAction *action){
227 }];
228
229 [alert addAction:defaultAction];
230 [self presentViewController:alert animated:YES completion:nil];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000231}
232
233@end