blob: f58ee6613c435cca2403bf43ffdc01c983494362 [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;
tkchind2511962016-05-06 18:54:15 -070038@synthesize delegate = _delegate;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000039
haysc913e6452015-10-02 11:44:03 -070040- (instancetype)initForRoom:(NSString *)room
41 isLoopback:(BOOL)isLoopback
tkchind2511962016-05-06 18:54:15 -070042 isAudioOnly:(BOOL)isAudioOnly
peah5085b0c2016-08-25 22:15:14 -070043 shouldMakeAecDump:(BOOL)shouldMakeAecDump
tkchinab1293a2016-08-30 12:35:05 -070044 shouldUseLevelControl:(BOOL)shouldUseLevelControl
tkchind2511962016-05-06 18:54:15 -070045 delegate:(id<ARDVideoCallViewControllerDelegate>)delegate {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000046 if (self = [super init]) {
denicija2256e042016-11-09 06:26:18 -080047 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
sakal68b5df92017-03-17 09:01:59 -070048 NSString* videoCodec = [settingsModel currentVideoCodecSettingFromStore];
49 _delegate = delegate;
50 _client = [[ARDAppClient alloc] initWithDelegate:self
51 preferVideoCodec:videoCodec];
denicijad17d5362016-11-02 02:56:09 -070052 RTCMediaConstraints *cameraConstraints = [[RTCMediaConstraints alloc]
53 initWithMandatoryConstraints:nil
denicija2256e042016-11-09 06:26:18 -080054 optionalConstraints:[settingsModel
denicijad17d5362016-11-02 02:56:09 -070055 currentMediaConstraintFromStoreAsRTCDictionary]];
denicija9af2b602016-11-17 00:43:43 -080056 [_client setMaxBitrate:[settingsModel currentMaxBitrateSettingFromStore]];
denicijad17d5362016-11-02 02:56:09 -070057 [_client setCameraConstraints:cameraConstraints];
haysc913e6452015-10-02 11:44:03 -070058 [_client connectToRoomWithId:room
59 isLoopback:isLoopback
peah5085b0c2016-08-25 22:15:14 -070060 isAudioOnly:isAudioOnly
tkchinab1293a2016-08-30 12:35:05 -070061 shouldMakeAecDump:shouldMakeAecDump
62 shouldUseLevelControl:shouldUseLevelControl];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000063 }
64 return self;
65}
66
67- (void)loadView {
68 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
69 _videoCallView.delegate = self;
70 _videoCallView.statusLabel.text =
hjon79858f82016-03-13 22:08:26 -070071 [self statusTextForState:RTCIceConnectionStateNew];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000072 self.view = _videoCallView;
73}
74
75#pragma mark - ARDAppClientDelegate
76
77- (void)appClient:(ARDAppClient *)client
78 didChangeState:(ARDAppClientState)state {
79 switch (state) {
80 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070081 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000082 break;
83 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070084 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000085 break;
86 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070087 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000088 [self hangup];
89 break;
90 }
91}
92
93- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -070094 didChangeConnectionState:(RTCIceConnectionState)state {
95 RTCLog(@"ICE state changed: %ld", (long)state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000096 __weak ARDVideoCallViewController *weakSelf = self;
97 dispatch_async(dispatch_get_main_queue(), ^{
98 ARDVideoCallViewController *strongSelf = weakSelf;
99 strongSelf.videoCallView.statusLabel.text =
100 [strongSelf statusTextForState:state];
101 });
102}
103
104- (void)appClient:(ARDAppClient *)client
105 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700106 self.localVideoTrack = localVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000107}
108
109- (void)appClient:(ARDAppClient *)client
110 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700111 self.remoteVideoTrack = remoteVideoTrack;
112 _videoCallView.statusLabel.hidden = YES;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000113}
114
115- (void)appClient:(ARDAppClient *)client
Zeke Chind3325802015-08-14 11:00:02 -0700116 didGetStats:(NSArray *)stats {
117 _videoCallView.statsView.stats = stats;
118 [_videoCallView setNeedsLayout];
119}
120
121- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000122 didError:(NSError *)error {
123 NSString *message =
124 [NSString stringWithFormat:@"%@", error.localizedDescription];
125 [self showAlertWithMessage:message];
126 [self hangup];
127}
128
129#pragma mark - ARDVideoCallViewDelegate
130
131- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
132 [self hangup];
133}
134
Zeke Chin57cc74e2015-05-05 07:52:31 -0700135- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
136 // TODO(tkchin): Rate limit this so you can't tap continously on it.
137 // Probably through an animation.
138 [self switchCamera];
139}
140
tkchin0ce3bf92016-03-12 16:52:04 -0800141- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view {
142 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
143 if (_portOverride == AVAudioSessionPortOverrideNone) {
144 override = AVAudioSessionPortOverrideSpeaker;
145 }
146 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession
147 block:^{
148 RTCAudioSession *session = [RTCAudioSession sharedInstance];
149 [session lockForConfiguration];
150 NSError *error = nil;
151 if ([session overrideOutputAudioPort:override error:&error]) {
152 _portOverride = override;
153 } else {
154 RTCLogError(@"Error overriding output port: %@",
155 error.localizedDescription);
156 }
157 [session unlockForConfiguration];
158 }];
159}
160
Zeke Chind3325802015-08-14 11:00:02 -0700161- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
162 _client.shouldGetStats = YES;
163 _videoCallView.statsView.hidden = NO;
164}
165
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000166#pragma mark - Private
167
Zeke Chin57cc74e2015-05-05 07:52:31 -0700168- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
169 if (_localVideoTrack == localVideoTrack) {
170 return;
171 }
Zeke Chin57cc74e2015-05-05 07:52:31 -0700172 _localVideoTrack = nil;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700173 _localVideoTrack = localVideoTrack;
hayscedd8fef2015-12-08 11:08:39 -0800174 RTCAVFoundationVideoSource *source = nil;
175 if ([localVideoTrack.source
176 isKindOfClass:[RTCAVFoundationVideoSource class]]) {
177 source = (RTCAVFoundationVideoSource*)localVideoTrack.source;
178 }
179 _videoCallView.localVideoView.captureSession = source.captureSession;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700180}
181
182- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
183 if (_remoteVideoTrack == remoteVideoTrack) {
184 return;
185 }
hayscedd8fef2015-12-08 11:08:39 -0800186 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700187 _remoteVideoTrack = nil;
188 [_videoCallView.remoteVideoView renderFrame:nil];
189 _remoteVideoTrack = remoteVideoTrack;
190 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
191}
192
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000193- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700194 self.remoteVideoTrack = nil;
195 self.localVideoTrack = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000196 [_client disconnect];
tkchind2511962016-05-06 18:54:15 -0700197 [_delegate viewControllerDidFinish:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000198}
199
Zeke Chin57cc74e2015-05-05 07:52:31 -0700200- (void)switchCamera {
201 RTCVideoSource* source = self.localVideoTrack.source;
202 if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
203 RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
204 avSource.useBackCamera = !avSource.useBackCamera;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700205 }
206}
207
hjon79858f82016-03-13 22:08:26 -0700208- (NSString *)statusTextForState:(RTCIceConnectionState)state {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000209 switch (state) {
hjon79858f82016-03-13 22:08:26 -0700210 case RTCIceConnectionStateNew:
211 case RTCIceConnectionStateChecking:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000212 return @"Connecting...";
hjon79858f82016-03-13 22:08:26 -0700213 case RTCIceConnectionStateConnected:
214 case RTCIceConnectionStateCompleted:
215 case RTCIceConnectionStateFailed:
216 case RTCIceConnectionStateDisconnected:
217 case RTCIceConnectionStateClosed:
hjon8bbbf2c2016-03-14 13:15:44 -0700218 case RTCIceConnectionStateCount:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000219 return nil;
220 }
221}
222
223- (void)showAlertWithMessage:(NSString*)message {
224 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
225 message:message
226 delegate:nil
227 cancelButtonTitle:@"OK"
228 otherButtonTitles:nil];
229 [alertView show];
230}
231
232@end