diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index ec69c82520..8f8027e23c 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -372,6 +372,12 @@ if (is_ios || is_mac) { "objc/Framework/Headers/WebRTC/RTCVideoCodecFactory.h", "objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h", ] + if (is_ios) { + sources += [ + "objc/Framework/Classes/Video/UIDevice+H264Profile.h", + "objc/Framework/Classes/Video/UIDevice+H264Profile.mm", + ] + } if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin # (bugs.webrtc.org/163). @@ -382,6 +388,7 @@ if (is_ios || is_mac) { ":common_objc", "../api/video_codecs:video_codecs_api", "../common_video", + "../media:rtc_h264_profile_id", "../media:rtc_media_base", "../modules:module_api", "../modules/video_coding:video_codec_interface", diff --git a/sdk/objc/Framework/Classes/Common/UIDevice+RTCDevice.mm b/sdk/objc/Framework/Classes/Common/UIDevice+RTCDevice.mm index b2cfb2094b..997666d503 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 8de3071b1e..60a0b5f00f 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCDefaultVideoEncoderFactory.m +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCDefaultVideoEncoderFactory.m @@ -25,7 +25,7 @@ + (NSArray *)supportedCodecs { NSDictionary *constrainedHighParams = @{ - @"profile-level-id" : kRTCLevel31ConstrainedHigh, + @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh, @"level-asymmetry-allowed" : @"1", @"packetization-mode" : @"1", }; @@ -34,7 +34,7 @@ parameters:constrainedHighParams]; NSDictionary *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 4a5d45062a..fc2c1cea14 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 = [UIDevice maxSupportedH264Profile]; + if (profileLevelId && profileLevelId->profile >= profile) { + const rtc::Optional 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 402e09fb7e..5477791e04 100644 --- a/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm +++ b/sdk/objc/Framework/Classes/PeerConnection/RTCVideoCodecH264.mm @@ -50,7 +50,7 @@ bool IsHighProfileEnabled() { if (IsHighProfileEnabled()) { NSDictionary *constrainedHighParams = @{ - @"profile-level-id" : kRTCLevel31ConstrainedHigh, + @"profile-level-id" : kRTCMaxSupportedH264ProfileLevelConstrainedHigh, @"level-asymmetry-allowed" : @"1", @"packetization-mode" : @"1", }; @@ -60,7 +60,7 @@ bool IsHighProfileEnabled() { } NSDictionary *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 0000000000..03ea780b2a --- /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 + +#include "media/base/h264_profile_level_id.h" + +@interface UIDevice (H264Profile) + ++ (rtc::Optional)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 0000000000..41123a533b --- /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 + +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 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)maxSupportedH264Profile { + return FindMaxSupportedProfileForDevice([self deviceType]); +} + +@end diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h index e9dd234c34..b30c137016 100644 --- a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodec.h @@ -20,6 +20,8 @@ RTC_EXPORT extern NSString *const kRTCVideoCodecVp9Name; RTC_EXPORT extern NSString *const kRTCVideoCodecH264Name; RTC_EXPORT extern NSString *const kRTCLevel31ConstrainedHigh; RTC_EXPORT extern NSString *const kRTCLevel31ConstrainedBaseline; +RTC_EXPORT extern NSString *const kRTCMaxSupportedH264ProfileLevelConstrainedHigh; +RTC_EXPORT extern NSString *const kRTCMaxSupportedH264ProfileLevelConstrainedBaseline; /** Represents an encoded frame's type. */ typedef NS_ENUM(NSUInteger, RTCFrameType) { diff --git a/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h b/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h index 79d2db8c4a..eb39ea9cc4 100644 --- a/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h +++ b/sdk/objc/Framework/Headers/WebRTC/UIDevice+RTCDevice.h @@ -30,6 +30,7 @@ typedef NS_ENUM(NSInteger, RTCDeviceType) { RTCDeviceTypeIPhone6SPlus, RTCDeviceTypeIPhone7, RTCDeviceTypeIPhone7Plus, + RTCDeviceTypeIPhoneSE, RTCDeviceTypeIPhone8, RTCDeviceTypeIPhone8Plus, RTCDeviceTypeIPhoneX, @@ -38,6 +39,7 @@ typedef NS_ENUM(NSInteger, RTCDeviceType) { RTCDeviceTypeIPodTouch3G, RTCDeviceTypeIPodTouch4G, RTCDeviceTypeIPodTouch5G, + RTCDeviceTypeIPodTouch6G, RTCDeviceTypeIPad, RTCDeviceTypeIPad2Wifi, RTCDeviceTypeIPad2GSM, @@ -52,10 +54,21 @@ typedef NS_ENUM(NSInteger, RTCDeviceType) { RTCDeviceTypeIPad4Wifi, RTCDeviceTypeIPad4GSM, RTCDeviceTypeIPad4GSM_CDMA, + RTCDeviceTypeIPad5, + RTCDeviceTypeIPad6, RTCDeviceTypeIPadAirWifi, RTCDeviceTypeIPadAirCellular, + RTCDeviceTypeIPadAirWifiCellular, + RTCDeviceTypeIPadAir2, RTCDeviceTypeIPadMini2GWifi, RTCDeviceTypeIPadMini2GCellular, + RTCDeviceTypeIPadMini2GWifiCellular, + RTCDeviceTypeIPadMini3, + RTCDeviceTypeIPadMini4, + RTCDeviceTypeIPadPro9Inch, + RTCDeviceTypeIPadPro12Inch, + RTCDeviceTypeIPadPro12Inch2, + RTCDeviceTypeIPadPro10Inch, RTCDeviceTypeSimulatori386, RTCDeviceTypeSimulatorx86_64, };