blob: ad5bc80d4b269d91c6e05a5f4e45ecc7fed3928b [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
denicija59ee91b2017-06-05 05:48:47 -070013#import "WebRTC/RTCAudioSession.h"
tkchin0ce3bf92016-03-12 16:52:04 -080014
denicijad17d5362016-11-02 02:56:09 -070015#import "ARDAppClient.h"
sakalc522e752017-04-05 12:17:48 -070016#import "ARDCaptureController.h"
denicija2256e042016-11-09 06:26:18 -080017#import "ARDSettingsModel.h"
denicijad17d5362016-11-02 02:56:09 -070018#import "ARDVideoCallView.h"
tkchin9eeb6242016-04-27 01:54:20 -070019#import "WebRTC/RTCAVFoundationVideoSource.h"
20#import "WebRTC/RTCDispatcher.h"
21#import "WebRTC/RTCLogging.h"
denicijad17d5362016-11-02 02:56:09 -070022#import "WebRTC/RTCMediaConstraints.h"
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000023
24@interface ARDVideoCallViewController () <ARDAppClientDelegate,
Anders Carlsson121ea322017-06-26 15:34:47 +020025 ARDVideoCallViewDelegate,
26 RTCAudioSessionDelegate>
Zeke Chin57cc74e2015-05-05 07:52:31 -070027@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000028@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
29@end
30
31@implementation ARDVideoCallViewController {
32 ARDAppClient *_client;
33 RTCVideoTrack *_remoteVideoTrack;
sakalc522e752017-04-05 12:17:48 -070034 ARDCaptureController *_captureController;
tkchin0ce3bf92016-03-12 16:52:04 -080035 AVAudioSessionPortOverride _portOverride;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000036}
37
38@synthesize videoCallView = _videoCallView;
kthelgasonb13237b2017-03-30 04:56:05 -070039@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 delegate:(id<ARDVideoCallViewControllerDelegate>)delegate {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000045 if (self = [super init]) {
denicija2256e042016-11-09 06:26:18 -080046 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
sakal68b5df92017-03-17 09:01:59 -070047 _delegate = delegate;
sakalc522e752017-04-05 12:17:48 -070048
sakalc4adacf2017-03-28 01:22:48 -070049 _client = [[ARDAppClient alloc] initWithDelegate:self];
Anders Carlssone1500582017-06-15 16:05:13 +020050 [_client connectToRoomWithId:room settings:settingsModel isLoopback:isLoopback];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000051 }
52 return self;
53}
54
55- (void)loadView {
56 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
57 _videoCallView.delegate = self;
58 _videoCallView.statusLabel.text =
hjon79858f82016-03-13 22:08:26 -070059 [self statusTextForState:RTCIceConnectionStateNew];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000060 self.view = _videoCallView;
Anders Carlsson121ea322017-06-26 15:34:47 +020061
62 RTCAudioSession *session = [RTCAudioSession sharedInstance];
63 [session addDelegate:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000064}
65
66#pragma mark - ARDAppClientDelegate
67
68- (void)appClient:(ARDAppClient *)client
69 didChangeState:(ARDAppClientState)state {
70 switch (state) {
71 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070072 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000073 break;
74 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070075 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000076 break;
77 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070078 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000079 [self hangup];
80 break;
81 }
82}
83
84- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -070085 didChangeConnectionState:(RTCIceConnectionState)state {
86 RTCLog(@"ICE state changed: %ld", (long)state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000087 __weak ARDVideoCallViewController *weakSelf = self;
88 dispatch_async(dispatch_get_main_queue(), ^{
89 ARDVideoCallViewController *strongSelf = weakSelf;
90 strongSelf.videoCallView.statusLabel.text =
91 [strongSelf statusTextForState:state];
92 });
93}
94
95- (void)appClient:(ARDAppClient *)client
sakalc522e752017-04-05 12:17:48 -070096 didCreateLocalCapturer:(RTCCameraVideoCapturer *)localCapturer {
97 _videoCallView.localVideoView.captureSession = localCapturer.captureSession;
98 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
99 _captureController =
100 [[ARDCaptureController alloc] initWithCapturer:localCapturer settings:settingsModel];
101 [_captureController startCapture];
102}
103
104- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000105 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000106}
107
108- (void)appClient:(ARDAppClient *)client
109 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700110 self.remoteVideoTrack = remoteVideoTrack;
111 _videoCallView.statusLabel.hidden = YES;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000112}
113
114- (void)appClient:(ARDAppClient *)client
Zeke Chind3325802015-08-14 11:00:02 -0700115 didGetStats:(NSArray *)stats {
116 _videoCallView.statsView.stats = stats;
117 [_videoCallView setNeedsLayout];
118}
119
120- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000121 didError:(NSError *)error {
122 NSString *message =
123 [NSString stringWithFormat:@"%@", error.localizedDescription];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000124 [self hangup];
hewwatt7cc881d2017-05-18 01:33:34 -0700125 [self showAlertWithMessage:message];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000126}
127
128#pragma mark - ARDVideoCallViewDelegate
129
130- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
131 [self hangup];
132}
133
Zeke Chin57cc74e2015-05-05 07:52:31 -0700134- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
135 // TODO(tkchin): Rate limit this so you can't tap continously on it.
136 // Probably through an animation.
sakalc522e752017-04-05 12:17:48 -0700137 [_captureController switchCamera];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700138}
139
tkchin0ce3bf92016-03-12 16:52:04 -0800140- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view {
141 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
142 if (_portOverride == AVAudioSessionPortOverrideNone) {
143 override = AVAudioSessionPortOverrideSpeaker;
144 }
145 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession
146 block:^{
147 RTCAudioSession *session = [RTCAudioSession sharedInstance];
148 [session lockForConfiguration];
149 NSError *error = nil;
150 if ([session overrideOutputAudioPort:override error:&error]) {
151 _portOverride = override;
152 } else {
153 RTCLogError(@"Error overriding output port: %@",
154 error.localizedDescription);
155 }
156 [session unlockForConfiguration];
157 }];
158}
159
Zeke Chind3325802015-08-14 11:00:02 -0700160- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
161 _client.shouldGetStats = YES;
162 _videoCallView.statsView.hidden = NO;
163}
164
Anders Carlsson121ea322017-06-26 15:34:47 +0200165#pragma mark - RTCAudioSessionDelegate
166
167- (void)audioSession:(RTCAudioSession *)audioSession
168 didDetectPlayoutGlitch:(int64_t)totalNumberOfGlitches {
169 RTCLog(@"Audio session detected glitch, total: %lld", totalNumberOfGlitches);
170}
171
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000172#pragma mark - Private
173
Zeke Chin57cc74e2015-05-05 07:52:31 -0700174- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
175 if (_remoteVideoTrack == remoteVideoTrack) {
176 return;
177 }
hayscedd8fef2015-12-08 11:08:39 -0800178 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700179 _remoteVideoTrack = nil;
180 [_videoCallView.remoteVideoView renderFrame:nil];
181 _remoteVideoTrack = remoteVideoTrack;
182 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
183}
184
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000185- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700186 self.remoteVideoTrack = nil;
sakalc522e752017-04-05 12:17:48 -0700187 _videoCallView.localVideoView.captureSession = nil;
188 [_captureController stopCapture];
189 _captureController = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000190 [_client disconnect];
tkchind2511962016-05-06 18:54:15 -0700191 [_delegate viewControllerDidFinish:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000192}
193
hjon79858f82016-03-13 22:08:26 -0700194- (NSString *)statusTextForState:(RTCIceConnectionState)state {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000195 switch (state) {
hjon79858f82016-03-13 22:08:26 -0700196 case RTCIceConnectionStateNew:
197 case RTCIceConnectionStateChecking:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000198 return @"Connecting...";
hjon79858f82016-03-13 22:08:26 -0700199 case RTCIceConnectionStateConnected:
200 case RTCIceConnectionStateCompleted:
201 case RTCIceConnectionStateFailed:
202 case RTCIceConnectionStateDisconnected:
203 case RTCIceConnectionStateClosed:
hjon8bbbf2c2016-03-14 13:15:44 -0700204 case RTCIceConnectionStateCount:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000205 return nil;
206 }
207}
208
209- (void)showAlertWithMessage:(NSString*)message {
kthelgasonb13237b2017-03-30 04:56:05 -0700210 UIAlertController *alert =
211 [UIAlertController alertControllerWithTitle:nil
212 message:message
213 preferredStyle:UIAlertControllerStyleAlert];
214
215 UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK"
216 style:UIAlertActionStyleDefault
217 handler:^(UIAlertAction *action){
218 }];
219
220 [alert addAction:defaultAction];
221 [self presentViewController:alert animated:YES completion:nil];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000222}
223
224@end