diff --git a/webrtc/api/BUILD.gn b/webrtc/api/BUILD.gn index 16c91c76a4..784c048905 100644 --- a/webrtc/api/BUILD.gn +++ b/webrtc/api/BUILD.gn @@ -53,6 +53,11 @@ if (is_ios) { #"objc/RTCMediaStreamTrack+Private.h", #"objc/RTCMediaStreamTrack.h", #"objc/RTCMediaStreamTrack.mm", + #"objc/RTCPeerConnection+DataChannel.h", + #"objc/RTCPeerConnection+Private.h", + #"objc/RTCPeerConnection+Stats.h", + #"objc/RTCPeerConnection.h", + #"objc/RTCPeerConnection.mm", #"objc/RTCPeerConnectionFactory+Private.h", #"objc/RTCPeerConnectionFactory.h", #"objc/RTCPeerConnectionFactory.mm", diff --git a/webrtc/api/api.gyp b/webrtc/api/api.gyp index fe7cd0eacc..1efd531456 100644 --- a/webrtc/api/api.gyp +++ b/webrtc/api/api.gyp @@ -176,6 +176,11 @@ 'objc/RTCMediaStreamTrack.mm', 'objc/RTCOpenGLVideoRenderer.h', 'objc/RTCOpenGLVideoRenderer.mm', + 'objc/RTCPeerConnection+DataChannel.mm', + 'objc/RTCPeerConnection+Private.h', + 'objc/RTCPeerConnection+Stats.mm', + 'objc/RTCPeerConnection.h', + 'objc/RTCPeerConnection.mm', 'objc/RTCPeerConnectionFactory+Private.h', 'objc/RTCPeerConnectionFactory.h', 'objc/RTCPeerConnectionFactory.mm', diff --git a/webrtc/api/objc/RTCIceCandidate+Private.h b/webrtc/api/objc/RTCIceCandidate+Private.h index b65f113f36..f98e04ba1c 100644 --- a/webrtc/api/objc/RTCIceCandidate+Private.h +++ b/webrtc/api/objc/RTCIceCandidate+Private.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN * ownership is taken of the native candidate. */ - (instancetype)initWithNativeCandidate: - (webrtc::IceCandidateInterface *)candidate; + (const webrtc::IceCandidateInterface *)candidate; @end diff --git a/webrtc/api/objc/RTCIceCandidate.mm b/webrtc/api/objc/RTCIceCandidate.mm index 9e094f6f06..b0b8abc8ca 100644 --- a/webrtc/api/objc/RTCIceCandidate.mm +++ b/webrtc/api/objc/RTCIceCandidate.mm @@ -42,7 +42,7 @@ #pragma mark - Private - (instancetype)initWithNativeCandidate: - (webrtc::IceCandidateInterface *)candidate { + (const webrtc::IceCandidateInterface *)candidate { NSParameterAssert(candidate); std::string sdp; candidate->ToString(&sdp); diff --git a/webrtc/api/objc/RTCPeerConnection+DataChannel.mm b/webrtc/api/objc/RTCPeerConnection+DataChannel.mm new file mode 100644 index 0000000000..cf646adda6 --- /dev/null +++ b/webrtc/api/objc/RTCPeerConnection+DataChannel.mm @@ -0,0 +1,31 @@ +/* + * Copyright 2015 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/api/objc/RTCPeerConnection+Private.h" + +#import "webrtc/api/objc/RTCDataChannel+Private.h" +#import "webrtc/api/objc/RTCDataChannelConfiguration+Private.h" +#import "webrtc/base/objc/NSString+StdString.h" + +@implementation RTCPeerConnection (DataChannel) + +- (RTCDataChannel *)dataChannelForLabel:(NSString *)label + configuration: + (RTCDataChannelConfiguration *)configuration { + std::string labelString = [NSString stdStringForString:label]; + const webrtc::DataChannelInit nativeInit = + configuration.nativeDataChannelInit; + rtc::scoped_refptr dataChannel = + self.nativePeerConnection->CreateDataChannel(labelString, + &nativeInit); + return [[RTCDataChannel alloc] initWithNativeDataChannel:dataChannel]; +} + +@end diff --git a/webrtc/api/objc/RTCPeerConnection+Private.h b/webrtc/api/objc/RTCPeerConnection+Private.h new file mode 100644 index 0000000000..feac8be6d9 --- /dev/null +++ b/webrtc/api/objc/RTCPeerConnection+Private.h @@ -0,0 +1,90 @@ +/* + * Copyright 2015 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/api/objc/RTCPeerConnection.h" + +#include "webrtc/api/peerconnectioninterface.h" + +NS_ASSUME_NONNULL_BEGIN + +namespace webrtc { + +/** + * These objects are created by RTCPeerConnectionFactory to wrap an + * id and call methods on that interface. + */ +class PeerConnectionDelegateAdapter : public PeerConnectionObserver { + + public: + PeerConnectionDelegateAdapter(RTCPeerConnection *peerConnection); + virtual ~PeerConnectionDelegateAdapter(); + + void OnSignalingChange( + PeerConnectionInterface::SignalingState new_state) override; + + void OnAddStream(MediaStreamInterface *stream) override; + + void OnRemoveStream(MediaStreamInterface *stream) override; + + void OnDataChannel(DataChannelInterface *data_channel) override; + + void OnRenegotiationNeeded() override; + + void OnIceConnectionChange( + PeerConnectionInterface::IceConnectionState new_state) override; + + void OnIceGatheringChange( + PeerConnectionInterface::IceGatheringState new_state) override; + + void OnIceCandidate(const IceCandidateInterface *candidate) override; + + private: + __weak RTCPeerConnection *peer_connection_; +}; + +} // namespace webrtc + + +@interface RTCPeerConnection () + +/** The native PeerConnectionInterface created during construction. */ +@property(nonatomic, readonly) + rtc::scoped_refptr nativePeerConnection; + ++ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState: + (RTCSignalingState)state; + ++ (RTCSignalingState)signalingStateForNativeState: + (webrtc::PeerConnectionInterface::SignalingState)nativeState; + ++ (NSString *)stringForSignalingState:(RTCSignalingState)state; + ++ (webrtc::PeerConnectionInterface::IceConnectionState) + nativeIceConnectionStateForState:(RTCIceConnectionState)state; + ++ (RTCIceConnectionState)iceConnectionStateForNativeState: + (webrtc::PeerConnectionInterface::IceConnectionState)nativeState; + ++ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state; + ++ (webrtc::PeerConnectionInterface::IceGatheringState) + nativeIceGatheringStateForState:(RTCIceGatheringState)state; + ++ (RTCIceGatheringState)iceGatheringStateForNativeState: + (webrtc::PeerConnectionInterface::IceGatheringState)nativeState; + ++ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state; + ++ (webrtc::PeerConnectionInterface::StatsOutputLevel) + nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level; + +@end + +NS_ASSUME_NONNULL_END diff --git a/webrtc/api/objc/RTCPeerConnection+Stats.mm b/webrtc/api/objc/RTCPeerConnection+Stats.mm new file mode 100644 index 0000000000..5032c84e54 --- /dev/null +++ b/webrtc/api/objc/RTCPeerConnection+Stats.mm @@ -0,0 +1,64 @@ +/* + * Copyright 2015 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/api/objc/RTCPeerConnection+Private.h" + +#include "webrtc/base/checks.h" + +#import "webrtc/api/objc/RTCMediaStreamTrack+Private.h" +#import "webrtc/api/objc/RTCStatsReport+Private.h" +#import "webrtc/base/objc/NSString+StdString.h" + +namespace webrtc { + +class StatsObserverAdapter : public StatsObserver { + public: + StatsObserverAdapter(void (^completionHandler) + (NSArray *stats)) { + completion_handler_ = completionHandler; + } + + ~StatsObserverAdapter() { + completion_handler_ = nil; + } + + void OnComplete(const StatsReports& reports) override { + RTC_DCHECK(completion_handler_); + NSMutableArray *stats = [NSMutableArray arrayWithCapacity:reports.size()]; + for (const auto* report : reports) { + RTCStatsReport *statsReport = + [[RTCStatsReport alloc] initWithNativeReport:*report]; + [stats addObject:statsReport]; + } + completion_handler_(stats); + completion_handler_ = nil; + } + + private: + void (^completion_handler_)(NSArray *stats); +}; +} // namespace webrtc + +@implementation RTCPeerConnection (Stats) + +- (void)statsForTrack:(RTCMediaStreamTrack *)mediaStreamTrack + statsOutputLevel:(RTCStatsOutputLevel)statsOutputLevel + completionHandler: + (void (^)(NSArray *stats))completionHandler { + rtc::scoped_refptr observer( + new rtc::RefCountedObject + (completionHandler)); + webrtc::PeerConnectionInterface::StatsOutputLevel nativeOutputLevel = + [[self class] nativeStatsOutputLevelForLevel:statsOutputLevel]; + self.nativePeerConnection->GetStats( + observer, mediaStreamTrack.nativeTrack, nativeOutputLevel); +} + +@end diff --git a/webrtc/api/objc/RTCPeerConnection.h b/webrtc/api/objc/RTCPeerConnection.h new file mode 100644 index 0000000000..46cb0855eb --- /dev/null +++ b/webrtc/api/objc/RTCPeerConnection.h @@ -0,0 +1,181 @@ +/* + * Copyright 2015 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 + +@class RTCConfiguration; +@class RTCDataChannel; +@class RTCDataChannelConfiguration; +@class RTCIceCandidate; +@class RTCMediaConstraints; +@class RTCMediaStream; +@class RTCMediaStreamTrack; +@class RTCPeerConnectionFactory; +@class RTCSessionDescription; +@class RTCStatsReport; + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kRTCPeerConnectionErrorDomain; +extern int const kRTCSessionDescriptionErrorCode; + +/** Represents the signaling state of the peer connection. */ +typedef NS_ENUM(NSInteger, RTCSignalingState) { + RTCSignalingStateStable, + RTCSignalingStateHaveLocalOffer, + RTCSignalingStateHaveLocalPrAnswer, + RTCSignalingStateHaveRemoteOffer, + RTCSignalingStateHaveRemotePrAnswer, + RTCSignalingStateClosed, +}; + +/** Represents the ice connection state of the peer connection. */ +typedef NS_ENUM(NSInteger, RTCIceConnectionState) { + RTCIceConnectionStateNew, + RTCIceConnectionStateChecking, + RTCIceConnectionStateConnected, + RTCIceConnectionStateCompleted, + RTCIceConnectionStateFailed, + RTCIceConnectionStateDisconnected, + RTCIceConnectionStateClosed, + RTCIceConnectionStateMax, +}; + +/** Represents the ice gathering state of the peer connection. */ +typedef NS_ENUM(NSInteger, RTCIceGatheringState) { + RTCIceGatheringStateNew, + RTCIceGatheringStateGathering, + RTCIceGatheringStateComplete, +}; + +/** Represents the stats output level. */ +typedef NS_ENUM(NSInteger, RTCStatsOutputLevel) { + RTCStatsOutputLevelStandard, + RTCStatsOutputLevelDebug, +}; + +@class RTCPeerConnection; + +@protocol RTCPeerConnectionDelegate + +/** Called when the SignalingState changed. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didChangeSignalingState:(RTCSignalingState)stateChanged; + +/** Called when media is received on a new stream from remote peer. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didAddStream:(RTCMediaStream *)stream; + +/** Called when a remote peer closes a stream. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didRemoveStream:(RTCMediaStream *)stream; + +/** Called when negotiation is needed, for example ICE has restarted. */ +- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection; + +/** Called any time the IceConnectionState changes. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didChangeIceConnectionState:(RTCIceConnectionState)newState; + +/** Called any time the IceGatheringState changes. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didChangeIceGatheringState:(RTCIceGatheringState)newState; + +/** New ice candidate has been found. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didGenerateIceCandidate:(RTCIceCandidate *)candidate; + +/** New data channel has been opened. */ +- (void)peerConnection:(RTCPeerConnection *)peerConnection + didOpenDataChannel:(RTCDataChannel *)dataChannel; + +@end + + +@interface RTCPeerConnection : NSObject + +/** The object that will be notifed about events such as state changes and + * streams being added or removed. + */ +@property(nonatomic, weak) id delegate; +@property(nonatomic, readonly) NSArray *localStreams; +@property(nonatomic, readonly, nullable) + RTCSessionDescription *localDescription; +@property(nonatomic, readonly, nullable) + RTCSessionDescription *remoteDescription; +@property(nonatomic, readonly) RTCSignalingState signalingState; +@property(nonatomic, readonly) RTCIceConnectionState iceConnectionState; +@property(nonatomic, readonly) RTCIceGatheringState iceGatheringState; + +- (instancetype)init NS_UNAVAILABLE; + +/** Initialize an RTCPeerConnection with a configuration, constraints, and + * delegate. + */ +- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory + configuration:(RTCConfiguration *)configuration + constraints:(RTCMediaConstraints *)constraints + delegate:(id)delegate + NS_DESIGNATED_INITIALIZER; + +/** Terminate all media and close the transport. */ +- (void)close; + +/** Provide a remote candidate to the ICE Agent. */ +- (void)addIceCandidate:(RTCIceCandidate *)candidate; + +/** Add a new media stream to be sent on this peer connection. */ +- (void)addStream:(RTCMediaStream *)stream; + +/** Remove the given media stream from this peer connection. */ +- (void)removeStream:(RTCMediaStream *)stream; + +/** Generate an SDP offer. */ +- (void)offerForConstraints:(RTCMediaConstraints *)constraints + completionHandler:(void (^)(RTCSessionDescription *sdp, + NSError *error))completionHandler; + +/** Generate an SDP answer. */ +- (void)answerForConstraints:(RTCMediaConstraints *)constraints + completionHandler:(void (^)(RTCSessionDescription *sdp, + NSError *error))completionHandler; + +/** Apply the supplied RTCSessionDescription as the local description. */ +- (void)setLocalDescription:(RTCSessionDescription *)sdp + completionHandler:(void (^)(NSError *error))completionHandler; + +/** Apply the supplied RTCSessionDescription as the remote description. */ +- (void)setRemoteDescription:(RTCSessionDescription *)sdp + completionHandler:(void (^)(NSError *error))completionHandler; + +@end + +@interface RTCPeerConnection (DataChannel) + +/** Create a new data channel with the given label and configuration. */ +- (RTCDataChannel *)dataChannelForLabel:(NSString *)label + configuration:(RTCDataChannelConfiguration *)configuration; + +@end + +@interface RTCPeerConnection (Stats) + +/** Gather stats for the given RTCMediaStreamTrack. If |mediaStreamTrack| is nil + * statistics are gathered for all tracks. + */ +- (void)statsForTrack: + (nullable RTCMediaStreamTrack *)mediaStreamTrack + statsOutputLevel:(RTCStatsOutputLevel)statsOutputLevel + completionHandler: + (void (^)(NSArray *stats))completionHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/webrtc/api/objc/RTCPeerConnection.mm b/webrtc/api/objc/RTCPeerConnection.mm new file mode 100644 index 0000000000..f75d6636fa --- /dev/null +++ b/webrtc/api/objc/RTCPeerConnection.mm @@ -0,0 +1,479 @@ +/* + * Copyright 2015 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/api/objc/RTCPeerConnection.h" + +#include "webrtc/base/checks.h" + +#import "webrtc/api/objc/RTCPeerConnection+Private.h" +#import "webrtc/api/objc/RTCConfiguration+Private.h" +#import "webrtc/api/objc/RTCDataChannel+Private.h" +#import "webrtc/api/objc/RTCIceCandidate+Private.h" +#import "webrtc/api/objc/RTCMediaConstraints+Private.h" +#import "webrtc/api/objc/RTCMediaStream+Private.h" +#import "webrtc/api/objc/RTCPeerConnectionFactory+Private.h" +#import "webrtc/api/objc/RTCSessionDescription+Private.h" +#import "webrtc/api/objc/RTCStatsReport+Private.h" +#import "webrtc/base/objc/RTCLogging.h" +#import "webrtc/base/objc/NSString+StdString.h" + +NSString * const kRTCPeerConnectionErrorDomain = + @"org.webrtc.RTCPeerConnection"; +int const kRTCPeerConnnectionSessionDescriptionError = -1; + +namespace webrtc { + +class CreateSessionDescriptionObserverAdapter + : public CreateSessionDescriptionObserver { + public: + CreateSessionDescriptionObserverAdapter( + void (^completionHandler)(RTCSessionDescription *sessionDescription, + NSError *error)) { + completion_handler_ = completionHandler; + } + + ~CreateSessionDescriptionObserverAdapter() { + completion_handler_ = nil; + } + + void OnSuccess(SessionDescriptionInterface *desc) override { + RTC_DCHECK(completion_handler_); + rtc::scoped_ptr description = + rtc::scoped_ptr(desc); + RTCSessionDescription* session = + [[RTCSessionDescription alloc] initWithNativeDescription: + description.get()]; + completion_handler_(session, nil); + completion_handler_ = nil; + } + + void OnFailure(const std::string& error) override { + RTC_DCHECK(completion_handler_); + NSString* str = [NSString stringForStdString:error]; + NSError* err = + [NSError errorWithDomain:kRTCPeerConnectionErrorDomain + code:kRTCPeerConnnectionSessionDescriptionError + userInfo:@{ NSLocalizedDescriptionKey : str }]; + completion_handler_(nil, err); + completion_handler_ = nil; + } + + private: + void (^completion_handler_) + (RTCSessionDescription *sessionDescription, NSError *error); +}; + +class SetSessionDescriptionObserverAdapter : + public SetSessionDescriptionObserver { + public: + SetSessionDescriptionObserverAdapter(void (^completionHandler) + (NSError *error)) { + completion_handler_ = completionHandler; + } + + ~SetSessionDescriptionObserverAdapter() { + completion_handler_ = nil; + } + + void OnSuccess() override { + RTC_DCHECK(completion_handler_); + completion_handler_(nil); + completion_handler_ = nil; + } + + void OnFailure(const std::string& error) override { + RTC_DCHECK(completion_handler_); + NSString* str = [NSString stringForStdString:error]; + NSError* err = + [NSError errorWithDomain:kRTCPeerConnectionErrorDomain + code:kRTCPeerConnnectionSessionDescriptionError + userInfo:@{ NSLocalizedDescriptionKey : str }]; + completion_handler_(err); + completion_handler_ = nil; + } + + private: + void (^completion_handler_)(NSError *error); +}; + +PeerConnectionDelegateAdapter::PeerConnectionDelegateAdapter( + RTCPeerConnection *peerConnection) { + peer_connection_ = peerConnection; +} + +PeerConnectionDelegateAdapter::~PeerConnectionDelegateAdapter() { + peer_connection_ = nil; +} + +void PeerConnectionDelegateAdapter::OnSignalingChange( + PeerConnectionInterface::SignalingState new_state) { + RTCSignalingState state = + [[RTCPeerConnection class] signalingStateForNativeState:new_state]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didChangeSignalingState:state]; +} + +void PeerConnectionDelegateAdapter::OnAddStream( + MediaStreamInterface *stream) { + RTCMediaStream *mediaStream = + [[RTCMediaStream alloc] initWithNativeMediaStream:stream]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didAddStream:mediaStream]; +} + +void PeerConnectionDelegateAdapter::OnRemoveStream( + MediaStreamInterface *stream) { + RTCMediaStream *mediaStream = + [[RTCMediaStream alloc] initWithNativeMediaStream:stream]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didRemoveStream:mediaStream]; +} + +void PeerConnectionDelegateAdapter::OnDataChannel( + DataChannelInterface *data_channel) { + RTCDataChannel *dataChannel = + [[RTCDataChannel alloc] initWithNativeDataChannel:data_channel]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didOpenDataChannel:dataChannel]; +} + +void PeerConnectionDelegateAdapter::OnRenegotiationNeeded() { + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnectionShouldNegotiate:peer_connection]; +} + +void PeerConnectionDelegateAdapter::OnIceConnectionChange( + PeerConnectionInterface::IceConnectionState new_state) { + RTCIceConnectionState state = + [[RTCPeerConnection class] iceConnectionStateForNativeState:new_state]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didChangeIceConnectionState:state]; +} + +void PeerConnectionDelegateAdapter::OnIceGatheringChange( + PeerConnectionInterface::IceGatheringState new_state) { + RTCIceGatheringState state = + [[RTCPeerConnection class] iceGatheringStateForNativeState:new_state]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didChangeIceGatheringState:state]; +} + +void PeerConnectionDelegateAdapter::OnIceCandidate( + const IceCandidateInterface *candidate) { + RTCIceCandidate *iceCandidate = + [[RTCIceCandidate alloc] initWithNativeCandidate:candidate]; + RTCPeerConnection *peer_connection = peer_connection_; + [peer_connection.delegate peerConnection:peer_connection + didGenerateIceCandidate:iceCandidate]; +} +} // namespace webrtc + + +@implementation RTCPeerConnection { + NSMutableArray *_localStreams; + rtc::scoped_ptr _observer; + rtc::scoped_refptr _peerConnection; +} + +@synthesize delegate = _delegate; + +- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory + configuration:(RTCConfiguration *)configuration + constraints:(RTCMediaConstraints *)constraints + delegate:(id)delegate { + NSParameterAssert(factory); + if (self = [super init]) { + _observer.reset(new webrtc::PeerConnectionDelegateAdapter(self)); + webrtc::PeerConnectionInterface::RTCConfiguration config = + configuration.nativeConfiguration; + webrtc::MediaConstraints *nativeConstraints = + constraints.nativeConstraints.get(); + _peerConnection = + factory.nativeFactory->CreatePeerConnection(config, + nativeConstraints, + nullptr, + nullptr, + _observer.get()); + _localStreams = [[NSMutableArray alloc] init]; + _delegate = delegate; + } + return self; +} + +- (NSArray *)localStreams { + return [_localStreams copy]; +} + +- (RTCSessionDescription *)localDescription { + const webrtc::SessionDescriptionInterface *description = + _peerConnection->local_description(); + return description ? + [[RTCSessionDescription alloc] initWithNativeDescription:description] + : nil; +} + +- (RTCSessionDescription *)remoteDescription { + const webrtc::SessionDescriptionInterface *description = + _peerConnection->remote_description(); + return description ? + [[RTCSessionDescription alloc] initWithNativeDescription:description] + : nil; +} + +- (RTCSignalingState)signalingState { + return [[self class] + signalingStateForNativeState:_peerConnection->signaling_state()]; +} + +- (RTCIceConnectionState)iceConnectionState { + return [[self class] iceConnectionStateForNativeState: + _peerConnection->ice_connection_state()]; +} + +- (RTCIceGatheringState)iceGatheringState { + return [[self class] iceGatheringStateForNativeState: + _peerConnection->ice_gathering_state()]; +} + +- (void)close { + _peerConnection->Close(); +} + +- (void)addIceCandidate:(RTCIceCandidate *)candidate { + rtc::scoped_ptr iceCandidate( + candidate.nativeCandidate); + _peerConnection->AddIceCandidate(iceCandidate.get()); +} + +- (void)addStream:(RTCMediaStream *)stream { + if (_peerConnection->AddStream(stream.nativeMediaStream)) { + RTCLogError(@"Failed to add stream: %@", stream); + return; + } + [_localStreams addObject:stream]; +} + +- (void)removeStream:(RTCMediaStream *)stream { + _peerConnection->RemoveStream(stream.nativeMediaStream); + [_localStreams removeObject:stream]; +} + +- (void)offerForConstraints:(RTCMediaConstraints *)constraints + completionHandler: + (void (^)(RTCSessionDescription *sessionDescription, + NSError *error))completionHandler { + rtc::scoped_refptr + observer(new rtc::RefCountedObject + (completionHandler)); + _peerConnection->CreateOffer(observer, constraints.nativeConstraints.get()); +} + +- (void)answerForConstraints:(RTCMediaConstraints *)constraints + completionHandler: + (void (^)(RTCSessionDescription *sessionDescription, + NSError *error))completionHandler { + rtc::scoped_refptr + observer(new rtc::RefCountedObject + (completionHandler)); + _peerConnection->CreateAnswer(observer, constraints.nativeConstraints.get()); +} + +- (void)setLocalDescription:(RTCSessionDescription *)sdp + completionHandler:(void (^)(NSError *error))completionHandler { + rtc::scoped_refptr observer( + new rtc::RefCountedObject( + completionHandler)); + _peerConnection->SetLocalDescription(observer, sdp.nativeDescription); +} + +- (void)setRemoteDescription:(RTCSessionDescription *)sdp + completionHandler:(void (^)(NSError *error))completionHandler { + rtc::scoped_refptr observer( + new rtc::RefCountedObject( + completionHandler)); + _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription); +} + +#pragma mark - Private + ++ (webrtc::PeerConnectionInterface::SignalingState)nativeSignalingStateForState: + (RTCSignalingState)state { + switch (state) { + case RTCSignalingStateStable: + return webrtc::PeerConnectionInterface::kStable; + case RTCSignalingStateHaveLocalOffer: + return webrtc::PeerConnectionInterface::kHaveLocalOffer; + case RTCSignalingStateHaveLocalPrAnswer: + return webrtc::PeerConnectionInterface::kHaveLocalPrAnswer; + case RTCSignalingStateHaveRemoteOffer: + return webrtc::PeerConnectionInterface::kHaveRemoteOffer; + case RTCSignalingStateHaveRemotePrAnswer: + return webrtc::PeerConnectionInterface::kHaveRemotePrAnswer; + case RTCSignalingStateClosed: + return webrtc::PeerConnectionInterface::kClosed; + } +} + ++ (RTCSignalingState)signalingStateForNativeState: + (webrtc::PeerConnectionInterface::SignalingState)nativeState { + switch (nativeState) { + case webrtc::PeerConnectionInterface::kStable: + return RTCSignalingStateStable; + case webrtc::PeerConnectionInterface::kHaveLocalOffer: + return RTCSignalingStateHaveLocalOffer; + case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: + return RTCSignalingStateHaveLocalPrAnswer; + case webrtc::PeerConnectionInterface::kHaveRemoteOffer: + return RTCSignalingStateHaveRemoteOffer; + case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: + return RTCSignalingStateHaveRemotePrAnswer; + case webrtc::PeerConnectionInterface::kClosed: + return RTCSignalingStateClosed; + } +} + ++ (NSString *)stringForSignalingState:(RTCSignalingState)state { + switch (state) { + case RTCSignalingStateStable: + return @"STABLE"; + case RTCSignalingStateHaveLocalOffer: + return @"HAVE_LOCAL_OFFER"; + case RTCSignalingStateHaveLocalPrAnswer: + return @"HAVE_LOCAL_PRANSWER"; + case RTCSignalingStateHaveRemoteOffer: + return @"HAVE_REMOTE_OFFER"; + case RTCSignalingStateHaveRemotePrAnswer: + return @"HAVE_REMOTE_PRANSWER"; + case RTCSignalingStateClosed: + return @"CLOSED"; + } +} + ++ (webrtc::PeerConnectionInterface::IceConnectionState) + nativeIceConnectionStateForState:(RTCIceConnectionState)state { + switch (state) { + case RTCIceConnectionStateNew: + return webrtc::PeerConnectionInterface::kIceConnectionNew; + case RTCIceConnectionStateChecking: + return webrtc::PeerConnectionInterface::kIceConnectionChecking; + case RTCIceConnectionStateConnected: + return webrtc::PeerConnectionInterface::kIceConnectionConnected; + case RTCIceConnectionStateCompleted: + return webrtc::PeerConnectionInterface::kIceConnectionCompleted; + case RTCIceConnectionStateFailed: + return webrtc::PeerConnectionInterface::kIceConnectionFailed; + case RTCIceConnectionStateDisconnected: + return webrtc::PeerConnectionInterface::kIceConnectionDisconnected; + case RTCIceConnectionStateClosed: + return webrtc::PeerConnectionInterface::kIceConnectionClosed; + case RTCIceConnectionStateMax: + return webrtc::PeerConnectionInterface::kIceConnectionMax; + } +} + ++ (RTCIceConnectionState)iceConnectionStateForNativeState: + (webrtc::PeerConnectionInterface::IceConnectionState)nativeState { + switch (nativeState) { + case webrtc::PeerConnectionInterface::kIceConnectionNew: + return RTCIceConnectionStateNew; + case webrtc::PeerConnectionInterface::kIceConnectionChecking: + return RTCIceConnectionStateChecking; + case webrtc::PeerConnectionInterface::kIceConnectionConnected: + return RTCIceConnectionStateConnected; + case webrtc::PeerConnectionInterface::kIceConnectionCompleted: + return RTCIceConnectionStateCompleted; + case webrtc::PeerConnectionInterface::kIceConnectionFailed: + return RTCIceConnectionStateFailed; + case webrtc::PeerConnectionInterface::kIceConnectionDisconnected: + return RTCIceConnectionStateDisconnected; + case webrtc::PeerConnectionInterface::kIceConnectionClosed: + return RTCIceConnectionStateClosed; + case webrtc::PeerConnectionInterface::kIceConnectionMax: + return RTCIceConnectionStateMax; + } +} + ++ (NSString *)stringForIceConnectionState:(RTCIceConnectionState)state { + switch (state) { + case RTCIceConnectionStateNew: + return @"NEW"; + case RTCIceConnectionStateChecking: + return @"CHECKING"; + case RTCIceConnectionStateConnected: + return @"CONNECTED"; + case RTCIceConnectionStateCompleted: + return @"COMPLETED"; + case RTCIceConnectionStateFailed: + return @"FAILED"; + case RTCIceConnectionStateDisconnected: + return @"DISCONNECTED"; + case RTCIceConnectionStateClosed: + return @"CLOSED"; + case RTCIceConnectionStateMax: + return @"MAX"; + } +} + ++ (webrtc::PeerConnectionInterface::IceGatheringState) + nativeIceGatheringStateForState:(RTCIceGatheringState)state { + switch (state) { + case RTCIceGatheringStateNew: + return webrtc::PeerConnectionInterface::kIceGatheringNew; + case RTCIceGatheringStateGathering: + return webrtc::PeerConnectionInterface::kIceGatheringGathering; + case RTCIceGatheringStateComplete: + return webrtc::PeerConnectionInterface::kIceGatheringComplete; + } +} + ++ (RTCIceGatheringState)iceGatheringStateForNativeState: + (webrtc::PeerConnectionInterface::IceGatheringState)nativeState { + switch (nativeState) { + case webrtc::PeerConnectionInterface::kIceGatheringNew: + return RTCIceGatheringStateNew; + case webrtc::PeerConnectionInterface::kIceGatheringGathering: + return RTCIceGatheringStateGathering; + case webrtc::PeerConnectionInterface::kIceGatheringComplete: + return RTCIceGatheringStateComplete; + } +} + ++ (NSString *)stringForIceGatheringState:(RTCIceGatheringState)state { + switch (state) { + case RTCIceGatheringStateNew: + return @"NEW"; + case RTCIceGatheringStateGathering: + return @"GATHERING"; + case RTCIceGatheringStateComplete: + return @"COMPLETE"; + } +} + ++ (webrtc::PeerConnectionInterface::StatsOutputLevel) + nativeStatsOutputLevelForLevel:(RTCStatsOutputLevel)level { + switch (level) { + case RTCStatsOutputLevelStandard: + return webrtc::PeerConnectionInterface::kStatsOutputLevelStandard; + case RTCStatsOutputLevelDebug: + return webrtc::PeerConnectionInterface::kStatsOutputLevelDebug; + } +} + +- (rtc::scoped_refptr)nativePeerConnection { + return _peerConnection; +} + +@end diff --git a/webrtc/api/objc/RTCSessionDescription+Private.h b/webrtc/api/objc/RTCSessionDescription+Private.h index b5c0fff671..2a9601d4d1 100644 --- a/webrtc/api/objc/RTCSessionDescription+Private.h +++ b/webrtc/api/objc/RTCSessionDescription+Private.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN * description. */ - (instancetype)initWithNativeDescription: - (webrtc::SessionDescriptionInterface *)nativeDescription; + (const webrtc::SessionDescriptionInterface *)nativeDescription; + (std::string)stringForType:(RTCSdpType)type; diff --git a/webrtc/api/objc/RTCSessionDescription.mm b/webrtc/api/objc/RTCSessionDescription.mm index 5066301fe7..e401fbc3fb 100644 --- a/webrtc/api/objc/RTCSessionDescription.mm +++ b/webrtc/api/objc/RTCSessionDescription.mm @@ -56,7 +56,7 @@ } - (instancetype)initWithNativeDescription: - (webrtc::SessionDescriptionInterface *)nativeDescription { + (const webrtc::SessionDescriptionInterface *)nativeDescription { NSParameterAssert(nativeDescription); std::string sdp; nativeDescription->ToString(&sdp);