Add new PeerConnection APIs to the ObjC SDK

This CL adds wrappers for the following PeerConnection native
APIs to the Objective C API:
- SdpSemantics enum added to the RTCConfiguration
- RTCRtpTransceiver
- RTCPeerConnection.addTrack
- RTCPeerConnection.removeTrack
- RTCPeerConnection.addTransceiver
- RTCPeerConnection.transceivers

Bug: webrtc:8870
Change-Id: I9449df9742a59e90894712dc7749ca30b569d94b
Reviewed-on: https://webrtc-review.googlesource.com/54780
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Kári Helgason <kthelgason@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22214}
This commit is contained in:
Steve Anton
2018-02-27 15:34:53 -08:00
committed by Commit Bot
parent ac7539e2d1
commit 8cb344acfd
12 changed files with 637 additions and 25 deletions

View File

@ -58,6 +58,12 @@ NS_ASSUME_NONNULL_BEGIN
+ (rtc::KeyType)nativeEncryptionKeyTypeForKeyType:(RTCEncryptionKeyType)keyType;
+ (webrtc::SdpSemantics)nativeSdpSemanticsForSdpSemantics:(RTCSdpSemantics)sdpSemantics;
+ (RTCSdpSemantics)sdpSemanticsForNativeSdpSemantics:(webrtc::SdpSemantics)sdpSemantics;
+ (NSString *)stringForSdpSemantics:(RTCSdpSemantics)sdpSemantics;
/**
* RTCConfiguration struct representation of this RTCConfiguration. This is
* needed to pass to the underlying C++ APIs.

View File

@ -43,6 +43,7 @@
_shouldPresumeWritableWhenFullyRelayed;
@synthesize iceCheckMinInterval = _iceCheckMinInterval;
@synthesize iceRegatherIntervalRange = _iceRegatherIntervalRange;
@synthesize sdpSemantics = _sdpSemantics;
@synthesize turnCustomizer = _turnCustomizer;
- (instancetype)init {
@ -96,35 +97,38 @@
_iceRegatherIntervalRange =
[[RTCIntervalRange alloc] initWithNativeIntervalRange:nativeIntervalRange];
}
_sdpSemantics = [[self class] sdpSemanticsForNativeSdpSemantics:config.sdp_semantics];
_turnCustomizer = config.turn_customizer;
}
return self;
}
- (NSString *)description {
static NSString *formatString = @"RTCConfiguration: "
@"{\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%@\n%@\n%d\n%d\n}\n";
static NSString *formatString =
@"RTCConfiguration: "
@"{\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%@\n%d\n%d\n%d\n%d\n%d\n%d\n%d\n%@\n%@\n%d\n%d\n}\n";
return
[NSString stringWithFormat:formatString,
_iceServers,
[[self class] stringForTransportPolicy:_iceTransportPolicy],
[[self class] stringForBundlePolicy:_bundlePolicy],
[[self class] stringForRtcpMuxPolicy:_rtcpMuxPolicy],
[[self class] stringForTcpCandidatePolicy:_tcpCandidatePolicy],
[[self class] stringForCandidateNetworkPolicy:_candidateNetworkPolicy],
[[self class] stringForContinualGatheringPolicy:_continualGatheringPolicy],
_audioJitterBufferMaxPackets,
_audioJitterBufferFastAccelerate,
_iceConnectionReceivingTimeout,
_iceBackupCandidatePairPingInterval,
_iceCandidatePoolSize,
_shouldPruneTurnPorts,
_shouldPresumeWritableWhenFullyRelayed,
_iceCheckMinInterval,
_iceRegatherIntervalRange,
_disableLinkLocalNetworks,
_maxIPv6Networks];
return [NSString
stringWithFormat:formatString,
_iceServers,
[[self class] stringForTransportPolicy:_iceTransportPolicy],
[[self class] stringForBundlePolicy:_bundlePolicy],
[[self class] stringForRtcpMuxPolicy:_rtcpMuxPolicy],
[[self class] stringForTcpCandidatePolicy:_tcpCandidatePolicy],
[[self class] stringForCandidateNetworkPolicy:_candidateNetworkPolicy],
[[self class] stringForContinualGatheringPolicy:_continualGatheringPolicy],
[[self class] stringForSdpSemantics:_sdpSemantics],
_audioJitterBufferMaxPackets,
_audioJitterBufferFastAccelerate,
_iceConnectionReceivingTimeout,
_iceBackupCandidatePairPingInterval,
_iceCandidatePoolSize,
_shouldPruneTurnPorts,
_shouldPresumeWritableWhenFullyRelayed,
_iceCheckMinInterval,
_iceRegatherIntervalRange,
_disableLinkLocalNetworks,
_maxIPv6Networks];
}
#pragma mark - Private
@ -186,6 +190,7 @@
nativeConfig->ice_regather_interval_range =
rtc::Optional<rtc::IntervalRange>(*nativeIntervalRange);
}
nativeConfig->sdp_semantics = [[self class] nativeSdpSemanticsForSdpSemantics:_sdpSemantics];
if (_turnCustomizer) {
nativeConfig->turn_customizer = _turnCustomizer;
}
@ -397,4 +402,37 @@
}
}
+ (webrtc::SdpSemantics)nativeSdpSemanticsForSdpSemantics:(RTCSdpSemantics)sdpSemantics {
switch (sdpSemantics) {
case RTCSdpSemanticsDefault:
return webrtc::SdpSemantics::kDefault;
case RTCSdpSemanticsPlanB:
return webrtc::SdpSemantics::kPlanB;
case RTCSdpSemanticsUnifiedPlan:
return webrtc::SdpSemantics::kUnifiedPlan;
}
}
+ (RTCSdpSemantics)sdpSemanticsForNativeSdpSemantics:(webrtc::SdpSemantics)sdpSemantics {
switch (sdpSemantics) {
case webrtc::SdpSemantics::kDefault:
return RTCSdpSemanticsDefault;
case webrtc::SdpSemantics::kPlanB:
return RTCSdpSemanticsPlanB;
case webrtc::SdpSemantics::kUnifiedPlan:
return RTCSdpSemanticsUnifiedPlan;
}
}
+ (NSString *)stringForSdpSemantics:(RTCSdpSemantics)sdpSemantics {
switch (sdpSemantics) {
case RTCSdpSemanticsDefault:
return @"DEFAULT";
case RTCSdpSemanticsPlanB:
return @"PLAN_B";
case RTCSdpSemanticsUnifiedPlan:
return @"UNIFIED_PLAN";
}
}
@end

View File

@ -33,6 +33,8 @@ class PeerConnectionDelegateAdapter : public PeerConnectionObserver {
void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) override;
void OnTrack(rtc::scoped_refptr<RtpTransceiverInterface> transceiver) override;
void OnDataChannel(
rtc::scoped_refptr<DataChannelInterface> data_channel) override;

View File

@ -17,10 +17,12 @@
#import "RTCLegacyStatsReport+Private.h"
#import "RTCMediaConstraints+Private.h"
#import "RTCMediaStream+Private.h"
#import "RTCMediaStreamTrack+Private.h"
#import "RTCPeerConnection+Native.h"
#import "RTCPeerConnectionFactory+Private.h"
#import "RTCRtpReceiver+Private.h"
#import "RTCRtpSender+Private.h"
#import "RTCRtpTransceiver+Private.h"
#import "RTCSessionDescription+Private.h"
#import "WebRTC/RTCLogging.h"
@ -144,6 +146,18 @@ void PeerConnectionDelegateAdapter::OnRemoveStream(
didRemoveStream:mediaStream];
}
void PeerConnectionDelegateAdapter::OnTrack(
rtc::scoped_refptr<RtpTransceiverInterface> nativeTransceiver) {
RTCRtpTransceiver *transceiver =
[[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiver];
RTCPeerConnection *peer_connection = peer_connection_;
if ([peer_connection.delegate
respondsToSelector:@selector(peerConnection:didStartReceivingOnTransceiver:)]) {
[peer_connection.delegate peerConnection:peer_connection
didStartReceivingOnTransceiver:transceiver];
}
}
void PeerConnectionDelegateAdapter::OnDataChannel(
rtc::scoped_refptr<DataChannelInterface> data_channel) {
RTCDataChannel *dataChannel =
@ -334,6 +348,65 @@ void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
[_localStreams removeObject:stream];
}
- (RTCRtpSender *)addTrack:(RTCMediaStreamTrack *)track
streamLabels:(NSArray<NSString *> *)streamLabels {
std::vector<std::string> nativeStreamLabels;
for (NSString *label in streamLabels) {
nativeStreamLabels.push_back([label UTF8String]);
}
webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenderOrError =
_peerConnection->AddTrack(track.nativeTrack, nativeStreamLabels);
if (!nativeSenderOrError.ok()) {
RTCLogError(@"Failed to add track %@: %s", track, nativeSenderOrError.error().message());
return nil;
}
return [[RTCRtpSender alloc] initWithNativeRtpSender:nativeSenderOrError.MoveValue()];
}
- (BOOL)removeTrack:(RTCRtpSender *)sender {
bool result = _peerConnection->RemoveTrack(sender.nativeRtpSender);
if (!result) {
RTCLogError(@"Failed to remote track %@", sender);
}
return result;
}
- (RTCRtpTransceiver *)addTransceiverWithTrack:(RTCMediaStreamTrack *)track {
return [self addTransceiverWithTrack:track init:[[RTCRtpTransceiverInit alloc] init]];
}
- (RTCRtpTransceiver *)addTransceiverWithTrack:(RTCMediaStreamTrack *)track
init:(RTCRtpTransceiverInit *)init {
webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
_peerConnection->AddTransceiver(track.nativeTrack, init.nativeInit);
if (!nativeTransceiverOrError.ok()) {
RTCLogError(
@"Failed to add transceiver %@: %s", track, nativeTransceiverOrError.error().message());
return nil;
}
return
[[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
}
- (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType {
return [self addTransceiverOfType:mediaType init:[[RTCRtpTransceiverInit alloc] init]];
}
- (RTCRtpTransceiver *)addTransceiverOfType:(RTCRtpMediaType)mediaType
init:(RTCRtpTransceiverInit *)init {
webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceiverOrError =
_peerConnection->AddTransceiver([RTCRtpReceiver nativeMediaTypeForMediaType:mediaType],
init.nativeInit);
if (!nativeTransceiverOrError.ok()) {
RTCLogError(@"Failed to add transceiver %@: %s",
[RTCRtpReceiver stringForMediaType:mediaType],
nativeTransceiverOrError.error().message());
return nil;
}
return
[[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiverOrError.MoveValue()];
}
- (void)offerForConstraints:(RTCMediaConstraints *)constraints
completionHandler:
(void (^)(RTCSessionDescription *sessionDescription,
@ -451,6 +524,18 @@ void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
return receivers;
}
- (NSArray<RTCRtpTransceiver *> *)transceivers {
std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> nativeTransceivers(
_peerConnection->GetTransceivers());
NSMutableArray *transceivers = [[NSMutableArray alloc] init];
for (auto nativeTransceiver : nativeTransceivers) {
RTCRtpTransceiver *transceiver =
[[RTCRtpTransceiver alloc] initWithNativeRtpTransceiver:nativeTransceiver];
[transceivers addObject:transceiver];
}
return transceivers;
}
#pragma mark - Private
+ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState:

View File

@ -40,6 +40,10 @@ class RtpReceiverDelegateAdapter : public RtpReceiverObserverInterface {
+ (RTCRtpMediaType)mediaTypeForNativeMediaType:(cricket::MediaType)nativeMediaType;
+ (cricket::MediaType)nativeMediaTypeForMediaType:(RTCRtpMediaType)mediaType;
+ (NSString*)stringForMediaType:(RTCRtpMediaType)mediaType;
@end
NS_ASSUME_NONNULL_END

View File

@ -126,4 +126,26 @@ void RtpReceiverDelegateAdapter::OnFirstPacketReceived(
}
}
+ (cricket::MediaType)nativeMediaTypeForMediaType:(RTCRtpMediaType)mediaType {
switch (mediaType) {
case RTCRtpMediaTypeAudio:
return cricket::MEDIA_TYPE_AUDIO;
case RTCRtpMediaTypeVideo:
return cricket::MEDIA_TYPE_VIDEO;
case RTCRtpMediaTypeData:
return cricket::MEDIA_TYPE_DATA;
}
}
+ (NSString *)stringForMediaType:(RTCRtpMediaType)mediaType {
switch (mediaType) {
case RTCRtpMediaTypeAudio:
return @"AUDIO";
case RTCRtpMediaTypeVideo:
return @"VIDEO";
case RTCRtpMediaTypeData:
return @"DATA";
}
}
@end

View File

@ -0,0 +1,41 @@
/*
* 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/RTCRtpTransceiver.h"
#include "api/rtptransceiverinterface.h"
NS_ASSUME_NONNULL_BEGIN
@interface RTCRtpTransceiverInit ()
@property(nonatomic, readonly) webrtc::RtpTransceiverInit nativeInit;
@end
@interface RTCRtpTransceiver ()
@property(nonatomic, readonly) rtc::scoped_refptr<webrtc::RtpTransceiverInterface>
nativeRtpTransceiver;
/** Initialize an RTCRtpTransceiver with a native RtpTransceiverInterface. */
- (instancetype)initWithNativeRtpTransceiver:
(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver
NS_DESIGNATED_INITIALIZER;
+ (webrtc::RtpTransceiverDirection)nativeRtpTransceiverDirectionFromDirection:
(RTCRtpTransceiverDirection)direction;
+ (RTCRtpTransceiverDirection)rtpTransceiverDirectionFromNativeDirection:
(webrtc::RtpTransceiverDirection)nativeDirection;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,163 @@
/*
* 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 "RTCRtpTransceiver+Private.h"
#import "NSString+StdString.h"
#import "RTCRtpEncodingParameters+Private.h"
#import "RTCRtpParameters+Private.h"
#import "RTCRtpReceiver+Private.h"
#import "RTCRtpSender+Private.h"
#import "WebRTC/RTCLogging.h"
@implementation RTCRtpTransceiverInit
@synthesize direction = _direction;
@synthesize streamLabels = _streamLabels;
@synthesize sendEncodings = _sendEncodings;
- (instancetype)init {
if (self = [super init]) {
_direction = RTCRtpTransceiverDirectionSendRecv;
}
return self;
}
- (webrtc::RtpTransceiverInit)nativeInit {
webrtc::RtpTransceiverInit init;
init.direction = [RTCRtpTransceiver nativeRtpTransceiverDirectionFromDirection:_direction];
for (NSString *streamLabel in _streamLabels) {
init.stream_labels.push_back([streamLabel UTF8String]);
}
for (RTCRtpEncodingParameters *sendEncoding in _sendEncodings) {
init.send_encodings.push_back(sendEncoding.nativeParameters);
}
return init;
}
@end
@implementation RTCRtpTransceiver {
rtc::scoped_refptr<webrtc::RtpTransceiverInterface> _nativeRtpTransceiver;
}
- (RTCRtpMediaType)mediaType {
return [RTCRtpReceiver mediaTypeForNativeMediaType:_nativeRtpTransceiver->media_type()];
}
- (NSString *)mid {
if (_nativeRtpTransceiver->mid()) {
return [NSString stringForStdString:*_nativeRtpTransceiver->mid()];
} else {
return nil;
}
}
@synthesize sender = _sender;
@synthesize receiver = _receiver;
- (BOOL)isStopped {
return _nativeRtpTransceiver->stopped();
}
- (RTCRtpTransceiverDirection)direction {
return [RTCRtpTransceiver
rtpTransceiverDirectionFromNativeDirection:_nativeRtpTransceiver->direction()];
}
- (void)setDirection:(RTCRtpTransceiverDirection)direction {
_nativeRtpTransceiver->SetDirection(
[RTCRtpTransceiver nativeRtpTransceiverDirectionFromDirection:direction]);
}
- (BOOL)currentDirection:(RTCRtpTransceiverDirection *)currentDirectionOut {
if (_nativeRtpTransceiver->current_direction()) {
*currentDirectionOut = [RTCRtpTransceiver
rtpTransceiverDirectionFromNativeDirection:*_nativeRtpTransceiver->current_direction()];
return YES;
} else {
return NO;
}
}
- (void)stop {
_nativeRtpTransceiver->Stop();
}
- (NSString *)description {
return [NSString
stringWithFormat:@"RTCRtpTransceiver {\n sender: %@\n receiver: %@\n}", _sender, _receiver];
}
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if (object == nil) {
return NO;
}
if (![object isMemberOfClass:[self class]]) {
return NO;
}
RTCRtpTransceiver *transceiver = (RTCRtpTransceiver *)object;
return _nativeRtpTransceiver == transceiver.nativeRtpTransceiver;
}
- (NSUInteger)hash {
return (NSUInteger)_nativeRtpTransceiver.get();
}
#pragma mark - Private
- (rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver {
return _nativeRtpTransceiver;
}
- (instancetype)initWithNativeRtpTransceiver:
(rtc::scoped_refptr<webrtc::RtpTransceiverInterface>)nativeRtpTransceiver {
NSParameterAssert(nativeRtpTransceiver);
if (self = [super init]) {
_nativeRtpTransceiver = nativeRtpTransceiver;
_sender = [[RTCRtpSender alloc] initWithNativeRtpSender:nativeRtpTransceiver->sender()];
_receiver = [[RTCRtpReceiver alloc] initWithNativeRtpReceiver:nativeRtpTransceiver->receiver()];
RTCLogInfo(@"RTCRtpTransceiver(%p): created transceiver: %@", self, self.description);
}
return self;
}
+ (webrtc::RtpTransceiverDirection)nativeRtpTransceiverDirectionFromDirection:
(RTCRtpTransceiverDirection)direction {
switch (direction) {
case RTCRtpTransceiverDirectionSendRecv:
return webrtc::RtpTransceiverDirection::kSendRecv;
case RTCRtpTransceiverDirectionSendOnly:
return webrtc::RtpTransceiverDirection::kSendOnly;
case RTCRtpTransceiverDirectionRecvOnly:
return webrtc::RtpTransceiverDirection::kRecvOnly;
case RTCRtpTransceiverDirectionInactive:
return webrtc::RtpTransceiverDirection::kInactive;
}
}
+ (RTCRtpTransceiverDirection)rtpTransceiverDirectionFromNativeDirection:
(webrtc::RtpTransceiverDirection)nativeDirection {
switch (nativeDirection) {
case webrtc::RtpTransceiverDirection::kSendRecv:
return RTCRtpTransceiverDirectionSendRecv;
case webrtc::RtpTransceiverDirection::kSendOnly:
return RTCRtpTransceiverDirectionSendOnly;
case webrtc::RtpTransceiverDirection::kRecvOnly:
return RTCRtpTransceiverDirectionRecvOnly;
case webrtc::RtpTransceiverDirection::kInactive:
return RTCRtpTransceiverDirectionInactive;
}
}
@end