Obj-C SDK for parsing and generating H264 ProfileLevelIds.

Expose this functionality in the Obj-C SDK to make it nicer to use for
Obj-C clients.

Bug: None
Change-Id: I5cb511af8799ac0fda15153d16f2550b848b93b2
Reviewed-on: https://webrtc-review.googlesource.com/80481
Reviewed-by: Peter Hanspers <peterhanspers@webrtc.org>
Commit-Queue: Anders Carlsson <andersc@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23488}
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index fa71058..3d9e4ee 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -439,6 +439,7 @@
       visibility = [ "*" ]
       sources = [
         "objc/Framework/Classes/PeerConnection/RTCEncodedImage.mm",
+        "objc/Framework/Classes/PeerConnection/RTCH264ProfileLevelId.mm",
         "objc/Framework/Classes/PeerConnection/RTCRtpFragmentationHeader.mm",
         "objc/Framework/Classes/PeerConnection/RTCVideoCodec+Private.h",
         "objc/Framework/Classes/PeerConnection/RTCVideoCodec.mm",
@@ -788,6 +789,7 @@
             "objc/Framework/UnitTests/RTCCallbackLogger_xctest.m",
             "objc/Framework/UnitTests/RTCDoNotPutCPlusPlusInFrameworkHeaders_xctest.m",
             "objc/Framework/UnitTests/RTCFileVideoCapturer_xctest.mm",
+            "objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m",
             "objc/Framework/UnitTests/frame_buffer_helpers.h",
             "objc/Framework/UnitTests/frame_buffer_helpers.mm",
           ]
@@ -810,6 +812,7 @@
             ":native_api_audio_device_module",
             ":native_video",
             ":videocapture_objc",
+            ":videocodec_objc",
             ":videoframebuffer_objc",
             ":videosource_objc",
             ":videotoolbox_objc",
diff --git a/sdk/objc/Framework/Classes/PeerConnection/RTCH264ProfileLevelId.mm b/sdk/objc/Framework/Classes/PeerConnection/RTCH264ProfileLevelId.mm
new file mode 100644
index 0000000..33f9ae9
--- /dev/null
+++ b/sdk/objc/Framework/Classes/PeerConnection/RTCH264ProfileLevelId.mm
@@ -0,0 +1,58 @@
+/*
+ *  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 "WebRTC/RTCVideoCodecH264.h"
+
+#include "media/base/h264_profile_level_id.h"
+
+@interface RTCH264ProfileLevelId ()
+
+@property(nonatomic, assign) RTCH264Profile profile;
+@property(nonatomic, assign) RTCH264Level level;
+@property(nonatomic, strong) NSString *hexString;
+
+@end
+
+@implementation RTCH264ProfileLevelId
+
+@synthesize profile = _profile;
+@synthesize level = _level;
+@synthesize hexString = _hexString;
+
+- (instancetype)initWithHexString:(NSString *)hexString {
+  if (self = [super init]) {
+    self.hexString = hexString;
+
+    rtc::Optional<webrtc::H264::ProfileLevelId> profile_level_id =
+        webrtc::H264::ParseProfileLevelId([hexString cStringUsingEncoding:NSUTF8StringEncoding]);
+    if (profile_level_id.has_value()) {
+      self.profile = static_cast<RTCH264Profile>(profile_level_id->profile);
+      self.level = static_cast<RTCH264Level>(profile_level_id->level);
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithProfile:(RTCH264Profile)profile level:(RTCH264Level)level {
+  if (self = [super init]) {
+    self.profile = profile;
+    self.level = level;
+
+    rtc::Optional<std::string> hex_string =
+        webrtc::H264::ProfileLevelIdToString(webrtc::H264::ProfileLevelId(
+            static_cast<webrtc::H264::Profile>(profile), static_cast<webrtc::H264::Level>(level)));
+    self.hexString =
+        [NSString stringWithCString:hex_string.value_or("").c_str() encoding:NSUTF8StringEncoding];
+  }
+  return self;
+}
+
+@end
diff --git a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h
index 1c307eb..d18e96d 100644
--- a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h
+++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h
@@ -26,6 +26,47 @@
 
 @end
 
+/** H264 Profiles and levels. */
+typedef NS_ENUM(NSUInteger, RTCH264Profile) {
+  RTCH264ProfileConstrainedBaseline,
+  RTCH264ProfileBaseline,
+  RTCH264ProfileMain,
+  RTCH264ProfileConstrainedHigh,
+  RTCH264ProfileHigh,
+};
+
+typedef NS_ENUM(NSUInteger, RTCH264Level) {
+  RTCH264Level1_b = 0,
+  RTCH264Level1 = 10,
+  RTCH264Level1_1 = 11,
+  RTCH264Level1_2 = 12,
+  RTCH264Level1_3 = 13,
+  RTCH264Level2 = 20,
+  RTCH264Level2_1 = 21,
+  RTCH264Level2_2 = 22,
+  RTCH264Level3 = 30,
+  RTCH264Level3_1 = 31,
+  RTCH264Level3_2 = 32,
+  RTCH264Level4 = 40,
+  RTCH264Level4_1 = 41,
+  RTCH264Level4_2 = 42,
+  RTCH264Level5 = 50,
+  RTCH264Level5_1 = 51,
+  RTCH264Level5_2 = 52
+};
+
+RTC_EXPORT
+@interface RTCH264ProfileLevelId : NSObject
+
+@property(nonatomic, readonly) RTCH264Profile profile;
+@property(nonatomic, readonly) RTCH264Level level;
+@property(nonatomic, readonly) NSString *hexString;
+
+- (instancetype)initWithHexString:(NSString *)hexString;
+- (instancetype)initWithProfile:(RTCH264Profile)profile level:(RTCH264Level)level;
+
+@end
+
 /** Encoder. */
 RTC_EXPORT
 @interface RTCVideoEncoderH264 : NSObject<RTCVideoEncoder>
