Init max supported H.264 profile at runtime on iOS

Bug: webrtc:9134, webrtc:7992
Change-Id: Id24c570bf3296298901f61ee817a3d7c3f8c6347
Reviewed-on: https://webrtc-review.googlesource.com/71560
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Commit-Queue: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23034}
diff --git a/sdk/objc/Framework/Classes/Common/UIDevice+RTCDevice.mm b/sdk/objc/Framework/Classes/Common/UIDevice+RTCDevice.mm
index b2cfb20..997666d 100644
--- a/sdk/objc/Framework/Classes/Common/UIDevice+RTCDevice.mm
+++ b/sdk/objc/Framework/Classes/Common/UIDevice+RTCDevice.mm
@@ -21,6 +21,7 @@
     @"iPhone1,2": @(RTCDeviceTypeIPhone3G),
     @"iPhone2,1": @(RTCDeviceTypeIPhone3GS),
     @"iPhone3,1": @(RTCDeviceTypeIPhone4),
+    @"iPhone3,2": @(RTCDeviceTypeIPhone4),
     @"iPhone3,3": @(RTCDeviceTypeIPhone4Verizon),
     @"iPhone4,1": @(RTCDeviceTypeIPhone4S),
     @"iPhone5,1": @(RTCDeviceTypeIPhone5GSM),
@@ -33,6 +34,7 @@
     @"iPhone7,2": @(RTCDeviceTypeIPhone6),
     @"iPhone8,1": @(RTCDeviceTypeIPhone6S),
     @"iPhone8,2": @(RTCDeviceTypeIPhone6SPlus),
+    @"iPhone8,4": @(RTCDeviceTypeIPhoneSE),
     @"iPhone9,1": @(RTCDeviceTypeIPhone7),
     @"iPhone9,2": @(RTCDeviceTypeIPhone7Plus),
     @"iPhone9,3": @(RTCDeviceTypeIPhone7),
@@ -48,6 +50,7 @@
     @"iPod3,1": @(RTCDeviceTypeIPodTouch3G),
     @"iPod4,1": @(RTCDeviceTypeIPodTouch4G),
     @"iPod5,1": @(RTCDeviceTypeIPodTouch5G),
+    @"iPod7,1": @(RTCDeviceTypeIPodTouch6G),
     @"iPad1,1": @(RTCDeviceTypeIPad),
     @"iPad2,1": @(RTCDeviceTypeIPad2Wifi),
     @"iPad2,2": @(RTCDeviceTypeIPad2GSM),
@@ -64,8 +67,29 @@
     @"iPad3,6": @(RTCDeviceTypeIPad4GSM_CDMA),
     @"iPad4,1": @(RTCDeviceTypeIPadAirWifi),
     @"iPad4,2": @(RTCDeviceTypeIPadAirCellular),
+    @"iPad4,3": @(RTCDeviceTypeIPadAirWifiCellular),
     @"iPad4,4": @(RTCDeviceTypeIPadMini2GWifi),
     @"iPad4,5": @(RTCDeviceTypeIPadMini2GCellular),
+    @"iPad4,6": @(RTCDeviceTypeIPadMini2GWifiCellular),
+    @"iPad4,7": @(RTCDeviceTypeIPadMini3),
+    @"iPad4,8": @(RTCDeviceTypeIPadMini3),
+    @"iPad4,9": @(RTCDeviceTypeIPadMini3),
+    @"iPad5,1": @(RTCDeviceTypeIPadMini4),
+    @"iPad5,2": @(RTCDeviceTypeIPadMini4),
+    @"iPad5,3": @(RTCDeviceTypeIPadAir2),
+    @"iPad5,4": @(RTCDeviceTypeIPadAir2),
+    @"iPad6,3": @(RTCDeviceTypeIPadPro9Inch),
+    @"iPad6,4": @(RTCDeviceTypeIPadPro9Inch),
+    @"iPad6,7": @(RTCDeviceTypeIPadPro12Inch),
+    @"iPad6,8": @(RTCDeviceTypeIPadPro12Inch),
+    @"iPad6,11": @(RTCDeviceTypeIPad5),
+    @"iPad6,12": @(RTCDeviceTypeIPad5),
+    @"iPad7,1": @(RTCDeviceTypeIPadPro12Inch2),
+    @"iPad7,2": @(RTCDeviceTypeIPadPro12Inch2),
+    @"iPad7,3": @(RTCDeviceTypeIPadPro10Inch),
+    @"iPad7,4": @(RTCDeviceTypeIPadPro10Inch),
+    @"iPad7,5": @(RTCDeviceTypeIPad6),
+    @"iPad7,6": @(RTCDeviceTypeIPad6),
     @"i386": @(RTCDeviceTypeSimulatori386),
     @"x86_64": @(RTCDeviceTypeSimulatorx86_64),
   };
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCDefaultVideoEncoderFactory.m b/sdk/objc/Framework/Classes/PeerConnection/RTCDefaultVideoEncoderFactory.m
index 8de3071..60a0b5f 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCDefaultVideoEncoderFactory.m
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCDefaultVideoEncoderFactory.m
@@ -25,7 +25,7 @@
 
 + (NSArray<RTCVideoCodecInfo *> *)supportedCodecs {
   NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
-    @"profile-level-id" : kRTCLevel31ConstrainedHigh,
+    @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh,
     @"level-asymmetry-allowed" : @"1",
     @"packetization-mode" : @"1",
   };
