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"
44 using webrtc::DataChannelInterface
;
45 using webrtc::IceCandidateInterface
;
46 using webrtc::MediaStreamInterface
;
47 using webrtc::PeerConnectionInterface
;
48 using webrtc::PeerConnectionObserver
;
49 using webrtc::StatsReport
;
50 using webrtc::StatsReports
;
55 // Converter functions from libjingle types to WebKit types.
56 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
57 GetWebKitIceGatheringState(
58 webrtc::PeerConnectionInterface::IceGatheringState state
) {
59 using blink::WebRTCPeerConnectionHandlerClient
;
61 case webrtc::PeerConnectionInterface::kIceGatheringNew
:
62 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
63 case webrtc::PeerConnectionInterface::kIceGatheringGathering
:
64 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering
;
65 case webrtc::PeerConnectionInterface::kIceGatheringComplete
:
66 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete
;
69 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
73 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
74 GetWebKitIceConnectionState(
75 webrtc::PeerConnectionInterface::IceConnectionState ice_state
) {
76 using blink::WebRTCPeerConnectionHandlerClient
;
78 case webrtc::PeerConnectionInterface::kIceConnectionNew
:
79 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting
;
80 case webrtc::PeerConnectionInterface::kIceConnectionChecking
:
81 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking
;
82 case webrtc::PeerConnectionInterface::kIceConnectionConnected
:
83 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected
;
84 case webrtc::PeerConnectionInterface::kIceConnectionCompleted
:
85 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted
;
86 case webrtc::PeerConnectionInterface::kIceConnectionFailed
:
87 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed
;
88 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected
:
89 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected
;
90 case webrtc::PeerConnectionInterface::kIceConnectionClosed
:
91 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
94 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
98 blink::WebRTCPeerConnectionHandlerClient::SignalingState
99 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state
) {
100 using blink::WebRTCPeerConnectionHandlerClient
;
102 case webrtc::PeerConnectionInterface::kStable
:
103 return WebRTCPeerConnectionHandlerClient::SignalingStateStable
;
104 case webrtc::PeerConnectionInterface::kHaveLocalOffer
:
105 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer
;
106 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer
:
107 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer
;
108 case webrtc::PeerConnectionInterface::kHaveRemoteOffer
:
109 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer
;
110 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer
:
112 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer
;
113 case webrtc::PeerConnectionInterface::kClosed
:
114 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
117 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
121 blink::WebRTCSessionDescription
CreateWebKitSessionDescription(
122 const std::string
& sdp
, const std::string
& type
) {
123 blink::WebRTCSessionDescription description
;
124 description
.initialize(base::UTF8ToUTF16(type
), base::UTF8ToUTF16(sdp
));
128 blink::WebRTCSessionDescription
129 CreateWebKitSessionDescription(
130 const webrtc::SessionDescriptionInterface
* native_desc
) {
132 LOG(ERROR
) << "Native session description is null.";
133 return blink::WebRTCSessionDescription();
137 if (!native_desc
->ToString(&sdp
)) {
138 LOG(ERROR
) << "Failed to get SDP string of native session description.";
139 return blink::WebRTCSessionDescription();
142 return CreateWebKitSessionDescription(sdp
, native_desc
->type());
145 void RunClosureWithTrace(const base::Closure
& closure
,
146 const char* trace_event_name
) {
147 TRACE_EVENT0("webrtc", trace_event_name
);
151 void RunSynchronousClosure(const base::Closure
& closure
,
152 const char* trace_event_name
,
153 base::WaitableEvent
* event
) {
155 TRACE_EVENT0("webrtc", trace_event_name
);
161 void GetSdpAndTypeFromSessionDescription(
162 const base::Callback
<const webrtc::SessionDescriptionInterface
*()>&
163 description_callback
,
164 std::string
* sdp
, std::string
* type
) {
165 const webrtc::SessionDescriptionInterface
* description
=
166 description_callback
.Run();
168 description
->ToString(sdp
);
169 *type
= description
->type();
173 // Converter functions from WebKit types to WebRTC types.
175 void GetNativeRtcConfiguration(
176 const blink::WebRTCConfiguration
& blink_config
,
177 webrtc::PeerConnectionInterface::RTCConfiguration
* webrtc_config
) {
178 if (blink_config
.isNull() || !webrtc_config
)
180 for (size_t i
= 0; i
< blink_config
.numberOfServers(); ++i
) {
181 webrtc::PeerConnectionInterface::IceServer server
;
182 const blink::WebRTCICEServer
& webkit_server
=
183 blink_config
.server(i
);
184 server
.username
= base::UTF16ToUTF8(webkit_server
.username());
185 server
.password
= base::UTF16ToUTF8(webkit_server
.credential());
186 server
.uri
= webkit_server
.uri().spec();
187 webrtc_config
->servers
.push_back(server
);
190 switch (blink_config
.iceTransports()) {
191 case blink::WebRTCIceTransportsNone
:
192 webrtc_config
->type
= webrtc::PeerConnectionInterface::kNone
;
194 case blink::WebRTCIceTransportsRelay
:
195 webrtc_config
->type
= webrtc::PeerConnectionInterface::kRelay
;
197 case blink::WebRTCIceTransportsAll
:
198 webrtc_config
->type
= webrtc::PeerConnectionInterface::kAll
;
204 switch (blink_config
.bundlePolicy()) {
205 case blink::WebRTCBundlePolicyBalanced
:
206 webrtc_config
->bundle_policy
=
207 webrtc::PeerConnectionInterface::kBundlePolicyBalanced
;
209 case blink::WebRTCBundlePolicyMaxBundle
:
210 webrtc_config
->bundle_policy
=
211 webrtc::PeerConnectionInterface::kBundlePolicyMaxBundle
;
213 case blink::WebRTCBundlePolicyMaxCompat
:
214 webrtc_config
->bundle_policy
=
215 webrtc::PeerConnectionInterface::kBundlePolicyMaxCompat
;
221 switch (blink_config
.rtcpMuxPolicy()) {
222 case blink::WebRTCRtcpMuxPolicyNegotiate
:
223 webrtc_config
->rtcp_mux_policy
=
224 webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate
;
226 case blink::WebRTCRtcpMuxPolicyRequire
:
227 webrtc_config
->rtcp_mux_policy
=
228 webrtc::PeerConnectionInterface::kRtcpMuxPolicyRequire
;
235 class SessionDescriptionRequestTracker
{
237 SessionDescriptionRequestTracker(
238 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
239 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
240 PeerConnectionTracker::Action action
)
241 : handler_(handler
), tracker_(tracker
), action_(action
) {}
243 void TrackOnSuccess(const webrtc::SessionDescriptionInterface
* desc
) {
244 DCHECK(thread_checker_
.CalledOnValidThread());
245 if (tracker_
&& handler_
) {
248 desc
->ToString(&value
);
249 value
= "type: " + desc
->type() + ", sdp: " + value
;
251 tracker_
->TrackSessionDescriptionCallback(
252 handler_
.get(), action_
, "OnSuccess", value
);
256 void TrackOnFailure(const std::string
& error
) {
257 DCHECK(thread_checker_
.CalledOnValidThread());
258 if (handler_
&& tracker_
) {
259 tracker_
->TrackSessionDescriptionCallback(
260 handler_
.get(), action_
, "OnFailure", error
);
265 const base::WeakPtr
<RTCPeerConnectionHandler
> handler_
;
266 const base::WeakPtr
<PeerConnectionTracker
> tracker_
;
267 PeerConnectionTracker::Action action_
;
268 base::ThreadChecker thread_checker_
;
271 // Class mapping responses from calls to libjingle CreateOffer/Answer and
272 // the blink::WebRTCSessionDescriptionRequest.
273 class CreateSessionDescriptionRequest
274 : public webrtc::CreateSessionDescriptionObserver
{
276 explicit CreateSessionDescriptionRequest(
277 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread
,
278 const blink::WebRTCSessionDescriptionRequest
& request
,
279 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
280 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
281 PeerConnectionTracker::Action action
)
282 : main_thread_(main_thread
),
283 webkit_request_(request
),
284 tracker_(handler
, tracker
, action
) {
287 void OnSuccess(webrtc::SessionDescriptionInterface
* desc
) override
{
288 if (!main_thread_
->BelongsToCurrentThread()) {
289 main_thread_
->PostTask(FROM_HERE
,
290 base::Bind(&CreateSessionDescriptionRequest::OnSuccess
, this, desc
));
294 tracker_
.TrackOnSuccess(desc
);
295 webkit_request_
.requestSucceeded(CreateWebKitSessionDescription(desc
));
296 webkit_request_
.reset();
299 void OnFailure(const std::string
& error
) override
{
300 if (!main_thread_
->BelongsToCurrentThread()) {
301 main_thread_
->PostTask(FROM_HERE
,
302 base::Bind(&CreateSessionDescriptionRequest::OnFailure
, this, error
));
306 tracker_
.TrackOnFailure(error
);
307 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
308 webkit_request_
.reset();
312 ~CreateSessionDescriptionRequest() override
{
313 CHECK(webkit_request_
.isNull());
316 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
317 blink::WebRTCSessionDescriptionRequest webkit_request_
;
318 SessionDescriptionRequestTracker tracker_
;
321 // Class mapping responses from calls to libjingle
322 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
323 class SetSessionDescriptionRequest
324 : public webrtc::SetSessionDescriptionObserver
{
326 explicit SetSessionDescriptionRequest(
327 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread
,
328 const blink::WebRTCVoidRequest
& request
,
329 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
330 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
331 PeerConnectionTracker::Action action
)
332 : main_thread_(main_thread
),
333 webkit_request_(request
),
334 tracker_(handler
, tracker
, action
) {
337 void OnSuccess() override
{
338 if (!main_thread_
->BelongsToCurrentThread()) {
339 main_thread_
->PostTask(FROM_HERE
,
340 base::Bind(&SetSessionDescriptionRequest::OnSuccess
, this));
343 tracker_
.TrackOnSuccess(NULL
);
344 webkit_request_
.requestSucceeded();
345 webkit_request_
.reset();
347 void OnFailure(const std::string
& error
) override
{
348 if (!main_thread_
->BelongsToCurrentThread()) {
349 main_thread_
->PostTask(FROM_HERE
,
350 base::Bind(&SetSessionDescriptionRequest::OnFailure
, this, error
));
353 tracker_
.TrackOnFailure(error
);
354 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
355 webkit_request_
.reset();
359 ~SetSessionDescriptionRequest() override
{
360 DCHECK(webkit_request_
.isNull());
364 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
365 blink::WebRTCVoidRequest webkit_request_
;
366 SessionDescriptionRequestTracker tracker_
;
369 // Class mapping responses from calls to libjingle
370 // GetStats into a blink::WebRTCStatsCallback.
371 class StatsResponse
: public webrtc::StatsObserver
{
373 explicit StatsResponse(const scoped_refptr
<LocalRTCStatsRequest
>& request
)
374 : request_(request
.get()),
375 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
376 // Measure the overall time it takes to satisfy a getStats request.
377 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
378 signaling_thread_checker_
.DetachFromThread();
381 void OnComplete(const StatsReports
& reports
) override
{
382 DCHECK(signaling_thread_checker_
.CalledOnValidThread());
383 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
384 // We can't use webkit objects directly since they use a single threaded
386 std::vector
<Report
*>* report_copies
= new std::vector
<Report
*>();
387 report_copies
->reserve(reports
.size());
388 for (auto* r
: reports
)
389 report_copies
->push_back(new Report(r
));
391 main_thread_
->PostTaskAndReply(FROM_HERE
,
392 base::Bind(&StatsResponse::DeliverCallback
, this,
393 base::Unretained(report_copies
)),
394 base::Bind(&StatsResponse::DeleteReports
,
395 base::Unretained(report_copies
)));
400 Report(const StatsReport
* report
)
401 : thread_checker(), id(report
->id()->ToString()),
402 type(report
->TypeToString()), timestamp(report
->timestamp()),
403 values(report
->values()) {
407 // Since the values vector holds pointers to const objects that are bound
408 // to the signaling thread, they must be released on the same thread.
409 DCHECK(thread_checker
.CalledOnValidThread());
412 const base::ThreadChecker thread_checker
;
413 const std::string id
, type
;
414 const double timestamp
;
415 const StatsReport::Values values
;
418 static void DeleteReports(std::vector
<Report
*>* reports
) {
419 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
420 for (auto* p
: *reports
)
425 void DeliverCallback(const std::vector
<Report
*>* reports
) {
426 DCHECK(main_thread_
->BelongsToCurrentThread());
427 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
429 rtc::scoped_refptr
<LocalRTCStatsResponse
> response(
430 request_
->createResponse().get());
431 for (const auto* report
: *reports
) {
432 if (report
->values
.size() > 0)
433 AddReport(response
.get(), *report
);
436 // Record the getStats operation as done before calling into Blink so that
437 // we don't skew the perf measurements of the native code with whatever the
438 // callback might be doing.
439 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
440 request_
->requestSucceeded(response
);
441 request_
= nullptr; // must be freed on the main thread.
444 void AddReport(LocalRTCStatsResponse
* response
, const Report
& report
) {
445 int idx
= response
->addReport(blink::WebString::fromUTF8(report
.id
),
446 blink::WebString::fromUTF8(report
.type
),
448 blink::WebString name
, value_str
;
449 for (const auto& value
: report
.values
) {
450 const StatsReport::ValuePtr
& v
= value
.second
;
451 name
= blink::WebString::fromUTF8(value
.second
->display_name());
453 if (v
->type() == StatsReport::Value::kString
)
454 value_str
= blink::WebString::fromUTF8(v
->string_val());
455 if (v
->type() == StatsReport::Value::kStaticString
)
456 value_str
= blink::WebString::fromUTF8(v
->static_string_val());
458 value_str
= blink::WebString::fromUTF8(v
->ToString());
460 response
->addStatistic(idx
, name
, value_str
);
464 rtc::scoped_refptr
<LocalRTCStatsRequest
> request_
;
465 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
466 base::ThreadChecker signaling_thread_checker_
;
469 void GetStatsOnSignalingThread(
470 const scoped_refptr
<webrtc::PeerConnectionInterface
>& pc
,
471 webrtc::PeerConnectionInterface::StatsOutputLevel level
,
472 const scoped_refptr
<webrtc::StatsObserver
>& observer
,
473 const std::string track_id
, blink::WebMediaStreamSource::Type track_type
) {
474 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
476 scoped_refptr
<webrtc::MediaStreamTrackInterface
> track
;
477 if (!track_id
.empty()) {
478 if (track_type
== blink::WebMediaStreamSource::TypeAudio
) {
479 track
= pc
->local_streams()->FindAudioTrack(track_id
);
481 track
= pc
->remote_streams()->FindAudioTrack(track_id
);
483 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo
, track_type
);
484 track
= pc
->local_streams()->FindVideoTrack(track_id
);
486 track
= pc
->remote_streams()->FindVideoTrack(track_id
);
490 DVLOG(1) << "GetStats: Track not found.";
491 observer
->OnComplete(StatsReports());
496 if (!pc
->GetStats(observer
.get(), track
.get(), level
)) {
497 DVLOG(1) << "GetStats failed.";
498 observer
->OnComplete(StatsReports());
502 class PeerConnectionUMAObserver
: public webrtc::UMAObserver
{
504 PeerConnectionUMAObserver() {}
505 ~PeerConnectionUMAObserver() override
{}
507 void IncrementCounter(
508 webrtc::PeerConnectionUMAMetricsCounter counter
) override
{
509 // Runs on libjingle's signaling thread.
510 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
515 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type
,
516 int value
) override
{
517 // Runs on libjingle's signaling thread.
519 case webrtc::kTimeToConnect
:
520 UMA_HISTOGRAM_MEDIUM_TIMES(
521 "WebRTC.PeerConnection.TimeToConnect",
522 base::TimeDelta::FromMilliseconds(value
));
524 case webrtc::kNetworkInterfaces_IPv4
:
525 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
528 case webrtc::kNetworkInterfaces_IPv6
:
529 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
538 base::LazyInstance
<std::set
<RTCPeerConnectionHandler
*> >::Leaky
539 g_peer_connection_handlers
= LAZY_INSTANCE_INITIALIZER
;
543 // Implementation of LocalRTCStatsRequest.
544 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl
)
548 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
549 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
551 bool LocalRTCStatsRequest::hasSelector() const {
552 return impl_
.hasSelector();
555 blink::WebMediaStreamTrack
LocalRTCStatsRequest::component() const {
556 return impl_
.component();
559 scoped_refptr
<LocalRTCStatsResponse
> LocalRTCStatsRequest::createResponse() {
560 return scoped_refptr
<LocalRTCStatsResponse
>(
561 new rtc::RefCountedObject
<LocalRTCStatsResponse
>(impl_
.createResponse()));
564 void LocalRTCStatsRequest::requestSucceeded(
565 const LocalRTCStatsResponse
* response
) {
566 impl_
.requestSucceeded(response
->webKitStatsResponse());
569 // Implementation of LocalRTCStatsResponse.
570 blink::WebRTCStatsResponse
LocalRTCStatsResponse::webKitStatsResponse() const {
574 size_t LocalRTCStatsResponse::addReport(blink::WebString type
,
577 return impl_
.addReport(type
, id
, timestamp
);
580 void LocalRTCStatsResponse::addStatistic(size_t report
,
581 blink::WebString name
,
582 blink::WebString value
) {
583 impl_
.addStatistic(report
, name
, value
);
586 // Receives notifications from a PeerConnection object about state changes,
587 // track addition/removal etc. The callbacks we receive here come on the
588 // signaling thread, so this class takes care of delivering them to an
589 // RTCPeerConnectionHandler instance on the main thread.
590 // In order to do safe PostTask-ing, the class is reference counted and
591 // checks for the existence of the RTCPeerConnectionHandler instance before
592 // delivering callbacks on the main thread.
593 class RTCPeerConnectionHandler::Observer
594 : public base::RefCountedThreadSafe
<RTCPeerConnectionHandler::Observer
>,
595 public PeerConnectionObserver
{
597 Observer(const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
)
598 : handler_(handler
), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
601 friend class base::RefCountedThreadSafe
<RTCPeerConnectionHandler::Observer
>;
602 virtual ~Observer() {}
604 void OnSignalingChange(
605 PeerConnectionInterface::SignalingState new_state
) override
{
606 if (!main_thread_
->BelongsToCurrentThread()) {
607 main_thread_
->PostTask(FROM_HERE
,
608 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange
,
610 } else if (handler_
) {
611 handler_
->OnSignalingChange(new_state
);
615 void OnAddStream(MediaStreamInterface
* stream
) override
{
617 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(
618 new RemoteMediaStreamImpl(main_thread_
, stream
));
620 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
621 // asynchronously and the posted task will execude after that initialization
623 main_thread_
->PostTask(FROM_HERE
,
624 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl
,
625 this, base::Passed(&remote_stream
)));
628 void OnRemoveStream(MediaStreamInterface
* stream
) override
{
629 main_thread_
->PostTask(FROM_HERE
,
630 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl
,
631 this, make_scoped_refptr(stream
)));
634 void OnDataChannel(DataChannelInterface
* data_channel
) override
{
635 scoped_ptr
<RtcDataChannelHandler
> handler(
636 new RtcDataChannelHandler(main_thread_
, data_channel
));
637 main_thread_
->PostTask(FROM_HERE
,
638 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl
,
639 this, base::Passed(&handler
)));
642 void OnRenegotiationNeeded() override
{
643 if (!main_thread_
->BelongsToCurrentThread()) {
644 main_thread_
->PostTask(FROM_HERE
,
645 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded
,
647 } else if (handler_
) {
648 handler_
->OnRenegotiationNeeded();
652 void OnIceConnectionChange(
653 PeerConnectionInterface::IceConnectionState new_state
) override
{
654 if (!main_thread_
->BelongsToCurrentThread()) {
655 main_thread_
->PostTask(FROM_HERE
,
657 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange
, this,
659 } else if (handler_
) {
660 handler_
->OnIceConnectionChange(new_state
);
664 void OnIceGatheringChange(
665 PeerConnectionInterface::IceGatheringState new_state
) override
{
666 if (!main_thread_
->BelongsToCurrentThread()) {
667 main_thread_
->PostTask(FROM_HERE
,
668 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange
,
670 } else if (handler_
) {
671 handler_
->OnIceGatheringChange(new_state
);
675 void OnIceCandidate(const IceCandidateInterface
* candidate
) override
{
677 if (!candidate
->ToString(&sdp
)) {
678 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
682 main_thread_
->PostTask(FROM_HERE
,
683 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl
,
684 this, sdp
, candidate
->sdp_mid(), candidate
->sdp_mline_index(),
685 candidate
->candidate().component(),
686 candidate
->candidate().address().family()));
689 void OnAddStreamImpl(scoped_ptr
<RemoteMediaStreamImpl
> stream
) {
690 DCHECK(stream
->webkit_stream().extraData()) << "Initialization not done";
692 handler_
->OnAddStream(stream
.Pass());
695 void OnRemoveStreamImpl(const scoped_refptr
<MediaStreamInterface
>& stream
) {
697 handler_
->OnRemoveStream(stream
);
700 void OnDataChannelImpl(scoped_ptr
<RtcDataChannelHandler
> handler
) {
702 handler_
->OnDataChannel(handler
.Pass());
705 void OnIceCandidateImpl(const std::string
& sdp
, const std::string
& sdp_mid
,
706 int sdp_mline_index
, int component
, int address_family
) {
708 handler_
->OnIceCandidate(sdp
, sdp_mid
, sdp_mline_index
, component
,
714 const base::WeakPtr
<RTCPeerConnectionHandler
> handler_
;
715 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
718 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
719 blink::WebRTCPeerConnectionHandlerClient
* client
,
720 PeerConnectionDependencyFactory
* dependency_factory
)
722 dependency_factory_(dependency_factory
),
724 num_data_channels_created_(0),
725 num_local_candidates_ipv4_(0),
726 num_local_candidates_ipv6_(0),
727 weak_factory_(this) {
728 g_peer_connection_handlers
.Get().insert(this);
731 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
732 DCHECK(thread_checker_
.CalledOnValidThread());
736 g_peer_connection_handlers
.Get().erase(this);
737 if (peer_connection_tracker_
)
738 peer_connection_tracker_
->UnregisterPeerConnection(this);
739 STLDeleteValues(&remote_streams_
);
741 UMA_HISTOGRAM_COUNTS_10000(
742 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_
);
746 void RTCPeerConnectionHandler::DestructAllHandlers() {
747 std::set
<RTCPeerConnectionHandler
*> handlers(
748 g_peer_connection_handlers
.Get().begin(),
749 g_peer_connection_handlers
.Get().end());
750 for (auto handler
: handlers
) {
751 if (handler
->client_
)
752 handler
->client_
->releasePeerConnectionHandler();
757 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
758 const blink::WebRTCOfferOptions
& options
,
759 RTCMediaConstraints
* output
) {
760 output
->AddMandatory(
761 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio
,
762 options
.offerToReceiveAudio() > 0 ? "true" : "false",
765 output
->AddMandatory(
766 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo
,
767 options
.offerToReceiveVideo() > 0 ? "true" : "false",
770 if (!options
.voiceActivityDetection()) {
771 output
->AddMandatory(
772 webrtc::MediaConstraintsInterface::kVoiceActivityDetection
,
777 if (options
.iceRestart()) {
778 output
->AddMandatory(
779 webrtc::MediaConstraintsInterface::kIceRestart
, "true", true);
783 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame
* frame
) {
784 DCHECK(thread_checker_
.CalledOnValidThread());
789 bool RTCPeerConnectionHandler::initialize(
790 const blink::WebRTCConfiguration
& server_configuration
,
791 const blink::WebMediaConstraints
& options
) {
792 DCHECK(thread_checker_
.CalledOnValidThread());
795 peer_connection_tracker_
=
796 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
798 webrtc::PeerConnectionInterface::RTCConfiguration config
;
799 GetNativeRtcConfiguration(server_configuration
, &config
);
801 RTCMediaConstraints
constraints(options
);
803 peer_connection_observer_
= new Observer(weak_factory_
.GetWeakPtr());
804 native_peer_connection_
= dependency_factory_
->CreatePeerConnection(
805 config
, &constraints
, frame_
, peer_connection_observer_
.get());
807 if (!native_peer_connection_
.get()) {
808 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
812 if (peer_connection_tracker_
) {
813 peer_connection_tracker_
->RegisterPeerConnection(
814 this, config
, constraints
, frame_
);
817 uma_observer_
= new rtc::RefCountedObject
<PeerConnectionUMAObserver
>();
818 native_peer_connection_
->RegisterUMAObserver(uma_observer_
.get());
822 bool RTCPeerConnectionHandler::InitializeForTest(
823 const blink::WebRTCConfiguration
& server_configuration
,
824 const blink::WebMediaConstraints
& options
,
825 const base::WeakPtr
<PeerConnectionTracker
>& peer_connection_tracker
) {
826 DCHECK(thread_checker_
.CalledOnValidThread());
827 webrtc::PeerConnectionInterface::RTCConfiguration config
;
828 GetNativeRtcConfiguration(server_configuration
, &config
);
830 peer_connection_observer_
= new Observer(weak_factory_
.GetWeakPtr());
831 RTCMediaConstraints
constraints(options
);
832 native_peer_connection_
= dependency_factory_
->CreatePeerConnection(
833 config
, &constraints
, NULL
, peer_connection_observer_
.get());
834 if (!native_peer_connection_
.get()) {
835 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
838 peer_connection_tracker_
= peer_connection_tracker
;
842 void RTCPeerConnectionHandler::createOffer(
843 const blink::WebRTCSessionDescriptionRequest
& request
,
844 const blink::WebMediaConstraints
& options
) {
845 DCHECK(thread_checker_
.CalledOnValidThread());
846 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
848 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
849 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
850 base::ThreadTaskRunnerHandle::Get(), request
,
851 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
852 PeerConnectionTracker::ACTION_CREATE_OFFER
));
854 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
855 RTCMediaConstraints
constraints(options
);
856 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
858 if (peer_connection_tracker_
)
859 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
862 void RTCPeerConnectionHandler::createOffer(
863 const blink::WebRTCSessionDescriptionRequest
& request
,
864 const blink::WebRTCOfferOptions
& options
) {
865 DCHECK(thread_checker_
.CalledOnValidThread());
866 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
868 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
869 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
870 base::ThreadTaskRunnerHandle::Get(), request
,
871 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
872 PeerConnectionTracker::ACTION_CREATE_OFFER
));
874 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
875 RTCMediaConstraints constraints
;
876 ConvertOfferOptionsToConstraints(options
, &constraints
);
877 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
879 if (peer_connection_tracker_
)
880 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
883 void RTCPeerConnectionHandler::createAnswer(
884 const blink::WebRTCSessionDescriptionRequest
& request
,
885 const blink::WebMediaConstraints
& options
) {
886 DCHECK(thread_checker_
.CalledOnValidThread());
887 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
888 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
889 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
890 base::ThreadTaskRunnerHandle::Get(), request
,
891 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
892 PeerConnectionTracker::ACTION_CREATE_ANSWER
));
893 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
894 RTCMediaConstraints
constraints(options
);
895 native_peer_connection_
->CreateAnswer(description_request
.get(),
898 if (peer_connection_tracker_
)
899 peer_connection_tracker_
->TrackCreateAnswer(this, constraints
);
902 void RTCPeerConnectionHandler::setLocalDescription(
903 const blink::WebRTCVoidRequest
& request
,
904 const blink::WebRTCSessionDescription
& description
) {
905 DCHECK(thread_checker_
.CalledOnValidThread());
906 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
908 std::string sdp
= base::UTF16ToUTF8(description
.sdp());
909 std::string type
= base::UTF16ToUTF8(description
.type());
911 webrtc::SdpParseError error
;
912 // Since CreateNativeSessionDescription uses the dependency factory, we need
913 // to make this call on the current thread to be safe.
914 webrtc::SessionDescriptionInterface
* native_desc
=
915 CreateNativeSessionDescription(sdp
, type
, &error
);
917 std::string reason_str
= "Failed to parse SessionDescription. ";
918 reason_str
.append(error
.line
);
919 reason_str
.append(" ");
920 reason_str
.append(error
.description
);
921 LOG(ERROR
) << reason_str
;
922 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
926 if (peer_connection_tracker_
) {
927 peer_connection_tracker_
->TrackSetSessionDescription(
928 this, sdp
, type
, PeerConnectionTracker::SOURCE_LOCAL
);
931 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
932 new rtc::RefCountedObject
<SetSessionDescriptionRequest
>(
933 base::ThreadTaskRunnerHandle::Get(), request
,
934 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
935 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION
));
937 signaling_thread()->PostTask(FROM_HERE
,
938 base::Bind(&RunClosureWithTrace
,
939 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription
,
940 native_peer_connection_
, set_request
,
941 base::Unretained(native_desc
)),
942 "SetLocalDescription"));
945 void RTCPeerConnectionHandler::setRemoteDescription(
946 const blink::WebRTCVoidRequest
& request
,
947 const blink::WebRTCSessionDescription
& description
) {
948 DCHECK(thread_checker_
.CalledOnValidThread());
949 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
950 std::string sdp
= base::UTF16ToUTF8(description
.sdp());
951 std::string type
= base::UTF16ToUTF8(description
.type());
953 webrtc::SdpParseError error
;
954 // Since CreateNativeSessionDescription uses the dependency factory, we need
955 // to make this call on the current thread to be safe.
956 webrtc::SessionDescriptionInterface
* native_desc
=
957 CreateNativeSessionDescription(sdp
, type
, &error
);
959 std::string reason_str
= "Failed to parse SessionDescription. ";
960 reason_str
.append(error
.line
);
961 reason_str
.append(" ");
962 reason_str
.append(error
.description
);
963 LOG(ERROR
) << reason_str
;
964 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
968 if (peer_connection_tracker_
) {
969 peer_connection_tracker_
->TrackSetSessionDescription(
970 this, sdp
, type
, PeerConnectionTracker::SOURCE_REMOTE
);
973 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
974 new rtc::RefCountedObject
<SetSessionDescriptionRequest
>(
975 base::ThreadTaskRunnerHandle::Get(), request
,
976 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
977 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION
));
978 signaling_thread()->PostTask(FROM_HERE
,
979 base::Bind(&RunClosureWithTrace
,
980 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription
,
981 native_peer_connection_
, set_request
,
982 base::Unretained(native_desc
)),
983 "SetRemoteDescription"));
986 blink::WebRTCSessionDescription
987 RTCPeerConnectionHandler::localDescription() {
988 DCHECK(thread_checker_
.CalledOnValidThread());
989 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
991 // Since local_description returns a pointer to a non-reference-counted object
992 // that lives on the signaling thread, we cannot fetch a pointer to it and use
993 // it directly here. Instead, we access the object completely on the signaling
995 std::string sdp
, type
;
996 base::Callback
<const webrtc::SessionDescriptionInterface
*()> description_cb
=
997 base::Bind(&webrtc::PeerConnectionInterface::local_description
,
998 native_peer_connection_
);
999 RunSynchronousClosureOnSignalingThread(
1000 base::Bind(&GetSdpAndTypeFromSessionDescription
, description_cb
,
1001 base::Unretained(&sdp
), base::Unretained(&type
)),
1002 "localDescription");
1004 return CreateWebKitSessionDescription(sdp
, type
);
1007 blink::WebRTCSessionDescription
1008 RTCPeerConnectionHandler::remoteDescription() {
1009 DCHECK(thread_checker_
.CalledOnValidThread());
1010 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
1011 // Since local_description returns a pointer to a non-reference-counted object
1012 // that lives on the signaling thread, we cannot fetch a pointer to it and use
1013 // it directly here. Instead, we access the object completely on the signaling
1015 std::string sdp
, type
;
1016 base::Callback
<const webrtc::SessionDescriptionInterface
*()> description_cb
=
1017 base::Bind(&webrtc::PeerConnectionInterface::remote_description
,
1018 native_peer_connection_
);
1019 RunSynchronousClosureOnSignalingThread(
1020 base::Bind(&GetSdpAndTypeFromSessionDescription
, description_cb
,
1021 base::Unretained(&sdp
), base::Unretained(&type
)),
1022 "remoteDescription");
1024 return CreateWebKitSessionDescription(sdp
, type
);
1027 bool RTCPeerConnectionHandler::updateICE(
1028 const blink::WebRTCConfiguration
& server_configuration
,
1029 const blink::WebMediaConstraints
& options
) {
1030 DCHECK(thread_checker_
.CalledOnValidThread());
1031 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1032 webrtc::PeerConnectionInterface::RTCConfiguration config
;
1033 GetNativeRtcConfiguration(server_configuration
, &config
);
1034 RTCMediaConstraints
constraints(options
);
1036 if (peer_connection_tracker_
)
1037 peer_connection_tracker_
->TrackUpdateIce(this, config
, constraints
);
1039 return native_peer_connection_
->UpdateIce(config
.servers
, &constraints
);
1042 bool RTCPeerConnectionHandler::addICECandidate(
1043 const blink::WebRTCVoidRequest
& request
,
1044 const blink::WebRTCICECandidate
& candidate
) {
1045 DCHECK(thread_checker_
.CalledOnValidThread());
1046 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1047 // Libjingle currently does not accept callbacks for addICECandidate.
1048 // For that reason we are going to call callbacks from here.
1050 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1051 // PostTaskAndReply kind of a thing.
1052 bool result
= addICECandidate(candidate
);
1053 base::ThreadTaskRunnerHandle::Get()->PostTask(
1054 FROM_HERE
, base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult
,
1055 weak_factory_
.GetWeakPtr(), request
, result
));
1056 // On failure callback will be triggered.
1060 bool RTCPeerConnectionHandler::addICECandidate(
1061 const blink::WebRTCICECandidate
& candidate
) {
1062 DCHECK(thread_checker_
.CalledOnValidThread());
1063 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1064 scoped_ptr
<webrtc::IceCandidateInterface
> native_candidate(
1065 dependency_factory_
->CreateIceCandidate(
1066 base::UTF16ToUTF8(candidate
.sdpMid()),
1067 candidate
.sdpMLineIndex(),
1068 base::UTF16ToUTF8(candidate
.candidate())));
1069 bool return_value
= false;
1071 if (native_candidate
) {
1073 native_peer_connection_
->AddIceCandidate(native_candidate
.get());
1074 LOG_IF(ERROR
, !return_value
) << "Error processing ICE candidate.";
1076 LOG(ERROR
) << "Could not create native ICE candidate.";
1079 if (peer_connection_tracker_
) {
1080 peer_connection_tracker_
->TrackAddIceCandidate(
1081 this, candidate
, PeerConnectionTracker::SOURCE_REMOTE
, return_value
);
1083 return return_value
;
1086 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1087 const blink::WebRTCVoidRequest
& webkit_request
, bool result
) {
1088 DCHECK(thread_checker_
.CalledOnValidThread());
1089 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1091 // We don't have the actual error code from the libjingle, so for now
1092 // using a generic error string.
1093 return webkit_request
.requestFailed(
1094 base::UTF8ToUTF16("Error processing ICE candidate"));
1097 return webkit_request
.requestSucceeded();
1100 bool RTCPeerConnectionHandler::addStream(
1101 const blink::WebMediaStream
& stream
,
1102 const blink::WebMediaConstraints
& options
) {
1103 DCHECK(thread_checker_
.CalledOnValidThread());
1104 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1105 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
1106 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
1108 if ((*adapter_it
)->IsEqual(stream
)) {
1109 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1110 << "stream twice. id=" << stream
.id().utf8();
1115 if (peer_connection_tracker_
) {
1116 peer_connection_tracker_
->TrackAddStream(
1117 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
1120 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1122 WebRtcMediaStreamAdapter
* adapter
=
1123 new WebRtcMediaStreamAdapter(stream
, dependency_factory_
);
1124 local_streams_
.push_back(adapter
);
1126 webrtc::MediaStreamInterface
* webrtc_stream
= adapter
->webrtc_media_stream();
1127 track_metrics_
.AddStream(MediaStreamTrackMetrics::SENT_STREAM
,
1130 RTCMediaConstraints
constraints(options
);
1131 if (!constraints
.GetMandatory().empty() ||
1132 !constraints
.GetOptional().empty()) {
1133 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1134 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1135 // should be removed from blink as well.
1137 << "mediaConstraints is not a supported argument to addStream.";
1140 return native_peer_connection_
->AddStream(webrtc_stream
);
1143 void RTCPeerConnectionHandler::removeStream(
1144 const blink::WebMediaStream
& stream
) {
1145 DCHECK(thread_checker_
.CalledOnValidThread());
1146 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1147 // Find the webrtc stream.
1148 scoped_refptr
<webrtc::MediaStreamInterface
> webrtc_stream
;
1149 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
1150 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
1152 if ((*adapter_it
)->IsEqual(stream
)) {
1153 webrtc_stream
= (*adapter_it
)->webrtc_media_stream();
1154 local_streams_
.erase(adapter_it
);
1158 DCHECK(webrtc_stream
.get());
1159 // TODO(tommi): Make this async (PostTaskAndReply).
1160 native_peer_connection_
->RemoveStream(webrtc_stream
.get());
1162 if (peer_connection_tracker_
) {
1163 peer_connection_tracker_
->TrackRemoveStream(
1164 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
1166 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1167 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM
,
1168 webrtc_stream
.get());
1171 void RTCPeerConnectionHandler::getStats(
1172 const blink::WebRTCStatsRequest
& request
) {
1173 DCHECK(thread_checker_
.CalledOnValidThread());
1174 scoped_refptr
<LocalRTCStatsRequest
> inner_request(
1175 new rtc::RefCountedObject
<LocalRTCStatsRequest
>(request
));
1176 getStats(inner_request
);
1179 void RTCPeerConnectionHandler::getStats(
1180 const scoped_refptr
<LocalRTCStatsRequest
>& request
) {
1181 DCHECK(thread_checker_
.CalledOnValidThread());
1182 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1185 rtc::scoped_refptr
<webrtc::StatsObserver
> observer(
1186 new rtc::RefCountedObject
<StatsResponse
>(request
));
1188 std::string track_id
;
1189 blink::WebMediaStreamSource::Type track_type
=
1190 blink::WebMediaStreamSource::TypeAudio
;
1191 if (request
->hasSelector()) {
1192 track_type
= request
->component().source().type();
1193 track_id
= request
->component().id().utf8();
1196 GetStats(observer
, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard
,
1197 track_id
, track_type
);
1200 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1201 void RTCPeerConnectionHandler::GetStats(
1202 webrtc::StatsObserver
* observer
,
1203 webrtc::PeerConnectionInterface::StatsOutputLevel level
,
1204 const std::string
& track_id
,
1205 blink::WebMediaStreamSource::Type track_type
) {
1206 DCHECK(thread_checker_
.CalledOnValidThread());
1207 signaling_thread()->PostTask(FROM_HERE
,
1208 base::Bind(&GetStatsOnSignalingThread
, native_peer_connection_
, level
,
1209 make_scoped_refptr(observer
), track_id
, track_type
));
1212 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1213 DCHECK(thread_checker_
.CalledOnValidThread());
1215 client_
->closePeerConnection();
1218 blink::WebRTCDataChannelHandler
* RTCPeerConnectionHandler::createDataChannel(
1219 const blink::WebString
& label
, const blink::WebRTCDataChannelInit
& init
) {
1220 DCHECK(thread_checker_
.CalledOnValidThread());
1221 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1222 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label
);
1224 webrtc::DataChannelInit config
;
1225 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1227 config
.reliable
= false;
1228 config
.id
= init
.id
;
1229 config
.ordered
= init
.ordered
;
1230 config
.negotiated
= init
.negotiated
;
1231 config
.maxRetransmits
= init
.maxRetransmits
;
1232 config
.maxRetransmitTime
= init
.maxRetransmitTime
;
1233 config
.protocol
= base::UTF16ToUTF8(init
.protocol
);
1235 rtc::scoped_refptr
<webrtc::DataChannelInterface
> webrtc_channel(
1236 native_peer_connection_
->CreateDataChannel(base::UTF16ToUTF8(label
),
1238 if (!webrtc_channel
) {
1239 DLOG(ERROR
) << "Could not create native data channel.";
1242 if (peer_connection_tracker_
) {
1243 peer_connection_tracker_
->TrackCreateDataChannel(
1244 this, webrtc_channel
.get(), PeerConnectionTracker::SOURCE_LOCAL
);
1247 ++num_data_channels_created_
;
1249 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1253 blink::WebRTCDTMFSenderHandler
* RTCPeerConnectionHandler::createDTMFSender(
1254 const blink::WebMediaStreamTrack
& track
) {
1255 DCHECK(thread_checker_
.CalledOnValidThread());
1256 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1257 DVLOG(1) << "createDTMFSender.";
1259 MediaStreamTrack
* native_track
= MediaStreamTrack::GetTrack(track
);
1260 if (!native_track
|| !native_track
->is_local_track() ||
1261 track
.source().type() != blink::WebMediaStreamSource::TypeAudio
) {
1262 DLOG(ERROR
) << "The DTMF sender requires a local audio track.";
1266 scoped_refptr
<webrtc::AudioTrackInterface
> audio_track
=
1267 native_track
->GetAudioAdapter();
1268 rtc::scoped_refptr
<webrtc::DtmfSenderInterface
> sender(
1269 native_peer_connection_
->CreateDtmfSender(audio_track
.get()));
1271 DLOG(ERROR
) << "Could not create native DTMF sender.";
1274 if (peer_connection_tracker_
)
1275 peer_connection_tracker_
->TrackCreateDTMFSender(this, track
);
1277 return new RtcDtmfSenderHandler(sender
);
1280 void RTCPeerConnectionHandler::stop() {
1281 DCHECK(thread_checker_
.CalledOnValidThread());
1282 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1284 if (!client_
|| !native_peer_connection_
.get())
1285 return; // Already stopped.
1287 if (peer_connection_tracker_
)
1288 peer_connection_tracker_
->TrackStop(this);
1290 native_peer_connection_
->Close();
1292 // The client_ pointer is not considered valid after this point and no further
1293 // callbacks must be made.
1297 void RTCPeerConnectionHandler::OnSignalingChange(
1298 webrtc::PeerConnectionInterface::SignalingState new_state
) {
1299 DCHECK(thread_checker_
.CalledOnValidThread());
1300 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1302 blink::WebRTCPeerConnectionHandlerClient::SignalingState state
=
1303 GetWebKitSignalingState(new_state
);
1304 if (peer_connection_tracker_
)
1305 peer_connection_tracker_
->TrackSignalingStateChange(this, state
);
1307 client_
->didChangeSignalingState(state
);
1310 // Called any time the IceConnectionState changes
1311 void RTCPeerConnectionHandler::OnIceConnectionChange(
1312 webrtc::PeerConnectionInterface::IceConnectionState new_state
) {
1313 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1314 DCHECK(thread_checker_
.CalledOnValidThread());
1315 if (new_state
== webrtc::PeerConnectionInterface::kIceConnectionChecking
) {
1316 ice_connection_checking_start_
= base::TimeTicks::Now();
1317 } else if (new_state
==
1318 webrtc::PeerConnectionInterface::kIceConnectionConnected
) {
1319 // If the state becomes connected, send the time needed for PC to become
1320 // connected from checking to UMA. UMA data will help to know how much
1321 // time needed for PC to connect with remote peer.
1322 if (ice_connection_checking_start_
.is_null()) {
1323 // From UMA, we have observed a large number of calls falling into the
1324 // overflow buckets. One possibility is that the Checking is not signaled
1325 // before Connected. This is to guard against that situation to make the
1326 // metric more robust.
1327 UMA_HISTOGRAM_MEDIUM_TIMES("WebRTC.PeerConnection.TimeToConnect",
1330 UMA_HISTOGRAM_MEDIUM_TIMES(
1331 "WebRTC.PeerConnection.TimeToConnect",
1332 base::TimeTicks::Now() - ice_connection_checking_start_
);
1336 track_metrics_
.IceConnectionChange(new_state
);
1337 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state
=
1338 GetWebKitIceConnectionState(new_state
);
1339 if (peer_connection_tracker_
)
1340 peer_connection_tracker_
->TrackIceConnectionStateChange(this, state
);
1342 client_
->didChangeICEConnectionState(state
);
1345 // Called any time the IceGatheringState changes
1346 void RTCPeerConnectionHandler::OnIceGatheringChange(
1347 webrtc::PeerConnectionInterface::IceGatheringState new_state
) {
1348 DCHECK(thread_checker_
.CalledOnValidThread());
1349 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1351 if (new_state
== webrtc::PeerConnectionInterface::kIceGatheringComplete
) {
1352 // If ICE gathering is completed, generate a NULL ICE candidate,
1353 // to signal end of candidates.
1355 blink::WebRTCICECandidate null_candidate
;
1356 client_
->didGenerateICECandidate(null_candidate
);
1359 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1360 num_local_candidates_ipv4_
);
1362 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1363 num_local_candidates_ipv6_
);
1364 } else if (new_state
==
1365 webrtc::PeerConnectionInterface::kIceGatheringGathering
) {
1366 // ICE restarts will change gathering state back to "gathering",
1367 // reset the counter.
1368 num_local_candidates_ipv6_
= 0;
1369 num_local_candidates_ipv4_
= 0;
1372 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state
=
1373 GetWebKitIceGatheringState(new_state
);
1374 if (peer_connection_tracker_
)
1375 peer_connection_tracker_
->TrackIceGatheringStateChange(this, state
);
1377 client_
->didChangeICEGatheringState(state
);
1380 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1381 DCHECK(thread_checker_
.CalledOnValidThread());
1382 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1383 if (peer_connection_tracker_
)
1384 peer_connection_tracker_
->TrackOnRenegotiationNeeded(this);
1386 client_
->negotiationNeeded();
1389 void RTCPeerConnectionHandler::OnAddStream(
1390 scoped_ptr
<RemoteMediaStreamImpl
> stream
) {
1391 DCHECK(thread_checker_
.CalledOnValidThread());
1392 DCHECK(remote_streams_
.find(stream
->webrtc_stream().get()) ==
1393 remote_streams_
.end());
1394 DCHECK(stream
->webkit_stream().extraData()) << "Initialization not done";
1395 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1397 // Ownership is with remote_streams_ now.
1398 RemoteMediaStreamImpl
* s
= stream
.release();
1399 remote_streams_
.insert(
1400 std::pair
<webrtc::MediaStreamInterface
*, RemoteMediaStreamImpl
*> (
1401 s
->webrtc_stream().get(), s
));
1403 if (peer_connection_tracker_
) {
1404 peer_connection_tracker_
->TrackAddStream(
1405 this, s
->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE
);
1408 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1410 track_metrics_
.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
1411 s
->webrtc_stream().get());
1413 client_
->didAddRemoteStream(s
->webkit_stream());
1416 void RTCPeerConnectionHandler::OnRemoveStream(
1417 const scoped_refptr
<webrtc::MediaStreamInterface
>& stream
) {
1418 DCHECK(thread_checker_
.CalledOnValidThread());
1419 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1420 RemoteStreamMap::iterator it
= remote_streams_
.find(stream
.get());
1421 if (it
== remote_streams_
.end()) {
1422 NOTREACHED() << "Stream not found";
1426 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
1428 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1430 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(it
->second
);
1431 const blink::WebMediaStream
& webkit_stream
= remote_stream
->webkit_stream();
1432 DCHECK(!webkit_stream
.isNull());
1433 remote_streams_
.erase(it
);
1435 if (peer_connection_tracker_
) {
1436 peer_connection_tracker_
->TrackRemoveStream(
1437 this, webkit_stream
, PeerConnectionTracker::SOURCE_REMOTE
);
1441 client_
->didRemoveRemoteStream(webkit_stream
);
1444 void RTCPeerConnectionHandler::OnDataChannel(
1445 scoped_ptr
<RtcDataChannelHandler
> handler
) {
1446 DCHECK(thread_checker_
.CalledOnValidThread());
1447 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1449 if (peer_connection_tracker_
) {
1450 peer_connection_tracker_
->TrackCreateDataChannel(
1451 this, handler
->channel().get(), PeerConnectionTracker::SOURCE_REMOTE
);
1455 client_
->didAddRemoteDataChannel(handler
.release());
1458 void RTCPeerConnectionHandler::OnIceCandidate(
1459 const std::string
& sdp
, const std::string
& sdp_mid
, int sdp_mline_index
,
1460 int component
, int address_family
) {
1461 DCHECK(thread_checker_
.CalledOnValidThread());
1462 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1463 blink::WebRTCICECandidate web_candidate
;
1464 web_candidate
.initialize(base::UTF8ToUTF16(sdp
),
1465 base::UTF8ToUTF16(sdp_mid
),
1467 if (peer_connection_tracker_
) {
1468 peer_connection_tracker_
->TrackAddIceCandidate(
1469 this, web_candidate
, PeerConnectionTracker::SOURCE_LOCAL
, true);
1472 // Only the first m line's first component is tracked to avoid
1473 // miscounting when doing BUNDLE or rtcp mux.
1474 if (sdp_mline_index
== 0 && component
== 1) {
1475 if (address_family
== AF_INET
) {
1476 ++num_local_candidates_ipv4_
;
1477 } else if (address_family
== AF_INET6
) {
1478 ++num_local_candidates_ipv6_
;
1484 client_
->didGenerateICECandidate(web_candidate
);
1487 webrtc::SessionDescriptionInterface
*
1488 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1489 const std::string
& sdp
, const std::string
& type
,
1490 webrtc::SdpParseError
* error
) {
1491 webrtc::SessionDescriptionInterface
* native_desc
=
1492 dependency_factory_
->CreateSessionDescription(type
, sdp
, error
);
1494 LOG_IF(ERROR
, !native_desc
) << "Failed to create native session description."
1495 << " Type: " << type
<< " SDP: " << sdp
;
1500 scoped_refptr
<base::SingleThreadTaskRunner
>
1501 RTCPeerConnectionHandler::signaling_thread() const {
1502 DCHECK(thread_checker_
.CalledOnValidThread());
1503 return dependency_factory_
->GetWebRtcSignalingThread();
1506 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1507 const base::Closure
& closure
,
1508 const char* trace_event_name
) {
1509 DCHECK(thread_checker_
.CalledOnValidThread());
1510 scoped_refptr
<base::SingleThreadTaskRunner
> thread(signaling_thread());
1511 if (!thread
.get() || thread
->BelongsToCurrentThread()) {
1512 TRACE_EVENT0("webrtc", trace_event_name
);
1515 base::WaitableEvent
event(false, false);
1516 thread
->PostTask(FROM_HERE
,
1517 base::Bind(&RunSynchronousClosure
, closure
,
1518 base::Unretained(trace_event_name
),
1519 base::Unretained(&event
)));
1524 } // namespace content