1/* 2 * Copyright 2018 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 * 10 */ 11 12#import "RTCH264ProfileLevelId.h" 13 14#import "helpers/NSString+StdString.h" 15#if defined(WEBRTC_IOS) 16#import "UIDevice+H264Profile.h" 17#endif 18 19#include "api/video_codecs/h264_profile_level_id.h" 20#include "media/base/media_constants.h" 21 22namespace { 23 24NSString *MaxSupportedProfileLevelConstrainedHigh(); 25NSString *MaxSupportedProfileLevelConstrainedBaseline(); 26 27} // namespace 28 29NSString *const kRTCVideoCodecH264Name = @(cricket::kH264CodecName); 30NSString *const kRTCLevel31ConstrainedHigh = @"640c1f"; 31NSString *const kRTCLevel31ConstrainedBaseline = @"42e01f"; 32NSString *const kRTCMaxSupportedH264ProfileLevelConstrainedHigh = 33 MaxSupportedProfileLevelConstrainedHigh(); 34NSString *const kRTCMaxSupportedH264ProfileLevelConstrainedBaseline = 35 MaxSupportedProfileLevelConstrainedBaseline(); 36 37namespace { 38 39#if defined(WEBRTC_IOS) 40 41NSString *MaxSupportedLevelForProfile(webrtc::H264Profile profile) { 42 const absl::optional<webrtc::H264ProfileLevelId> profileLevelId = 43 [UIDevice maxSupportedH264Profile]; 44 if (profileLevelId && profileLevelId->profile >= profile) { 45 const absl::optional<std::string> profileString = 46 H264ProfileLevelIdToString(webrtc::H264ProfileLevelId(profile, profileLevelId->level)); 47 if (profileString) { 48 return [NSString stringForStdString:*profileString]; 49 } 50 } 51 return nil; 52} 53#endif 54 55NSString *MaxSupportedProfileLevelConstrainedBaseline() { 56#if defined(WEBRTC_IOS) 57 NSString *profile = MaxSupportedLevelForProfile(webrtc::H264Profile::kProfileConstrainedBaseline); 58 if (profile != nil) { 59 return profile; 60 } 61#endif 62 return kRTCLevel31ConstrainedBaseline; 63} 64 65NSString *MaxSupportedProfileLevelConstrainedHigh() { 66#if defined(WEBRTC_IOS) 67 NSString *profile = MaxSupportedLevelForProfile(webrtc::H264Profile::kProfileConstrainedHigh); 68 if (profile != nil) { 69 return profile; 70 } 71#endif 72 return kRTCLevel31ConstrainedHigh; 73} 74 75} // namespace 76 77@interface RTC_OBJC_TYPE (RTCH264ProfileLevelId) 78() 79 80 @property(nonatomic, assign) RTCH264Profile profile; 81@property(nonatomic, assign) RTCH264Level level; 82@property(nonatomic, strong) NSString *hexString; 83 84@end 85 86@implementation RTC_OBJC_TYPE (RTCH264ProfileLevelId) 87 88@synthesize profile = _profile; 89@synthesize level = _level; 90@synthesize hexString = _hexString; 91 92- (instancetype)initWithHexString:(NSString *)hexString { 93 if (self = [super init]) { 94 self.hexString = hexString; 95 96 absl::optional<webrtc::H264ProfileLevelId> profile_level_id = 97 webrtc::ParseH264ProfileLevelId([hexString cStringUsingEncoding:NSUTF8StringEncoding]); 98 if (profile_level_id.has_value()) { 99 self.profile = static_cast<RTCH264Profile>(profile_level_id->profile); 100 self.level = static_cast<RTCH264Level>(profile_level_id->level); 101 } 102 } 103 return self; 104} 105 106- (instancetype)initWithProfile:(RTCH264Profile)profile level:(RTCH264Level)level { 107 if (self = [super init]) { 108 self.profile = profile; 109 self.level = level; 110 111 absl::optional<std::string> hex_string = 112 webrtc::H264ProfileLevelIdToString(webrtc::H264ProfileLevelId( 113 static_cast<webrtc::H264Profile>(profile), static_cast<webrtc::H264Level>(level))); 114 self.hexString = 115 [NSString stringWithCString:hex_string.value_or("").c_str() encoding:NSUTF8StringEncoding]; 116 } 117 return self; 118} 119 120@end 121