| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * 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. | |
| 9 */ | |
| 10 | |
| 11 #import "ARDVideoCallViewController.h" | |
| 12 | |
| 13 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" | |
| 14 | |
| 15 #import "WebRTC/RTCAVFoundationVideoSource.h" | |
| 16 #import "WebRTC/RTCDispatcher.h" | |
| 17 #import "WebRTC/RTCLogging.h" | |
| 18 | |
| 19 #import "ARDAppClient.h" | |
| 20 #import "ARDVideoCallView.h" | |
| 21 | |
| 22 @interface ARDVideoCallViewController () <ARDAppClientDelegate, | |
| 23 ARDVideoCallViewDelegate> | |
| 24 @property(nonatomic, strong) RTCVideoTrack *localVideoTrack; | |
| 25 @property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack; | |
| 26 @property(nonatomic, readonly) ARDVideoCallView *videoCallView; | |
| 27 @end | |
| 28 | |
| 29 @implementation ARDVideoCallViewController { | |
| 30 ARDAppClient *_client; | |
| 31 RTCVideoTrack *_remoteVideoTrack; | |
| 32 RTCVideoTrack *_localVideoTrack; | |
| 33 AVAudioSessionPortOverride _portOverride; | |
| 34 } | |
| 35 | |
| 36 @synthesize videoCallView = _videoCallView; | |
| 37 @synthesize delegate = _delegate; | |
| 38 | |
| 39 - (instancetype)initForRoom:(NSString *)room | |
| 40 isLoopback:(BOOL)isLoopback | |
| 41 isAudioOnly:(BOOL)isAudioOnly | |
| 42 shouldMakeAecDump:(BOOL)shouldMakeAecDump | |
| 43 shouldUseLevelControl:(BOOL)shouldUseLevelControl | |
| 44 delegate:(id<ARDVideoCallViewControllerDelegate>)delegate { | |
| 45 if (self = [super init]) { | |
| 46 _delegate = delegate; | |
| 47 _client = [[ARDAppClient alloc] initWithDelegate:self]; | |
| 48 [_client connectToRoomWithId:room | |
| 49 isLoopback:isLoopback | |
| 50 isAudioOnly:isAudioOnly | |
| 51 shouldMakeAecDump:shouldMakeAecDump | |
| 52 shouldUseLevelControl:shouldUseLevelControl]; | |
| 53 } | |
| 54 return self; | |
| 55 } | |
| 56 | |
| 57 - (void)loadView { | |
| 58 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero]; | |
| 59 _videoCallView.delegate = self; | |
| 60 _videoCallView.statusLabel.text = | |
| 61 [self statusTextForState:RTCIceConnectionStateNew]; | |
| 62 self.view = _videoCallView; | |
| 63 } | |
| 64 | |
| 65 #pragma mark - ARDAppClientDelegate | |
| 66 | |
| 67 - (void)appClient:(ARDAppClient *)client | |
| 68 didChangeState:(ARDAppClientState)state { | |
| 69 switch (state) { | |
| 70 case kARDAppClientStateConnected: | |
| 71 RTCLog(@"Client connected."); | |
| 72 break; | |
| 73 case kARDAppClientStateConnecting: | |
| 74 RTCLog(@"Client connecting."); | |
| 75 break; | |
| 76 case kARDAppClientStateDisconnected: | |
| 77 RTCLog(@"Client disconnected."); | |
| 78 [self hangup]; | |
| 79 break; | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 - (void)appClient:(ARDAppClient *)client | |
| 84 didChangeConnectionState:(RTCIceConnectionState)state { | |
| 85 RTCLog(@"ICE state changed: %ld", (long)state); | |
| 86 __weak ARDVideoCallViewController *weakSelf = self; | |
| 87 dispatch_async(dispatch_get_main_queue(), ^{ | |
| 88 ARDVideoCallViewController *strongSelf = weakSelf; | |
| 89 strongSelf.videoCallView.statusLabel.text = | |
| 90 [strongSelf statusTextForState:state]; | |
| 91 }); | |
| 92 } | |
| 93 | |
| 94 - (void)appClient:(ARDAppClient *)client | |
| 95 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { | |
| 96 self.localVideoTrack = localVideoTrack; | |
| 97 } | |
| 98 | |
| 99 - (void)appClient:(ARDAppClient *)client | |
| 100 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { | |
| 101 self.remoteVideoTrack = remoteVideoTrack; | |
| 102 _videoCallView.statusLabel.hidden = YES; | |
| 103 } | |
| 104 | |
| 105 - (void)appClient:(ARDAppClient *)client | |
| 106 didGetStats:(NSArray *)stats { | |
| 107 _videoCallView.statsView.stats = stats; | |
| 108 [_videoCallView setNeedsLayout]; | |
| 109 } | |
| 110 | |
| 111 - (void)appClient:(ARDAppClient *)client | |
| 112 didError:(NSError *)error { | |
| 113 NSString *message = | |
| 114 [NSString stringWithFormat:@"%@", error.localizedDescription]; | |
| 115 [self showAlertWithMessage:message]; | |
| 116 [self hangup]; | |
| 117 } | |
| 118 | |
| 119 #pragma mark - ARDVideoCallViewDelegate | |
| 120 | |
| 121 - (void)videoCallViewDidHangup:(ARDVideoCallView *)view { | |
| 122 [self hangup]; | |
| 123 } | |
| 124 | |
| 125 - (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view { | |
| 126 // TODO(tkchin): Rate limit this so you can't tap continously on it. | |
| 127 // Probably through an animation. | |
| 128 [self switchCamera]; | |
| 129 } | |
| 130 | |
| 131 - (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view { | |
| 132 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone; | |
| 133 if (_portOverride == AVAudioSessionPortOverrideNone) { | |
| 134 override = AVAudioSessionPortOverrideSpeaker; | |
| 135 } | |
| 136 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession | |
| 137 block:^{ | |
| 138 RTCAudioSession *session = [RTCAudioSession sharedInstance]; | |
| 139 [session lockForConfiguration]; | |
| 140 NSError *error = nil; | |
| 141 if ([session overrideOutputAudioPort:override error:&error]) { | |
| 142 _portOverride = override; | |
| 143 } else { | |
| 144 RTCLogError(@"Error overriding output port: %@", | |
| 145 error.localizedDescription); | |
| 146 } | |
| 147 [session unlockForConfiguration]; | |
| 148 }]; | |
| 149 } | |
| 150 | |
| 151 - (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view { | |
| 152 _client.shouldGetStats = YES; | |
| 153 _videoCallView.statsView.hidden = NO; | |
| 154 } | |
| 155 | |
| 156 #pragma mark - Private | |
| 157 | |
| 158 - (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { | |
| 159 if (_localVideoTrack == localVideoTrack) { | |
| 160 return; | |
| 161 } | |
| 162 _localVideoTrack = nil; | |
| 163 _localVideoTrack = localVideoTrack; | |
| 164 RTCAVFoundationVideoSource *source = nil; | |
| 165 if ([localVideoTrack.source | |
| 166 isKindOfClass:[RTCAVFoundationVideoSource class]]) { | |
| 167 source = (RTCAVFoundationVideoSource*)localVideoTrack.source; | |
| 168 } | |
| 169 _videoCallView.localVideoView.captureSession = source.captureSession; | |
| 170 } | |
| 171 | |
| 172 - (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { | |
| 173 if (_remoteVideoTrack == remoteVideoTrack) { | |
| 174 return; | |
| 175 } | |
| 176 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView]; | |
| 177 _remoteVideoTrack = nil; | |
| 178 [_videoCallView.remoteVideoView renderFrame:nil]; | |
| 179 _remoteVideoTrack = remoteVideoTrack; | |
| 180 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView]; | |
| 181 } | |
| 182 | |
| 183 - (void)hangup { | |
| 184 self.remoteVideoTrack = nil; | |
| 185 self.localVideoTrack = nil; | |
| 186 [_client disconnect]; | |
| 187 [_delegate viewControllerDidFinish:self]; | |
| 188 } | |
| 189 | |
| 190 - (void)switchCamera { | |
| 191 RTCVideoSource* source = self.localVideoTrack.source; | |
| 192 if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) { | |
| 193 RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source; | |
| 194 avSource.useBackCamera = !avSource.useBackCamera; | |
| 195 } | |
| 196 } | |
| 197 | |
| 198 - (NSString *)statusTextForState:(RTCIceConnectionState)state { | |
| 199 switch (state) { | |
| 200 case RTCIceConnectionStateNew: | |
| 201 case RTCIceConnectionStateChecking: | |
| 202 return @"Connecting..."; | |
| 203 case RTCIceConnectionStateConnected: | |
| 204 case RTCIceConnectionStateCompleted: | |
| 205 case RTCIceConnectionStateFailed: | |
| 206 case RTCIceConnectionStateDisconnected: | |
| 207 case RTCIceConnectionStateClosed: | |
| 208 case RTCIceConnectionStateCount: | |
| 209 return nil; | |
| 210 } | |
| 211 } | |
| 212 | |
| 213 - (void)showAlertWithMessage:(NSString*)message { | |
| 214 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil | |
| 215 message:message | |
| 216 delegate:nil | |
| 217 cancelButtonTitle:@"OK" | |
| 218 otherButtonTitles:nil]; | |
| 219 [alertView show]; | |
| 220 } | |
| 221 | |
| 222 @end | |
| OLD | NEW |