@@ -34,7 +34,7 @@
                                    parameters:constrainedHighParams];
 
   NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
-    @"profile-level-id" : kRTCLevel31ConstrainedBaseline,
+    @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline,
     @"level-asymmetry-allowed" : @"1",
     @"packetization-mode" : @"1",
   };
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm
index 4a5d450..fc2c1ce 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm
@@ -12,15 +12,70 @@
 
 #import "NSString+StdString.h"
 #import "RTCVideoCodec+Private.h"
+#if defined(WEBRTC_IOS)
+#import "UIDevice+H264Profile.h"
+#endif
 #import "WebRTC/RTCVideoCodecFactory.h"
 
 #include "media/base/mediaconstants.h"
 
+namespace {
+
+NSString *MaxSupportedProfileLevelConstrainedHigh();
+NSString *MaxSupportedProfileLevelConstrainedBaseline();
+
+}  // namespace
+
 NSString *const kRTCVideoCodecVp8Name = @(cricket::kVp8CodecName);
 NSString *const kRTCVideoCodecVp9Name = @(cricket::kVp9CodecName);
 NSString *const kRTCVideoCodecH264Name = @(cricket::kH264CodecName);
 NSString *const kRTCLevel31ConstrainedHigh = @"640c1f";
 NSString *const kRTCLevel31ConstrainedBaseline = @"42e01f";
+NSString *const kRTCMaxSupportedH264ProfileLevelConstrainedHigh =
+    MaxSupportedProfileLevelConstrainedHigh();
+NSString *const kRTCMaxSupportedH264ProfileLevelConstrainedBaseline =
+    MaxSupportedProfileLevelConstrainedBaseline();
+
+namespace {
+
+#if defined(WEBRTC_IOS)
+
+using namespace webrtc::H264;
+
+NSString *MaxSupportedLevelForProfile(Profile profile) {
+  const rtc::Optional<ProfileLevelId> profileLevelId = [UIDevice maxSupportedH264Profile];
+  if (profileLevelId && profileLevelId->profile >= profile) {
+    const rtc::Optional<std::string> profileString =
+        ProfileLevelIdToString(ProfileLevelId(profile, profileLevelId->level));
+    if (profileString) {
+      return [NSString stringForStdString:*profileString];
+    }
+  }
+  return nil;
+}
+#endif
+
+NSString *MaxSupportedProfileLevelConstrainedBaseline() {
+#if defined(WEBRTC_IOS)
+  NSString *profile = MaxSupportedLevelForProfile(webrtc::H264::kProfileConstrainedBaseline);
+  if (profile != nil) {
+    return profile;
+  }
+#endif
+  return kRTCLevel31ConstrainedBaseline;
+}
+
+NSString *MaxSupportedProfileLevelConstrainedHigh() {
+#if defined(WEBRTC_IOS)
+  NSString *profile = MaxSupportedLevelForProfile(webrtc::H264::kProfileConstrainedHigh);
+  if (profile != nil) {
+    return profile;
+  }
+#endif
+  return kRTCLevel31ConstrainedHigh;
+}
+
+}  // namespace
 
 @implementation RTCVideoCodecInfo
 
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm
index 402e09f..5477791 100644
--- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm
@@ -50,7 +50,7 @@
 
   if (IsHighProfileEnabled()) {
     NSDictionary<NSString *, NSString *> *constrainedHighParams = @{
-      @"profile-level-id" : kRTCLevel31ConstrainedHigh,
+      @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh,
       @"level-asymmetry-allowed" : @"1",
       @"packetization-mode" : @"1",
     };
@@ -60,7 +60,7 @@
   }
 
   NSDictionary<NSString *, NSString *> *constrainedBaselineParams = @{
-    @"profile-level-id" : kRTCLevel31ConstrainedBaseline,
+    @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedBaseline,
     @"level-asymmetry-allowed" : @"1",
     @"packetization-mode" : @"1",
   };