diff --git a/sdk/objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m b/sdk/objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m
new file mode 100644
index 0000000..4f0c7c7
--- /dev/null
+++ b/sdk/objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m
@@ -0,0 +1,46 @@
+/*
+ *  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 "WebRTC/RTCVideoCodecH264.h"
+
+#import <XCTest/XCTest.h>
+
+@interface RTCH264ProfileLevelIdTests : XCTestCase
+
+@end
+
+static NSString *level31ConstrainedHigh = @"640c1f";
+static NSString *level31ConstrainedBaseline = @"42e01f";
+
+@implementation RTCH264ProfileLevelIdTests
+
+- (void)testInitWithString {
+  RTCH264ProfileLevelId *profileLevelId =
+      [[RTCH264ProfileLevelId alloc] initWithHexString:level31ConstrainedHigh];
+  XCTAssertEqual(profileLevelId.profile, RTCH264ProfileConstrainedHigh);
+  XCTAssertEqual(profileLevelId.level, RTCH264Level3_1);
+
+  profileLevelId = [[RTCH264ProfileLevelId alloc] initWithHexString:level31ConstrainedBaseline];
+  XCTAssertEqual(profileLevelId.profile, RTCH264ProfileConstrainedBaseline);
+  XCTAssertEqual(profileLevelId.level, RTCH264Level3_1);
+}
+
+- (void)testInitWithProfileAndLevel {
+  RTCH264ProfileLevelId *profileLevelId =
+      [[RTCH264ProfileLevelId alloc] initWithProfile:RTCH264ProfileConstrainedHigh
+                                               level:RTCH264Level3_1];
+  XCTAssertEqualObjects(profileLevelId.hexString, level31ConstrainedHigh);
+
+  profileLevelId = [[RTCH264ProfileLevelId alloc] initWithProfile:RTCH264ProfileConstrainedBaseline
+                                                            level:RTCH264Level3_1];
+  XCTAssertEqualObjects(profileLevelId.hexString, level31ConstrainedBaseline);
+}
+
+@end