blob: a82d90b290b6e2310929f4926fd01b7549be0d3f [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
Mirko Bonadei19640aa2020-10-19 16:12:43 +020013#import "sdk/objc/api/peerconnection/RTCMediaConstraints.h"
14#import "sdk/objc/base/RTCLogging.h"
15#import "sdk/objc/components/audio/RTCAudioSession.h"
16#import "sdk/objc/components/capturer/RTCCameraVideoCapturer.h"
17#import "sdk/objc/helpers/RTCDispatcher.h"
tkchin0ce3bf92016-03-12 16:52:04 -080018
denicijad17d5362016-11-02 02:56:09 -070019#import "ARDAppClient.h"
sakalc522e752017-04-05 12:17:48 -070020#import "ARDCaptureController.h"
Daniela012b56b2017-11-15 13:15:24 +010021#import "ARDFileCaptureController.h"
denicija2256e042016-11-09 06:26:18 -080022#import "ARDSettingsModel.h"
denicijad17d5362016-11-02 02:56:09 -070023#import "ARDVideoCallView.h"
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000024
25@interface ARDVideoCallViewController () <ARDAppClientDelegate,
Anders Carlsson121ea322017-06-26 15:34:47 +020026 ARDVideoCallViewDelegate,
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020027 RTC_OBJC_TYPE (RTCAudioSessionDelegate)>
28@property(nonatomic, strong) RTC_OBJC_TYPE(RTCVideoTrack) * remoteVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000029@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
Jiawei Ou4aeb35b2018-11-09 13:55:45 -080030@property(nonatomic, assign) AVAudioSessionPortOverride portOverride;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000031@end
32
33@implementation ARDVideoCallViewController {
34 ARDAppClient *_client;
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020035 RTC_OBJC_TYPE(RTCVideoTrack) * _remoteVideoTrack;
sakalc522e752017-04-05 12:17:48 -070036 ARDCaptureController *_captureController;
Daniela012b56b2017-11-15 13:15:24 +010037 ARDFileCaptureController *_fileCaptureController NS_AVAILABLE_IOS(10);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000038}
39
40@synthesize videoCallView = _videoCallView;
kthelgasonb13237b2017-03-30 04:56:05 -070041@synthesize remoteVideoTrack = _remoteVideoTrack;
tkchind2511962016-05-06 18:54:15 -070042@synthesize delegate = _delegate;
Jiawei Ou4aeb35b2018-11-09 13:55:45 -080043@synthesize portOverride = _portOverride;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000044
haysc913e6452015-10-02 11:44:03 -070045- (instancetype)initForRoom:(NSString *)room
46 isLoopback:(BOOL)isLoopback
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;
sakalc522e752017-04-05 12:17:48 -070051
sakalc4adacf2017-03-28 01:22:48 -070052 _client = [[ARDAppClient alloc] initWithDelegate:self];
Anders Carlssone1500582017-06-15 16:05:13 +020053 [_client connectToRoomWithId:room settings:settingsModel isLoopback:isLoopback];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000054 }
55 return self;
56}
57
58- (void)loadView {
59 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
60 _videoCallView.delegate = self;
61 _videoCallView.statusLabel.text =
hjon79858f82016-03-13 22:08:26 -070062 [self statusTextForState:RTCIceConnectionStateNew];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000063 self.view = _videoCallView;
Anders Carlsson121ea322017-06-26 15:34:47 +020064
Mirko Bonadeia81e9c82020-05-04 16:14:32 +020065 RTC_OBJC_TYPE(RTCAudioSession) *session = [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
Anders Carlsson121ea322017-06-26 15:34:47 +020066 [session addDelegate:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000067}
68
Gustavo Garcia gustavo@lifeonair.com19d77c12017-11-15 16:03:18 +020069- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
70 return UIInterfaceOrientationMaskAll;
71}
72
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000073#pragma mark - ARDAppClientDelegate
74
75- (void)appClient:(ARDAppClient *)client
76 didChangeState:(ARDAppClientState)state {
77 switch (state) {
78 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070079 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000080 break;
81 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070082 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000083 break;
84 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070085 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000086 [self hangup];
87 break;
88 }
89}
90
91- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -070092 didChangeConnectionState:(RTCIceConnectionState)state {
93 RTCLog(@"ICE state changed: %ld", (long)state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000094 __weak ARDVideoCallViewController *weakSelf = self;
95 dispatch_async(dispatch_get_main_queue(), ^{
96 ARDVideoCallViewController *strongSelf = weakSelf;
97 strongSelf.videoCallView.statusLabel.text =
98 [strongSelf statusTextForState:state];
99 });
100}
101
102- (void)appClient:(ARDAppClient *)client
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200103 didCreateLocalCapturer:(RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)localCapturer {
sakalc522e752017-04-05 12:17:48 -0700104 _videoCallView.localVideoView.captureSession = localCapturer.captureSession;
105 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
106 _captureController =
107 [[ARDCaptureController alloc] initWithCapturer:localCapturer settings:settingsModel];
108 [_captureController startCapture];
109}
110
111- (void)appClient:(ARDAppClient *)client
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200112 didCreateLocalFileCapturer:(RTC_OBJC_TYPE(RTCFileVideoCapturer) *)fileCapturer {
Daniela012b56b2017-11-15 13:15:24 +0100113#if defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
114 if (@available(iOS 10, *)) {
115 _fileCaptureController = [[ARDFileCaptureController alloc] initWithCapturer:fileCapturer];
116 [_fileCaptureController startCapture];
117 }
118#endif
119}
120
121- (void)appClient:(ARDAppClient *)client
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200122 didReceiveLocalVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)localVideoTrack {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000123}
124
125- (void)appClient:(ARDAppClient *)client
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200126 didReceiveRemoteVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700127 self.remoteVideoTrack = remoteVideoTrack;
Peter Hanspersa1f566b2018-05-02 13:07:53 +0200128 __weak ARDVideoCallViewController *weakSelf = self;
129 dispatch_async(dispatch_get_main_queue(), ^{
130 ARDVideoCallViewController *strongSelf = weakSelf;
131 strongSelf.videoCallView.statusLabel.hidden = YES;
132 });
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000133}
134
Jaehyun Ko193f4bf2021-05-20 15:04:02 +0900135- (void)appClient:(ARDAppClient *)client didGetStats:(RTC_OBJC_TYPE(RTCStatisticsReport) *)stats {
Zeke Chind3325802015-08-14 11:00:02 -0700136 _videoCallView.statsView.stats = stats;
137 [_videoCallView setNeedsLayout];
138}
139
140- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000141 didError:(NSError *)error {
142 NSString *message =
143 [NSString stringWithFormat:@"%@", error.localizedDescription];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000144 [self hangup];
hewwatt7cc881d2017-05-18 01:33:34 -0700145 [self showAlertWithMessage:message];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000146}
147
148#pragma mark - ARDVideoCallViewDelegate
149
150- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
151 [self hangup];
152}
153
dharmeshf824ef82020-07-20 14:40:28 +0530154- (void)videoCallView:(ARDVideoCallView *)view
155 shouldSwitchCameraWithCompletion:(void (^)(NSError *))completion {
156 [_captureController switchCamera:completion];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700157}
158
dharmeshf824ef82020-07-20 14:40:28 +0530159- (void)videoCallView:(ARDVideoCallView *)view
160 shouldChangeRouteWithCompletion:(void (^)(void))completion {
161 NSParameterAssert(completion);
tkchin0ce3bf92016-03-12 16:52:04 -0800162 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
163 if (_portOverride == AVAudioSessionPortOverrideNone) {
164 override = AVAudioSessionPortOverrideSpeaker;
165 }
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200166 [RTC_OBJC_TYPE(RTCDispatcher) dispatchAsyncOnType:RTCDispatcherTypeAudioSession
167 block:^{
168 RTC_OBJC_TYPE(RTCAudioSession) *session =
169 [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
170 [session lockForConfiguration];
171 NSError *error = nil;
172 if ([session overrideOutputAudioPort:override
173 error:&error]) {
174 self.portOverride = override;
175 } else {
176 RTCLogError(@"Error overriding output port: %@",
177 error.localizedDescription);
178 }
179 [session unlockForConfiguration];
dharmeshf824ef82020-07-20 14:40:28 +0530180 completion();
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200181 }];
tkchin0ce3bf92016-03-12 16:52:04 -0800182}
183
Zeke Chind3325802015-08-14 11:00:02 -0700184- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
185 _client.shouldGetStats = YES;
186 _videoCallView.statsView.hidden = NO;
187}
188
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200189#pragma mark - RTC_OBJC_TYPE(RTCAudioSessionDelegate)
Anders Carlsson121ea322017-06-26 15:34:47 +0200190
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200191- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession
Anders Carlsson121ea322017-06-26 15:34:47 +0200192 didDetectPlayoutGlitch:(int64_t)totalNumberOfGlitches {
193 RTCLog(@"Audio session detected glitch, total: %lld", totalNumberOfGlitches);
194}
195
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000196#pragma mark - Private
197
Mirko Bonadeia81e9c82020-05-04 16:14:32 +0200198- (void)setRemoteVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700199 if (_remoteVideoTrack == remoteVideoTrack) {
200 return;
201 }
hayscedd8fef2015-12-08 11:08:39 -0800202 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700203 _remoteVideoTrack = nil;
204 [_videoCallView.remoteVideoView renderFrame:nil];
205 _remoteVideoTrack = remoteVideoTrack;
206 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
207}
208
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000209- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700210 self.remoteVideoTrack = nil;
sakalc522e752017-04-05 12:17:48 -0700211 _videoCallView.localVideoView.captureSession = nil;
212 [_captureController stopCapture];
213 _captureController = nil;
Daniela012b56b2017-11-15 13:15:24 +0100214 [_fileCaptureController stopCapture];
215 _fileCaptureController = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000216 [_client disconnect];
tkchind2511962016-05-06 18:54:15 -0700217 [_delegate viewControllerDidFinish:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000218}
219
hjon79858f82016-03-13 22:08:26 -0700220- (NSString *)statusTextForState:(RTCIceConnectionState)state {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000221 switch (state) {
hjon79858f82016-03-13 22:08:26 -0700222 case RTCIceConnectionStateNew:
223 case RTCIceConnectionStateChecking:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000224 return @"Connecting...";
hjon79858f82016-03-13 22:08:26 -0700225 case RTCIceConnectionStateConnected:
226 case RTCIceConnectionStateCompleted:
227 case RTCIceConnectionStateFailed:
228 case RTCIceConnectionStateDisconnected:
229 case RTCIceConnectionStateClosed:
hjon8bbbf2c2016-03-14 13:15:44 -0700230 case RTCIceConnectionStateCount:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000231 return nil;
232 }
233}
234
235- (void)showAlertWithMessage:(NSString*)message {
kthelgasonb13237b2017-03-30 04:56:05 -0700236 UIAlertController *alert =
237 [UIAlertController alertControllerWithTitle:nil
238 message:message
239 preferredStyle:UIAlertControllerStyleAlert];
240
241 UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK"
242 style:UIAlertActionStyleDefault
243 handler:^(UIAlertAction *action){
244 }];
245
246 [alert addAction:defaultAction];
247 [self presentViewController:alert animated:YES completion:nil];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000248}
249
250@end