diff --git a/sdk/objc/Framework/Classes/Video/UIDevice+H264Profile.h b/sdk/objc/Framework/Classes/Video/UIDevice+H264Profile.h
new file mode 100644
index 0000000..03ea780
--- /dev/null
+++ b/sdk/objc/Framework/Classes/Video/UIDevice+H264Profile.h
@@ -0,0 +1,19 @@
+/*
+ *  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 <UIKit/UIKit.h>
+
+#include "media/base/h264_profile_level_id.h"
+
+@interface UIDevice (H264Profile)
+
++ (rtc::Optional<webrtc::H264::ProfileLevelId>)maxSupportedH264Profile;
+
+@end
diff --git a/sdk/objc/Framework/Classes/Video/UIDevice+H264Profile.mm b/sdk/objc/Framework/Classes/Video/UIDevice+H264Profile.mm
new file mode 100644
index 0000000..41123a5
--- /dev/null
+++ b/sdk/objc/Framework/Classes/Video/UIDevice+H264Profile.mm
@@ -0,0 +1,108 @@
+/*
+ *  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 "UIDevice+H264Profile.h"
+#import "WebRTC/UIDevice+RTCDevice.h"
+
+#include <algorithm>
+
+namespace {
+
+using namespace webrtc::H264;
+
+struct SupportedH264Profile {
+  const RTCDeviceType deviceType;
+  const ProfileLevelId profile;
+};
+
+const SupportedH264Profile kH264MaxSupportedProfiles[] = {
+    // iPhones with at least iOS 9
+    {RTCDeviceTypeIPhoneX, {kProfileHigh, kLevel5_2}},       // https://support.apple.com/kb/SP770
+    {RTCDeviceTypeIPhone8, {kProfileHigh, kLevel5_2}},       // https://support.apple.com/kb/SP767
+    {RTCDeviceTypeIPhone8Plus, {kProfileHigh, kLevel5_2}},   // https://support.apple.com/kb/SP768
+    {RTCDeviceTypeIPhone7, {kProfileHigh, kLevel5_1}},       // https://support.apple.com/kb/SP743
+    {RTCDeviceTypeIPhone7Plus, {kProfileHigh, kLevel5_1}},   // https://support.apple.com/kb/SP744
+    {RTCDeviceTypeIPhoneSE, {kProfileHigh, kLevel4_2}},      // https://support.apple.com/kb/SP738
+    {RTCDeviceTypeIPhone6S, {kProfileHigh, kLevel4_2}},      // https://support.apple.com/kb/SP726
+    {RTCDeviceTypeIPhone6SPlus, {kProfileHigh, kLevel4_2}},  // https://support.apple.com/kb/SP727
+    {RTCDeviceTypeIPhone6, {kProfileHigh, kLevel4_2}},       // https://support.apple.com/kb/SP705
+    {RTCDeviceTypeIPhone6Plus, {kProfileHigh, kLevel4_2}},   // https://support.apple.com/kb/SP706
+    {RTCDeviceTypeIPhone5SGSM, {kProfileHigh, kLevel4_2}},   // https://support.apple.com/kb/SP685
+    {RTCDeviceTypeIPhone5SGSM_CDMA,
+     {kProfileHigh, kLevel4_2}},                           // https://support.apple.com/kb/SP685
+    {RTCDeviceTypeIPhone5GSM, {kProfileHigh, kLevel4_1}},  // https://support.apple.com/kb/SP655
+    {RTCDeviceTypeIPhone5GSM_CDMA,
+     {kProfileHigh, kLevel4_1}},                            // https://support.apple.com/kb/SP655
+    {RTCDeviceTypeIPhone5CGSM, {kProfileHigh, kLevel4_1}},  // https://support.apple.com/kb/SP684
+    {RTCDeviceTypeIPhone5CGSM_CDMA,
+     {kProfileHigh, kLevel4_1}},                         // https://support.apple.com/kb/SP684
+    {RTCDeviceTypeIPhone4S, {kProfileHigh, kLevel4_1}},  // https://support.apple.com/kb/SP643
+
+    // iPods with at least iOS 9
+    {RTCDeviceTypeIPodTouch6G, {kProfileMain, kLevel4_1}},  // https://support.apple.com/kb/SP720
+    {RTCDeviceTypeIPodTouch5G, {kProfileMain, kLevel3_1}},  // https://support.apple.com/kb/SP657
+
+    // iPads with at least iOS 9
+    {RTCDeviceTypeIPad2Wifi, {kProfileHigh, kLevel4_1}},     // https://support.apple.com/kb/SP622
+    {RTCDeviceTypeIPad2GSM, {kProfileHigh, kLevel4_1}},      // https://support.apple.com/kb/SP622
+    {RTCDeviceTypeIPad2CDMA, {kProfileHigh, kLevel4_1}},     // https://support.apple.com/kb/SP622
+    {RTCDeviceTypeIPad2Wifi2, {kProfileHigh, kLevel4_1}},    // https://support.apple.com/kb/SP622
+    {RTCDeviceTypeIPadMiniWifi, {kProfileHigh, kLevel4_1}},  // https://support.apple.com/kb/SP661
+    {RTCDeviceTypeIPadMiniGSM, {kProfileHigh, kLevel4_1}},   // https://support.apple.com/kb/SP661
+    {RTCDeviceTypeIPadMiniGSM_CDMA,
+     {kProfileHigh, kLevel4_1}},                              // https://support.apple.com/kb/SP661
+    {RTCDeviceTypeIPad3Wifi, {kProfileHigh, kLevel4_1}},      // https://support.apple.com/kb/SP647
+    {RTCDeviceTypeIPad3GSM_CDMA, {kProfileHigh, kLevel4_1}},  // https://support.apple.com/kb/SP647
+    {RTCDeviceTypeIPad3GSM, {kProfileHigh, kLevel4_1}},       // https://support.apple.com/kb/SP647
+    {RTCDeviceTypeIPad4Wifi, {kProfileHigh, kLevel4_1}},      // https://support.apple.com/kb/SP662
+    {RTCDeviceTypeIPad4GSM, {kProfileHigh, kLevel4_1}},       // https://support.apple.com/kb/SP662
+    {RTCDeviceTypeIPad4GSM_CDMA, {kProfileHigh, kLevel4_1}},  // https://support.apple.com/kb/SP662
+    {RTCDeviceTypeIPad5, {kProfileHigh, kLevel4_2}},          // https://support.apple.com/kb/SP751
+    {RTCDeviceTypeIPad6, {kProfileHigh, kLevel4_2}},          // https://support.apple.com/kb/SP774
+    {RTCDeviceTypeIPadAirWifi, {kProfileHigh, kLevel4_2}},    // https://support.apple.com/kb/SP692
+    {RTCDeviceTypeIPadAirCellular,
+     {kProfileHigh, kLevel4_2}},  // https://support.apple.com/kb/SP692
+    {RTCDeviceTypeIPadAirWifiCellular,
+     {kProfileHigh, kLevel4_2}},                               // https://support.apple.com/kb/SP692
+    {RTCDeviceTypeIPadAir2, {kProfileHigh, kLevel4_2}},        // https://support.apple.com/kb/SP708
+    {RTCDeviceTypeIPadMini2GWifi, {kProfileHigh, kLevel4_2}},  // https://support.apple.com/kb/SP693
+    {RTCDeviceTypeIPadMini2GCellular,
+     {kProfileHigh, kLevel4_2}},  // https://support.apple.com/kb/SP693
+    {RTCDeviceTypeIPadMini2GWifiCellular,
+     {kProfileHigh, kLevel4_2}},                               // https://support.apple.com/kb/SP693
+    {RTCDeviceTypeIPadMini3, {kProfileHigh, kLevel4_2}},       // https://support.apple.com/kb/SP709
+    {RTCDeviceTypeIPadMini4, {kProfileHigh, kLevel4_2}},       // https://support.apple.com/kb/SP725
+    {RTCDeviceTypeIPadPro9Inch, {kProfileHigh, kLevel4_2}},    // https://support.apple.com/kb/SP739
+    {RTCDeviceTypeIPadPro12Inch, {kProfileHigh, kLevel4_2}},   // https://support.apple.com/kb/sp723
+    {RTCDeviceTypeIPadPro12Inch2, {kProfileHigh, kLevel4_2}},  // https://support.apple.com/kb/SP761
+    {RTCDeviceTypeIPadPro10Inch, {kProfileHigh, kLevel4_2}},   // https://support.apple.com/kb/SP762
+};
+
+rtc::Optional<ProfileLevelId> FindMaxSupportedProfileForDevice(RTCDeviceType deviceType) {
+  const auto* result = std::find_if(std::begin(kH264MaxSupportedProfiles),
+                                    std::end(kH264MaxSupportedProfiles),
+                                    [deviceType](const SupportedH264Profile& supportedProfile) {
+                                      return supportedProfile.deviceType == deviceType;
+                                    });
+  if (result != std::end(kH264MaxSupportedProfiles)) {
+    return result->profile;
+  }
+  return rtc::nullopt;
+}
+
+}  // namespace
+
+@implementation UIDevice (H264Profile)
+
++ (rtc::Optional<webrtc::H264::ProfileLevelId>)maxSupportedH264Profile {
+  return FindMaxSupportedProfileForDevice([self deviceType]);
+}
+
+@end