• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "RTCAVFoundationVideoSource.h"
14#import "RTCLogging.h"
15
16#import "ARDAppClient.h"
17#import "ARDVideoCallView.h"
18
19@interface ARDVideoCallViewController () <ARDAppClientDelegate,
20    ARDVideoCallViewDelegate>
21@property(nonatomic, strong) RTCVideoTrack *localVideoTrack;
22@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
23@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
24@end
25
26@implementation ARDVideoCallViewController {
27  ARDAppClient *_client;
28  RTCVideoTrack *_remoteVideoTrack;
29  RTCVideoTrack *_localVideoTrack;
30}
31
32@synthesize videoCallView = _videoCallView;
33
34- (instancetype)initForRoom:(NSString *)room
35                 isLoopback:(BOOL)isLoopback
36                isAudioOnly:(BOOL)isAudioOnly {
37  if (self = [super init]) {
38    _client = [[ARDAppClient alloc] initWithDelegate:self];
39    [_client connectToRoomWithId:room
40                      isLoopback:isLoopback
41                     isAudioOnly:isAudioOnly];
42  }
43  return self;
44}
45
46- (void)loadView {
47  _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
48  _videoCallView.delegate = self;
49  _videoCallView.statusLabel.text =
50      [self statusTextForState:RTCICEConnectionNew];
51  self.view = _videoCallView;
52}
53
54#pragma mark - ARDAppClientDelegate
55
56- (void)appClient:(ARDAppClient *)client
57    didChangeState:(ARDAppClientState)state {
58  switch (state) {
59    case kARDAppClientStateConnected:
60      RTCLog(@"Client connected.");
61      break;
62    case kARDAppClientStateConnecting:
63      RTCLog(@"Client connecting.");
64      break;
65    case kARDAppClientStateDisconnected:
66      RTCLog(@"Client disconnected.");
67      [self hangup];
68      break;
69  }
70}
71
72- (void)appClient:(ARDAppClient *)client
73    didChangeConnectionState:(RTCICEConnectionState)state {
74  RTCLog(@"ICE state changed: %d", state);
75  __weak ARDVideoCallViewController *weakSelf = self;
76  dispatch_async(dispatch_get_main_queue(), ^{
77    ARDVideoCallViewController *strongSelf = weakSelf;
78    strongSelf.videoCallView.statusLabel.text =
79        [strongSelf statusTextForState:state];
80  });
81}
82
83- (void)appClient:(ARDAppClient *)client
84    didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
85  self.localVideoTrack = localVideoTrack;
86}
87
88- (void)appClient:(ARDAppClient *)client
89    didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
90  self.remoteVideoTrack = remoteVideoTrack;
91  _videoCallView.statusLabel.hidden = YES;
92}
93
94- (void)appClient:(ARDAppClient *)client
95      didGetStats:(NSArray *)stats {
96  _videoCallView.statsView.stats = stats;
97  [_videoCallView setNeedsLayout];
98}
99
100- (void)appClient:(ARDAppClient *)client
101         didError:(NSError *)error {
102  NSString *message =
103      [NSString stringWithFormat:@"%@", error.localizedDescription];
104  [self showAlertWithMessage:message];
105  [self hangup];
106}
107
108#pragma mark - ARDVideoCallViewDelegate
109
110- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
111  [self hangup];
112}
113
114- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
115  // TODO(tkchin): Rate limit this so you can't tap continously on it.
116  // Probably through an animation.
117  [self switchCamera];
118}
119
120- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
121  _client.shouldGetStats = YES;
122  _videoCallView.statsView.hidden = NO;
123}
124
125#pragma mark - Private
126
127- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
128  if (_localVideoTrack == localVideoTrack) {
129    return;
130  }
131  _localVideoTrack = nil;
132  _localVideoTrack = localVideoTrack;
133  RTCAVFoundationVideoSource *source = nil;
134  if ([localVideoTrack.source
135          isKindOfClass:[RTCAVFoundationVideoSource class]]) {
136    source = (RTCAVFoundationVideoSource*)localVideoTrack.source;
137  }
138  _videoCallView.localVideoView.captureSession = source.captureSession;
139}
140
141- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
142  if (_remoteVideoTrack == remoteVideoTrack) {
143    return;
144  }
145  [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
146  _remoteVideoTrack = nil;
147  [_videoCallView.remoteVideoView renderFrame:nil];
148  _remoteVideoTrack = remoteVideoTrack;
149  [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
150}
151
152- (void)hangup {
153  self.remoteVideoTrack = nil;
154  self.localVideoTrack = nil;
155  [_client disconnect];
156  if (![self isBeingDismissed]) {
157    [self.presentingViewController dismissViewControllerAnimated:YES
158                                                      completion:nil];
159  }
160}
161
162- (void)switchCamera {
163  RTCVideoSource* source = self.localVideoTrack.source;
164  if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
165    RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
166    avSource.useBackCamera = !avSource.useBackCamera;
167    _videoCallView.localVideoView.transform = avSource.useBackCamera ?
168        CGAffineTransformIdentity : CGAffineTransformMakeScale(-1, 1);
169  }
170}
171
172- (NSString *)statusTextForState:(RTCICEConnectionState)state {
173  switch (state) {
174    case RTCICEConnectionNew:
175    case RTCICEConnectionChecking:
176      return @"Connecting...";
177    case RTCICEConnectionConnected:
178    case RTCICEConnectionCompleted:
179    case RTCICEConnectionFailed:
180    case RTCICEConnectionDisconnected:
181    case RTCICEConnectionClosed:
182    case RTCICEConnectionMax:
183      return nil;
184  }
185}
186
187- (void)showAlertWithMessage:(NSString*)message {
188  UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
189                                                      message:message
190                                                     delegate:nil
191                                            cancelButtonTitle:@"OK"
192                                            otherButtonTitles:nil];
193  [alertView show];
194}
195
196@end
197