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