| /* |
| * Copyright 2018 The WebRTC Project Authors. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #import "NADViewController.h" |
| |
| #import "sdk/objc/base/RTCVideoRenderer.h" |
| #import "sdk/objc/components/capturer/RTCCameraVideoCapturer.h" |
| #if defined(RTC_SUPPORTS_METAL) |
| #import "sdk/objc/components/renderer/metal/RTCMTLVideoView.h" // nogncheck |
| #endif |
| #import "sdk/objc/components/renderer/opengl/RTCEAGLVideoView.h" |
| #import "sdk/objc/helpers/RTCCameraPreviewView.h" |
| |
| #include <memory> |
| |
| #include "objccallclient.h" |
| |
| @interface NADViewController () |
| |
| @property(nonatomic) RTCCameraVideoCapturer *capturer; |
| @property(nonatomic) RTCCameraPreviewView *localVideoView; |
| @property(nonatomic) __kindof UIView<RTCVideoRenderer> *remoteVideoView; |
| @property(nonatomic) UIButton *callButton; |
| @property(nonatomic) UIButton *hangUpButton; |
| |
| @end |
| |
| @implementation NADViewController { |
| std::unique_ptr<webrtc_examples::ObjCCallClient> _call_client; |
| |
| UIView *_view; |
| } |
| |
| @synthesize capturer = _capturer; |
| @synthesize localVideoView = _localVideoView; |
| @synthesize remoteVideoView = _remoteVideoView; |
| @synthesize callButton = _callButton; |
| @synthesize hangUpButton = _hangUpButton; |
| |
| #pragma mark - View controller lifecycle |
| |
| - (void)loadView { |
| _view = [[UIView alloc] initWithFrame:CGRectZero]; |
| |
| #if defined(RTC_SUPPORTS_METAL) |
| _remoteVideoView = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero]; |
| #else |
| _remoteVideoView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectZero]; |
| #endif |
| _remoteVideoView.translatesAutoresizingMaskIntoConstraints = NO; |
| [_view addSubview:_remoteVideoView]; |
| |
| _localVideoView = [[RTCCameraPreviewView alloc] initWithFrame:CGRectZero]; |
| _localVideoView.translatesAutoresizingMaskIntoConstraints = NO; |
| [_view addSubview:_localVideoView]; |
| |
| _callButton = [UIButton buttonWithType:UIButtonTypeSystem]; |
| _callButton.translatesAutoresizingMaskIntoConstraints = NO; |
| [_callButton setTitle:@"Call" forState:UIControlStateNormal]; |
| [_callButton addTarget:self action:@selector(call:) forControlEvents:UIControlEventTouchUpInside]; |
| [_view addSubview:_callButton]; |
| |
| _hangUpButton = [UIButton buttonWithType:UIButtonTypeSystem]; |
| _hangUpButton.translatesAutoresizingMaskIntoConstraints = NO; |
| [_hangUpButton setTitle:@"Hang up" forState:UIControlStateNormal]; |
| [_hangUpButton addTarget:self |
| action:@selector(hangUp:) |
| forControlEvents:UIControlEventTouchUpInside]; |
| [_view addSubview:_hangUpButton]; |
| |
| UILayoutGuide *margin = _view.layoutMarginsGuide; |
| [_remoteVideoView.leadingAnchor constraintEqualToAnchor:margin.leadingAnchor].active = YES; |
| [_remoteVideoView.topAnchor constraintEqualToAnchor:margin.topAnchor].active = YES; |
| [_remoteVideoView.trailingAnchor constraintEqualToAnchor:margin.trailingAnchor].active = YES; |
| [_remoteVideoView.bottomAnchor constraintEqualToAnchor:margin.bottomAnchor].active = YES; |
| |
| [_localVideoView.leadingAnchor constraintEqualToAnchor:margin.leadingAnchor constant:8.0].active = |
| YES; |
| [_localVideoView.topAnchor constraintEqualToAnchor:margin.topAnchor constant:8.0].active = YES; |
| [_localVideoView.widthAnchor constraintEqualToConstant:60].active = YES; |
| [_localVideoView.heightAnchor constraintEqualToConstant:60].active = YES; |
| |
| [_callButton.leadingAnchor constraintEqualToAnchor:margin.leadingAnchor constant:8.0].active = |
| YES; |
| [_callButton.bottomAnchor constraintEqualToAnchor:margin.bottomAnchor constant:8.0].active = YES; |
| [_callButton.widthAnchor constraintEqualToConstant:100].active = YES; |
| [_callButton.heightAnchor constraintEqualToConstant:40].active = YES; |
| |
| [_hangUpButton.trailingAnchor constraintEqualToAnchor:margin.trailingAnchor constant:8.0].active = |
| YES; |
| [_hangUpButton.bottomAnchor constraintEqualToAnchor:margin.bottomAnchor constant:8.0].active = |
| YES; |
| [_hangUpButton.widthAnchor constraintEqualToConstant:100].active = YES; |
| [_hangUpButton.heightAnchor constraintEqualToConstant:40].active = YES; |
| |
| self.view = _view; |
| } |
| |
| - (void)viewDidLoad { |
| [super viewDidLoad]; |
| |
| self.capturer = [[RTCCameraVideoCapturer alloc] init]; |
| self.localVideoView.captureSession = self.capturer.captureSession; |
| |
| _call_client.reset(new webrtc_examples::ObjCCallClient()); |
| |
| // Start capturer. |
| AVCaptureDevice *selectedDevice = nil; |
| NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices]; |
| for (AVCaptureDevice *device in captureDevices) { |
| if (device.position == AVCaptureDevicePositionFront) { |
| selectedDevice = device; |
| break; |
| } |
| } |
| |
| AVCaptureDeviceFormat *selectedFormat = nil; |
| int targetWidth = 640; |
| int targetHeight = 480; |
| int currentDiff = INT_MAX; |
| NSArray<AVCaptureDeviceFormat *> *formats = |
| [RTCCameraVideoCapturer supportedFormatsForDevice:selectedDevice]; |
| for (AVCaptureDeviceFormat *format in formats) { |
| CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); |
| FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription); |
| int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height); |
| if (diff < currentDiff) { |
| selectedFormat = format; |
| currentDiff = diff; |
| } else if (diff == currentDiff && pixelFormat == [_capturer preferredOutputPixelFormat]) { |
| selectedFormat = format; |
| } |
| } |
| |
| [self.capturer startCaptureWithDevice:selectedDevice format:selectedFormat fps:30]; |
| } |
| |
| - (void)didReceiveMemoryWarning { |
| [super didReceiveMemoryWarning]; |
| // Dispose of any resources that can be recreated. |
| } |
| |
| #pragma mark - Actions |
| |
| - (IBAction)call:(id)sender { |
| _call_client->Call(self.capturer, self.remoteVideoView); |
| } |
| |
| - (IBAction)hangUp:(id)sender { |
| _call_client->Hangup(); |
| } |
| |
| @end |