iOS camera switching video capturer.

Introduces a new capture class derived from cricket::VideoCapturer that
provides the ability to switch cameras and updates AppRTCDemo to use it.
Some future work pending to clean up AppRTCDemo UI.

BUG=4070
R=magjed@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/48279005

Cr-Commit-Position: refs/heads/master@{#9137}
diff --git a/talk/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m b/talk/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
index af4aaff..b12a61a 100644
--- a/talk/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
+++ b/talk/examples/objc/AppRTCDemo/ios/ARDVideoCallViewController.m
@@ -27,11 +27,15 @@
 
 #import "ARDVideoCallViewController.h"
 
+#import "RTCAVFoundationVideoSource.h"
+
 #import "ARDAppClient.h"
 #import "ARDVideoCallView.h"
 
 @interface ARDVideoCallViewController () <ARDAppClientDelegate,
     ARDVideoCallViewDelegate>
+@property(nonatomic, strong) RTCVideoTrack *localVideoTrack;
+@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
 @property(nonatomic, readonly) ARDVideoCallView *videoCallView;
 @end
 
@@ -90,19 +94,13 @@
 
 - (void)appClient:(ARDAppClient *)client
     didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
-  if (!_localVideoTrack) {
-    _localVideoTrack = localVideoTrack;
-    [_localVideoTrack addRenderer:_videoCallView.localVideoView];
-  }
+  self.localVideoTrack = localVideoTrack;
 }
 
 - (void)appClient:(ARDAppClient *)client
     didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
-  if (!_remoteVideoTrack) {
-    _remoteVideoTrack = remoteVideoTrack;
-    [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
-    _videoCallView.statusLabel.hidden = YES;
-  }
+  self.remoteVideoTrack = remoteVideoTrack;
+  _videoCallView.statusLabel.hidden = YES;
 }
 
 - (void)appClient:(ARDAppClient *)client
@@ -119,24 +117,54 @@
   [self hangup];
 }
 
+- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
+  // TODO(tkchin): Rate limit this so you can't tap continously on it.
+  // Probably through an animation.
+  [self switchCamera];
+}
+
 #pragma mark - Private
 
+- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
+  if (_localVideoTrack == localVideoTrack) {
+    return;
+  }
+  [_localVideoTrack removeRenderer:_videoCallView.localVideoView];
+  _localVideoTrack = nil;
+  [_videoCallView.localVideoView renderFrame:nil];
+  _localVideoTrack = localVideoTrack;
+  [_localVideoTrack addRenderer:_videoCallView.localVideoView];
+}
+
+- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
+  if (_remoteVideoTrack == remoteVideoTrack) {
+    return;
+  }
+  [_remoteVideoTrack removeRenderer:_videoCallView.localVideoView];
+  _remoteVideoTrack = nil;
+  [_videoCallView.remoteVideoView renderFrame:nil];
+  _remoteVideoTrack = remoteVideoTrack;
+  [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
+}
+
 - (void)hangup {
-  if (_remoteVideoTrack) {
-    [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
-    _remoteVideoTrack = nil;
-    [_videoCallView.remoteVideoView renderFrame:nil];
-  }
-  if (_localVideoTrack) {
-    [_localVideoTrack removeRenderer:_videoCallView.localVideoView];
-    _localVideoTrack = nil;
-    [_videoCallView.localVideoView renderFrame:nil];
-  }
+  self.remoteVideoTrack = nil;
+  self.localVideoTrack = nil;
   [_client disconnect];
   [self.presentingViewController dismissViewControllerAnimated:YES
                                                     completion:nil];
 }
 
+- (void)switchCamera {
+  RTCVideoSource* source = self.localVideoTrack.source;
+  if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
+    RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
+    avSource.useBackCamera = !avSource.useBackCamera;
+    _videoCallView.localVideoView.transform = avSource.useBackCamera ?
+        CGAffineTransformIdentity : CGAffineTransformMakeScale(-1, 1);
+  }
+}
+
 - (NSString *)statusTextForState:(RTCICEConnectionState)state {
   switch (state) {
     case RTCICEConnectionNew: