• 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 "ARDVideoCallView.h"
12
13#import <AVFoundation/AVFoundation.h>
14#import "UIImage+ARDUtilities.h"
15
16static CGFloat const kButtonPadding = 16;
17static CGFloat const kButtonSize = 48;
18static CGFloat const kLocalVideoViewSize = 120;
19static CGFloat const kLocalVideoViewPadding = 8;
20static CGFloat const kStatusBarHeight = 20;
21
22@interface ARDVideoCallView () <RTCEAGLVideoViewDelegate>
23@end
24
25@implementation ARDVideoCallView {
26  UIButton *_cameraSwitchButton;
27  UIButton *_hangupButton;
28  CGSize _remoteVideoSize;
29  BOOL _useRearCamera;
30}
31
32@synthesize statusLabel = _statusLabel;
33@synthesize localVideoView = _localVideoView;
34@synthesize remoteVideoView = _remoteVideoView;
35@synthesize statsView = _statsView;
36@synthesize delegate = _delegate;
37
38- (instancetype)initWithFrame:(CGRect)frame {
39  if (self = [super initWithFrame:frame]) {
40    _remoteVideoView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectZero];
41    _remoteVideoView.delegate = self;
42    [self addSubview:_remoteVideoView];
43
44    _localVideoView = [[RTCCameraPreviewView alloc] initWithFrame:CGRectZero];
45    [self addSubview:_localVideoView];
46
47    _statsView = [[ARDStatsView alloc] initWithFrame:CGRectZero];
48    _statsView.hidden = YES;
49    [self addSubview:_statsView];
50
51    // TODO(tkchin): don't display this if we can't actually do camera switch.
52    _cameraSwitchButton = [UIButton buttonWithType:UIButtonTypeCustom];
53    _cameraSwitchButton.backgroundColor = [UIColor whiteColor];
54    _cameraSwitchButton.layer.cornerRadius = kButtonSize / 2;
55    _cameraSwitchButton.layer.masksToBounds = YES;
56    UIImage *image = [UIImage imageNamed:@"ic_switch_video_black_24dp.png"];
57    [_cameraSwitchButton setImage:image forState:UIControlStateNormal];
58    [_cameraSwitchButton addTarget:self
59                      action:@selector(onCameraSwitch:)
60            forControlEvents:UIControlEventTouchUpInside];
61    [self addSubview:_cameraSwitchButton];
62
63    _hangupButton = [UIButton buttonWithType:UIButtonTypeCustom];
64    _hangupButton.backgroundColor = [UIColor redColor];
65    _hangupButton.layer.cornerRadius = kButtonSize / 2;
66    _hangupButton.layer.masksToBounds = YES;
67    image = [UIImage imageForName:@"ic_call_end_black_24dp.png"
68                            color:[UIColor whiteColor]];
69    [_hangupButton setImage:image forState:UIControlStateNormal];
70    [_hangupButton addTarget:self
71                      action:@selector(onHangup:)
72            forControlEvents:UIControlEventTouchUpInside];
73    [self addSubview:_hangupButton];
74
75    _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
76    _statusLabel.font = [UIFont fontWithName:@"Roboto" size:16];
77    _statusLabel.textColor = [UIColor whiteColor];
78    [self addSubview:_statusLabel];
79
80    UITapGestureRecognizer *tapRecognizer =
81        [[UITapGestureRecognizer alloc]
82            initWithTarget:self
83                    action:@selector(didTripleTap:)];
84    tapRecognizer.numberOfTapsRequired = 3;
85    [self addGestureRecognizer:tapRecognizer];
86  }
87  return self;
88}
89
90- (void)layoutSubviews {
91  CGRect bounds = self.bounds;
92  if (_remoteVideoSize.width > 0 && _remoteVideoSize.height > 0) {
93    // Aspect fill remote video into bounds.
94    CGRect remoteVideoFrame =
95        AVMakeRectWithAspectRatioInsideRect(_remoteVideoSize, bounds);
96    CGFloat scale = 1;
97    if (remoteVideoFrame.size.width > remoteVideoFrame.size.height) {
98      // Scale by height.
99      scale = bounds.size.height / remoteVideoFrame.size.height;
100    } else {
101      // Scale by width.
102      scale = bounds.size.width / remoteVideoFrame.size.width;
103    }
104    remoteVideoFrame.size.height *= scale;
105    remoteVideoFrame.size.width *= scale;
106    _remoteVideoView.frame = remoteVideoFrame;
107    _remoteVideoView.center =
108        CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
109  } else {
110    _remoteVideoView.frame = bounds;
111  }
112
113  // Aspect fit local video view into a square box.
114  CGRect localVideoFrame =
115      CGRectMake(0, 0, kLocalVideoViewSize, kLocalVideoViewSize);
116  // Place the view in the bottom right.
117  localVideoFrame.origin.x = CGRectGetMaxX(bounds)
118      - localVideoFrame.size.width - kLocalVideoViewPadding;
119  localVideoFrame.origin.y = CGRectGetMaxY(bounds)
120      - localVideoFrame.size.height - kLocalVideoViewPadding;
121  _localVideoView.frame = localVideoFrame;
122
123  // Place stats at the top.
124  CGSize statsSize = [_statsView sizeThatFits:bounds.size];
125  _statsView.frame = CGRectMake(CGRectGetMinX(bounds),
126                                CGRectGetMinY(bounds) + kStatusBarHeight,
127                                statsSize.width, statsSize.height);
128
129  // Place hangup button in the bottom left.
130  _hangupButton.frame =
131      CGRectMake(CGRectGetMinX(bounds) + kButtonPadding,
132                 CGRectGetMaxY(bounds) - kButtonPadding -
133                     kButtonSize,
134                 kButtonSize,
135                 kButtonSize);
136
137  // Place button to the right of hangup button.
138  CGRect cameraSwitchFrame = _hangupButton.frame;
139  cameraSwitchFrame.origin.x =
140      CGRectGetMaxX(cameraSwitchFrame) + kButtonPadding;
141  _cameraSwitchButton.frame = cameraSwitchFrame;
142
143  [_statusLabel sizeToFit];
144  _statusLabel.center =
145      CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
146}
147
148#pragma mark - RTCEAGLVideoViewDelegate
149
150- (void)videoView:(RTCEAGLVideoView*)videoView didChangeVideoSize:(CGSize)size {
151 if (videoView == _remoteVideoView) {
152    _remoteVideoSize = size;
153  }
154  [self setNeedsLayout];
155}
156
157#pragma mark - Private
158
159- (void)onCameraSwitch:(id)sender {
160  [_delegate videoCallViewDidSwitchCamera:self];
161}
162
163- (void)onHangup:(id)sender {
164  [_delegate videoCallViewDidHangup:self];
165}
166
167- (void)didTripleTap:(UITapGestureRecognizer *)recognizer {
168  [_delegate videoCallViewDidEnableStats:self];
169}
170
171@end
172