Add an example app for iOS native API.

Demonstrates how to use the iOS native API to wrap components into
C++ classes.

This CL also introduces a native API wrapper for the capturer.

The C++ code is forked from the corresponding CL for Android at
https://webrtc-review.googlesource.com/c/src/+/60540

Bug: webrtc:8832
Change-Id: I12d9f30e701c0222628e329218f6d5bfca26e6e0
Reviewed-on: https://webrtc-review.googlesource.com/61422
Commit-Queue: Anders Carlsson <andersc@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22484}
diff --git a/examples/objcnativeapi/objc/NADViewController.mm b/examples/objcnativeapi/objc/NADViewController.mm
new file mode 100644
index 0000000..0d5ac9a
--- /dev/null
+++ b/examples/objcnativeapi/objc/NADViewController.mm
@@ -0,0 +1,157 @@
+/*
+ *  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 <WebRTC/RTCCameraPreviewView.h>
+#import <WebRTC/RTCCameraVideoCapturer.h>
+#import <WebRTC/RTCEAGLVideoView.h>
+#import <WebRTC/RTCMTLVideoView.h>
+#import <WebRTC/RTCVideoRenderer.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