1/* 2 * Copyright 2018 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 "NADViewController.h" 12 13#import "sdk/objc/base/RTCVideoRenderer.h" 14#import "sdk/objc/components/capturer/RTCCameraVideoCapturer.h" 15#if defined(RTC_SUPPORTS_METAL) 16#import "sdk/objc/components/renderer/metal/RTCMTLVideoView.h" // nogncheck 17#endif 18#import "sdk/objc/components/renderer/opengl/RTCEAGLVideoView.h" 19#import "sdk/objc/helpers/RTCCameraPreviewView.h" 20 21#include <memory> 22 23#include "examples/objcnativeapi/objc/objc_call_client.h" 24 25@interface NADViewController () 26 27@property(nonatomic) RTC_OBJC_TYPE(RTCCameraVideoCapturer) * capturer; 28@property(nonatomic) RTC_OBJC_TYPE(RTCCameraPreviewView) * localVideoView; 29@property(nonatomic) __kindof UIView<RTC_OBJC_TYPE(RTCVideoRenderer)> *remoteVideoView; 30@property(nonatomic) UIButton *callButton; 31@property(nonatomic) UIButton *hangUpButton; 32 33@end 34 35@implementation NADViewController { 36 std::unique_ptr<webrtc_examples::ObjCCallClient> _call_client; 37 38 UIView *_view; 39} 40 41@synthesize capturer = _capturer; 42@synthesize localVideoView = _localVideoView; 43@synthesize remoteVideoView = _remoteVideoView; 44@synthesize callButton = _callButton; 45@synthesize hangUpButton = _hangUpButton; 46 47#pragma mark - View controller lifecycle 48 49- (void)loadView { 50 _view = [[UIView alloc] initWithFrame:CGRectZero]; 51 52#if defined(RTC_SUPPORTS_METAL) 53 _remoteVideoView = [[RTC_OBJC_TYPE(RTCMTLVideoView) alloc] initWithFrame:CGRectZero]; 54#else 55 _remoteVideoView = [[RTC_OBJC_TYPE(RTCEAGLVideoView) alloc] initWithFrame:CGRectZero]; 56#endif 57 _remoteVideoView.translatesAutoresizingMaskIntoConstraints = NO; 58 [_view addSubview:_remoteVideoView]; 59 60 _localVideoView = [[RTC_OBJC_TYPE(RTCCameraPreviewView) alloc] initWithFrame:CGRectZero]; 61 _localVideoView.translatesAutoresizingMaskIntoConstraints = NO; 62 [_view addSubview:_localVideoView]; 63 64 _callButton = [UIButton buttonWithType:UIButtonTypeSystem]; 65 _callButton.translatesAutoresizingMaskIntoConstraints = NO; 66 [_callButton setTitle:@"Call" forState:UIControlStateNormal]; 67 [_callButton addTarget:self action:@selector(call:) forControlEvents:UIControlEventTouchUpInside]; 68 [_view addSubview:_callButton]; 69 70 _hangUpButton = [UIButton buttonWithType:UIButtonTypeSystem]; 71 _hangUpButton.translatesAutoresizingMaskIntoConstraints = NO; 72 [_hangUpButton setTitle:@"Hang up" forState:UIControlStateNormal]; 73 [_hangUpButton addTarget:self 74 action:@selector(hangUp:) 75 forControlEvents:UIControlEventTouchUpInside]; 76 [_view addSubview:_hangUpButton]; 77 78 UILayoutGuide *margin = _view.layoutMarginsGuide; 79 [_remoteVideoView.leadingAnchor constraintEqualToAnchor:margin.leadingAnchor].active = YES; 80 [_remoteVideoView.topAnchor constraintEqualToAnchor:margin.topAnchor].active = YES; 81 [_remoteVideoView.trailingAnchor constraintEqualToAnchor:margin.trailingAnchor].active = YES; 82 [_remoteVideoView.bottomAnchor constraintEqualToAnchor:margin.bottomAnchor].active = YES; 83 84 [_localVideoView.leadingAnchor constraintEqualToAnchor:margin.leadingAnchor constant:8.0].active = 85 YES; 86 [_localVideoView.topAnchor constraintEqualToAnchor:margin.topAnchor constant:8.0].active = YES; 87 [_localVideoView.widthAnchor constraintEqualToConstant:60].active = YES; 88 [_localVideoView.heightAnchor constraintEqualToConstant:60].active = YES; 89 90 [_callButton.leadingAnchor constraintEqualToAnchor:margin.leadingAnchor constant:8.0].active = 91 YES; 92 [_callButton.bottomAnchor constraintEqualToAnchor:margin.bottomAnchor constant:8.0].active = YES; 93 [_callButton.widthAnchor constraintEqualToConstant:100].active = YES; 94 [_callButton.heightAnchor constraintEqualToConstant:40].active = YES; 95 96 [_hangUpButton.trailingAnchor constraintEqualToAnchor:margin.trailingAnchor constant:8.0].active = 97 YES; 98 [_hangUpButton.bottomAnchor constraintEqualToAnchor:margin.bottomAnchor constant:8.0].active = 99 YES; 100 [_hangUpButton.widthAnchor constraintEqualToConstant:100].active = YES; 101 [_hangUpButton.heightAnchor constraintEqualToConstant:40].active = YES; 102 103 self.view = _view; 104} 105 106- (void)viewDidLoad { 107 [super viewDidLoad]; 108 109 self.capturer = [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) alloc] init]; 110 self.localVideoView.captureSession = self.capturer.captureSession; 111 112 _call_client.reset(new webrtc_examples::ObjCCallClient()); 113 114 // Start capturer. 115 AVCaptureDevice *selectedDevice = nil; 116 NSArray<AVCaptureDevice *> *captureDevices = 117 [RTC_OBJC_TYPE(RTCCameraVideoCapturer) captureDevices]; 118 for (AVCaptureDevice *device in captureDevices) { 119 if (device.position == AVCaptureDevicePositionFront) { 120 selectedDevice = device; 121 break; 122 } 123 } 124 125 AVCaptureDeviceFormat *selectedFormat = nil; 126 int targetWidth = 640; 127 int targetHeight = 480; 128 int currentDiff = INT_MAX; 129 NSArray<AVCaptureDeviceFormat *> *formats = 130 [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:selectedDevice]; 131 for (AVCaptureDeviceFormat *format in formats) { 132 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); 133 FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription); 134 int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height); 135 if (diff < currentDiff) { 136 selectedFormat = format; 137 currentDiff = diff; 138 } else if (diff == currentDiff && pixelFormat == [_capturer preferredOutputPixelFormat]) { 139 selectedFormat = format; 140 } 141 } 142 143 [self.capturer startCaptureWithDevice:selectedDevice format:selectedFormat fps:30]; 144} 145 146- (void)didReceiveMemoryWarning { 147 [super didReceiveMemoryWarning]; 148 // Dispose of any resources that can be recreated. 149} 150 151#pragma mark - Actions 152 153- (IBAction)call:(id)sender { 154 _call_client->Call(self.capturer, self.remoteVideoView); 155} 156 157- (IBAction)hangUp:(id)sender { 158 _call_client->Hangup(); 159} 160 161@end 162