From 0c4b9fd122265548f6b7fbb6784a88ba61c5a1cb Mon Sep 17 00:00:00 2001 From: David Liu Date: Mon, 15 May 2023 00:45:47 +0900 Subject: [PATCH] Expose getCapabilities/setCodecPreferences for objc Bug: None Change-Id: I31cf22bae595cf2b995ff648523d25485106fcd5 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/305200 Reviewed-by: Magnus Jedvert Reviewed-by: Peter Hanspers Commit-Queue: Peter Hanspers Cr-Commit-Position: refs/heads/main@{#40841} --- sdk/BUILD.gn | 10 ++ .../peerconnection/RTCPeerConnectionFactory.h | 8 ++ .../RTCPeerConnectionFactory.mm | 16 +++ .../RTCRtpCapabilities+Private.h | 29 ++++ .../api/peerconnection/RTCRtpCapabilities.h | 28 ++++ .../api/peerconnection/RTCRtpCapabilities.mm | 44 ++++++ .../RTCRtpCodecCapability+Private.h | 27 ++++ .../peerconnection/RTCRtpCodecCapability.h | 54 +++++++ .../peerconnection/RTCRtpCodecCapability.mm | 132 ++++++++++++++++++ .../api/peerconnection/RTCRtpTransceiver.h | 18 +++ .../api/peerconnection/RTCRtpTransceiver.mm | 36 +++++ 11 files changed, 402 insertions(+) create mode 100644 sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h create mode 100644 sdk/objc/api/peerconnection/RTCRtpCapabilities.h create mode 100644 sdk/objc/api/peerconnection/RTCRtpCapabilities.mm create mode 100644 sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h create mode 100644 sdk/objc/api/peerconnection/RTCRtpCodecCapability.h create mode 100644 sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index 4f5ceb5ed3..f86c1ec071 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -991,6 +991,12 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCRtcpParameters+Private.h", "objc/api/peerconnection/RTCRtcpParameters.h", "objc/api/peerconnection/RTCRtcpParameters.mm", + "objc/api/peerconnection/RTCRtpCapabilities+Private.h", + "objc/api/peerconnection/RTCRtpCapabilities.h", + "objc/api/peerconnection/RTCRtpCapabilities.mm", + "objc/api/peerconnection/RTCRtpCodecCapability+Private.h", + "objc/api/peerconnection/RTCRtpCodecCapability.h", + "objc/api/peerconnection/RTCRtpCodecCapability.mm", "objc/api/peerconnection/RTCRtpCodecParameters+Private.h", "objc/api/peerconnection/RTCRtpCodecParameters.h", "objc/api/peerconnection/RTCRtpCodecParameters.mm", @@ -1309,6 +1315,8 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCPeerConnectionFactory.h", "objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h", "objc/api/peerconnection/RTCRtcpParameters.h", + "objc/api/peerconnection/RTCRtpCapabilities.h", + "objc/api/peerconnection/RTCRtpCodecCapability.h", "objc/api/peerconnection/RTCRtpCodecParameters.h", "objc/api/peerconnection/RTCRtpEncodingParameters.h", "objc/api/peerconnection/RTCRtpHeaderExtension.h", @@ -1423,6 +1431,8 @@ if (is_ios || is_mac) { "objc/api/peerconnection/RTCPeerConnectionFactory.h", "objc/api/peerconnection/RTCPeerConnectionFactoryOptions.h", "objc/api/peerconnection/RTCRtcpParameters.h", + "objc/api/peerconnection/RTCRtpCapabilities.h", + "objc/api/peerconnection/RTCRtpCodecCapability.h", "objc/api/peerconnection/RTCRtpCodecParameters.h", "objc/api/peerconnection/RTCRtpEncodingParameters.h", "objc/api/peerconnection/RTCRtpHeaderExtension.h", diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h index 5575af98c9..41d1ab1c1d 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h +++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.h @@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN @class RTC_OBJC_TYPE(RTCVideoSource); @class RTC_OBJC_TYPE(RTCVideoTrack); @class RTC_OBJC_TYPE(RTCPeerConnectionFactoryOptions); +@class RTC_OBJC_TYPE(RTCRtpCapabilities); +typedef NS_ENUM(NSInteger, RTCRtpMediaType); @protocol RTC_OBJC_TYPE (RTCPeerConnectionDelegate); @protocol RTC_OBJC_TYPE @@ -99,6 +101,12 @@ RTC_OBJC_EXPORT (id)certificateVerifier delegate:(nullable id)delegate; +/** Returns the capabilities of an RTP sender for a specific mediaType. */ +- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpSenderCapabilitiesFor:(RTCRtpMediaType)mediaType; + +/** Returns the capabilities of an RTP receiver for a specific mediaType. */ +- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpReceiverCapabilitiesFor:(RTCRtpMediaType)mediaType; + /** Set the options to be used for subsequently created RTCPeerConnections */ - (void)setOptions:(nonnull RTC_OBJC_TYPE(RTCPeerConnectionFactoryOptions) *)options; diff --git a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm index 62b55543d4..fe77ff1634 100644 --- a/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm +++ b/sdk/objc/api/peerconnection/RTCPeerConnectionFactory.mm @@ -19,6 +19,10 @@ #import "RTCMediaConstraints+Private.h" #import "RTCMediaStream+Private.h" #import "RTCPeerConnection+Private.h" +#import "RTCRtpCapabilities+Private.h" +#import "RTCRtpCodecCapability+Private.h" +#import "RTCRtpReceiver+Private.h" +#import "RTCRtpSender+Private.h" #import "RTCVideoSource+Private.h" #import "RTCVideoTrack+Private.h" #import "base/RTCLogging.h" @@ -303,6 +307,18 @@ - (instancetype)initWithNativeAudioEncoderFactory: delegate:delegate]; } +- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpSenderCapabilitiesFor:(RTCRtpMediaType)mediaType { + webrtc::RtpCapabilities capabilities = _nativeFactory->GetRtpSenderCapabilities( + [RTCRtpReceiver nativeMediaTypeForMediaType:mediaType]); + return [[RTCRtpCapabilities alloc] initWithNativeCapabilities:capabilities]; +} + +- (RTC_OBJC_TYPE(RTCRtpCapabilities) *)rtpReceiverCapabilitiesFor:(RTCRtpMediaType)mediaType { + webrtc::RtpCapabilities capabilities = _nativeFactory->GetRtpReceiverCapabilities( + [RTCRtpReceiver nativeMediaTypeForMediaType:mediaType]); + return [[RTCRtpCapabilities alloc] initWithNativeCapabilities:capabilities]; +} + - (void)setOptions:(nonnull RTC_OBJC_TYPE(RTCPeerConnectionFactoryOptions) *)options { RTC_DCHECK(options != nil); _nativeFactory->SetOptions(options.nativeOptions); diff --git a/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h b/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h new file mode 100644 index 0000000000..3ccfe58376 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpCapabilities+Private.h @@ -0,0 +1,29 @@ +/* + * Copyright 2023 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 "RTCRtpCapabilities.h" + +#include "api/rtp_parameters.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RTC_OBJC_TYPE (RTCRtpCapabilities) +() + + /** Returns the equivalent native RtpCapabilities structure. */ + @property(nonatomic, readonly) webrtc::RtpCapabilities nativeCapabilities; + +/** Initialize the object with a native RtpCapabilities structure. */ +- (instancetype)initWithNativeCapabilities:(const webrtc::RtpCapabilities &)nativeCapabilities + NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCRtpCapabilities.h b/sdk/objc/api/peerconnection/RTCRtpCapabilities.h new file mode 100644 index 0000000000..ebeb8edc20 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpCapabilities.h @@ -0,0 +1,28 @@ +/* + * Copyright 2023 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 + +#import "RTCMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +@class RTC_OBJC_TYPE(RTCRtpCodecCapability); + +RTC_OBJC_EXPORT +@interface RTC_OBJC_TYPE (RTCRtpCapabilities) : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +@property(nonatomic, readonly) NSArray *codecs; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm b/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm new file mode 100644 index 0000000000..5005e5bd4e --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpCapabilities.mm @@ -0,0 +1,44 @@ +/* + * Copyright 2023 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 "RTCRtpCapabilities+Private.h" +#import "RTCRtpCodecCapability+Private.h" + +#import "RTCMediaStreamTrack.h" +#import "helpers/NSString+StdString.h" + +#include "media/base/media_constants.h" +#include "rtc_base/checks.h" + +@implementation RTC_OBJC_TYPE (RTCRtpCapabilities) + +@synthesize nativeCapabilities = _nativeCapabilities; + +- (instancetype)initWithNativeCapabilities:(const webrtc::RtpCapabilities &)nativeCapabilities { + if (self = [super init]) { + _nativeCapabilities = nativeCapabilities; + } + + return self; +} + +- (NSArray *)codecs { + NSMutableArray *result = [NSMutableArray array]; + + for (auto &element : _nativeCapabilities.codecs) { + RTCRtpCodecCapability *object = + [[RTCRtpCodecCapability alloc] initWithNativeCodecCapability:element]; + [result addObject:object]; + } + + return result; +} + +@end diff --git a/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h b/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h new file mode 100644 index 0000000000..ee578d7c8d --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpCodecCapability+Private.h @@ -0,0 +1,27 @@ +/* + * Copyright 2023 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 "RTCRtpCodecCapability.h" + +#include "api/rtp_parameters.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface RTC_OBJC_TYPE (RTCRtpCodecCapability) +() + + @property(nonatomic, readonly) webrtc::RtpCodecCapability nativeCodecCapability; + +- (instancetype)initWithNativeCodecCapability: + (const webrtc::RtpCodecCapability &)nativeCodecCapability NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h b/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h new file mode 100644 index 0000000000..0d607613fa --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpCodecCapability.h @@ -0,0 +1,54 @@ +/* + * Copyright 2023 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 + +#import "RTCMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, RTCRtpMediaType); + +RTC_OBJC_EXPORT +@interface RTC_OBJC_TYPE (RTCRtpCodecCapability) : NSObject + +/** Build MIME "type/subtype" string from name and kind. */ +@property(nonatomic, readonly) NSString *mimeType; + +/** Used to identify the codec. Equivalent to MIME subtype. */ +@property(nonatomic, copy) NSString *name; + +/** The media type of this codec. Equivalent to MIME top-level type. */ +@property(nonatomic, assign) RTCRtpMediaType kind; + +/** Clock rate in Hertz. If unset, the codec is applicable to any clock rate. */ +@property(nonatomic, copy, nullable) NSNumber *clockRate; + +/** Default payload type for this codec. Mainly needed for codecs that use + * that have statically assigned payload types. + */ +@property(nonatomic, copy, nullable) NSNumber *preferredPayloadType; + +/** The number of audio channels supported. Unused for video codecs. */ +@property(nonatomic, copy, nullable) NSNumber *numChannels; + +/**Codec-specific parameters that must be signaled to the remote party. + * + * Corresponds to "a=fmtp" parameters in SDP. + * + * Contrary to ORTC, these parameters are named using all lowercase strings. + * This helps make the mapping to SDP simpler, if an application is using SDP. + * Boolean values are represented by the string "1". + */ +@property(nonatomic, copy) NSDictionary *parameters; + +@end + +NS_ASSUME_NONNULL_END diff --git a/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm b/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm new file mode 100644 index 0000000000..bb48ade659 --- /dev/null +++ b/sdk/objc/api/peerconnection/RTCRtpCodecCapability.mm @@ -0,0 +1,132 @@ +/* + * Copyright 2023 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 "RTCRtpCodecCapability+Private.h" + +#import "RTCRtpReceiver+Private.h" + +#import "RTCMediaStreamTrack.h" +#import "helpers/NSString+StdString.h" + +#include "media/base/media_constants.h" +#include "rtc_base/checks.h" + +@implementation RTC_OBJC_TYPE (RTCRtpCodecCapability) + +@synthesize nativeCodecCapability = _nativeCodecCapability; + +- (instancetype)init { + return [self initWithNativeCodecCapability:webrtc::RtpCodecCapability()]; +} + +- (instancetype)initWithNativeCodecCapability: + (const webrtc::RtpCodecCapability &)nativeCodecCapability { + if (self = [super init]) { + _nativeCodecCapability = nativeCodecCapability; + } + + return self; +} + +- (NSString *)mimeType { + return [NSString stringWithUTF8String:_nativeCodecCapability.mime_type().c_str()]; +} + +- (NSString *)name { + return [NSString stringWithUTF8String:_nativeCodecCapability.name.c_str()]; +} + +- (void)setName:(NSString *)name { + _nativeCodecCapability.name = std::string([name UTF8String]); +} + +- (RTCRtpMediaType)kind { + return [RTCRtpReceiver mediaTypeForNativeMediaType:_nativeCodecCapability.kind]; +} + +- (void)setKind:(RTCRtpMediaType)kind { + _nativeCodecCapability.kind = [RTCRtpReceiver nativeMediaTypeForMediaType:kind]; +} + +- (NSNumber *)clockRate { + if (!_nativeCodecCapability.clock_rate) { + return nil; + } + + return [NSNumber numberWithInt:*_nativeCodecCapability.clock_rate]; +} + +- (void)setClockRate:(NSNumber *)clockRate { + if (clockRate == nil) { + _nativeCodecCapability.clock_rate = absl::optional(); + return; + } + + _nativeCodecCapability.clock_rate = absl::optional(clockRate.intValue); +} + +- (NSNumber *)preferredPayloadType { + if (!_nativeCodecCapability.preferred_payload_type) { + return nil; + } + + return [NSNumber numberWithInt:*_nativeCodecCapability.preferred_payload_type]; +} + +- (void)setPreferredPayloadType:(NSNumber *)preferredPayloadType { + if (preferredPayloadType == nil) { + _nativeCodecCapability.preferred_payload_type = absl::optional(); + return; + } + + _nativeCodecCapability.preferred_payload_type = + absl::optional(preferredPayloadType.intValue); +} + +- (NSNumber *)numChannels { + if (!_nativeCodecCapability.num_channels) { + return nil; + } + + return [NSNumber numberWithInt:*_nativeCodecCapability.num_channels]; +} + +- (void)setNumChannels:(NSNumber *)numChannels { + if (numChannels == nil) { + _nativeCodecCapability.num_channels = absl::optional(); + return; + } + + _nativeCodecCapability.num_channels = absl::optional(numChannels.intValue); +} + +- (NSDictionary *)parameters { + NSMutableDictionary *result = [NSMutableDictionary dictionary]; + auto _parameters = _nativeCodecCapability.parameters; + for (auto it = _parameters.begin(); it != _parameters.end(); ++it) { + [result setObject:[NSString stringForStdString:it->second] + forKey:[NSString stringForStdString:it->first]]; + } + + return result; +} + +- (void)setParameters:(NSDictionary *)parameters { + std::map _parameters; + for (NSString *paramKey in parameters.allKeys) { + std::string key = [NSString stdStringForString:paramKey]; + std::string value = [NSString stdStringForString:parameters[paramKey]]; + _parameters[key] = value; + } + + _nativeCodecCapability.parameters = _parameters; +} + +@end diff --git a/sdk/objc/api/peerconnection/RTCRtpTransceiver.h b/sdk/objc/api/peerconnection/RTCRtpTransceiver.h index fd59013639..a10a260856 100644 --- a/sdk/objc/api/peerconnection/RTCRtpTransceiver.h +++ b/sdk/objc/api/peerconnection/RTCRtpTransceiver.h @@ -16,6 +16,8 @@ NS_ASSUME_NONNULL_BEGIN +@class RTC_OBJC_TYPE(RTCRtpCodecCapability); + extern NSString *const kRTCRtpTransceiverErrorDomain; /** https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection */ @@ -104,6 +106,13 @@ RTC_OBJC_EXPORT */ @property(nonatomic, readonly) RTCRtpTransceiverDirection direction; +/** The codecPreferences indicates any overridden codec preferences, which + * will be used in calls to createOffer and createAnswer. An empty array + * indicates that the default codec preferences will be used. + * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-setcodecpreferences + */ +@property(nonatomic, readonly) NSArray *codecPreferences; + /** The currentDirection attribute indicates the current direction negotiated * for this transceiver. If this transceiver has never been represented in an * offer/answer exchange, or if the transceiver is stopped, the value is not @@ -125,6 +134,15 @@ RTC_OBJC_EXPORT */ - (void)setDirection:(RTCRtpTransceiverDirection)direction error:(NSError **)error; +/** The setCodecPreferences method will reject attempts to set codecs not + * matching codecs found in sender or receiver capabilities for kind, where + * kind is the mediaType of the RTCRtpTransceiver on which the method is + * called. + * https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-setcodecpreferences + */ +- (void)setCodecPreferences:(NSArray *)codecPreferences + error:(NSError **)error; + @end RTC_OBJC_EXPORT diff --git a/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm b/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm index ae1cf79864..36834ea436 100644 --- a/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm +++ b/sdk/objc/api/peerconnection/RTCRtpTransceiver.mm @@ -10,6 +10,8 @@ #import "RTCRtpTransceiver+Private.h" +#import "RTCRtpCodecCapability+Private.h" +#import "RTCRtpCodecCapability.h" #import "RTCRtpEncodingParameters+Private.h" #import "RTCRtpParameters+Private.h" #import "RTCRtpReceiver+Private.h" @@ -65,6 +67,40 @@ - (NSString *)mid { } } +- (NSArray *)codecPreferences { + NSMutableArray *result = [NSMutableArray array]; + std::vector capabilities = _nativeRtpTransceiver->codec_preferences(); + + for (auto &element : capabilities) { + RTCRtpCodecCapability *object = + [[RTCRtpCodecCapability alloc] initWithNativeCodecCapability:element]; + [result addObject:object]; + } + + return result; +} + +- (void)setCodecPreferences:(NSArray *)codecPreferences + error:(NSError **)error { + std::vector objects; + + for (RTCRtpCodecCapability *object in codecPreferences) { + objects.push_back(object.nativeCodecCapability); + } + + webrtc::RTCError nativeError = _nativeRtpTransceiver->SetCodecPreferences( + rtc::ArrayView(objects.data(), objects.size())); + + if (!nativeError.ok() && error) { + *error = [NSError errorWithDomain:kRTCRtpTransceiverErrorDomain + code:static_cast(nativeError.type()) + userInfo:@{ + @"message" : [NSString stringWithCString:nativeError.message() + encoding:NSUTF8StringEncoding] + }]; + } +} + @synthesize sender = _sender; @synthesize receiver = _receiver;