From 79ce820a1382054143be44d75a658daa313c0ace Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 1 Jun 2018 12:51:09 +0200 Subject: [PATCH] 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 Commit-Queue: Anders Carlsson Cr-Commit-Position: refs/heads/master@{#23488} --- sdk/BUILD.gn | 3 + .../PeerConnection/RTCH264ProfileLevelId.mm | 58 +++++++++++++++++++ .../Headers/WebRTC/RTCVideoCodecH264.h | 41 +++++++++++++ .../UnitTests/RTCH264ProfileLevelId_xctest.m | 46 +++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 sdk/objc/Framework/Classes/PeerConnection/RTCH264ProfileLevelId.mm create mode 100644 sdk/objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index fa71058cc1..3d9e4ee136 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -439,6 +439,7 @@ if (is_ios || is_mac) { 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 @@ if (is_ios || is_mac) { "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 @@ if (is_ios || is_mac) { ":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 0000000000..33f9ae92e1 --- /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 profile_level_id = + webrtc::H264::ParseProfileLevelId([hexString cStringUsingEncoding:NSUTF8StringEncoding]); + if (profile_level_id.has_value()) { + self.profile = static_cast(profile_level_id->profile); + self.level = static_cast(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 hex_string = + webrtc::H264::ProfileLevelIdToString(webrtc::H264::ProfileLevelId( + static_cast(profile), static_cast(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 1c307ebe84..d18e96dd47 100644 --- a/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h +++ b/sdk/objc/Framework/Headers/WebRTC/RTCVideoCodecH264.h @@ -26,6 +26,47 @@ RTC_EXPORT @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 diff --git a/sdk/objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m b/sdk/objc/Framework/UnitTests/RTCH264ProfileLevelId_xctest.m new file mode 100644 index 0000000000..4f0c7c7a27 --- /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 + +@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