Use 15fps for iPhone 4S

NOTRY=True
BUG=

Review-Url: https://codereview.webrtc.org/2188883002
Cr-Commit-Position: refs/heads/master@{#13564}
diff --git a/webrtc/sdk/objc/Framework/Classes/UIDevice+RTCDevice.mm b/webrtc/sdk/objc/Framework/Classes/UIDevice+RTCDevice.mm
new file mode 100644
index 0000000..523c950
--- /dev/null
+++ b/webrtc/sdk/objc/Framework/Classes/UIDevice+RTCDevice.mm
@@ -0,0 +1,168 @@
+/*
+ *  Copyright 2016 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 "WebRTC/UIDevice+RTCDevice.h"
+
+#include <memory>
+#include <sys/sysctl.h>
+
+@implementation UIDevice (RTCDevice)
+
++ (RTCDeviceType)deviceType {
+  NSDictionary *machineNameToType = @{
+    @"iPhone1,1": @(RTCDeviceTypeIPhone1G),
+    @"iPhone1,2": @(RTCDeviceTypeIPhone3G),
+    @"iPhone2,1": @(RTCDeviceTypeIPhone3GS),
+    @"iPhone3,1": @(RTCDeviceTypeIPhone4),
+    @"iPhone3,3": @(RTCDeviceTypeIPhone4Verizon),
+    @"iPhone4,1": @(RTCDeviceTypeIPhone4S),
+    @"iPhone5,1": @(RTCDeviceTypeIPhone5GSM),
+    @"iPhone5,2": @(RTCDeviceTypeIPhone5GSM_CDMA),
+    @"iPhone5,3": @(RTCDeviceTypeIPhone5CGSM),
+    @"iPhone5,4": @(RTCDeviceTypeIPhone5CGSM_CDMA),
+    @"iPhone6,1": @(RTCDeviceTypeIPhone5SGSM),
+    @"iPhone6,2": @(RTCDeviceTypeIPhone5SGSM_CDMA),
+    @"iPhone7,1": @(RTCDeviceTypeIPhone6Plus),
+    @"iPhone7,2": @(RTCDeviceTypeIPhone6),
+    @"iPhone8,1": @(RTCDeviceTypeIPhone6S),
+    @"iPhone8,2": @(RTCDeviceTypeIPhone6SPlus),
+    @"iPod1,1": @(RTCDeviceTypeIPodTouch1G),
+    @"iPod2,1": @(RTCDeviceTypeIPodTouch2G),
+    @"iPod3,1": @(RTCDeviceTypeIPodTouch3G),
+    @"iPod4,1": @(RTCDeviceTypeIPodTouch4G),
+    @"iPod5,1": @(RTCDeviceTypeIPodTouch5G),
+    @"iPad1,1": @(RTCDeviceTypeIPad),
+    @"iPad2,1": @(RTCDeviceTypeIPad2Wifi),
+    @"iPad2,2": @(RTCDeviceTypeIPad2GSM),
+    @"iPad2,3": @(RTCDeviceTypeIPad2CDMA),
+    @"iPad2,4": @(RTCDeviceTypeIPad2Wifi2),
+    @"iPad2,5": @(RTCDeviceTypeIPadMiniWifi),
+    @"iPad2,6": @(RTCDeviceTypeIPadMiniGSM),
+    @"iPad2,7": @(RTCDeviceTypeIPadMiniGSM_CDMA),
+    @"iPad3,1": @(RTCDeviceTypeIPad3Wifi),
+    @"iPad3,2": @(RTCDeviceTypeIPad3GSM_CDMA),
+    @"iPad3,3": @(RTCDeviceTypeIPad3GSM),
+    @"iPad3,4": @(RTCDeviceTypeIPad4Wifi),
+    @"iPad3,5": @(RTCDeviceTypeIPad4GSM),
+    @"iPad3,6": @(RTCDeviceTypeIPad4GSM_CDMA),
+    @"iPad4,1": @(RTCDeviceTypeIPadAirWifi),
+    @"iPad4,2": @(RTCDeviceTypeIPadAirCellular),
+    @"iPad4,4": @(RTCDeviceTypeIPadMini2GWifi),
+    @"iPad4,5": @(RTCDeviceTypeIPadMini2GCellular),
+    @"i386": @(RTCDeviceTypeSimulatori386),
+    @"x86_64": @(RTCDeviceTypeSimulatorx86_64),
+  };
+
+  size_t size = 0;
+  sysctlbyname("hw.machine", NULL, &size, NULL, 0);
+  std::unique_ptr<char[]> machine;
+  machine.reset(new char[size]);
+  sysctlbyname("hw.machine", machine.get(), &size, NULL, 0);
+  NSString *machineName = [[NSString alloc] initWithCString:machine.get()
+                                                   encoding:NSUTF8StringEncoding];
+  RTCDeviceType deviceType = RTCDeviceTypeUnknown;
+  NSNumber *typeNumber = machineNameToType[machineName];
+  if (typeNumber) {
+    deviceType = static_cast<RTCDeviceType>(typeNumber.integerValue);
+  }
+  return deviceType;
+}
+
++ (NSString *)stringForDeviceType:(RTCDeviceType)deviceType {
+  switch (deviceType) {
+    case RTCDeviceTypeUnknown:
+      return @"Unknown";
+    case RTCDeviceTypeIPhone1G:
+      return @"iPhone 1G";
+    case RTCDeviceTypeIPhone3G:
+      return @"iPhone 3G";
+    case RTCDeviceTypeIPhone3GS:
+      return @"iPhone 3GS";
+    case RTCDeviceTypeIPhone4:
+      return @"iPhone 4";
+    case RTCDeviceTypeIPhone4Verizon:
+      return @"iPhone 4 Verizon";
+    case RTCDeviceTypeIPhone4S:
+      return @"iPhone 4S";
+    case RTCDeviceTypeIPhone5GSM:
+      return @"iPhone 5 (GSM)";
+    case RTCDeviceTypeIPhone5GSM_CDMA:
+      return @"iPhone 5 (GSM+CDMA)";
+    case RTCDeviceTypeIPhone5CGSM:
+      return @"iPhone 5C (GSM)";
+    case RTCDeviceTypeIPhone5CGSM_CDMA:
+      return @"iPhone 5C (GSM+CDMA)";
+    case RTCDeviceTypeIPhone5SGSM:
+      return @"iPhone 5S (GSM)";
+    case RTCDeviceTypeIPhone5SGSM_CDMA:
+      return @"iPhone 5S (GSM+CDMA)";
+    case RTCDeviceTypeIPhone6Plus:
+      return @"iPhone 6 Plus";
+    case RTCDeviceTypeIPhone6:
+      return @"iPhone 6";
+    case RTCDeviceTypeIPhone6S:
+      return @"iPhone 6S";
+    case RTCDeviceTypeIPhone6SPlus:
+      return @"iPhone 6S Plus";
+    case RTCDeviceTypeIPodTouch1G:
+      return @"iPod Touch 1G";
+    case RTCDeviceTypeIPodTouch2G:
+      return @"iPod Touch 2G";
+    case RTCDeviceTypeIPodTouch3G:
+      return @"iPod Touch 3G";
+    case RTCDeviceTypeIPodTouch4G:
+      return @"iPod Touch 4G";
+    case RTCDeviceTypeIPodTouch5G:
+      return @"iPod Touch 5G";
+    case RTCDeviceTypeIPad:
+      return @"iPad";
+    case RTCDeviceTypeIPad2Wifi:
+      return @"iPad 2 (WiFi)";
+    case RTCDeviceTypeIPad2GSM:
+      return @"iPad 2 (GSM)";
+    case RTCDeviceTypeIPad2CDMA:
+      return @"iPad 2 (CDMA)";
+    case RTCDeviceTypeIPad2Wifi2:
+      return @"iPad 2 (WiFi) 2";
+    case RTCDeviceTypeIPadMiniWifi:
+      return @"iPad Mini (WiFi)";
+    case RTCDeviceTypeIPadMiniGSM:
+      return @"iPad Mini (GSM)";
+    case RTCDeviceTypeIPadMiniGSM_CDMA:
+      return @"iPad Mini (GSM+CDMA)";
+    case RTCDeviceTypeIPad3Wifi:
+      return @"iPad 3 (WiFi)";
+    case RTCDeviceTypeIPad3GSM_CDMA:
+      return @"iPad 3 (GSM+CDMA)";
+    case RTCDeviceTypeIPad3GSM:
+      return @"iPad 3 (GSM)";
+    case RTCDeviceTypeIPad4Wifi:
+      return @"iPad 4 (WiFi)";
+    case RTCDeviceTypeIPad4GSM:
+      return @"iPad 4 (GSM)";
+    case RTCDeviceTypeIPad4GSM_CDMA:
+      return @"iPad 4 (GSM+CDMA)";
+    case RTCDeviceTypeIPadAirWifi:
+      return @"iPad Air (WiFi)";
+    case RTCDeviceTypeIPadAirCellular:
+      return @"iPad Air (Cellular)";
+    case RTCDeviceTypeIPadMini2GWifi:
+      return @"iPad Mini 2G (Wifi)";
+    case RTCDeviceTypeIPadMini2GCellular:
+      return @"iPad Mini 2G (Cellular)";
+    case RTCDeviceTypeSimulatori386:
+      return @"i386 Simulator";
+    case RTCDeviceTypeSimulatorx86_64:
+      return @"x86_64 Simulator";
+  }
+  return @"Unknown";
+}
+
+@end
diff --git a/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm b/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
index 9b1a783..810bc62 100644
--- a/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
+++ b/webrtc/sdk/objc/Framework/Classes/avfoundationvideocapturer.mm
@@ -18,6 +18,9 @@
 
 #import "RTCDispatcher+Private.h"
 #import "WebRTC/RTCLogging.h"
+#if TARGET_OS_IPHONE
+#import "WebRTC/UIDevice+RTCDevice.h"
+#endif
 
 #include "webrtc/base/bind.h"
 #include "webrtc/base/checks.h"
@@ -31,6 +34,12 @@
                          480,
                          cricket::VideoFormat::FpsToInterval(30),
                          cricket::FOURCC_NV12);
+// iPhone4S is too slow to handle 30fps.
+static cricket::VideoFormat const kIPhone4SFormat =
+    cricket::VideoFormat(640,
+                         480,
+                         cricket::VideoFormat::FpsToInterval(15),
+                         cricket::FOURCC_NV12);
 
 // This class used to capture frames using AVFoundation APIs on iOS. It is meant
 // to be owned by an instance of AVFoundationVideoCapturer. The reason for this
@@ -383,6 +392,11 @@
   AVCaptureDeviceInput *input = self.useBackCamera ?
       backCameraInput : frontCameraInput;
   [captureSession addInput:input];
+#if TARGET_OS_IPHONE
+  if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) {
+    [self setMinFrameDuration:CMTimeMake(1, 15) forDevice:input.device];
+  }
+#endif
   _captureSession = captureSession;
   return YES;
 }
@@ -465,6 +479,17 @@
   return _backCameraInput;
 }
 
+- (void)setMinFrameDuration:(CMTime)minFrameDuration
+                  forDevice:(AVCaptureDevice *)device {
+  NSError *error = nil;
+  if (![device lockForConfiguration:&error]) {
+    RTCLogError(@"Failed to lock device for configuration. Error: %@", error.localizedDescription);
+    return;
+  }
+  device.activeVideoMinFrameDuration = minFrameDuration;
+  [device unlockForConfiguration];
+}
+
 // Called from capture session queue.
 - (void)updateOrientation {
   AVCaptureConnection *connection =
@@ -520,6 +545,11 @@
     }
     [self updateOrientation];
     [_captureSession commitConfiguration];
+#if TARGET_OS_IPHONE
+    if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) {
+      [self setMinFrameDuration:CMTimeMake(1, 15) forDevice:newInput.device];
+    }
+#endif
   }];
 }
 
@@ -541,9 +571,17 @@
 AVFoundationVideoCapturer::AVFoundationVideoCapturer()
     : _capturer(nil), _startThread(nullptr) {
   // Set our supported formats. This matches kDefaultPreset.
-  std::vector<cricket::VideoFormat> supportedFormats;
-  supportedFormats.push_back(cricket::VideoFormat(kDefaultFormat));
-  SetSupportedFormats(supportedFormats);
+  std::vector<cricket::VideoFormat> supported_formats;
+#if TARGET_OS_IPHONE
+  if ([UIDevice deviceType] == RTCDeviceTypeIPhone4S) {
+    supported_formats.push_back(cricket::VideoFormat(kIPhone4SFormat));
+  } else {
+    supported_formats.push_back(cricket::VideoFormat(kDefaultFormat));
+  }
+#else
+  supported_formats.push_back(cricket::VideoFormat(kDefaultFormat));
+#endif
+  SetSupportedFormats(supported_formats);
   _capturer =
       [[RTCAVFoundationVideoCapturerInternal alloc] initWithCapturer:this];
 }
@@ -562,7 +600,7 @@
     LOG(LS_ERROR) << "The capturer is already running.";
     return cricket::CaptureState::CS_FAILED;
   }
-  if (format != kDefaultFormat) {
+  if (format != kDefaultFormat && format != kIPhone4SFormat) {
     LOG(LS_ERROR) << "Unsupported format provided.";
     return cricket::CaptureState::CS_FAILED;
   }
diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h
new file mode 100644
index 0000000..d38a3cb
--- /dev/null
+++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h
@@ -0,0 +1,63 @@
+/*
+ *  Copyright 2016 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 <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, RTCDeviceType) {
+  RTCDeviceTypeUnknown,
+  RTCDeviceTypeIPhone1G,
+  RTCDeviceTypeIPhone3G,
+  RTCDeviceTypeIPhone3GS,
+  RTCDeviceTypeIPhone4,
+  RTCDeviceTypeIPhone4Verizon,
+  RTCDeviceTypeIPhone4S,
+  RTCDeviceTypeIPhone5GSM,
+  RTCDeviceTypeIPhone5GSM_CDMA,
+  RTCDeviceTypeIPhone5CGSM,
+  RTCDeviceTypeIPhone5CGSM_CDMA,
+  RTCDeviceTypeIPhone5SGSM,
+  RTCDeviceTypeIPhone5SGSM_CDMA,
+  RTCDeviceTypeIPhone6Plus,
+  RTCDeviceTypeIPhone6,
+  RTCDeviceTypeIPhone6S,
+  RTCDeviceTypeIPhone6SPlus,
+  RTCDeviceTypeIPodTouch1G,
+  RTCDeviceTypeIPodTouch2G,
+  RTCDeviceTypeIPodTouch3G,
+  RTCDeviceTypeIPodTouch4G,
+  RTCDeviceTypeIPodTouch5G,
+  RTCDeviceTypeIPad,
+  RTCDeviceTypeIPad2Wifi,
+  RTCDeviceTypeIPad2GSM,
+  RTCDeviceTypeIPad2CDMA,
+  RTCDeviceTypeIPad2Wifi2,
+  RTCDeviceTypeIPadMiniWifi,
+  RTCDeviceTypeIPadMiniGSM,
+  RTCDeviceTypeIPadMiniGSM_CDMA,
+  RTCDeviceTypeIPad3Wifi,
+  RTCDeviceTypeIPad3GSM_CDMA,
+  RTCDeviceTypeIPad3GSM,
+  RTCDeviceTypeIPad4Wifi,
+  RTCDeviceTypeIPad4GSM,
+  RTCDeviceTypeIPad4GSM_CDMA,
+  RTCDeviceTypeIPadAirWifi,
+  RTCDeviceTypeIPadAirCellular,
+  RTCDeviceTypeIPadMini2GWifi,
+  RTCDeviceTypeIPadMini2GCellular,
+  RTCDeviceTypeSimulatori386,
+  RTCDeviceTypeSimulatorx86_64,
+};
+
+@interface UIDevice (RTCDevice)
+
++ (RTCDeviceType)deviceType;
++ (NSString *)stringForDeviceType:(RTCDeviceType)deviceType;
+
+@end
diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/WebRTC.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/WebRTC.h
index ad23236..27f6152 100644
--- a/webrtc/sdk/objc/Framework/Headers/WebRTC/WebRTC.h
+++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/WebRTC.h
@@ -42,3 +42,4 @@
 #import <WebRTC/RTCVideoRenderer.h>
 #import <WebRTC/RTCVideoSource.h>
 #import <WebRTC/RTCVideoTrack.h>
+#import <WebRTC/UIDevice+RTCDevice.h>