1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/rtc_peer_connection_handler.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram.h"
17 #include "base/stl_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/renderer/media/media_stream_track.h"
21 #include "content/renderer/media/peer_connection_tracker.h"
22 #include "content/renderer/media/remote_media_stream_impl.h"
23 #include "content/renderer/media/rtc_data_channel_handler.h"
24 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
25 #include "content/renderer/media/rtc_media_constraints.h"
26 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
27 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
28 #include "content/renderer/media/webrtc_audio_capturer.h"
29 #include "content/renderer/media/webrtc_audio_device_impl.h"
30 #include "content/renderer/media/webrtc_uma_histograms.h"
31 #include "content/renderer/render_thread_impl.h"
32 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
33 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
34 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
35 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
36 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
37 #include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
38 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
39 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
40 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
41 #include "third_party/WebKit/public/platform/WebURL.h"
45 // Converter functions from libjingle types to WebKit types.
46 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
47 GetWebKitIceGatheringState(
48 webrtc::PeerConnectionInterface::IceGatheringState state
) {
49 using blink::WebRTCPeerConnectionHandlerClient
;
51 case webrtc::PeerConnectionInterface::kIceGatheringNew
:
52 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
53 case webrtc::PeerConnectionInterface::kIceGatheringGathering
:
54 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering
;
55 case webrtc::PeerConnectionInterface::kIceGatheringComplete
:
56 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete
;
59 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
63 static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
64 GetWebKitIceConnectionState(
65 webrtc::PeerConnectionInterface::IceConnectionState ice_state
) {
66 using blink::WebRTCPeerConnectionHandlerClient
;
68 case webrtc::PeerConnectionInterface::kIceConnectionNew
:
69 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting
;
70 case webrtc::PeerConnectionInterface::kIceConnectionChecking
:
71 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking
;
72 case webrtc::PeerConnectionInterface::kIceConnectionConnected
:
73 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected
;
74 case webrtc::PeerConnectionInterface::kIceConnectionCompleted
:
75 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted
;
76 case webrtc::PeerConnectionInterface::kIceConnectionFailed
:
77 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed
;
78 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected
:
79 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected
;
80 case webrtc::PeerConnectionInterface::kIceConnectionClosed
:
81 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
84 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
88 static blink::WebRTCPeerConnectionHandlerClient::SignalingState
89 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state
) {
90 using blink::WebRTCPeerConnectionHandlerClient
;
92 case webrtc::PeerConnectionInterface::kStable
:
93 return WebRTCPeerConnectionHandlerClient::SignalingStateStable
;
94 case webrtc::PeerConnectionInterface::kHaveLocalOffer
:
95 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer
;
96 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer
:
97 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer
;
98 case webrtc::PeerConnectionInterface::kHaveRemoteOffer
:
99 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer
;
100 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer
:
102 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer
;
103 case webrtc::PeerConnectionInterface::kClosed
:
104 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
107 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
111 static blink::WebRTCSessionDescription
112 CreateWebKitSessionDescription(
113 const webrtc::SessionDescriptionInterface
* native_desc
) {
114 blink::WebRTCSessionDescription description
;
116 LOG(ERROR
) << "Native session description is null.";
121 if (!native_desc
->ToString(&sdp
)) {
122 LOG(ERROR
) << "Failed to get SDP string of native session description.";
126 description
.initialize(base::UTF8ToUTF16(native_desc
->type()),
127 base::UTF8ToUTF16(sdp
));
131 // Converter functions from WebKit types to libjingle types.
133 static void GetNativeRtcConfiguration(
134 const blink::WebRTCConfiguration
& server_configuration
,
135 webrtc::PeerConnectionInterface::RTCConfiguration
* config
) {
136 if (server_configuration
.isNull() || !config
)
138 for (size_t i
= 0; i
< server_configuration
.numberOfServers(); ++i
) {
139 webrtc::PeerConnectionInterface::IceServer server
;
140 const blink::WebRTCICEServer
& webkit_server
=
141 server_configuration
.server(i
);
142 server
.username
= base::UTF16ToUTF8(webkit_server
.username());
143 server
.password
= base::UTF16ToUTF8(webkit_server
.credential());
144 server
.uri
= webkit_server
.uri().spec();
145 config
->servers
.push_back(server
);
148 switch (server_configuration
.iceTransports()) {
149 case blink::WebRTCIceTransportsNone
:
150 config
->type
= webrtc::PeerConnectionInterface::kNone
;
152 case blink::WebRTCIceTransportsRelay
:
153 config
->type
= webrtc::PeerConnectionInterface::kRelay
;
155 case blink::WebRTCIceTransportsAll
:
156 config
->type
= webrtc::PeerConnectionInterface::kAll
;
163 class SessionDescriptionRequestTracker
{
165 SessionDescriptionRequestTracker(RTCPeerConnectionHandler
* handler
,
166 PeerConnectionTracker::Action action
)
167 : handler_(handler
), action_(action
) {}
169 void TrackOnSuccess(const webrtc::SessionDescriptionInterface
* desc
) {
172 desc
->ToString(&value
);
173 value
= "type: " + desc
->type() + ", sdp: " + value
;
175 if (handler_
->peer_connection_tracker())
176 handler_
->peer_connection_tracker()->TrackSessionDescriptionCallback(
177 handler_
, action_
, "OnSuccess", value
);
180 void TrackOnFailure(const std::string
& error
) {
181 if (handler_
->peer_connection_tracker())
182 handler_
->peer_connection_tracker()->TrackSessionDescriptionCallback(
183 handler_
, action_
, "OnFailure", error
);
187 RTCPeerConnectionHandler
* handler_
;
188 PeerConnectionTracker::Action action_
;
191 // Class mapping responses from calls to libjingle CreateOffer/Answer and
192 // the blink::WebRTCSessionDescriptionRequest.
193 class CreateSessionDescriptionRequest
194 : public webrtc::CreateSessionDescriptionObserver
{
196 explicit CreateSessionDescriptionRequest(
197 const blink::WebRTCSessionDescriptionRequest
& request
,
198 RTCPeerConnectionHandler
* handler
,
199 PeerConnectionTracker::Action action
)
200 : webkit_request_(request
), tracker_(handler
, action
) {}
202 virtual void OnSuccess(webrtc::SessionDescriptionInterface
* desc
) OVERRIDE
{
203 tracker_
.TrackOnSuccess(desc
);
204 webkit_request_
.requestSucceeded(CreateWebKitSessionDescription(desc
));
207 virtual void OnFailure(const std::string
& error
) OVERRIDE
{
208 tracker_
.TrackOnFailure(error
);
209 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
213 virtual ~CreateSessionDescriptionRequest() {}
216 blink::WebRTCSessionDescriptionRequest webkit_request_
;
217 SessionDescriptionRequestTracker tracker_
;
220 // Class mapping responses from calls to libjingle
221 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
222 class SetSessionDescriptionRequest
223 : public webrtc::SetSessionDescriptionObserver
{
225 explicit SetSessionDescriptionRequest(
226 const blink::WebRTCVoidRequest
& request
,
227 RTCPeerConnectionHandler
* handler
,
228 PeerConnectionTracker::Action action
)
229 : webkit_request_(request
), tracker_(handler
, action
) {}
231 virtual void OnSuccess() OVERRIDE
{
232 tracker_
.TrackOnSuccess(NULL
);
233 webkit_request_
.requestSucceeded();
235 virtual void OnFailure(const std::string
& error
) OVERRIDE
{
236 tracker_
.TrackOnFailure(error
);
237 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
241 virtual ~SetSessionDescriptionRequest() {}
244 blink::WebRTCVoidRequest webkit_request_
;
245 SessionDescriptionRequestTracker tracker_
;
248 // Class mapping responses from calls to libjingle
249 // GetStats into a blink::WebRTCStatsCallback.
250 class StatsResponse
: public webrtc::StatsObserver
{
252 explicit StatsResponse(const scoped_refptr
<LocalRTCStatsRequest
>& request
)
253 : request_(request
.get()), response_(request_
->createResponse().get()) {
254 // Measure the overall time it takes to satisfy a getStats request.
255 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
258 virtual void OnComplete(
259 const std::vector
<webrtc::StatsReport
>& reports
) OVERRIDE
{
260 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete")
261 for (std::vector
<webrtc::StatsReport
>::const_iterator it
= reports
.begin();
262 it
!= reports
.end(); ++it
) {
263 if (it
->values
.size() > 0) {
268 // Record the getSync operation as done before calling into Blink so that
269 // we don't skew the perf measurements of the native code with whatever the
270 // callback might be doing.
271 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
273 request_
->requestSucceeded(response_
);
277 void AddReport(const webrtc::StatsReport
& report
) {
278 int idx
= response_
->addReport(blink::WebString::fromUTF8(report
.id
),
279 blink::WebString::fromUTF8(report
.type
),
281 for (webrtc::StatsReport::Values::const_iterator value_it
=
282 report
.values
.begin();
283 value_it
!= report
.values
.end(); ++value_it
) {
284 AddStatistic(idx
, value_it
->name
, value_it
->value
);
288 void AddStatistic(int idx
, const std::string
& name
,
289 const std::string
& value
) {
290 response_
->addStatistic(idx
,
291 blink::WebString::fromUTF8(name
),
292 blink::WebString::fromUTF8(value
));
295 talk_base::scoped_refptr
<LocalRTCStatsRequest
> request_
;
296 talk_base::scoped_refptr
<LocalRTCStatsResponse
> response_
;
299 // Implementation of LocalRTCStatsRequest.
300 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl
)
305 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
306 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
308 bool LocalRTCStatsRequest::hasSelector() const {
309 return impl_
.hasSelector();
312 blink::WebMediaStreamTrack
LocalRTCStatsRequest::component() const {
313 return impl_
.component();
316 scoped_refptr
<LocalRTCStatsResponse
> LocalRTCStatsRequest::createResponse() {
318 response_
= new talk_base::RefCountedObject
<LocalRTCStatsResponse
>(
319 impl_
.createResponse());
320 return response_
.get();
323 void LocalRTCStatsRequest::requestSucceeded(
324 const LocalRTCStatsResponse
* response
) {
325 impl_
.requestSucceeded(response
->webKitStatsResponse());
328 // Implementation of LocalRTCStatsResponse.
329 blink::WebRTCStatsResponse
LocalRTCStatsResponse::webKitStatsResponse() const {
333 size_t LocalRTCStatsResponse::addReport(blink::WebString type
,
336 return impl_
.addReport(type
, id
, timestamp
);
339 void LocalRTCStatsResponse::addStatistic(size_t report
,
340 blink::WebString name
,
341 blink::WebString value
) {
342 impl_
.addStatistic(report
, name
, value
);
347 class PeerConnectionUMAObserver
: public webrtc::UMAObserver
{
349 PeerConnectionUMAObserver() {}
350 virtual ~PeerConnectionUMAObserver() {}
352 virtual void IncrementCounter(
353 webrtc::PeerConnectionUMAMetricsCounter counter
) OVERRIDE
{
354 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
359 virtual void AddHistogramSample(
360 webrtc::PeerConnectionUMAMetricsName type
, int value
) OVERRIDE
{
362 case webrtc::kTimeToConnect
:
363 UMA_HISTOGRAM_MEDIUM_TIMES(
364 "WebRTC.PeerConnection.TimeToConnect",
365 base::TimeDelta::FromMilliseconds(value
));
367 case webrtc::kNetworkInterfaces_IPv4
:
368 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
371 case webrtc::kNetworkInterfaces_IPv6
:
372 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
381 base::LazyInstance
<std::set
<RTCPeerConnectionHandler
*> >::Leaky
382 g_peer_connection_handlers
= LAZY_INSTANCE_INITIALIZER
;
386 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
387 blink::WebRTCPeerConnectionHandlerClient
* client
,
388 PeerConnectionDependencyFactory
* dependency_factory
)
390 dependency_factory_(dependency_factory
),
392 peer_connection_tracker_(NULL
),
393 num_data_channels_created_(0) {
394 g_peer_connection_handlers
.Get().insert(this);
397 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
398 g_peer_connection_handlers
.Get().erase(this);
399 if (peer_connection_tracker_
)
400 peer_connection_tracker_
->UnregisterPeerConnection(this);
401 STLDeleteValues(&remote_streams_
);
403 UMA_HISTOGRAM_COUNTS_10000(
404 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_
);
408 void RTCPeerConnectionHandler::DestructAllHandlers() {
409 std::set
<RTCPeerConnectionHandler
*> handlers(
410 g_peer_connection_handlers
.Get().begin(),
411 g_peer_connection_handlers
.Get().end());
412 for (std::set
<RTCPeerConnectionHandler
*>::iterator handler
= handlers
.begin();
413 handler
!= handlers
.end();
415 (*handler
)->client_
->releasePeerConnectionHandler();
419 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
420 const blink::WebRTCOfferOptions
& options
,
421 RTCMediaConstraints
* output
) {
422 output
->AddMandatory(
423 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio
,
424 options
.offerToReceiveAudio() > 0 ? "true" : "false",
427 output
->AddMandatory(
428 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo
,
429 options
.offerToReceiveVideo() > 0 ? "true" : "false",
432 if (!options
.voiceActivityDetection()) {
433 output
->AddMandatory(
434 webrtc::MediaConstraintsInterface::kVoiceActivityDetection
,
439 if (options
.iceRestart()) {
440 output
->AddMandatory(
441 webrtc::MediaConstraintsInterface::kIceRestart
, "true", true);
445 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame
* frame
) {
450 bool RTCPeerConnectionHandler::initialize(
451 const blink::WebRTCConfiguration
& server_configuration
,
452 const blink::WebMediaConstraints
& options
) {
455 peer_connection_tracker_
=
456 RenderThreadImpl::current()->peer_connection_tracker();
458 webrtc::PeerConnectionInterface::RTCConfiguration config
;
459 GetNativeRtcConfiguration(server_configuration
, &config
);
461 RTCMediaConstraints
constraints(options
);
463 native_peer_connection_
=
464 dependency_factory_
->CreatePeerConnection(
465 config
, &constraints
, frame_
, this);
467 if (!native_peer_connection_
.get()) {
468 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
471 if (peer_connection_tracker_
)
472 peer_connection_tracker_
->RegisterPeerConnection(
473 this, config
, constraints
, frame_
);
475 uma_observer_
= new talk_base::RefCountedObject
<PeerConnectionUMAObserver
>();
476 native_peer_connection_
->RegisterUMAObserver(uma_observer_
.get());
480 bool RTCPeerConnectionHandler::InitializeForTest(
481 const blink::WebRTCConfiguration
& server_configuration
,
482 const blink::WebMediaConstraints
& options
,
483 PeerConnectionTracker
* peer_connection_tracker
) {
484 webrtc::PeerConnectionInterface::RTCConfiguration config
;
485 GetNativeRtcConfiguration(server_configuration
, &config
);
487 RTCMediaConstraints
constraints(options
);
488 native_peer_connection_
=
489 dependency_factory_
->CreatePeerConnection(
490 config
, &constraints
, NULL
, this);
491 if (!native_peer_connection_
.get()) {
492 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
495 peer_connection_tracker_
= peer_connection_tracker
;
499 void RTCPeerConnectionHandler::createOffer(
500 const blink::WebRTCSessionDescriptionRequest
& request
,
501 const blink::WebMediaConstraints
& options
) {
502 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
503 new talk_base::RefCountedObject
<CreateSessionDescriptionRequest
>(
504 request
, this, PeerConnectionTracker::ACTION_CREATE_OFFER
));
505 RTCMediaConstraints
constraints(options
);
506 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
508 if (peer_connection_tracker_
)
509 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
512 void RTCPeerConnectionHandler::createOffer(
513 const blink::WebRTCSessionDescriptionRequest
& request
,
514 const blink::WebRTCOfferOptions
& options
) {
515 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
516 new talk_base::RefCountedObject
<CreateSessionDescriptionRequest
>(
517 request
, this, PeerConnectionTracker::ACTION_CREATE_OFFER
));
519 RTCMediaConstraints constraints
;
520 ConvertOfferOptionsToConstraints(options
, &constraints
);
521 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
523 if (peer_connection_tracker_
)
524 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
527 void RTCPeerConnectionHandler::createAnswer(
528 const blink::WebRTCSessionDescriptionRequest
& request
,
529 const blink::WebMediaConstraints
& options
) {
530 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
531 new talk_base::RefCountedObject
<CreateSessionDescriptionRequest
>(
532 request
, this, PeerConnectionTracker::ACTION_CREATE_ANSWER
));
533 RTCMediaConstraints
constraints(options
);
534 native_peer_connection_
->CreateAnswer(description_request
.get(),
537 if (peer_connection_tracker_
)
538 peer_connection_tracker_
->TrackCreateAnswer(this, constraints
);
541 void RTCPeerConnectionHandler::setLocalDescription(
542 const blink::WebRTCVoidRequest
& request
,
543 const blink::WebRTCSessionDescription
& description
) {
544 webrtc::SdpParseError error
;
545 webrtc::SessionDescriptionInterface
* native_desc
=
546 CreateNativeSessionDescription(description
, &error
);
548 std::string reason_str
= "Failed to parse SessionDescription. ";
549 reason_str
.append(error
.line
);
550 reason_str
.append(" ");
551 reason_str
.append(error
.description
);
552 LOG(ERROR
) << reason_str
;
553 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
556 if (peer_connection_tracker_
)
557 peer_connection_tracker_
->TrackSetSessionDescription(
558 this, description
, PeerConnectionTracker::SOURCE_LOCAL
);
560 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
561 new talk_base::RefCountedObject
<SetSessionDescriptionRequest
>(
562 request
, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION
));
563 native_peer_connection_
->SetLocalDescription(set_request
.get(), native_desc
);
566 void RTCPeerConnectionHandler::setRemoteDescription(
567 const blink::WebRTCVoidRequest
& request
,
568 const blink::WebRTCSessionDescription
& description
) {
569 webrtc::SdpParseError error
;
570 webrtc::SessionDescriptionInterface
* native_desc
=
571 CreateNativeSessionDescription(description
, &error
);
573 std::string reason_str
= "Failed to parse SessionDescription. ";
574 reason_str
.append(error
.line
);
575 reason_str
.append(" ");
576 reason_str
.append(error
.description
);
577 LOG(ERROR
) << reason_str
;
578 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
581 if (peer_connection_tracker_
)
582 peer_connection_tracker_
->TrackSetSessionDescription(
583 this, description
, PeerConnectionTracker::SOURCE_REMOTE
);
585 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
586 new talk_base::RefCountedObject
<SetSessionDescriptionRequest
>(
587 request
, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION
));
588 native_peer_connection_
->SetRemoteDescription(set_request
.get(), native_desc
);
591 blink::WebRTCSessionDescription
592 RTCPeerConnectionHandler::localDescription() {
593 const webrtc::SessionDescriptionInterface
* native_desc
=
594 native_peer_connection_
->local_description();
595 blink::WebRTCSessionDescription description
=
596 CreateWebKitSessionDescription(native_desc
);
600 blink::WebRTCSessionDescription
601 RTCPeerConnectionHandler::remoteDescription() {
602 const webrtc::SessionDescriptionInterface
* native_desc
=
603 native_peer_connection_
->remote_description();
604 blink::WebRTCSessionDescription description
=
605 CreateWebKitSessionDescription(native_desc
);
609 bool RTCPeerConnectionHandler::updateICE(
610 const blink::WebRTCConfiguration
& server_configuration
,
611 const blink::WebMediaConstraints
& options
) {
612 webrtc::PeerConnectionInterface::RTCConfiguration config
;
613 GetNativeRtcConfiguration(server_configuration
, &config
);
614 RTCMediaConstraints
constraints(options
);
616 if (peer_connection_tracker_
)
617 peer_connection_tracker_
->TrackUpdateIce(this, config
, constraints
);
619 return native_peer_connection_
->UpdateIce(config
.servers
,
623 bool RTCPeerConnectionHandler::addICECandidate(
624 const blink::WebRTCVoidRequest
& request
,
625 const blink::WebRTCICECandidate
& candidate
) {
626 // Libjingle currently does not accept callbacks for addICECandidate.
627 // For that reason we are going to call callbacks from here.
628 bool result
= addICECandidate(candidate
);
629 base::MessageLoop::current()->PostTask(
631 base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult
,
632 base::Unretained(this), request
, result
));
633 // On failure callback will be triggered.
637 bool RTCPeerConnectionHandler::addICECandidate(
638 const blink::WebRTCICECandidate
& candidate
) {
639 scoped_ptr
<webrtc::IceCandidateInterface
> native_candidate(
640 dependency_factory_
->CreateIceCandidate(
641 base::UTF16ToUTF8(candidate
.sdpMid()),
642 candidate
.sdpMLineIndex(),
643 base::UTF16ToUTF8(candidate
.candidate())));
644 if (!native_candidate
) {
645 LOG(ERROR
) << "Could not create native ICE candidate.";
650 native_peer_connection_
->AddIceCandidate(native_candidate
.get());
651 LOG_IF(ERROR
, !return_value
) << "Error processing ICE candidate.";
653 if (peer_connection_tracker_
)
654 peer_connection_tracker_
->TrackAddIceCandidate(
655 this, candidate
, PeerConnectionTracker::SOURCE_REMOTE
);
660 void RTCPeerConnectionHandler::OnaddICECandidateResult(
661 const blink::WebRTCVoidRequest
& webkit_request
, bool result
) {
663 // We don't have the actual error code from the libjingle, so for now
664 // using a generic error string.
665 return webkit_request
.requestFailed(
666 base::UTF8ToUTF16("Error processing ICE candidate"));
669 return webkit_request
.requestSucceeded();
672 bool RTCPeerConnectionHandler::addStream(
673 const blink::WebMediaStream
& stream
,
674 const blink::WebMediaConstraints
& options
) {
676 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
677 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
679 if ((*adapter_it
)->IsEqual(stream
)) {
680 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
681 << "stream twice. id=" << stream
.id().utf8();
686 if (peer_connection_tracker_
)
687 peer_connection_tracker_
->TrackAddStream(
688 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
690 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
692 WebRtcMediaStreamAdapter
* adapter
=
693 new WebRtcMediaStreamAdapter(stream
, dependency_factory_
);
694 local_streams_
.push_back(adapter
);
696 webrtc::MediaStreamInterface
* webrtc_stream
= adapter
->webrtc_media_stream();
697 track_metrics_
.AddStream(MediaStreamTrackMetrics::SENT_STREAM
,
700 RTCMediaConstraints
constraints(options
);
701 return native_peer_connection_
->AddStream(webrtc_stream
, &constraints
);
704 void RTCPeerConnectionHandler::removeStream(
705 const blink::WebMediaStream
& stream
) {
706 // Find the webrtc stream.
707 scoped_refptr
<webrtc::MediaStreamInterface
> webrtc_stream
;
708 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
709 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
711 if ((*adapter_it
)->IsEqual(stream
)) {
712 webrtc_stream
= (*adapter_it
)->webrtc_media_stream();
713 local_streams_
.erase(adapter_it
);
717 DCHECK(webrtc_stream
);
718 native_peer_connection_
->RemoveStream(webrtc_stream
);
720 if (peer_connection_tracker_
)
721 peer_connection_tracker_
->TrackRemoveStream(
722 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
723 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
724 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM
,
728 void RTCPeerConnectionHandler::getStats(
729 const blink::WebRTCStatsRequest
& request
) {
730 scoped_refptr
<LocalRTCStatsRequest
> inner_request(
731 new talk_base::RefCountedObject
<LocalRTCStatsRequest
>(request
));
732 getStats(inner_request
.get());
735 void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest
* request
) {
736 talk_base::scoped_refptr
<webrtc::StatsObserver
> observer(
737 new talk_base::RefCountedObject
<StatsResponse
>(request
));
738 webrtc::MediaStreamTrackInterface
* track
= NULL
;
739 if (request
->hasSelector()) {
740 blink::WebMediaStreamSource::Type type
=
741 request
->component().source().type();
742 std::string track_id
= request
->component().id().utf8();
743 if (type
== blink::WebMediaStreamSource::TypeAudio
) {
745 native_peer_connection_
->local_streams()->FindAudioTrack(track_id
);
748 native_peer_connection_
->remote_streams()->FindAudioTrack(track_id
);
751 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo
, type
);
753 native_peer_connection_
->local_streams()->FindVideoTrack(track_id
);
756 native_peer_connection_
->remote_streams()->FindVideoTrack(track_id
);
760 DVLOG(1) << "GetStats: Track not found.";
761 // TODO(hta): Consider how to get an error back.
762 std::vector
<webrtc::StatsReport
> no_reports
;
763 observer
->OnComplete(no_reports
);
769 webrtc::PeerConnectionInterface::kStatsOutputLevelStandard
);
772 void RTCPeerConnectionHandler::GetStats(
773 webrtc::StatsObserver
* observer
,
774 webrtc::MediaStreamTrackInterface
* track
,
775 webrtc::PeerConnectionInterface::StatsOutputLevel level
) {
776 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::GetStats");
777 if (!native_peer_connection_
->GetStats(observer
, track
, level
)) {
778 DVLOG(1) << "GetStats failed.";
779 // TODO(hta): Consider how to get an error back.
780 std::vector
<webrtc::StatsReport
> no_reports
;
781 observer
->OnComplete(no_reports
);
786 blink::WebRTCDataChannelHandler
* RTCPeerConnectionHandler::createDataChannel(
787 const blink::WebString
& label
, const blink::WebRTCDataChannelInit
& init
) {
788 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label
);
790 webrtc::DataChannelInit config
;
791 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
793 config
.reliable
= false;
795 config
.ordered
= init
.ordered
;
796 config
.negotiated
= init
.negotiated
;
797 config
.maxRetransmits
= init
.maxRetransmits
;
798 config
.maxRetransmitTime
= init
.maxRetransmitTime
;
799 config
.protocol
= base::UTF16ToUTF8(init
.protocol
);
801 talk_base::scoped_refptr
<webrtc::DataChannelInterface
> webrtc_channel(
802 native_peer_connection_
->CreateDataChannel(base::UTF16ToUTF8(label
),
804 if (!webrtc_channel
) {
805 DLOG(ERROR
) << "Could not create native data channel.";
808 if (peer_connection_tracker_
)
809 peer_connection_tracker_
->TrackCreateDataChannel(
810 this, webrtc_channel
.get(), PeerConnectionTracker::SOURCE_LOCAL
);
812 ++num_data_channels_created_
;
814 return new RtcDataChannelHandler(webrtc_channel
);
817 blink::WebRTCDTMFSenderHandler
* RTCPeerConnectionHandler::createDTMFSender(
818 const blink::WebMediaStreamTrack
& track
) {
819 DVLOG(1) << "createDTMFSender.";
821 MediaStreamTrack
* native_track
= MediaStreamTrack::GetTrack(track
);
823 track
.source().type() != blink::WebMediaStreamSource::TypeAudio
) {
824 DLOG(ERROR
) << "Could not create DTMF sender from a non-audio track.";
828 webrtc::AudioTrackInterface
* audio_track
= native_track
->GetAudioAdapter();
829 talk_base::scoped_refptr
<webrtc::DtmfSenderInterface
> sender(
830 native_peer_connection_
->CreateDtmfSender(audio_track
));
832 DLOG(ERROR
) << "Could not create native DTMF sender.";
835 if (peer_connection_tracker_
)
836 peer_connection_tracker_
->TrackCreateDTMFSender(this, track
);
838 return new RtcDtmfSenderHandler(sender
);
841 void RTCPeerConnectionHandler::stop() {
842 DVLOG(1) << "RTCPeerConnectionHandler::stop";
844 if (peer_connection_tracker_
)
845 peer_connection_tracker_
->TrackStop(this);
846 native_peer_connection_
->Close();
849 void RTCPeerConnectionHandler::OnError() {
850 // TODO(perkj): Implement.
854 void RTCPeerConnectionHandler::OnSignalingChange(
855 webrtc::PeerConnectionInterface::SignalingState new_state
) {
856 blink::WebRTCPeerConnectionHandlerClient::SignalingState state
=
857 GetWebKitSignalingState(new_state
);
858 if (peer_connection_tracker_
)
859 peer_connection_tracker_
->TrackSignalingStateChange(this, state
);
860 client_
->didChangeSignalingState(state
);
863 // Called any time the IceConnectionState changes
864 void RTCPeerConnectionHandler::OnIceConnectionChange(
865 webrtc::PeerConnectionInterface::IceConnectionState new_state
) {
866 if (new_state
== webrtc::PeerConnectionInterface::kIceConnectionChecking
) {
867 ice_connection_checking_start_
= base::TimeTicks::Now();
868 } else if (new_state
==
869 webrtc::PeerConnectionInterface::kIceConnectionConnected
) {
870 // If the state becomes connected, send the time needed for PC to become
871 // connected from checking to UMA. UMA data will help to know how much
872 // time needed for PC to connect with remote peer.
873 UMA_HISTOGRAM_MEDIUM_TIMES(
874 "WebRTC.PeerConnection.TimeToConnect",
875 base::TimeTicks::Now() - ice_connection_checking_start_
);
878 track_metrics_
.IceConnectionChange(new_state
);
879 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state
=
880 GetWebKitIceConnectionState(new_state
);
881 if (peer_connection_tracker_
)
882 peer_connection_tracker_
->TrackIceConnectionStateChange(this, state
);
883 client_
->didChangeICEConnectionState(state
);
886 // Called any time the IceGatheringState changes
887 void RTCPeerConnectionHandler::OnIceGatheringChange(
888 webrtc::PeerConnectionInterface::IceGatheringState new_state
) {
889 if (new_state
== webrtc::PeerConnectionInterface::kIceGatheringComplete
) {
890 // If ICE gathering is completed, generate a NULL ICE candidate,
891 // to signal end of candidates.
892 blink::WebRTCICECandidate null_candidate
;
893 client_
->didGenerateICECandidate(null_candidate
);
896 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state
=
897 GetWebKitIceGatheringState(new_state
);
898 if (peer_connection_tracker_
)
899 peer_connection_tracker_
->TrackIceGatheringStateChange(this, state
);
900 client_
->didChangeICEGatheringState(state
);
903 void RTCPeerConnectionHandler::OnAddStream(
904 webrtc::MediaStreamInterface
* stream_interface
) {
905 DCHECK(stream_interface
);
906 DCHECK(remote_streams_
.find(stream_interface
) == remote_streams_
.end());
908 RemoteMediaStreamImpl
* remote_stream
=
909 new RemoteMediaStreamImpl(stream_interface
);
910 remote_streams_
.insert(
911 std::pair
<webrtc::MediaStreamInterface
*, RemoteMediaStreamImpl
*> (
912 stream_interface
, remote_stream
));
914 if (peer_connection_tracker_
)
915 peer_connection_tracker_
->TrackAddStream(
916 this, remote_stream
->webkit_stream(),
917 PeerConnectionTracker::SOURCE_REMOTE
);
919 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
921 track_metrics_
.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
924 client_
->didAddRemoteStream(remote_stream
->webkit_stream());
927 void RTCPeerConnectionHandler::OnRemoveStream(
928 webrtc::MediaStreamInterface
* stream_interface
) {
929 DCHECK(stream_interface
);
930 RemoteStreamMap::iterator it
= remote_streams_
.find(stream_interface
);
931 if (it
== remote_streams_
.end()) {
932 NOTREACHED() << "Stream not found";
936 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
938 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
940 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(it
->second
);
941 const blink::WebMediaStream
& webkit_stream
= remote_stream
->webkit_stream();
942 DCHECK(!webkit_stream
.isNull());
943 remote_streams_
.erase(it
);
945 if (peer_connection_tracker_
)
946 peer_connection_tracker_
->TrackRemoveStream(
947 this, webkit_stream
, PeerConnectionTracker::SOURCE_REMOTE
);
949 client_
->didRemoveRemoteStream(webkit_stream
);
952 void RTCPeerConnectionHandler::OnIceCandidate(
953 const webrtc::IceCandidateInterface
* candidate
) {
956 if (!candidate
->ToString(&sdp
)) {
957 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
960 blink::WebRTCICECandidate web_candidate
;
961 web_candidate
.initialize(base::UTF8ToUTF16(sdp
),
962 base::UTF8ToUTF16(candidate
->sdp_mid()),
963 candidate
->sdp_mline_index());
964 if (peer_connection_tracker_
)
965 peer_connection_tracker_
->TrackAddIceCandidate(
966 this, web_candidate
, PeerConnectionTracker::SOURCE_LOCAL
);
968 client_
->didGenerateICECandidate(web_candidate
);
971 void RTCPeerConnectionHandler::OnDataChannel(
972 webrtc::DataChannelInterface
* data_channel
) {
973 if (peer_connection_tracker_
)
974 peer_connection_tracker_
->TrackCreateDataChannel(
975 this, data_channel
, PeerConnectionTracker::SOURCE_REMOTE
);
977 DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
978 << data_channel
->label();
979 client_
->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel
));
982 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
983 if (peer_connection_tracker_
)
984 peer_connection_tracker_
->TrackOnRenegotiationNeeded(this);
985 client_
->negotiationNeeded();
988 PeerConnectionTracker
* RTCPeerConnectionHandler::peer_connection_tracker() {
989 return peer_connection_tracker_
;
992 webrtc::SessionDescriptionInterface
*
993 RTCPeerConnectionHandler::CreateNativeSessionDescription(
994 const blink::WebRTCSessionDescription
& description
,
995 webrtc::SdpParseError
* error
) {
996 std::string sdp
= base::UTF16ToUTF8(description
.sdp());
997 std::string type
= base::UTF16ToUTF8(description
.type());
998 webrtc::SessionDescriptionInterface
* native_desc
=
999 dependency_factory_
->CreateSessionDescription(type
, sdp
, error
);
1001 LOG_IF(ERROR
, !native_desc
) << "Failed to create native session description."
1002 << " Type: " << type
<< " SDP: " << sdp
;
1007 } // namespace content