2016-02-11 16:19:06 -08:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2016-04-27 01:54:20 -07:00
|
|
|
#import "RTCPeerConnection+Private.h"
|
|
|
|
|
|
|
|
|
|
#import "NSString+StdString.h"
|
|
|
|
|
#import "RTCConfiguration+Private.h"
|
|
|
|
|
#import "RTCDataChannel+Private.h"
|
|
|
|
|
#import "RTCIceCandidate+Private.h"
|
2016-09-09 01:36:28 -07:00
|
|
|
#import "RTCLegacyStatsReport+Private.h"
|
2016-04-27 01:54:20 -07:00
|
|
|
#import "RTCMediaConstraints+Private.h"
|
|
|
|
|
#import "RTCMediaStream+Private.h"
|
|
|
|
|
#import "RTCPeerConnectionFactory+Private.h"
|
2016-05-16 11:40:30 -07:00
|
|
|
#import "RTCRtpReceiver+Private.h"
|
2016-04-27 01:54:20 -07:00
|
|
|
#import "RTCRtpSender+Private.h"
|
|
|
|
|
#import "RTCSessionDescription+Private.h"
|
|
|
|
|
#import "WebRTC/RTCLogging.h"
|
2016-02-11 16:19:06 -08:00
|
|
|
|
2016-05-01 14:53:46 -07:00
|
|
|
#include <memory>
|
|
|
|
|
|
2016-05-23 11:53:14 -07:00
|
|
|
#include "webrtc/api/jsepicecandidate.h"
|
2017-07-07 03:09:51 -07:00
|
|
|
#include "webrtc/rtc_base/checks.h"
|
2016-02-11 16:19:06 -08:00
|
|
|
|
|
|
|
|
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_);
|
2016-05-01 14:53:46 -07:00
|
|
|
std::unique_ptr<webrtc::SessionDescriptionInterface> description =
|
|
|
|
|
std::unique_ptr<webrtc::SessionDescriptionInterface>(desc);
|
2016-02-11 16:19:06 -08:00
|
|
|
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(
|
2016-06-08 13:31:45 -07:00
|
|
|
rtc::scoped_refptr<MediaStreamInterface> stream) {
|
Revert of Add the OnAddTrack callback for Objective-C wrapper. (patchset #7 id:240001 of https://codereview.webrtc.org/2513063003/ )
Reason for revert:
This CL breaks iOS AppRTCMobile. We don't have any automatic tests running on the bots yet, so please try AppRTCMobile locally before relanding.
Stack trace:
* thread #15: tid = 0x20e933, 0x0000000100488440 AppRTCMobile`webrtc::AudioRtpReceiver::OnFirstPacketReceived(this=0x0000000170156c60, channel=0x000000010511a600) + 48 at rtpreceiver.cc:133, name = 'Thread 0x0x10421b2a0', stop reason = EXC_BAD_ACCESS (code=1, address=0x1a1aac71979)
* frame #0: 0x0000000100488440 AppRTCMobile`webrtc::AudioRtpReceiver::OnFirstPacketReceived(this=0x0000000170156c60, channel=0x000000010511a600) + 48 at rtpreceiver.cc:133
frame #1: 0x000000010048a3f8 AppRTCMobile`void sigslot::_opaque_connection::emitter<webrtc::AudioRtpReceiver, cricket::BaseChannel*>(self=0x000000017424b380, args=0x000000010511a600) + 184 at sigslot.h:391
frame #2: 0x00000001005a30ec AppRTCMobile`void sigslot::_opaque_connection::emit<cricket::BaseChannel*>(this=0x000000017424b380, args=0x000000010511a600) const + 56 at sigslot.h:381
frame #3: 0x00000001005a3094 AppRTCMobile`sigslot::signal_with_thread_policy<sigslot::single_threaded, cricket::BaseChannel*>::emit(this=0x000000010511a678, args=0x000000010511a600) + 504 at sigslot.h:615
frame #4: 0x000000010057ef5c AppRTCMobile`sigslot::signal_with_thread_policy<sigslot::single_threaded, cricket::BaseChannel*>::operator(this=0x000000010511a678, args=0x000000010511a600)(cricket::BaseChannel*) + 32 at sigslot.h:621
frame #5: 0x000000010057ef00 AppRTCMobile`cricket::BaseChannel::OnMessage(this=0x000000010511a600, pmsg=0x000000016e676db0) + 600 at channel.cc:1494
frame #6: 0x0000000100584a58 AppRTCMobile`cricket::VoiceChannel::OnMessage(this=0x000000010511a600, pmsg=0x000000016e676db0) + 152 at channel.cc:1909
frame #7: 0x000000010017c0dc AppRTCMobile`rtc::MessageQueue::Dispatch(this=0x000000010421b2a0, pmsg=0x000000016e676db0) + 336 at messagequeue.cc:538
frame #8: 0x00000001001d8efc AppRTCMobile`rtc::Thread::ProcessMessages(this=0x000000010421b2a0, cmsLoop=-1) + 228 at thread.cc:496
frame #9: 0x00000001001d8e08 AppRTCMobile`rtc::Thread::Run(this=0x000000010421b2a0) + 28 at thread.cc:327
frame #10: 0x00000001001d8b0c AppRTCMobile`rtc::Thread::PreRun(pv=0x000000017000f030) + 300 at thread.cc:316
frame #11: 0x00000001843f1850 libsystem_pthread.dylib`_pthread_body + 240
frame #12: 0x00000001843f1760 libsystem_pthread.dylib`_pthread_start + 284
frame #13: 0x00000001843eed94 libsystem_pthread.dylib`thread_start + 4
Original issue's description:
> Add the OnAddTrack callback for Objective-C wrapper.
>
> Created an Obj-C wrapper for the callback OnAddTrack in this CL since it has been added to native C++ API
> The callback function is called when a track is signaled by remote side and a new RtpReceiver is created.
> The application can tell when tracks are added to the streams by listening to this callback.
>
> BUG=webrtc:6112
>
> Review-Url: https://codereview.webrtc.org/2513063003
> Cr-Commit-Position: refs/heads/master@{#16835}
> Committed: https://chromium.googlesource.com/external/webrtc/+/633f6fe0046131ed815098298b9a3120bac1d7a0
TBR=tkchin@webrtc.org,deadbeef@webrtc.org,zhihuang@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:6112
Review-Url: https://codereview.webrtc.org/2720753002
Cr-Commit-Position: refs/heads/master@{#16871}
2017-02-27 07:04:25 -08:00
|
|
|
RTCMediaStream *mediaStream =
|
|
|
|
|
[[RTCMediaStream alloc] initWithNativeMediaStream:stream];
|
2016-02-11 16:19:06 -08:00
|
|
|
RTCPeerConnection *peer_connection = peer_connection_;
|
|
|
|
|
[peer_connection.delegate peerConnection:peer_connection
|
|
|
|
|
didAddStream:mediaStream];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnectionDelegateAdapter::OnRemoveStream(
|
2016-06-08 13:31:45 -07:00
|
|
|
rtc::scoped_refptr<MediaStreamInterface> stream) {
|
2016-02-11 16:19:06 -08:00
|
|
|
RTCMediaStream *mediaStream =
|
|
|
|
|
[[RTCMediaStream alloc] initWithNativeMediaStream:stream];
|
|
|
|
|
RTCPeerConnection *peer_connection = peer_connection_;
|
|
|
|
|
[peer_connection.delegate peerConnection:peer_connection
|
|
|
|
|
didRemoveStream:mediaStream];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PeerConnectionDelegateAdapter::OnDataChannel(
|
2016-06-08 13:31:45 -07:00
|
|
|
rtc::scoped_refptr<DataChannelInterface> data_channel) {
|
2016-02-11 16:19:06 -08:00
|
|
|
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];
|
|
|
|
|
}
|
2016-05-23 11:53:14 -07:00
|
|
|
|
|
|
|
|
void PeerConnectionDelegateAdapter::OnIceCandidatesRemoved(
|
|
|
|
|
const std::vector<cricket::Candidate>& candidates) {
|
|
|
|
|
NSMutableArray* ice_candidates =
|
|
|
|
|
[NSMutableArray arrayWithCapacity:candidates.size()];
|
|
|
|
|
for (const auto& candidate : candidates) {
|
|
|
|
|
std::unique_ptr<JsepIceCandidate> candidate_wrapper(
|
|
|
|
|
new JsepIceCandidate(candidate.transport_name(), -1, candidate));
|
|
|
|
|
RTCIceCandidate* ice_candidate = [[RTCIceCandidate alloc]
|
|
|
|
|
initWithNativeCandidate:candidate_wrapper.get()];
|
|
|
|
|
[ice_candidates addObject:ice_candidate];
|
|
|
|
|
}
|
|
|
|
|
RTCPeerConnection* peer_connection = peer_connection_;
|
|
|
|
|
[peer_connection.delegate peerConnection:peer_connection
|
|
|
|
|
didRemoveIceCandidates:ice_candidates];
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 16:19:06 -08:00
|
|
|
} // namespace webrtc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation RTCPeerConnection {
|
2016-08-18 14:21:20 -07:00
|
|
|
NSMutableArray<RTCMediaStream *> *_localStreams;
|
2016-05-01 14:53:46 -07:00
|
|
|
std::unique_ptr<webrtc::PeerConnectionDelegateAdapter> _observer;
|
2016-02-11 16:19:06 -08:00
|
|
|
rtc::scoped_refptr<webrtc::PeerConnectionInterface> _peerConnection;
|
2017-01-09 16:05:28 -08:00
|
|
|
std::unique_ptr<webrtc::MediaConstraints> _nativeConstraints;
|
2016-07-04 07:06:55 -07:00
|
|
|
BOOL _hasStartedRtcEventLog;
|
2016-02-11 16:19:06 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@synthesize delegate = _delegate;
|
|
|
|
|
|
|
|
|
|
- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
|
|
|
|
|
configuration:(RTCConfiguration *)configuration
|
|
|
|
|
constraints:(RTCMediaConstraints *)constraints
|
|
|
|
|
delegate:(id<RTCPeerConnectionDelegate>)delegate {
|
|
|
|
|
NSParameterAssert(factory);
|
2016-05-13 13:50:38 +02:00
|
|
|
std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
|
2016-05-17 03:28:58 -07:00
|
|
|
[configuration createNativeConfiguration]);
|
|
|
|
|
if (!config) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2016-02-11 16:19:06 -08:00
|
|
|
if (self = [super init]) {
|
|
|
|
|
_observer.reset(new webrtc::PeerConnectionDelegateAdapter(self));
|
2017-01-09 16:05:28 -08:00
|
|
|
_nativeConstraints = constraints.nativeConstraints;
|
|
|
|
|
CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(),
|
|
|
|
|
config.get());
|
2016-02-11 16:19:06 -08:00
|
|
|
_peerConnection =
|
Revert of Replacing DtlsIdentityStoreInterface with RTCCertificateGeneratorInterface. (patchset #2 id:20001 of https://codereview.webrtc.org/2013523002/ )
Reason for revert:
There are more CreatePeerConnection calls than I anticipated/had found in Chromium, like remoting/protocol/webrtc_transport.cc. Reverting due to broken Chromium FYI bots.
Original issue's description:
> Replacing DtlsIdentityStoreInterface with RTCCertificateGeneratorInterface.
>
> The store was used in WebRtcSessionDescriptionFactory to generate certificates,
> now a generator is used instead (new API). PeerConnection[Factory][Interface],
> and WebRtcSession are updated to pass generators all the way down to the
> WebRtcSessionDescriptionFactory instead of stores.
>
> The webrtc implementation of a generator, RTCCertificateGenerator, is used as
> the default generator (peerconnectionfactory.cc:189) instead of the webrtc
> implementation of a store, DtlsIdentityStoreImpl.
> The generator is fully parameterized and does not generate RSA-1024 unless you
> ask for it (which makes sense not to do beforehand since ECDSA is now default).
> The store was not fully parameterized (known filed bug).
>
> The "top" layer, PeerConnectionFactoryInterface::CreatePeerConnection, is
> updated to take a generator instead of a store. But as to not break Chromium,
> the old function signature taking a store is kept. It is implemented to invoke
> the generator version by wrapping the store in an
> RTCCertificateGeneratorStoreWrapper. As soon as Chromium is updated to use the
> new function signature we can remove the old CreatePeerConnection.
> Due to having multiple CreatePeerConnection signatures, some calling places
> are updated to resolve the ambiguity introduced.
>
> BUG=webrtc:5707, webrtc:5708
> R=phoglund@webrtc.org, tommi@webrtc.org
> TBR=tkchin@webrc.org
>
> Committed: https://chromium.googlesource.com/external/webrtc/+/400781a2091d09a725b32c6953247036b22478e8
TBR=tkchin@webrtc.org,tommi@webrtc.org,phoglund@webrtc.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=webrtc:5707, webrtc:5708
Review-Url: https://codereview.webrtc.org/2020633002
Cr-Commit-Position: refs/heads/master@{#12948}
2016-05-27 06:08:53 -07:00
|
|
|
factory.nativeFactory->CreatePeerConnection(*config,
|
|
|
|
|
nullptr,
|
|
|
|
|
nullptr,
|
|
|
|
|
_observer.get());
|
2016-08-11 14:29:25 -07:00
|
|
|
if (!_peerConnection) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2016-02-11 16:19:06 -08:00
|
|
|
_localStreams = [[NSMutableArray alloc] init];
|
|
|
|
|
_delegate = delegate;
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-18 14:21:20 -07:00
|
|
|
- (NSArray<RTCMediaStream *> *)localStreams {
|
2016-02-11 16:19:06 -08:00
|
|
|
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()];
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-09 21:49:40 -08:00
|
|
|
- (BOOL)setConfiguration:(RTCConfiguration *)configuration {
|
2016-05-13 13:50:38 +02:00
|
|
|
std::unique_ptr<webrtc::PeerConnectionInterface::RTCConfiguration> config(
|
2016-05-17 03:28:58 -07:00
|
|
|
[configuration createNativeConfiguration]);
|
|
|
|
|
if (!config) {
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2017-01-09 16:05:28 -08:00
|
|
|
CopyConstraintsIntoRtcConfiguration(_nativeConstraints.get(),
|
|
|
|
|
config.get());
|
2016-05-13 13:50:38 +02:00
|
|
|
return _peerConnection->SetConfiguration(*config);
|
2016-03-09 21:49:40 -08:00
|
|
|
}
|
|
|
|
|
|
2017-04-03 15:06:37 -07:00
|
|
|
- (RTCConfiguration *)configuration {
|
|
|
|
|
webrtc::PeerConnectionInterface::RTCConfiguration config =
|
|
|
|
|
_peerConnection->GetConfiguration();
|
2017-04-04 14:00:16 -07:00
|
|
|
return [[RTCConfiguration alloc] initWithNativeConfiguration:config];
|
2017-04-03 15:06:37 -07:00
|
|
|
}
|
|
|
|
|
|
2016-02-11 16:19:06 -08:00
|
|
|
- (void)close {
|
|
|
|
|
_peerConnection->Close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)addIceCandidate:(RTCIceCandidate *)candidate {
|
2016-05-01 14:53:46 -07:00
|
|
|
std::unique_ptr<const webrtc::IceCandidateInterface> iceCandidate(
|
2016-02-11 16:19:06 -08:00
|
|
|
candidate.nativeCandidate);
|
|
|
|
|
_peerConnection->AddIceCandidate(iceCandidate.get());
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-23 11:53:14 -07:00
|
|
|
- (void)removeIceCandidates:(NSArray<RTCIceCandidate *> *)iceCandidates {
|
|
|
|
|
std::vector<cricket::Candidate> candidates;
|
|
|
|
|
for (RTCIceCandidate *iceCandidate in iceCandidates) {
|
|
|
|
|
std::unique_ptr<const webrtc::IceCandidateInterface> candidate(
|
|
|
|
|
iceCandidate.nativeCandidate);
|
|
|
|
|
if (candidate) {
|
|
|
|
|
candidates.push_back(candidate->candidate());
|
|
|
|
|
// Need to fill the transport name from the sdp_mid.
|
|
|
|
|
candidates.back().set_transport_name(candidate->sdp_mid());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!candidates.empty()) {
|
|
|
|
|
_peerConnection->RemoveIceCandidates(candidates);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 16:19:06 -08:00
|
|
|
- (void)addStream:(RTCMediaStream *)stream {
|
2016-03-04 07:09:09 -08:00
|
|
|
if (!_peerConnection->AddStream(stream.nativeMediaStream)) {
|
2016-02-11 16:19:06 -08:00
|
|
|
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<webrtc::CreateSessionDescriptionObserverAdapter>
|
|
|
|
|
observer(new rtc::RefCountedObject
|
|
|
|
|
<webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
|
|
|
|
|
_peerConnection->CreateOffer(observer, constraints.nativeConstraints.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)answerForConstraints:(RTCMediaConstraints *)constraints
|
|
|
|
|
completionHandler:
|
|
|
|
|
(void (^)(RTCSessionDescription *sessionDescription,
|
|
|
|
|
NSError *error))completionHandler {
|
|
|
|
|
rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserverAdapter>
|
|
|
|
|
observer(new rtc::RefCountedObject
|
|
|
|
|
<webrtc::CreateSessionDescriptionObserverAdapter>(completionHandler));
|
|
|
|
|
_peerConnection->CreateAnswer(observer, constraints.nativeConstraints.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)setLocalDescription:(RTCSessionDescription *)sdp
|
|
|
|
|
completionHandler:(void (^)(NSError *error))completionHandler {
|
|
|
|
|
rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
|
|
|
|
|
new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
|
|
|
|
|
completionHandler));
|
|
|
|
|
_peerConnection->SetLocalDescription(observer, sdp.nativeDescription);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)setRemoteDescription:(RTCSessionDescription *)sdp
|
|
|
|
|
completionHandler:(void (^)(NSError *error))completionHandler {
|
|
|
|
|
rtc::scoped_refptr<webrtc::SetSessionDescriptionObserverAdapter> observer(
|
|
|
|
|
new rtc::RefCountedObject<webrtc::SetSessionDescriptionObserverAdapter>(
|
|
|
|
|
completionHandler));
|
|
|
|
|
_peerConnection->SetRemoteDescription(observer, sdp.nativeDescription);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-05 14:43:03 -07:00
|
|
|
- (BOOL)setBweMinBitrateBps:(nullable NSNumber *)minBitrateBps
|
|
|
|
|
currentBitrateBps:(nullable NSNumber *)currentBitrateBps
|
|
|
|
|
maxBitrateBps:(nullable NSNumber *)maxBitrateBps {
|
2017-08-09 14:29:42 -07:00
|
|
|
webrtc::PeerConnectionInterface::BitrateParameters params;
|
|
|
|
|
if (minBitrateBps != nil) {
|
|
|
|
|
params.min_bitrate_bps = rtc::Optional<int>(minBitrateBps.intValue);
|
|
|
|
|
}
|
|
|
|
|
if (currentBitrateBps != nil) {
|
|
|
|
|
params.current_bitrate_bps = rtc::Optional<int>(currentBitrateBps.intValue);
|
|
|
|
|
}
|
|
|
|
|
if (maxBitrateBps != nil) {
|
|
|
|
|
params.max_bitrate_bps = rtc::Optional<int>(maxBitrateBps.intValue);
|
|
|
|
|
}
|
|
|
|
|
return _peerConnection->SetBitrate(params).ok();
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-04 07:06:55 -07:00
|
|
|
- (BOOL)startRtcEventLogWithFilePath:(NSString *)filePath
|
|
|
|
|
maxSizeInBytes:(int64_t)maxSizeInBytes {
|
|
|
|
|
RTC_DCHECK(filePath.length);
|
|
|
|
|
RTC_DCHECK_GT(maxSizeInBytes, 0);
|
|
|
|
|
RTC_DCHECK(!_hasStartedRtcEventLog);
|
|
|
|
|
if (_hasStartedRtcEventLog) {
|
|
|
|
|
RTCLogError(@"Event logging already started.");
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
int fd = open(filePath.UTF8String, O_WRONLY | O_CREAT | O_TRUNC,
|
|
|
|
|
S_IRUSR | S_IWUSR);
|
|
|
|
|
if (fd < 0) {
|
|
|
|
|
RTCLogError(@"Error opening file: %@. Error: %d", filePath, errno);
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
_hasStartedRtcEventLog =
|
|
|
|
|
_peerConnection->StartRtcEventLog(fd, maxSizeInBytes);
|
|
|
|
|
return _hasStartedRtcEventLog;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)stopRtcEventLog {
|
|
|
|
|
_peerConnection->StopRtcEventLog();
|
|
|
|
|
_hasStartedRtcEventLog = NO;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 15:30:16 -07:00
|
|
|
- (RTCRtpSender *)senderWithKind:(NSString *)kind
|
|
|
|
|
streamId:(NSString *)streamId {
|
|
|
|
|
std::string nativeKind = [NSString stdStringForString:kind];
|
|
|
|
|
std::string nativeStreamId = [NSString stdStringForString:streamId];
|
|
|
|
|
rtc::scoped_refptr<webrtc::RtpSenderInterface> nativeSender(
|
|
|
|
|
_peerConnection->CreateSender(nativeKind, nativeStreamId));
|
|
|
|
|
return nativeSender ?
|
|
|
|
|
[[RTCRtpSender alloc] initWithNativeRtpSender:nativeSender]
|
|
|
|
|
: nil;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-08 17:28:55 -07:00
|
|
|
- (NSArray<RTCRtpSender *> *)senders {
|
|
|
|
|
std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> nativeSenders(
|
|
|
|
|
_peerConnection->GetSenders());
|
|
|
|
|
NSMutableArray *senders = [[NSMutableArray alloc] init];
|
|
|
|
|
for (const auto &nativeSender : nativeSenders) {
|
|
|
|
|
RTCRtpSender *sender =
|
|
|
|
|
[[RTCRtpSender alloc] initWithNativeRtpSender:nativeSender];
|
|
|
|
|
[senders addObject:sender];
|
|
|
|
|
}
|
|
|
|
|
return senders;
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-16 11:40:30 -07:00
|
|
|
- (NSArray<RTCRtpReceiver *> *)receivers {
|
|
|
|
|
std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> nativeReceivers(
|
|
|
|
|
_peerConnection->GetReceivers());
|
|
|
|
|
NSMutableArray *receivers = [[NSMutableArray alloc] init];
|
|
|
|
|
for (const auto &nativeReceiver : nativeReceivers) {
|
|
|
|
|
RTCRtpReceiver *receiver =
|
|
|
|
|
[[RTCRtpReceiver alloc] initWithNativeRtpReceiver:nativeReceiver];
|
|
|
|
|
[receivers addObject:receiver];
|
|
|
|
|
}
|
|
|
|
|
return receivers;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-11 16:19:06 -08:00
|
|
|
#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;
|
2016-03-14 13:15:44 -07:00
|
|
|
case RTCIceConnectionStateCount:
|
2016-02-11 16:19:06 -08:00
|
|
|
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:
|
2016-03-14 13:15:44 -07:00
|
|
|
return RTCIceConnectionStateCount;
|
2016-02-11 16:19:06 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (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";
|
2016-03-14 13:15:44 -07:00
|
|
|
case RTCIceConnectionStateCount:
|
|
|
|
|
return @"COUNT";
|
2016-02-11 16:19:06 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (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<webrtc::PeerConnectionInterface>)nativePeerConnection {
|
|
|
|
|
return _peerConnection;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|