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/lazy_instance.h"
13 #include "base/location.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 "base/thread_task_runner_handle.h"
20 #include "base/trace_event/trace_event.h"
21 #include "content/public/common/content_switches.h"
22 #include "content/renderer/media/media_stream_track.h"
23 #include "content/renderer/media/peer_connection_tracker.h"
24 #include "content/renderer/media/remote_media_stream_impl.h"
25 #include "content/renderer/media/rtc_data_channel_handler.h"
26 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
27 #include "content/renderer/media/rtc_media_constraints.h"
28 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
29 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
30 #include "content/renderer/media/webrtc_audio_capturer.h"
31 #include "content/renderer/media/webrtc_audio_device_impl.h"
32 #include "content/renderer/media/webrtc_uma_histograms.h"
33 #include "content/renderer/render_thread_impl.h"
34 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
35 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
36 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
37 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
38 #include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
39 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
40 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
41 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
42 #include "third_party/WebKit/public/platform/WebURL.h"
43 #include "third_party/libjingle/source/talk/session/media/mediasession.h"
45 using webrtc::DataChannelInterface
;
46 using webrtc::IceCandidateInterface
;
47 using webrtc::MediaStreamInterface
;
48 using webrtc::PeerConnectionInterface
;
49 using webrtc::PeerConnectionObserver
;
50 using webrtc::StatsReport
;
51 using webrtc::StatsReports
;
56 // Used to back histogram value of "WebRTC.PeerConnection.RtcpMux",
57 // so treat as append-only.
65 // Converter functions from libjingle types to WebKit types.
66 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
67 GetWebKitIceGatheringState(
68 webrtc::PeerConnectionInterface::IceGatheringState state
) {
69 using blink::WebRTCPeerConnectionHandlerClient
;
71 case webrtc::PeerConnectionInterface::kIceGatheringNew
:
72 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
73 case webrtc::PeerConnectionInterface::kIceGatheringGathering
:
74 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering
;
75 case webrtc::PeerConnectionInterface::kIceGatheringComplete
:
76 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete
;
79 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
83 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
84 GetWebKitIceConnectionState(
85 webrtc::PeerConnectionInterface::IceConnectionState ice_state
) {
86 using blink::WebRTCPeerConnectionHandlerClient
;
88 case webrtc::PeerConnectionInterface::kIceConnectionNew
:
89 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting
;
90 case webrtc::PeerConnectionInterface::kIceConnectionChecking
:
91 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking
;
92 case webrtc::PeerConnectionInterface::kIceConnectionConnected
:
93 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected
;
94 case webrtc::PeerConnectionInterface::kIceConnectionCompleted
:
95 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted
;
96 case webrtc::PeerConnectionInterface::kIceConnectionFailed
:
97 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed
;
98 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected
:
99 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected
;
100 case webrtc::PeerConnectionInterface::kIceConnectionClosed
:
101 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
104 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
108 blink::WebRTCPeerConnectionHandlerClient::SignalingState
109 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state
) {
110 using blink::WebRTCPeerConnectionHandlerClient
;
112 case webrtc::PeerConnectionInterface::kStable
:
113 return WebRTCPeerConnectionHandlerClient::SignalingStateStable
;
114 case webrtc::PeerConnectionInterface::kHaveLocalOffer
:
115 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer
;
116 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer
:
117 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer
;
118 case webrtc::PeerConnectionInterface::kHaveRemoteOffer
:
119 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer
;
120 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer
:
122 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer
;
123 case webrtc::PeerConnectionInterface::kClosed
:
124 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
127 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
131 blink::WebRTCSessionDescription
CreateWebKitSessionDescription(
132 const std::string
& sdp
, const std::string
& type
) {
133 blink::WebRTCSessionDescription description
;
134 description
.initialize(base::UTF8ToUTF16(type
), base::UTF8ToUTF16(sdp
));
138 blink::WebRTCSessionDescription
139 CreateWebKitSessionDescription(
140 const webrtc::SessionDescriptionInterface
* native_desc
) {
142 LOG(ERROR
) << "Native session description is null.";
143 return blink::WebRTCSessionDescription();
147 if (!native_desc
->ToString(&sdp
)) {
148 LOG(ERROR
) << "Failed to get SDP string of native session description.";
149 return blink::WebRTCSessionDescription();
152 return CreateWebKitSessionDescription(sdp
, native_desc
->type());
155 void RunClosureWithTrace(const base::Closure
& closure
,
156 const char* trace_event_name
) {
157 TRACE_EVENT0("webrtc", trace_event_name
);
161 void RunSynchronousClosure(const base::Closure
& closure
,
162 const char* trace_event_name
,
163 base::WaitableEvent
* event
) {
165 TRACE_EVENT0("webrtc", trace_event_name
);
171 void GetSdpAndTypeFromSessionDescription(
172 const base::Callback
<const webrtc::SessionDescriptionInterface
*()>&
173 description_callback
,
174 std::string
* sdp
, std::string
* type
) {
175 const webrtc::SessionDescriptionInterface
* description
=
176 description_callback
.Run();
178 description
->ToString(sdp
);
179 *type
= description
->type();
183 // Converter functions from WebKit types to WebRTC types.
185 void GetNativeRtcConfiguration(
186 const blink::WebRTCConfiguration
& blink_config
,
187 webrtc::PeerConnectionInterface::RTCConfiguration
* webrtc_config
) {
188 DCHECK_EQ(webrtc_config
->enable_localhost_ice_candidate
, false);
190 // When we don't have WebRTCConfiguration, treat it as a special case where we
191 // should generate local host candidate. This will only be honored if
192 // enable_multiple_routes is disabled.
193 if (blink_config
.isNull()) {
194 webrtc_config
->enable_localhost_ice_candidate
= true;
198 if (blink_config
.iceServers().isNull()) {
199 // Same as when iceServers is undefined or unspecified.
200 webrtc_config
->enable_localhost_ice_candidate
= true;
202 for (size_t i
= 0; i
< blink_config
.iceServers().numberOfServers(); ++i
) {
203 webrtc::PeerConnectionInterface::IceServer server
;
204 const blink::WebRTCICEServer
& webkit_server
=
205 blink_config
.iceServers().server(i
);
207 base::UTF16ToUTF8(base::StringPiece16(webkit_server
.username()));
209 base::UTF16ToUTF8(base::StringPiece16(webkit_server
.credential()));
210 server
.uri
= webkit_server
.uri().spec();
211 webrtc_config
->servers
.push_back(server
);
215 switch (blink_config
.iceTransports()) {
216 case blink::WebRTCIceTransportsNone
:
217 webrtc_config
->type
= webrtc::PeerConnectionInterface::kNone
;
219 case blink::WebRTCIceTransportsRelay
:
220 webrtc_config
->type
= webrtc::PeerConnectionInterface::kRelay
;
222 case blink::WebRTCIceTransportsAll
:
223 webrtc_config
->type
= webrtc::PeerConnectionInterface::kAll
;
229 switch (blink_config
.bundlePolicy()) {
230 case blink::WebRTCBundlePolicyBalanced
:
231 webrtc_config
->bundle_policy
=
232 webrtc::PeerConnectionInterface::kBundlePolicyBalanced
;
234 case blink::WebRTCBundlePolicyMaxBundle
:
235 webrtc_config
->bundle_policy
=
236 webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle
;
238 case blink::WebRTCBundlePolicyMaxCompat
:
239 webrtc_config
->bundle_policy
=
240 webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat
;
246 switch (blink_config
.rtcpMuxPolicy()) {
247 case blink::WebRTCRtcpMuxPolicyNegotiate
:
248 webrtc_config
->rtcp_mux_policy
=
249 webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate
;
251 case blink::WebRTCRtcpMuxPolicyRequire
:
252 webrtc_config
->rtcp_mux_policy
=
253 webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire
;
260 class SessionDescriptionRequestTracker
{
262 SessionDescriptionRequestTracker(
263 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
264 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
265 PeerConnectionTracker::Action action
)
266 : handler_(handler
), tracker_(tracker
), action_(action
) {}
268 void TrackOnSuccess(const webrtc::SessionDescriptionInterface
* desc
) {
269 DCHECK(thread_checker_
.CalledOnValidThread());
270 if (tracker_
&& handler_
) {
273 desc
->ToString(&value
);
274 value
= "type: " + desc
->type() + ", sdp: " + value
;
276 tracker_
->TrackSessionDescriptionCallback(
277 handler_
.get(), action_
, "OnSuccess", value
);
281 void TrackOnFailure(const std::string
& error
) {
282 DCHECK(thread_checker_
.CalledOnValidThread());
283 if (handler_
&& tracker_
) {
284 tracker_
->TrackSessionDescriptionCallback(
285 handler_
.get(), action_
, "OnFailure", error
);
290 const base::WeakPtr
<RTCPeerConnectionHandler
> handler_
;
291 const base::WeakPtr
<PeerConnectionTracker
> tracker_
;
292 PeerConnectionTracker::Action action_
;
293 base::ThreadChecker thread_checker_
;
296 // Class mapping responses from calls to libjingle CreateOffer/Answer and
297 // the blink::WebRTCSessionDescriptionRequest.
298 class CreateSessionDescriptionRequest
299 : public webrtc::CreateSessionDescriptionObserver
{
301 explicit CreateSessionDescriptionRequest(
302 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread
,
303 const blink::WebRTCSessionDescriptionRequest
& request
,
304 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
305 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
306 PeerConnectionTracker::Action action
)
307 : main_thread_(main_thread
),
308 webkit_request_(request
),
309 tracker_(handler
, tracker
, action
) {
312 void OnSuccess(webrtc::SessionDescriptionInterface
* desc
) override
{
313 if (!main_thread_
->BelongsToCurrentThread()) {
314 main_thread_
->PostTask(FROM_HERE
,
315 base::Bind(&CreateSessionDescriptionRequest::OnSuccess
, this, desc
));
319 tracker_
.TrackOnSuccess(desc
);
320 webkit_request_
.requestSucceeded(CreateWebKitSessionDescription(desc
));
321 webkit_request_
.reset();
324 void OnFailure(const std::string
& error
) override
{
325 if (!main_thread_
->BelongsToCurrentThread()) {
326 main_thread_
->PostTask(FROM_HERE
,
327 base::Bind(&CreateSessionDescriptionRequest::OnFailure
, this, error
));
331 tracker_
.TrackOnFailure(error
);
332 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
333 webkit_request_
.reset();
337 ~CreateSessionDescriptionRequest() override
{
338 CHECK(webkit_request_
.isNull());
341 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
342 blink::WebRTCSessionDescriptionRequest webkit_request_
;
343 SessionDescriptionRequestTracker tracker_
;
346 // Class mapping responses from calls to libjingle
347 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
348 class SetSessionDescriptionRequest
349 : public webrtc::SetSessionDescriptionObserver
{
351 explicit SetSessionDescriptionRequest(
352 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread
,
353 const blink::WebRTCVoidRequest
& request
,
354 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
355 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
356 PeerConnectionTracker::Action action
)
357 : main_thread_(main_thread
),
358 webkit_request_(request
),
359 tracker_(handler
, tracker
, action
) {
362 void OnSuccess() override
{
363 if (!main_thread_
->BelongsToCurrentThread()) {
364 main_thread_
->PostTask(FROM_HERE
,
365 base::Bind(&SetSessionDescriptionRequest::OnSuccess
, this));
368 tracker_
.TrackOnSuccess(NULL
);
369 webkit_request_
.requestSucceeded();
370 webkit_request_
.reset();
372 void OnFailure(const std::string
& error
) override
{
373 if (!main_thread_
->BelongsToCurrentThread()) {
374 main_thread_
->PostTask(FROM_HERE
,
375 base::Bind(&SetSessionDescriptionRequest::OnFailure
, this, error
));
378 tracker_
.TrackOnFailure(error
);
379 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
380 webkit_request_
.reset();
384 ~SetSessionDescriptionRequest() override
{
385 DCHECK(webkit_request_
.isNull());
389 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
390 blink::WebRTCVoidRequest webkit_request_
;
391 SessionDescriptionRequestTracker tracker_
;
394 // Class mapping responses from calls to libjingle
395 // GetStats into a blink::WebRTCStatsCallback.
396 class StatsResponse
: public webrtc::StatsObserver
{
398 explicit StatsResponse(const scoped_refptr
<LocalRTCStatsRequest
>& request
)
399 : request_(request
.get()),
400 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
401 // Measure the overall time it takes to satisfy a getStats request.
402 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
403 signaling_thread_checker_
.DetachFromThread();
406 void OnComplete(const StatsReports
& reports
) override
{
407 DCHECK(signaling_thread_checker_
.CalledOnValidThread());
408 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
409 // We can't use webkit objects directly since they use a single threaded
411 std::vector
<Report
*>* report_copies
= new std::vector
<Report
*>();
412 report_copies
->reserve(reports
.size());
413 for (auto* r
: reports
)
414 report_copies
->push_back(new Report(r
));
416 main_thread_
->PostTaskAndReply(FROM_HERE
,
417 base::Bind(&StatsResponse::DeliverCallback
, this,
418 base::Unretained(report_copies
)),
419 base::Bind(&StatsResponse::DeleteReports
,
420 base::Unretained(report_copies
)));
425 Report(const StatsReport
* report
)
426 : thread_checker(), id(report
->id()->ToString()),
427 type(report
->TypeToString()), timestamp(report
->timestamp()),
428 values(report
->values()) {
432 // Since the values vector holds pointers to const objects that are bound
433 // to the signaling thread, they must be released on the same thread.
434 DCHECK(thread_checker
.CalledOnValidThread());
437 const base::ThreadChecker thread_checker
;
438 const std::string id
, type
;
439 const double timestamp
;
440 const StatsReport::Values values
;
443 static void DeleteReports(std::vector
<Report
*>* reports
) {
444 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
445 for (auto* p
: *reports
)
450 void DeliverCallback(const std::vector
<Report
*>* reports
) {
451 DCHECK(main_thread_
->BelongsToCurrentThread());
452 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
454 rtc::scoped_refptr
<LocalRTCStatsResponse
> response(
455 request_
->createResponse().get());
456 for (const auto* report
: *reports
) {
457 if (report
->values
.size() > 0)
458 AddReport(response
.get(), *report
);
461 // Record the getStats operation as done before calling into Blink so that
462 // we don't skew the perf measurements of the native code with whatever the
463 // callback might be doing.
464 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
465 request_
->requestSucceeded(response
);
466 request_
= nullptr; // must be freed on the main thread.
469 void AddReport(LocalRTCStatsResponse
* response
, const Report
& report
) {
470 int idx
= response
->addReport(blink::WebString::fromUTF8(report
.id
),
471 blink::WebString::fromUTF8(report
.type
),
473 blink::WebString name
, value_str
;
474 for (const auto& value
: report
.values
) {
475 const StatsReport::ValuePtr
& v
= value
.second
;
476 name
= blink::WebString::fromUTF8(value
.second
->display_name());
478 if (v
->type() == StatsReport::Value::kString
)
479 value_str
= blink::WebString::fromUTF8(v
->string_val());
480 if (v
->type() == StatsReport::Value::kStaticString
)
481 value_str
= blink::WebString::fromUTF8(v
->static_string_val());
483 value_str
= blink::WebString::fromUTF8(v
->ToString());
485 response
->addStatistic(idx
, name
, value_str
);
489 rtc::scoped_refptr
<LocalRTCStatsRequest
> request_
;
490 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
491 base::ThreadChecker signaling_thread_checker_
;
494 void GetStatsOnSignalingThread(
495 const scoped_refptr
<webrtc::PeerConnectionInterface
>& pc
,
496 webrtc::PeerConnectionInterface::StatsOutputLevel level
,
497 const scoped_refptr
<webrtc::StatsObserver
>& observer
,
498 const std::string track_id
, blink::WebMediaStreamSource::Type track_type
) {
499 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
501 scoped_refptr
<webrtc::MediaStreamTrackInterface
> track
;
502 if (!track_id
.empty()) {
503 if (track_type
== blink::WebMediaStreamSource::TypeAudio
) {
504 track
= pc
->local_streams()->FindAudioTrack(track_id
);
506 track
= pc
->remote_streams()->FindAudioTrack(track_id
);
508 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo
, track_type
);
509 track
= pc
->local_streams()->FindVideoTrack(track_id
);
511 track
= pc
->remote_streams()->FindVideoTrack(track_id
);
515 DVLOG(1) << "GetStats: Track not found.";
516 observer
->OnComplete(StatsReports());
521 if (!pc
->GetStats(observer
.get(), track
.get(), level
)) {
522 DVLOG(1) << "GetStats failed.";
523 observer
->OnComplete(StatsReports());
527 class PeerConnectionUMAObserver
: public webrtc::UMAObserver
{
529 PeerConnectionUMAObserver() {}
530 ~PeerConnectionUMAObserver() override
{}
531 void IncrementEnumCounter(webrtc::PeerConnectionEnumCounterType counter_type
,
533 int counter_max
) override
{
534 switch (counter_type
) {
535 case webrtc::kEnumCounterAddressFamily
:
536 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics", counter
,
539 case webrtc::kEnumCounterIceCandidatePairTypeUdp
:
540 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_UDP",
541 counter
, counter_max
);
543 case webrtc::kEnumCounterIceCandidatePairTypeTcp
:
544 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.CandidatePairType_TCP",
545 counter
, counter_max
);
548 // The default clause is expected to reach when new enum types are
554 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type
,
555 int value
) override
{
556 // Runs on libjingle's signaling thread.
558 case webrtc::kTimeToConnect
:
559 UMA_HISTOGRAM_MEDIUM_TIMES(
560 "WebRTC.PeerConnection.TimeToConnect",
561 base::TimeDelta::FromMilliseconds(value
));
563 case webrtc::kNetworkInterfaces_IPv4
:
564 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
567 case webrtc::kNetworkInterfaces_IPv6
:
568 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
572 // The default clause is expected to reach when new enum types are
579 base::LazyInstance
<std::set
<RTCPeerConnectionHandler
*> >::Leaky
580 g_peer_connection_handlers
= LAZY_INSTANCE_INITIALIZER
;
584 // Implementation of LocalRTCStatsRequest.
585 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl
)
589 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
590 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
592 bool LocalRTCStatsRequest::hasSelector() const {
593 return impl_
.hasSelector();
596 blink::WebMediaStreamTrack
LocalRTCStatsRequest::component() const {
597 return impl_
.component();
600 scoped_refptr
<LocalRTCStatsResponse
> LocalRTCStatsRequest::createResponse() {
601 return scoped_refptr
<LocalRTCStatsResponse
>(
602 new rtc::RefCountedObject
<LocalRTCStatsResponse
>(impl_
.createResponse()));
605 void LocalRTCStatsRequest::requestSucceeded(
606 const LocalRTCStatsResponse
* response
) {
607 impl_
.requestSucceeded(response
->webKitStatsResponse());
610 // Implementation of LocalRTCStatsResponse.
611 blink::WebRTCStatsResponse
LocalRTCStatsResponse::webKitStatsResponse() const {
615 size_t LocalRTCStatsResponse::addReport(blink::WebString type
,
618 return impl_
.addReport(type
, id
, timestamp
);
621 void LocalRTCStatsResponse::addStatistic(size_t report
,
622 blink::WebString name
,
623 blink::WebString value
) {
624 impl_
.addStatistic(report
, name
, value
);
627 // Receives notifications from a PeerConnection object about state changes,
628 // track addition/removal etc. The callbacks we receive here come on the
629 // signaling thread, so this class takes care of delivering them to an
630 // RTCPeerConnectionHandler instance on the main thread.
631 // In order to do safe PostTask-ing, the class is reference counted and
632 // checks for the existence of the RTCPeerConnectionHandler instance before
633 // delivering callbacks on the main thread.
634 class RTCPeerConnectionHandler::Observer
635 : public base::RefCountedThreadSafe
<RTCPeerConnectionHandler::Observer
>,
636 public PeerConnectionObserver
{
638 Observer(const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
)
639 : handler_(handler
), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
642 friend class base::RefCountedThreadSafe
<RTCPeerConnectionHandler::Observer
>;
643 virtual ~Observer() {}
645 void OnSignalingChange(
646 PeerConnectionInterface::SignalingState new_state
) override
{
647 if (!main_thread_
->BelongsToCurrentThread()) {
648 main_thread_
->PostTask(FROM_HERE
,
649 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange
,
651 } else if (handler_
) {
652 handler_
->OnSignalingChange(new_state
);
656 void OnAddStream(MediaStreamInterface
* stream
) override
{
658 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(
659 new RemoteMediaStreamImpl(main_thread_
, stream
));
661 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
662 // asynchronously and the posted task will execude after that initialization
664 main_thread_
->PostTask(FROM_HERE
,
665 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl
,
666 this, base::Passed(&remote_stream
)));
669 void OnRemoveStream(MediaStreamInterface
* stream
) override
{
670 main_thread_
->PostTask(FROM_HERE
,
671 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl
,
672 this, make_scoped_refptr(stream
)));
675 void OnDataChannel(DataChannelInterface
* data_channel
) override
{
676 scoped_ptr
<RtcDataChannelHandler
> handler(
677 new RtcDataChannelHandler(main_thread_
, data_channel
));
678 main_thread_
->PostTask(FROM_HERE
,
679 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl
,
680 this, base::Passed(&handler
)));
683 void OnRenegotiationNeeded() override
{
684 if (!main_thread_
->BelongsToCurrentThread()) {
685 main_thread_
->PostTask(FROM_HERE
,
686 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded
,
688 } else if (handler_
) {
689 handler_
->OnRenegotiationNeeded();
693 void OnIceConnectionChange(
694 PeerConnectionInterface::IceConnectionState new_state
) override
{
695 if (!main_thread_
->BelongsToCurrentThread()) {
696 main_thread_
->PostTask(FROM_HERE
,
698 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange
, this,
700 } else if (handler_
) {
701 handler_
->OnIceConnectionChange(new_state
);
705 void OnIceGatheringChange(
706 PeerConnectionInterface::IceGatheringState new_state
) override
{
707 if (!main_thread_
->BelongsToCurrentThread()) {
708 main_thread_
->PostTask(FROM_HERE
,
709 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange
,
711 } else if (handler_
) {
712 handler_
->OnIceGatheringChange(new_state
);
716 void OnIceCandidate(const IceCandidateInterface
* candidate
) override
{
718 if (!candidate
->ToString(&sdp
)) {
719 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
723 main_thread_
->PostTask(FROM_HERE
,
724 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl
,
725 this, sdp
, candidate
->sdp_mid(), candidate
->sdp_mline_index(),
726 candidate
->candidate().component(),
727 candidate
->candidate().address().family()));
730 void OnAddStreamImpl(scoped_ptr
<RemoteMediaStreamImpl
> stream
) {
731 DCHECK(stream
->webkit_stream().extraData()) << "Initialization not done";
733 handler_
->OnAddStream(stream
.Pass());
736 void OnRemoveStreamImpl(const scoped_refptr
<MediaStreamInterface
>& stream
) {
738 handler_
->OnRemoveStream(stream
);
741 void OnDataChannelImpl(scoped_ptr
<RtcDataChannelHandler
> handler
) {
743 handler_
->OnDataChannel(handler
.Pass());
746 void OnIceCandidateImpl(const std::string
& sdp
, const std::string
& sdp_mid
,
747 int sdp_mline_index
, int component
, int address_family
) {
749 handler_
->OnIceCandidate(sdp
, sdp_mid
, sdp_mline_index
, component
,
755 const base::WeakPtr
<RTCPeerConnectionHandler
> handler_
;
756 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
759 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
760 blink::WebRTCPeerConnectionHandlerClient
* client
,
761 PeerConnectionDependencyFactory
* dependency_factory
)
763 dependency_factory_(dependency_factory
),
764 weak_factory_(this) {
765 g_peer_connection_handlers
.Get().insert(this);
768 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
769 DCHECK(thread_checker_
.CalledOnValidThread());
773 g_peer_connection_handlers
.Get().erase(this);
774 if (peer_connection_tracker_
)
775 peer_connection_tracker_
->UnregisterPeerConnection(this);
776 STLDeleteValues(&remote_streams_
);
778 UMA_HISTOGRAM_COUNTS_10000(
779 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_
);
783 void RTCPeerConnectionHandler::DestructAllHandlers() {
784 std::set
<RTCPeerConnectionHandler
*> handlers(
785 g_peer_connection_handlers
.Get().begin(),
786 g_peer_connection_handlers
.Get().end());
787 for (auto handler
: handlers
) {
788 if (handler
->client_
)
789 handler
->client_
->releasePeerConnectionHandler();
794 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
795 const blink::WebRTCOfferOptions
& options
,
796 RTCMediaConstraints
* output
) {
797 output
->AddMandatory(
798 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio
,
799 options
.offerToReceiveAudio() > 0 ? "true" : "false",
802 output
->AddMandatory(
803 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo
,
804 options
.offerToReceiveVideo() > 0 ? "true" : "false",
807 if (!options
.voiceActivityDetection()) {
808 output
->AddMandatory(
809 webrtc::MediaConstraintsInterface::kVoiceActivityDetection
,
814 if (options
.iceRestart()) {
815 output
->AddMandatory(
816 webrtc::MediaConstraintsInterface::kIceRestart
, "true", true);
820 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame
* frame
) {
821 DCHECK(thread_checker_
.CalledOnValidThread());
826 bool RTCPeerConnectionHandler::initialize(
827 const blink::WebRTCConfiguration
& server_configuration
,
828 const blink::WebMediaConstraints
& options
) {
829 DCHECK(thread_checker_
.CalledOnValidThread());
832 peer_connection_tracker_
=
833 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
835 webrtc::PeerConnectionInterface::RTCConfiguration config
;
836 GetNativeRtcConfiguration(server_configuration
, &config
);
838 RTCMediaConstraints
constraints(options
);
840 peer_connection_observer_
= new Observer(weak_factory_
.GetWeakPtr());
841 native_peer_connection_
= dependency_factory_
->CreatePeerConnection(
842 config
, &constraints
, frame_
, peer_connection_observer_
.get());
844 if (!native_peer_connection_
.get()) {
845 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
849 if (peer_connection_tracker_
) {
850 peer_connection_tracker_
->RegisterPeerConnection(
851 this, config
, constraints
, frame_
);
854 uma_observer_
= new rtc::RefCountedObject
<PeerConnectionUMAObserver
>();
855 native_peer_connection_
->RegisterUMAObserver(uma_observer_
.get());
859 bool RTCPeerConnectionHandler::InitializeForTest(
860 const blink::WebRTCConfiguration
& server_configuration
,
861 const blink::WebMediaConstraints
& options
,
862 const base::WeakPtr
<PeerConnectionTracker
>& peer_connection_tracker
) {
863 DCHECK(thread_checker_
.CalledOnValidThread());
864 webrtc::PeerConnectionInterface::RTCConfiguration config
;
865 GetNativeRtcConfiguration(server_configuration
, &config
);
867 peer_connection_observer_
= new Observer(weak_factory_
.GetWeakPtr());
868 RTCMediaConstraints
constraints(options
);
869 native_peer_connection_
= dependency_factory_
->CreatePeerConnection(
870 config
, &constraints
, NULL
, peer_connection_observer_
.get());
871 if (!native_peer_connection_
.get()) {
872 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
875 peer_connection_tracker_
= peer_connection_tracker
;
879 void RTCPeerConnectionHandler::createOffer(
880 const blink::WebRTCSessionDescriptionRequest
& request
,
881 const blink::WebMediaConstraints
& options
) {
882 DCHECK(thread_checker_
.CalledOnValidThread());
883 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
885 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
886 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
887 base::ThreadTaskRunnerHandle::Get(), request
,
888 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
889 PeerConnectionTracker::ACTION_CREATE_OFFER
));
891 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
892 RTCMediaConstraints
constraints(options
);
893 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
895 if (peer_connection_tracker_
)
896 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
899 void RTCPeerConnectionHandler::createOffer(
900 const blink::WebRTCSessionDescriptionRequest
& request
,
901 const blink::WebRTCOfferOptions
& options
) {
902 DCHECK(thread_checker_
.CalledOnValidThread());
903 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
905 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
906 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
907 base::ThreadTaskRunnerHandle::Get(), request
,
908 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
909 PeerConnectionTracker::ACTION_CREATE_OFFER
));
911 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
912 RTCMediaConstraints constraints
;
913 ConvertOfferOptionsToConstraints(options
, &constraints
);
914 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
916 if (peer_connection_tracker_
)
917 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
920 void RTCPeerConnectionHandler::createAnswer(
921 const blink::WebRTCSessionDescriptionRequest
& request
,
922 const blink::WebMediaConstraints
& options
) {
923 DCHECK(thread_checker_
.CalledOnValidThread());
924 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
925 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
926 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
927 base::ThreadTaskRunnerHandle::Get(), request
,
928 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
929 PeerConnectionTracker::ACTION_CREATE_ANSWER
));
930 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
931 RTCMediaConstraints
constraints(options
);
932 native_peer_connection_
->CreateAnswer(description_request
.get(),
935 if (peer_connection_tracker_
)
936 peer_connection_tracker_
->TrackCreateAnswer(this, constraints
);
939 bool IsOfferOrAnswer(const webrtc::SessionDescriptionInterface
* native_desc
) {
941 return native_desc
->type() == "offer" || native_desc
->type() == "answer";
944 void RTCPeerConnectionHandler::setLocalDescription(
945 const blink::WebRTCVoidRequest
& request
,
946 const blink::WebRTCSessionDescription
& description
) {
947 DCHECK(thread_checker_
.CalledOnValidThread());
948 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
950 std::string sdp
= base::UTF16ToUTF8(base::StringPiece16(description
.sdp()));
952 base::UTF16ToUTF8(base::StringPiece16(description
.type()));
954 webrtc::SdpParseError error
;
955 // Since CreateNativeSessionDescription uses the dependency factory, we need
956 // to make this call on the current thread to be safe.
957 webrtc::SessionDescriptionInterface
* native_desc
=
958 CreateNativeSessionDescription(sdp
, type
, &error
);
960 std::string reason_str
= "Failed to parse SessionDescription. ";
961 reason_str
.append(error
.line
);
962 reason_str
.append(" ");
963 reason_str
.append(error
.description
);
964 LOG(ERROR
) << reason_str
;
965 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
969 if (peer_connection_tracker_
) {
970 peer_connection_tracker_
->TrackSetSessionDescription(
971 this, sdp
, type
, PeerConnectionTracker::SOURCE_LOCAL
);
974 if (!first_local_description_
&& IsOfferOrAnswer(native_desc
)) {
975 first_local_description_
.reset(new FirstSessionDescription(native_desc
));
976 if (first_remote_description_
) {
977 ReportFirstSessionDescriptions(
978 *first_local_description_
,
979 *first_remote_description_
);
983 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
984 new rtc::RefCountedObject
<SetSessionDescriptionRequest
>(
985 base::ThreadTaskRunnerHandle::Get(), request
,
986 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
987 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION
));
989 signaling_thread()->PostTask(FROM_HERE
,
990 base::Bind(&RunClosureWithTrace
,
991 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription
,
992 native_peer_connection_
, set_request
,
993 base::Unretained(native_desc
)),
994 "SetLocalDescription"));
997 void RTCPeerConnectionHandler::setRemoteDescription(
998 const blink::WebRTCVoidRequest
& request
,
999 const blink::WebRTCSessionDescription
& description
) {
1000 DCHECK(thread_checker_
.CalledOnValidThread());
1001 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
1002 std::string sdp
= base::UTF16ToUTF8(base::StringPiece16(description
.sdp()));
1004 base::UTF16ToUTF8(base::StringPiece16(description
.type()));
1006 webrtc::SdpParseError error
;
1007 // Since CreateNativeSessionDescription uses the dependency factory, we need
1008 // to make this call on the current thread to be safe.
1009 webrtc::SessionDescriptionInterface
* native_desc
=
1010 CreateNativeSessionDescription(sdp
, type
, &error
);
1012 std::string reason_str
= "Failed to parse SessionDescription. ";
1013 reason_str
.append(error
.line
);
1014 reason_str
.append(" ");
1015 reason_str
.append(error
.description
);
1016 LOG(ERROR
) << reason_str
;
1017 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
1021 if (peer_connection_tracker_
) {
1022 peer_connection_tracker_
->TrackSetSessionDescription(
1023 this, sdp
, type
, PeerConnectionTracker::SOURCE_REMOTE
);
1026 if (!first_remote_description_
&& IsOfferOrAnswer(native_desc
)) {
1027 first_remote_description_
.reset(new FirstSessionDescription(native_desc
));
1028 if (first_local_description_
) {
1029 ReportFirstSessionDescriptions(
1030 *first_local_description_
,
1031 *first_remote_description_
);
1035 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
1036 new rtc::RefCountedObject
<SetSessionDescriptionRequest
>(
1037 base::ThreadTaskRunnerHandle::Get(), request
,
1038 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
1039 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION
));
1040 signaling_thread()->PostTask(FROM_HERE
,
1041 base::Bind(&RunClosureWithTrace
,
1042 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription
,
1043 native_peer_connection_
, set_request
,
1044 base::Unretained(native_desc
)),
1045 "SetRemoteDescription"));
1048 blink::WebRTCSessionDescription
1049 RTCPeerConnectionHandler::localDescription() {
1050 DCHECK(thread_checker_
.CalledOnValidThread());
1051 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
1053 // Since local_description returns a pointer to a non-reference-counted object
1054 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1055 // it directly here. Instead, we access the object completely on the signaling
1057 std::string sdp
, type
;
1058 base::Callback
<const webrtc::SessionDescriptionInterface
*()> description_cb
=
1059 base::Bind(&webrtc::PeerConnectionInterface::local_description
,
1060 native_peer_connection_
);
1061 RunSynchronousClosureOnSignalingThread(
1062 base::Bind(&GetSdpAndTypeFromSessionDescription
, description_cb
,
1063 base::Unretained(&sdp
), base::Unretained(&type
)),
1064 "localDescription");
1066 return CreateWebKitSessionDescription(sdp
, type
);
1069 blink::WebRTCSessionDescription
1070 RTCPeerConnectionHandler::remoteDescription() {
1071 DCHECK(thread_checker_
.CalledOnValidThread());
1072 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
1073 // Since local_description returns a pointer to a non-reference-counted object
1074 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1075 // it directly here. Instead, we access the object completely on the signaling
1077 std::string sdp
, type
;
1078 base::Callback
<const webrtc::SessionDescriptionInterface
*()> description_cb
=
1079 base::Bind(&webrtc::PeerConnectionInterface::remote_description
,
1080 native_peer_connection_
);
1081 RunSynchronousClosureOnSignalingThread(
1082 base::Bind(&GetSdpAndTypeFromSessionDescription
, description_cb
,
1083 base::Unretained(&sdp
), base::Unretained(&type
)),
1084 "remoteDescription");
1086 return CreateWebKitSessionDescription(sdp
, type
);
1089 bool RTCPeerConnectionHandler::updateICE(
1090 const blink::WebRTCConfiguration
& server_configuration
,
1091 const blink::WebMediaConstraints
& options
) {
1092 DCHECK(thread_checker_
.CalledOnValidThread());
1093 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1094 webrtc::PeerConnectionInterface::RTCConfiguration config
;
1095 GetNativeRtcConfiguration(server_configuration
, &config
);
1096 RTCMediaConstraints
constraints(options
);
1098 if (peer_connection_tracker_
)
1099 peer_connection_tracker_
->TrackUpdateIce(this, config
, constraints
);
1101 return native_peer_connection_
->UpdateIce(config
.servers
, &constraints
);
1104 bool RTCPeerConnectionHandler::addICECandidate(
1105 const blink::WebRTCVoidRequest
& request
,
1106 const blink::WebRTCICECandidate
& candidate
) {
1107 DCHECK(thread_checker_
.CalledOnValidThread());
1108 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1109 // Libjingle currently does not accept callbacks for addICECandidate.
1110 // For that reason we are going to call callbacks from here.
1112 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1113 // PostTaskAndReply kind of a thing.
1114 bool result
= addICECandidate(candidate
);
1115 base::ThreadTaskRunnerHandle::Get()->PostTask(
1116 FROM_HERE
, base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult
,
1117 weak_factory_
.GetWeakPtr(), request
, result
));
1118 // On failure callback will be triggered.
1122 bool RTCPeerConnectionHandler::addICECandidate(
1123 const blink::WebRTCICECandidate
& candidate
) {
1124 DCHECK(thread_checker_
.CalledOnValidThread());
1125 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1126 scoped_ptr
<webrtc::IceCandidateInterface
> native_candidate(
1127 dependency_factory_
->CreateIceCandidate(
1128 base::UTF16ToUTF8(base::StringPiece16(candidate
.sdpMid())),
1129 candidate
.sdpMLineIndex(),
1130 base::UTF16ToUTF8(base::StringPiece16(candidate
.candidate()))));
1131 bool return_value
= false;
1133 if (native_candidate
) {
1135 native_peer_connection_
->AddIceCandidate(native_candidate
.get());
1136 LOG_IF(ERROR
, !return_value
) << "Error processing ICE candidate.";
1138 LOG(ERROR
) << "Could not create native ICE candidate.";
1141 if (peer_connection_tracker_
) {
1142 peer_connection_tracker_
->TrackAddIceCandidate(
1143 this, candidate
, PeerConnectionTracker::SOURCE_REMOTE
, return_value
);
1145 return return_value
;
1148 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1149 const blink::WebRTCVoidRequest
& webkit_request
, bool result
) {
1150 DCHECK(thread_checker_
.CalledOnValidThread());
1151 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1153 // We don't have the actual error code from the libjingle, so for now
1154 // using a generic error string.
1155 return webkit_request
.requestFailed(
1156 base::UTF8ToUTF16("Error processing ICE candidate"));
1159 return webkit_request
.requestSucceeded();
1162 bool RTCPeerConnectionHandler::addStream(
1163 const blink::WebMediaStream
& stream
,
1164 const blink::WebMediaConstraints
& options
) {
1165 DCHECK(thread_checker_
.CalledOnValidThread());
1166 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1167 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
1168 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
1170 if ((*adapter_it
)->IsEqual(stream
)) {
1171 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1172 << "stream twice. id=" << stream
.id().utf8();
1177 if (peer_connection_tracker_
) {
1178 peer_connection_tracker_
->TrackAddStream(
1179 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
1182 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1184 WebRtcMediaStreamAdapter
* adapter
=
1185 new WebRtcMediaStreamAdapter(stream
, dependency_factory_
);
1186 local_streams_
.push_back(adapter
);
1188 webrtc::MediaStreamInterface
* webrtc_stream
= adapter
->webrtc_media_stream();
1189 track_metrics_
.AddStream(MediaStreamTrackMetrics::SENT_STREAM
,
1192 RTCMediaConstraints
constraints(options
);
1193 if (!constraints
.GetMandatory().empty() ||
1194 !constraints
.GetOptional().empty()) {
1195 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1196 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1197 // should be removed from blink as well.
1199 << "mediaConstraints is not a supported argument to addStream.";
1202 return native_peer_connection_
->AddStream(webrtc_stream
);
1205 void RTCPeerConnectionHandler::removeStream(
1206 const blink::WebMediaStream
& stream
) {
1207 DCHECK(thread_checker_
.CalledOnValidThread());
1208 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1209 // Find the webrtc stream.
1210 scoped_refptr
<webrtc::MediaStreamInterface
> webrtc_stream
;
1211 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
1212 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
1214 if ((*adapter_it
)->IsEqual(stream
)) {
1215 webrtc_stream
= (*adapter_it
)->webrtc_media_stream();
1216 local_streams_
.erase(adapter_it
);
1220 DCHECK(webrtc_stream
.get());
1221 // TODO(tommi): Make this async (PostTaskAndReply).
1222 native_peer_connection_
->RemoveStream(webrtc_stream
.get());
1224 if (peer_connection_tracker_
) {
1225 peer_connection_tracker_
->TrackRemoveStream(
1226 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
1228 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1229 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM
,
1230 webrtc_stream
.get());
1233 void RTCPeerConnectionHandler::getStats(
1234 const blink::WebRTCStatsRequest
& request
) {
1235 DCHECK(thread_checker_
.CalledOnValidThread());
1236 scoped_refptr
<LocalRTCStatsRequest
> inner_request(
1237 new rtc::RefCountedObject
<LocalRTCStatsRequest
>(request
));
1238 getStats(inner_request
);
1241 void RTCPeerConnectionHandler::getStats(
1242 const scoped_refptr
<LocalRTCStatsRequest
>& request
) {
1243 DCHECK(thread_checker_
.CalledOnValidThread());
1244 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1247 rtc::scoped_refptr
<webrtc::StatsObserver
> observer(
1248 new rtc::RefCountedObject
<StatsResponse
>(request
));
1250 std::string track_id
;
1251 blink::WebMediaStreamSource::Type track_type
=
1252 blink::WebMediaStreamSource::TypeAudio
;
1253 if (request
->hasSelector()) {
1254 track_type
= request
->component().source().type();
1255 track_id
= request
->component().id().utf8();
1258 GetStats(observer
, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard
,
1259 track_id
, track_type
);
1262 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1263 void RTCPeerConnectionHandler::GetStats(
1264 webrtc::StatsObserver
* observer
,
1265 webrtc::PeerConnectionInterface::StatsOutputLevel level
,
1266 const std::string
& track_id
,
1267 blink::WebMediaStreamSource::Type track_type
) {
1268 DCHECK(thread_checker_
.CalledOnValidThread());
1269 signaling_thread()->PostTask(FROM_HERE
,
1270 base::Bind(&GetStatsOnSignalingThread
, native_peer_connection_
, level
,
1271 make_scoped_refptr(observer
), track_id
, track_type
));
1274 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1275 DCHECK(thread_checker_
.CalledOnValidThread());
1277 client_
->closePeerConnection();
1280 blink::WebRTCDataChannelHandler
* RTCPeerConnectionHandler::createDataChannel(
1281 const blink::WebString
& label
, const blink::WebRTCDataChannelInit
& init
) {
1282 DCHECK(thread_checker_
.CalledOnValidThread());
1283 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1284 DVLOG(1) << "createDataChannel label "
1285 << base::UTF16ToUTF8(base::StringPiece16(label
));
1287 webrtc::DataChannelInit config
;
1288 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1290 config
.reliable
= false;
1291 config
.id
= init
.id
;
1292 config
.ordered
= init
.ordered
;
1293 config
.negotiated
= init
.negotiated
;
1294 config
.maxRetransmits
= init
.maxRetransmits
;
1295 config
.maxRetransmitTime
= init
.maxRetransmitTime
;
1296 config
.protocol
= base::UTF16ToUTF8(base::StringPiece16(init
.protocol
));
1298 rtc::scoped_refptr
<webrtc::DataChannelInterface
> webrtc_channel(
1299 native_peer_connection_
->CreateDataChannel(
1300 base::UTF16ToUTF8(base::StringPiece16(label
)), &config
));
1301 if (!webrtc_channel
) {
1302 DLOG(ERROR
) << "Could not create native data channel.";
1305 if (peer_connection_tracker_
) {
1306 peer_connection_tracker_
->TrackCreateDataChannel(
1307 this, webrtc_channel
.get(), PeerConnectionTracker::SOURCE_LOCAL
);
1310 ++num_data_channels_created_
;
1312 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1316 blink::WebRTCDTMFSenderHandler
* RTCPeerConnectionHandler::createDTMFSender(
1317 const blink::WebMediaStreamTrack
& track
) {
1318 DCHECK(thread_checker_
.CalledOnValidThread());
1319 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1320 DVLOG(1) << "createDTMFSender.";
1322 MediaStreamTrack
* native_track
= MediaStreamTrack::GetTrack(track
);
1323 if (!native_track
|| !native_track
->is_local_track() ||
1324 track
.source().type() != blink::WebMediaStreamSource::TypeAudio
) {
1325 DLOG(ERROR
) << "The DTMF sender requires a local audio track.";
1329 scoped_refptr
<webrtc::AudioTrackInterface
> audio_track
=
1330 native_track
->GetAudioAdapter();
1331 rtc::scoped_refptr
<webrtc::DtmfSenderInterface
> sender(
1332 native_peer_connection_
->CreateDtmfSender(audio_track
.get()));
1334 DLOG(ERROR
) << "Could not create native DTMF sender.";
1337 if (peer_connection_tracker_
)
1338 peer_connection_tracker_
->TrackCreateDTMFSender(this, track
);
1340 return new RtcDtmfSenderHandler(sender
);
1343 void RTCPeerConnectionHandler::stop() {
1344 DCHECK(thread_checker_
.CalledOnValidThread());
1345 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1347 if (!client_
|| !native_peer_connection_
.get())
1348 return; // Already stopped.
1350 if (peer_connection_tracker_
)
1351 peer_connection_tracker_
->TrackStop(this);
1353 native_peer_connection_
->Close();
1355 // The client_ pointer is not considered valid after this point and no further
1356 // callbacks must be made.
1360 void RTCPeerConnectionHandler::OnSignalingChange(
1361 webrtc::PeerConnectionInterface::SignalingState new_state
) {
1362 DCHECK(thread_checker_
.CalledOnValidThread());
1363 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1365 blink::WebRTCPeerConnectionHandlerClient::SignalingState state
=
1366 GetWebKitSignalingState(new_state
);
1367 if (peer_connection_tracker_
)
1368 peer_connection_tracker_
->TrackSignalingStateChange(this, state
);
1370 client_
->didChangeSignalingState(state
);
1373 // Called any time the IceConnectionState changes
1374 void RTCPeerConnectionHandler::OnIceConnectionChange(
1375 webrtc::PeerConnectionInterface::IceConnectionState new_state
) {
1376 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1377 DCHECK(thread_checker_
.CalledOnValidThread());
1378 ReportICEState(new_state
);
1379 if (new_state
== webrtc::PeerConnectionInterface::kIceConnectionChecking
) {
1380 ice_connection_checking_start_
= base::TimeTicks::Now();
1381 } else if (new_state
==
1382 webrtc::PeerConnectionInterface::kIceConnectionConnected
) {
1383 // If the state becomes connected, send the time needed for PC to become
1384 // connected from checking to UMA. UMA data will help to know how much
1385 // time needed for PC to connect with remote peer.
1386 if (ice_connection_checking_start_
.is_null()) {
1387 // From UMA, we have observed a large number of calls falling into the
1388 // overflow buckets. One possibility is that the Checking is not signaled
1389 // before Connected. This is to guard against that situation to make the
1390 // metric more robust.
1391 UMA_HISTOGRAM_MEDIUM_TIMES("WebRTC.PeerConnection.TimeToConnect",
1394 UMA_HISTOGRAM_MEDIUM_TIMES(
1395 "WebRTC.PeerConnection.TimeToConnect",
1396 base::TimeTicks::Now() - ice_connection_checking_start_
);
1400 track_metrics_
.IceConnectionChange(new_state
);
1401 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state
=
1402 GetWebKitIceConnectionState(new_state
);
1403 if (peer_connection_tracker_
)
1404 peer_connection_tracker_
->TrackIceConnectionStateChange(this, state
);
1406 client_
->didChangeICEConnectionState(state
);
1409 // Called any time the IceGatheringState changes
1410 void RTCPeerConnectionHandler::OnIceGatheringChange(
1411 webrtc::PeerConnectionInterface::IceGatheringState new_state
) {
1412 DCHECK(thread_checker_
.CalledOnValidThread());
1413 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1415 if (new_state
== webrtc::PeerConnectionInterface::kIceGatheringComplete
) {
1416 // If ICE gathering is completed, generate a NULL ICE candidate,
1417 // to signal end of candidates.
1419 blink::WebRTCICECandidate null_candidate
;
1420 client_
->didGenerateICECandidate(null_candidate
);
1423 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1424 num_local_candidates_ipv4_
);
1426 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1427 num_local_candidates_ipv6_
);
1428 } else if (new_state
==
1429 webrtc::PeerConnectionInterface::kIceGatheringGathering
) {
1430 // ICE restarts will change gathering state back to "gathering",
1431 // reset the counter.
1435 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state
=
1436 GetWebKitIceGatheringState(new_state
);
1437 if (peer_connection_tracker_
)
1438 peer_connection_tracker_
->TrackIceGatheringStateChange(this, state
);
1440 client_
->didChangeICEGatheringState(state
);
1443 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1444 DCHECK(thread_checker_
.CalledOnValidThread());
1445 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1446 if (peer_connection_tracker_
)
1447 peer_connection_tracker_
->TrackOnRenegotiationNeeded(this);
1449 client_
->negotiationNeeded();
1452 void RTCPeerConnectionHandler::OnAddStream(
1453 scoped_ptr
<RemoteMediaStreamImpl
> stream
) {
1454 DCHECK(thread_checker_
.CalledOnValidThread());
1455 DCHECK(remote_streams_
.find(stream
->webrtc_stream().get()) ==
1456 remote_streams_
.end());
1457 DCHECK(stream
->webkit_stream().extraData()) << "Initialization not done";
1458 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1460 // Ownership is with remote_streams_ now.
1461 RemoteMediaStreamImpl
* s
= stream
.release();
1462 remote_streams_
.insert(
1463 std::pair
<webrtc::MediaStreamInterface
*, RemoteMediaStreamImpl
*> (
1464 s
->webrtc_stream().get(), s
));
1466 if (peer_connection_tracker_
) {
1467 peer_connection_tracker_
->TrackAddStream(
1468 this, s
->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE
);
1471 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1473 track_metrics_
.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
1474 s
->webrtc_stream().get());
1476 client_
->didAddRemoteStream(s
->webkit_stream());
1479 void RTCPeerConnectionHandler::OnRemoveStream(
1480 const scoped_refptr
<webrtc::MediaStreamInterface
>& stream
) {
1481 DCHECK(thread_checker_
.CalledOnValidThread());
1482 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1483 RemoteStreamMap::iterator it
= remote_streams_
.find(stream
.get());
1484 if (it
== remote_streams_
.end()) {
1485 NOTREACHED() << "Stream not found";
1489 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
1491 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1493 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(it
->second
);
1494 const blink::WebMediaStream
& webkit_stream
= remote_stream
->webkit_stream();
1495 DCHECK(!webkit_stream
.isNull());
1496 remote_streams_
.erase(it
);
1498 if (peer_connection_tracker_
) {
1499 peer_connection_tracker_
->TrackRemoveStream(
1500 this, webkit_stream
, PeerConnectionTracker::SOURCE_REMOTE
);
1504 client_
->didRemoveRemoteStream(webkit_stream
);
1507 void RTCPeerConnectionHandler::OnDataChannel(
1508 scoped_ptr
<RtcDataChannelHandler
> handler
) {
1509 DCHECK(thread_checker_
.CalledOnValidThread());
1510 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1512 if (peer_connection_tracker_
) {
1513 peer_connection_tracker_
->TrackCreateDataChannel(
1514 this, handler
->channel().get(), PeerConnectionTracker::SOURCE_REMOTE
);
1518 client_
->didAddRemoteDataChannel(handler
.release());
1521 void RTCPeerConnectionHandler::OnIceCandidate(
1522 const std::string
& sdp
, const std::string
& sdp_mid
, int sdp_mline_index
,
1523 int component
, int address_family
) {
1524 DCHECK(thread_checker_
.CalledOnValidThread());
1525 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1526 blink::WebRTCICECandidate web_candidate
;
1527 web_candidate
.initialize(base::UTF8ToUTF16(sdp
),
1528 base::UTF8ToUTF16(sdp_mid
),
1530 if (peer_connection_tracker_
) {
1531 peer_connection_tracker_
->TrackAddIceCandidate(
1532 this, web_candidate
, PeerConnectionTracker::SOURCE_LOCAL
, true);
1535 // Only the first m line's first component is tracked to avoid
1536 // miscounting when doing BUNDLE or rtcp mux.
1537 if (sdp_mline_index
== 0 && component
== 1) {
1538 if (address_family
== AF_INET
) {
1539 ++num_local_candidates_ipv4_
;
1540 } else if (address_family
== AF_INET6
) {
1541 ++num_local_candidates_ipv6_
;
1547 client_
->didGenerateICECandidate(web_candidate
);
1550 webrtc::SessionDescriptionInterface
*
1551 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1552 const std::string
& sdp
, const std::string
& type
,
1553 webrtc::SdpParseError
* error
) {
1554 webrtc::SessionDescriptionInterface
* native_desc
=
1555 dependency_factory_
->CreateSessionDescription(type
, sdp
, error
);
1557 LOG_IF(ERROR
, !native_desc
) << "Failed to create native session description."
1558 << " Type: " << type
<< " SDP: " << sdp
;
1563 RTCPeerConnectionHandler::FirstSessionDescription::FirstSessionDescription(
1564 const webrtc::SessionDescriptionInterface
* sdesc
) {
1567 for (const auto& content
: sdesc
->description()->contents()) {
1568 if (content
.type
== cricket::NS_JINGLE_RTP
) {
1570 static_cast<cricket::MediaContentDescription
*>(content
.description
);
1571 audio
= audio
|| (mdesc
->type() == cricket::MEDIA_TYPE_AUDIO
);
1572 video
= video
|| (mdesc
->type() == cricket::MEDIA_TYPE_VIDEO
);
1573 rtcp_mux
= rtcp_mux
|| mdesc
->rtcp_mux();
1578 void RTCPeerConnectionHandler::ReportFirstSessionDescriptions(
1579 const FirstSessionDescription
& local
,
1580 const FirstSessionDescription
& remote
) {
1581 RtcpMux rtcp_mux
= RTCP_MUX_ENABLED
;
1582 if ((!local
.audio
&& !local
.video
) || (!remote
.audio
&& !remote
.video
)) {
1583 rtcp_mux
= RTCP_MUX_NO_MEDIA
;
1584 } else if (!local
.rtcp_mux
|| !remote
.rtcp_mux
) {
1585 rtcp_mux
= RTCP_MUX_DISABLED
;
1588 UMA_HISTOGRAM_ENUMERATION(
1589 "WebRTC.PeerConnection.RtcpMux", rtcp_mux
, RTCP_MUX_MAX
);
1591 // TODO(pthatcher): Reports stats about whether we have audio and
1595 scoped_refptr
<base::SingleThreadTaskRunner
>
1596 RTCPeerConnectionHandler::signaling_thread() const {
1597 DCHECK(thread_checker_
.CalledOnValidThread());
1598 return dependency_factory_
->GetWebRtcSignalingThread();
1601 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1602 const base::Closure
& closure
,
1603 const char* trace_event_name
) {
1604 DCHECK(thread_checker_
.CalledOnValidThread());
1605 scoped_refptr
<base::SingleThreadTaskRunner
> thread(signaling_thread());
1606 if (!thread
.get() || thread
->BelongsToCurrentThread()) {
1607 TRACE_EVENT0("webrtc", trace_event_name
);
1610 base::WaitableEvent
event(false, false);
1611 thread
->PostTask(FROM_HERE
,
1612 base::Bind(&RunSynchronousClosure
, closure
,
1613 base::Unretained(trace_event_name
),
1614 base::Unretained(&event
)));
1619 void RTCPeerConnectionHandler::ReportICEState(
1620 webrtc::PeerConnectionInterface::IceConnectionState new_state
) {
1621 DCHECK(thread_checker_
.CalledOnValidThread());
1622 if (ice_state_seen_
[new_state
])
1624 ice_state_seen_
[new_state
] = true;
1625 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.ConnectionState", new_state
,
1626 webrtc::PeerConnectionInterface::kIceConnectionMax
);
1629 void RTCPeerConnectionHandler::ResetUMAStats() {
1630 DCHECK(thread_checker_
.CalledOnValidThread());
1631 num_local_candidates_ipv6_
= 0;
1632 num_local_candidates_ipv4_
= 0;
1633 ice_connection_checking_start_
= base::TimeTicks();
1634 memset(ice_state_seen_
, 0, sizeof(ice_state_seen_
));
1636 } // namespace content