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/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram.h"
16 #include "base/stl_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/trace_event/trace_event.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/renderer/media/media_stream_track.h"
22 #include "content/renderer/media/peer_connection_tracker.h"
23 #include "content/renderer/media/remote_media_stream_impl.h"
24 #include "content/renderer/media/rtc_data_channel_handler.h"
25 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
26 #include "content/renderer/media/rtc_media_constraints.h"
27 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
28 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
29 #include "content/renderer/media/webrtc_audio_capturer.h"
30 #include "content/renderer/media/webrtc_audio_device_impl.h"
31 #include "content/renderer/media/webrtc_uma_histograms.h"
32 #include "content/renderer/render_thread_impl.h"
33 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
34 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
35 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
36 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
37 #include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
38 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
39 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
40 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
41 #include "third_party/WebKit/public/platform/WebURL.h"
43 using webrtc::DataChannelInterface
;
44 using webrtc::IceCandidateInterface
;
45 using webrtc::MediaStreamInterface
;
46 using webrtc::PeerConnectionInterface
;
47 using webrtc::PeerConnectionObserver
;
48 using webrtc::StatsReport
;
49 using webrtc::StatsReports
;
54 // Converter functions from libjingle types to WebKit types.
55 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
56 GetWebKitIceGatheringState(
57 webrtc::PeerConnectionInterface::IceGatheringState state
) {
58 using blink::WebRTCPeerConnectionHandlerClient
;
60 case webrtc::PeerConnectionInterface::kIceGatheringNew
:
61 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
62 case webrtc::PeerConnectionInterface::kIceGatheringGathering
:
63 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering
;
64 case webrtc::PeerConnectionInterface::kIceGatheringComplete
:
65 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete
;
68 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
72 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
73 GetWebKitIceConnectionState(
74 webrtc::PeerConnectionInterface::IceConnectionState ice_state
) {
75 using blink::WebRTCPeerConnectionHandlerClient
;
77 case webrtc::PeerConnectionInterface::kIceConnectionNew
:
78 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting
;
79 case webrtc::PeerConnectionInterface::kIceConnectionChecking
:
80 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking
;
81 case webrtc::PeerConnectionInterface::kIceConnectionConnected
:
82 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected
;
83 case webrtc::PeerConnectionInterface::kIceConnectionCompleted
:
84 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted
;
85 case webrtc::PeerConnectionInterface::kIceConnectionFailed
:
86 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed
;
87 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected
:
88 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected
;
89 case webrtc::PeerConnectionInterface::kIceConnectionClosed
:
90 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
93 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
97 blink::WebRTCPeerConnectionHandlerClient::SignalingState
98 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state
) {
99 using blink::WebRTCPeerConnectionHandlerClient
;
101 case webrtc::PeerConnectionInterface::kStable
:
102 return WebRTCPeerConnectionHandlerClient::SignalingStateStable
;
103 case webrtc::PeerConnectionInterface::kHaveLocalOffer
:
104 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer
;
105 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer
:
106 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer
;
107 case webrtc::PeerConnectionInterface::kHaveRemoteOffer
:
108 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer
;
109 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer
:
111 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer
;
112 case webrtc::PeerConnectionInterface::kClosed
:
113 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
116 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
120 blink::WebRTCSessionDescription
CreateWebKitSessionDescription(
121 const std::string
& sdp
, const std::string
& type
) {
122 blink::WebRTCSessionDescription description
;
123 description
.initialize(base::UTF8ToUTF16(type
), base::UTF8ToUTF16(sdp
));
127 blink::WebRTCSessionDescription
128 CreateWebKitSessionDescription(
129 const webrtc::SessionDescriptionInterface
* native_desc
) {
131 LOG(ERROR
) << "Native session description is null.";
132 return blink::WebRTCSessionDescription();
136 if (!native_desc
->ToString(&sdp
)) {
137 LOG(ERROR
) << "Failed to get SDP string of native session description.";
138 return blink::WebRTCSessionDescription();
141 return CreateWebKitSessionDescription(sdp
, native_desc
->type());
144 void RunClosureWithTrace(const base::Closure
& closure
,
145 const char* trace_event_name
) {
146 TRACE_EVENT0("webrtc", trace_event_name
);
150 void RunSynchronousClosure(const base::Closure
& closure
,
151 const char* trace_event_name
,
152 base::WaitableEvent
* event
) {
154 TRACE_EVENT0("webrtc", trace_event_name
);
160 void GetSdpAndTypeFromSessionDescription(
161 const base::Callback
<const webrtc::SessionDescriptionInterface
*()>&
162 description_callback
,
163 std::string
* sdp
, std::string
* type
) {
164 const webrtc::SessionDescriptionInterface
* description
=
165 description_callback
.Run();
167 description
->ToString(sdp
);
168 *type
= description
->type();
172 // Converter functions from WebKit types to libjingle types.
174 void GetNativeRtcConfiguration(
175 const blink::WebRTCConfiguration
& server_configuration
,
176 webrtc::PeerConnectionInterface::RTCConfiguration
* config
) {
177 if (server_configuration
.isNull() || !config
)
179 for (size_t i
= 0; i
< server_configuration
.numberOfServers(); ++i
) {
180 webrtc::PeerConnectionInterface::IceServer server
;
181 const blink::WebRTCICEServer
& webkit_server
=
182 server_configuration
.server(i
);
183 server
.username
= base::UTF16ToUTF8(webkit_server
.username());
184 server
.password
= base::UTF16ToUTF8(webkit_server
.credential());
185 server
.uri
= webkit_server
.uri().spec();
186 config
->servers
.push_back(server
);
189 switch (server_configuration
.iceTransports()) {
190 case blink::WebRTCIceTransportsNone
:
191 config
->type
= webrtc::PeerConnectionInterface::kNone
;
193 case blink::WebRTCIceTransportsRelay
:
194 config
->type
= webrtc::PeerConnectionInterface::kRelay
;
196 case blink::WebRTCIceTransportsAll
:
197 config
->type
= webrtc::PeerConnectionInterface::kAll
;
204 class SessionDescriptionRequestTracker
{
206 SessionDescriptionRequestTracker(
207 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
208 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
209 PeerConnectionTracker::Action action
)
210 : handler_(handler
), tracker_(tracker
), action_(action
) {}
212 void TrackOnSuccess(const webrtc::SessionDescriptionInterface
* desc
) {
213 DCHECK(thread_checker_
.CalledOnValidThread());
214 if (tracker_
&& handler_
) {
217 desc
->ToString(&value
);
218 value
= "type: " + desc
->type() + ", sdp: " + value
;
220 tracker_
->TrackSessionDescriptionCallback(
221 handler_
.get(), action_
, "OnSuccess", value
);
225 void TrackOnFailure(const std::string
& error
) {
226 DCHECK(thread_checker_
.CalledOnValidThread());
227 if (handler_
&& tracker_
) {
228 tracker_
->TrackSessionDescriptionCallback(
229 handler_
.get(), action_
, "OnFailure", error
);
234 const base::WeakPtr
<RTCPeerConnectionHandler
> handler_
;
235 const base::WeakPtr
<PeerConnectionTracker
> tracker_
;
236 PeerConnectionTracker::Action action_
;
237 base::ThreadChecker thread_checker_
;
240 // Class mapping responses from calls to libjingle CreateOffer/Answer and
241 // the blink::WebRTCSessionDescriptionRequest.
242 class CreateSessionDescriptionRequest
243 : public webrtc::CreateSessionDescriptionObserver
{
245 explicit CreateSessionDescriptionRequest(
246 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread
,
247 const blink::WebRTCSessionDescriptionRequest
& request
,
248 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
249 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
250 PeerConnectionTracker::Action action
)
251 : main_thread_(main_thread
),
252 webkit_request_(request
),
253 tracker_(handler
, tracker
, action
) {
256 void OnSuccess(webrtc::SessionDescriptionInterface
* desc
) override
{
257 if (!main_thread_
->BelongsToCurrentThread()) {
258 main_thread_
->PostTask(FROM_HERE
,
259 base::Bind(&CreateSessionDescriptionRequest::OnSuccess
, this, desc
));
263 tracker_
.TrackOnSuccess(desc
);
264 webkit_request_
.requestSucceeded(CreateWebKitSessionDescription(desc
));
265 webkit_request_
.reset();
268 void OnFailure(const std::string
& error
) override
{
269 if (!main_thread_
->BelongsToCurrentThread()) {
270 main_thread_
->PostTask(FROM_HERE
,
271 base::Bind(&CreateSessionDescriptionRequest::OnFailure
, this, error
));
275 tracker_
.TrackOnFailure(error
);
276 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
277 webkit_request_
.reset();
281 ~CreateSessionDescriptionRequest() override
{
282 DCHECK(webkit_request_
.isNull());
285 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
286 blink::WebRTCSessionDescriptionRequest webkit_request_
;
287 SessionDescriptionRequestTracker tracker_
;
290 // Class mapping responses from calls to libjingle
291 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
292 class SetSessionDescriptionRequest
293 : public webrtc::SetSessionDescriptionObserver
{
295 explicit SetSessionDescriptionRequest(
296 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_thread
,
297 const blink::WebRTCVoidRequest
& request
,
298 const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
,
299 const base::WeakPtr
<PeerConnectionTracker
>& tracker
,
300 PeerConnectionTracker::Action action
)
301 : main_thread_(main_thread
),
302 webkit_request_(request
),
303 tracker_(handler
, tracker
, action
) {
306 void OnSuccess() override
{
307 if (!main_thread_
->BelongsToCurrentThread()) {
308 main_thread_
->PostTask(FROM_HERE
,
309 base::Bind(&SetSessionDescriptionRequest::OnSuccess
, this));
312 tracker_
.TrackOnSuccess(NULL
);
313 webkit_request_
.requestSucceeded();
314 webkit_request_
.reset();
316 void OnFailure(const std::string
& error
) override
{
317 if (!main_thread_
->BelongsToCurrentThread()) {
318 main_thread_
->PostTask(FROM_HERE
,
319 base::Bind(&SetSessionDescriptionRequest::OnFailure
, this, error
));
322 tracker_
.TrackOnFailure(error
);
323 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
324 webkit_request_
.reset();
328 ~SetSessionDescriptionRequest() override
{
329 DCHECK(webkit_request_
.isNull());
333 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
334 blink::WebRTCVoidRequest webkit_request_
;
335 SessionDescriptionRequestTracker tracker_
;
338 // Class mapping responses from calls to libjingle
339 // GetStats into a blink::WebRTCStatsCallback.
340 class StatsResponse
: public webrtc::StatsObserver
{
342 explicit StatsResponse(const scoped_refptr
<LocalRTCStatsRequest
>& request
)
343 : request_(request
.get()),
344 main_thread_(base::ThreadTaskRunnerHandle::Get()) {
345 // Measure the overall time it takes to satisfy a getStats request.
346 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
347 signaling_thread_checker_
.DetachFromThread();
350 void OnComplete(const StatsReports
& reports
) override
{
351 DCHECK(signaling_thread_checker_
.CalledOnValidThread());
352 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete");
353 // We can't use webkit objects directly since they use a single threaded
355 std::vector
<Report
*>* report_copies
= new std::vector
<Report
*>();
356 report_copies
->reserve(reports
.size());
357 for (auto* r
: reports
)
358 report_copies
->push_back(new Report(r
));
360 main_thread_
->PostTaskAndReply(FROM_HERE
,
361 base::Bind(&StatsResponse::DeliverCallback
, this,
362 base::Unretained(report_copies
)),
363 base::Bind(&StatsResponse::DeleteReports
,
364 base::Unretained(report_copies
)));
369 Report(const StatsReport
* report
)
370 : thread_checker(), id(report
->id()->ToString()),
371 type(report
->TypeToString()), timestamp(report
->timestamp()),
372 values(report
->values()) {
376 // Since the values vector holds pointers to const objects that are bound
377 // to the signaling thread, they must be released on the same thread.
378 DCHECK(thread_checker
.CalledOnValidThread());
381 const base::ThreadChecker thread_checker
;
382 const std::string id
, type
;
383 const double timestamp
;
384 const StatsReport::Values values
;
387 static void DeleteReports(std::vector
<Report
*>* reports
) {
388 TRACE_EVENT0("webrtc", "StatsResponse::DeleteReports");
389 for (auto* p
: *reports
)
394 void DeliverCallback(const std::vector
<Report
*>* reports
) {
395 DCHECK(main_thread_
->BelongsToCurrentThread());
396 TRACE_EVENT0("webrtc", "StatsResponse::DeliverCallback");
398 rtc::scoped_refptr
<LocalRTCStatsResponse
> response(
399 request_
->createResponse().get());
400 for (const auto* report
: *reports
) {
401 if (report
->values
.size() > 0)
402 AddReport(response
.get(), *report
);
405 // Record the getStats operation as done before calling into Blink so that
406 // we don't skew the perf measurements of the native code with whatever the
407 // callback might be doing.
408 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
409 request_
->requestSucceeded(response
);
410 request_
= nullptr; // must be freed on the main thread.
413 void AddReport(LocalRTCStatsResponse
* response
, const Report
& report
) {
414 int idx
= response
->addReport(blink::WebString::fromUTF8(report
.id
),
415 blink::WebString::fromUTF8(report
.type
),
417 blink::WebString name
, value_str
;
418 for (const auto& value
: report
.values
) {
419 const StatsReport::ValuePtr
& v
= value
.second
;
420 name
= blink::WebString::fromUTF8(value
.second
->display_name());
422 if (v
->type() == StatsReport::Value::kString
)
423 value_str
= blink::WebString::fromUTF8(v
->string_val());
424 if (v
->type() == StatsReport::Value::kStaticString
)
425 value_str
= blink::WebString::fromUTF8(v
->static_string_val());
427 value_str
= blink::WebString::fromUTF8(v
->ToString());
429 response
->addStatistic(idx
, name
, value_str
);
433 rtc::scoped_refptr
<LocalRTCStatsRequest
> request_
;
434 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
435 base::ThreadChecker signaling_thread_checker_
;
438 void GetStatsOnSignalingThread(
439 const scoped_refptr
<webrtc::PeerConnectionInterface
>& pc
,
440 webrtc::PeerConnectionInterface::StatsOutputLevel level
,
441 const scoped_refptr
<webrtc::StatsObserver
>& observer
,
442 const std::string track_id
, blink::WebMediaStreamSource::Type track_type
) {
443 TRACE_EVENT0("webrtc", "GetStatsOnSignalingThread");
445 scoped_refptr
<webrtc::MediaStreamTrackInterface
> track
;
446 if (!track_id
.empty()) {
447 if (track_type
== blink::WebMediaStreamSource::TypeAudio
) {
448 track
= pc
->local_streams()->FindAudioTrack(track_id
);
450 track
= pc
->remote_streams()->FindAudioTrack(track_id
);
452 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo
, track_type
);
453 track
= pc
->local_streams()->FindVideoTrack(track_id
);
455 track
= pc
->remote_streams()->FindVideoTrack(track_id
);
459 DVLOG(1) << "GetStats: Track not found.";
460 observer
->OnComplete(StatsReports());
465 if (!pc
->GetStats(observer
.get(), track
.get(), level
)) {
466 DVLOG(1) << "GetStats failed.";
467 observer
->OnComplete(StatsReports());
471 class PeerConnectionUMAObserver
: public webrtc::UMAObserver
{
473 PeerConnectionUMAObserver() {}
474 ~PeerConnectionUMAObserver() override
{}
476 void IncrementCounter(
477 webrtc::PeerConnectionUMAMetricsCounter counter
) override
{
478 // Runs on libjingle's signaling thread.
479 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
484 void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type
,
485 int value
) override
{
486 // Runs on libjingle's signaling thread.
488 case webrtc::kTimeToConnect
:
489 UMA_HISTOGRAM_MEDIUM_TIMES(
490 "WebRTC.PeerConnection.TimeToConnect",
491 base::TimeDelta::FromMilliseconds(value
));
493 case webrtc::kNetworkInterfaces_IPv4
:
494 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
497 case webrtc::kNetworkInterfaces_IPv6
:
498 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
507 base::LazyInstance
<std::set
<RTCPeerConnectionHandler
*> >::Leaky
508 g_peer_connection_handlers
= LAZY_INSTANCE_INITIALIZER
;
512 // Implementation of LocalRTCStatsRequest.
513 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl
)
517 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
518 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
520 bool LocalRTCStatsRequest::hasSelector() const {
521 return impl_
.hasSelector();
524 blink::WebMediaStreamTrack
LocalRTCStatsRequest::component() const {
525 return impl_
.component();
528 scoped_refptr
<LocalRTCStatsResponse
> LocalRTCStatsRequest::createResponse() {
529 return scoped_refptr
<LocalRTCStatsResponse
>(
530 new rtc::RefCountedObject
<LocalRTCStatsResponse
>(impl_
.createResponse()));
533 void LocalRTCStatsRequest::requestSucceeded(
534 const LocalRTCStatsResponse
* response
) {
535 impl_
.requestSucceeded(response
->webKitStatsResponse());
538 // Implementation of LocalRTCStatsResponse.
539 blink::WebRTCStatsResponse
LocalRTCStatsResponse::webKitStatsResponse() const {
543 size_t LocalRTCStatsResponse::addReport(blink::WebString type
,
546 return impl_
.addReport(type
, id
, timestamp
);
549 void LocalRTCStatsResponse::addStatistic(size_t report
,
550 blink::WebString name
,
551 blink::WebString value
) {
552 impl_
.addStatistic(report
, name
, value
);
555 // Receives notifications from a PeerConnection object about state changes,
556 // track addition/removal etc. The callbacks we receive here come on the
557 // signaling thread, so this class takes care of delivering them to an
558 // RTCPeerConnectionHandler instance on the main thread.
559 // In order to do safe PostTask-ing, the class is reference counted and
560 // checks for the existence of the RTCPeerConnectionHandler instance before
561 // delivering callbacks on the main thread.
562 class RTCPeerConnectionHandler::Observer
563 : public base::RefCountedThreadSafe
<RTCPeerConnectionHandler::Observer
>,
564 public PeerConnectionObserver
{
566 Observer(const base::WeakPtr
<RTCPeerConnectionHandler
>& handler
)
567 : handler_(handler
), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
570 friend class base::RefCountedThreadSafe
<RTCPeerConnectionHandler::Observer
>;
571 virtual ~Observer() {}
573 void OnSignalingChange(
574 PeerConnectionInterface::SignalingState new_state
) override
{
575 if (!main_thread_
->BelongsToCurrentThread()) {
576 main_thread_
->PostTask(FROM_HERE
,
577 base::Bind(&RTCPeerConnectionHandler::Observer::OnSignalingChange
,
579 } else if (handler_
) {
580 handler_
->OnSignalingChange(new_state
);
584 void OnAddStream(MediaStreamInterface
* stream
) override
{
586 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(
587 new RemoteMediaStreamImpl(main_thread_
, stream
));
589 // The webkit object owned by RemoteMediaStreamImpl, will be initialized
590 // asynchronously and the posted task will execude after that initialization
592 main_thread_
->PostTask(FROM_HERE
,
593 base::Bind(&RTCPeerConnectionHandler::Observer::OnAddStreamImpl
,
594 this, base::Passed(&remote_stream
)));
597 void OnRemoveStream(MediaStreamInterface
* stream
) override
{
598 main_thread_
->PostTask(FROM_HERE
,
599 base::Bind(&RTCPeerConnectionHandler::Observer::OnRemoveStreamImpl
,
600 this, make_scoped_refptr(stream
)));
603 void OnDataChannel(DataChannelInterface
* data_channel
) override
{
604 scoped_ptr
<RtcDataChannelHandler
> handler(
605 new RtcDataChannelHandler(main_thread_
, data_channel
));
606 main_thread_
->PostTask(FROM_HERE
,
607 base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl
,
608 this, base::Passed(&handler
)));
611 void OnRenegotiationNeeded() override
{
612 if (!main_thread_
->BelongsToCurrentThread()) {
613 main_thread_
->PostTask(FROM_HERE
,
614 base::Bind(&RTCPeerConnectionHandler::Observer::OnRenegotiationNeeded
,
616 } else if (handler_
) {
617 handler_
->OnRenegotiationNeeded();
621 void OnIceConnectionChange(
622 PeerConnectionInterface::IceConnectionState new_state
) override
{
623 if (!main_thread_
->BelongsToCurrentThread()) {
624 main_thread_
->PostTask(FROM_HERE
,
626 &RTCPeerConnectionHandler::Observer::OnIceConnectionChange
, this,
628 } else if (handler_
) {
629 handler_
->OnIceConnectionChange(new_state
);
633 void OnIceGatheringChange(
634 PeerConnectionInterface::IceGatheringState new_state
) override
{
635 if (!main_thread_
->BelongsToCurrentThread()) {
636 main_thread_
->PostTask(FROM_HERE
,
637 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceGatheringChange
,
639 } else if (handler_
) {
640 handler_
->OnIceGatheringChange(new_state
);
644 void OnIceCandidate(const IceCandidateInterface
* candidate
) override
{
646 if (!candidate
->ToString(&sdp
)) {
647 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
651 main_thread_
->PostTask(FROM_HERE
,
652 base::Bind(&RTCPeerConnectionHandler::Observer::OnIceCandidateImpl
,
653 this, sdp
, candidate
->sdp_mid(), candidate
->sdp_mline_index(),
654 candidate
->candidate().component(),
655 candidate
->candidate().address().family()));
658 void OnAddStreamImpl(scoped_ptr
<RemoteMediaStreamImpl
> stream
) {
659 DCHECK(stream
->webkit_stream().extraData()) << "Initialization not done";
661 handler_
->OnAddStream(stream
.Pass());
664 void OnRemoveStreamImpl(const scoped_refptr
<MediaStreamInterface
>& stream
) {
666 handler_
->OnRemoveStream(stream
);
669 void OnDataChannelImpl(scoped_ptr
<RtcDataChannelHandler
> handler
) {
671 handler_
->OnDataChannel(handler
.Pass());
674 void OnIceCandidateImpl(const std::string
& sdp
, const std::string
& sdp_mid
,
675 int sdp_mline_index
, int component
, int address_family
) {
677 handler_
->OnIceCandidate(sdp
, sdp_mid
, sdp_mline_index
, component
,
683 const base::WeakPtr
<RTCPeerConnectionHandler
> handler_
;
684 const scoped_refptr
<base::SingleThreadTaskRunner
> main_thread_
;
687 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
688 blink::WebRTCPeerConnectionHandlerClient
* client
,
689 PeerConnectionDependencyFactory
* dependency_factory
)
691 dependency_factory_(dependency_factory
),
693 num_data_channels_created_(0),
694 num_local_candidates_ipv4_(0),
695 num_local_candidates_ipv6_(0),
696 weak_factory_(this) {
697 g_peer_connection_handlers
.Get().insert(this);
700 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
701 DCHECK(thread_checker_
.CalledOnValidThread());
705 g_peer_connection_handlers
.Get().erase(this);
706 if (peer_connection_tracker_
)
707 peer_connection_tracker_
->UnregisterPeerConnection(this);
708 STLDeleteValues(&remote_streams_
);
710 UMA_HISTOGRAM_COUNTS_10000(
711 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_
);
715 void RTCPeerConnectionHandler::DestructAllHandlers() {
716 std::set
<RTCPeerConnectionHandler
*> handlers(
717 g_peer_connection_handlers
.Get().begin(),
718 g_peer_connection_handlers
.Get().end());
719 for (auto handler
: handlers
) {
720 if (handler
->client_
)
721 handler
->client_
->releasePeerConnectionHandler();
726 void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
727 const blink::WebRTCOfferOptions
& options
,
728 RTCMediaConstraints
* output
) {
729 output
->AddMandatory(
730 webrtc::MediaConstraintsInterface::kOfferToReceiveAudio
,
731 options
.offerToReceiveAudio() > 0 ? "true" : "false",
734 output
->AddMandatory(
735 webrtc::MediaConstraintsInterface::kOfferToReceiveVideo
,
736 options
.offerToReceiveVideo() > 0 ? "true" : "false",
739 if (!options
.voiceActivityDetection()) {
740 output
->AddMandatory(
741 webrtc::MediaConstraintsInterface::kVoiceActivityDetection
,
746 if (options
.iceRestart()) {
747 output
->AddMandatory(
748 webrtc::MediaConstraintsInterface::kIceRestart
, "true", true);
752 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame
* frame
) {
753 DCHECK(thread_checker_
.CalledOnValidThread());
758 bool RTCPeerConnectionHandler::initialize(
759 const blink::WebRTCConfiguration
& server_configuration
,
760 const blink::WebMediaConstraints
& options
) {
761 DCHECK(thread_checker_
.CalledOnValidThread());
764 peer_connection_tracker_
=
765 RenderThreadImpl::current()->peer_connection_tracker()->AsWeakPtr();
767 webrtc::PeerConnectionInterface::RTCConfiguration config
;
768 GetNativeRtcConfiguration(server_configuration
, &config
);
770 RTCMediaConstraints
constraints(options
);
772 peer_connection_observer_
= new Observer(weak_factory_
.GetWeakPtr());
773 native_peer_connection_
= dependency_factory_
->CreatePeerConnection(
774 config
, &constraints
, frame_
, peer_connection_observer_
.get());
776 if (!native_peer_connection_
.get()) {
777 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
781 if (peer_connection_tracker_
) {
782 peer_connection_tracker_
->RegisterPeerConnection(
783 this, config
, constraints
, frame_
);
786 uma_observer_
= new rtc::RefCountedObject
<PeerConnectionUMAObserver
>();
787 native_peer_connection_
->RegisterUMAObserver(uma_observer_
.get());
791 bool RTCPeerConnectionHandler::InitializeForTest(
792 const blink::WebRTCConfiguration
& server_configuration
,
793 const blink::WebMediaConstraints
& options
,
794 const base::WeakPtr
<PeerConnectionTracker
>& peer_connection_tracker
) {
795 DCHECK(thread_checker_
.CalledOnValidThread());
796 webrtc::PeerConnectionInterface::RTCConfiguration config
;
797 GetNativeRtcConfiguration(server_configuration
, &config
);
799 peer_connection_observer_
= new Observer(weak_factory_
.GetWeakPtr());
800 RTCMediaConstraints
constraints(options
);
801 native_peer_connection_
= dependency_factory_
->CreatePeerConnection(
802 config
, &constraints
, NULL
, peer_connection_observer_
.get());
803 if (!native_peer_connection_
.get()) {
804 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
807 peer_connection_tracker_
= peer_connection_tracker
;
811 void RTCPeerConnectionHandler::createOffer(
812 const blink::WebRTCSessionDescriptionRequest
& request
,
813 const blink::WebMediaConstraints
& options
) {
814 DCHECK(thread_checker_
.CalledOnValidThread());
815 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
817 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
818 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
819 base::ThreadTaskRunnerHandle::Get(), request
,
820 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
821 PeerConnectionTracker::ACTION_CREATE_OFFER
));
823 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
824 RTCMediaConstraints
constraints(options
);
825 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
827 if (peer_connection_tracker_
)
828 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
831 void RTCPeerConnectionHandler::createOffer(
832 const blink::WebRTCSessionDescriptionRequest
& request
,
833 const blink::WebRTCOfferOptions
& options
) {
834 DCHECK(thread_checker_
.CalledOnValidThread());
835 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer");
837 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
838 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
839 base::ThreadTaskRunnerHandle::Get(), request
,
840 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
841 PeerConnectionTracker::ACTION_CREATE_OFFER
));
843 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
844 RTCMediaConstraints constraints
;
845 ConvertOfferOptionsToConstraints(options
, &constraints
);
846 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
848 if (peer_connection_tracker_
)
849 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
852 void RTCPeerConnectionHandler::createAnswer(
853 const blink::WebRTCSessionDescriptionRequest
& request
,
854 const blink::WebMediaConstraints
& options
) {
855 DCHECK(thread_checker_
.CalledOnValidThread());
856 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
857 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
858 new rtc::RefCountedObject
<CreateSessionDescriptionRequest
>(
859 base::ThreadTaskRunnerHandle::Get(), request
,
860 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
861 PeerConnectionTracker::ACTION_CREATE_ANSWER
));
862 // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
863 RTCMediaConstraints
constraints(options
);
864 native_peer_connection_
->CreateAnswer(description_request
.get(),
867 if (peer_connection_tracker_
)
868 peer_connection_tracker_
->TrackCreateAnswer(this, constraints
);
871 void RTCPeerConnectionHandler::setLocalDescription(
872 const blink::WebRTCVoidRequest
& request
,
873 const blink::WebRTCSessionDescription
& description
) {
874 DCHECK(thread_checker_
.CalledOnValidThread());
875 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription");
877 std::string sdp
= base::UTF16ToUTF8(description
.sdp());
878 std::string type
= base::UTF16ToUTF8(description
.type());
880 webrtc::SdpParseError error
;
881 // Since CreateNativeSessionDescription uses the dependency factory, we need
882 // to make this call on the current thread to be safe.
883 webrtc::SessionDescriptionInterface
* native_desc
=
884 CreateNativeSessionDescription(sdp
, type
, &error
);
886 std::string reason_str
= "Failed to parse SessionDescription. ";
887 reason_str
.append(error
.line
);
888 reason_str
.append(" ");
889 reason_str
.append(error
.description
);
890 LOG(ERROR
) << reason_str
;
891 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
895 if (peer_connection_tracker_
) {
896 peer_connection_tracker_
->TrackSetSessionDescription(
897 this, sdp
, type
, PeerConnectionTracker::SOURCE_LOCAL
);
900 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
901 new rtc::RefCountedObject
<SetSessionDescriptionRequest
>(
902 base::ThreadTaskRunnerHandle::Get(), request
,
903 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
904 PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION
));
906 signaling_thread()->PostTask(FROM_HERE
,
907 base::Bind(&RunClosureWithTrace
,
908 base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription
,
909 native_peer_connection_
, set_request
,
910 base::Unretained(native_desc
)),
911 "SetLocalDescription"));
914 void RTCPeerConnectionHandler::setRemoteDescription(
915 const blink::WebRTCVoidRequest
& request
,
916 const blink::WebRTCSessionDescription
& description
) {
917 DCHECK(thread_checker_
.CalledOnValidThread());
918 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription");
919 std::string sdp
= base::UTF16ToUTF8(description
.sdp());
920 std::string type
= base::UTF16ToUTF8(description
.type());
922 webrtc::SdpParseError error
;
923 // Since CreateNativeSessionDescription uses the dependency factory, we need
924 // to make this call on the current thread to be safe.
925 webrtc::SessionDescriptionInterface
* native_desc
=
926 CreateNativeSessionDescription(sdp
, type
, &error
);
928 std::string reason_str
= "Failed to parse SessionDescription. ";
929 reason_str
.append(error
.line
);
930 reason_str
.append(" ");
931 reason_str
.append(error
.description
);
932 LOG(ERROR
) << reason_str
;
933 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
937 if (peer_connection_tracker_
) {
938 peer_connection_tracker_
->TrackSetSessionDescription(
939 this, sdp
, type
, PeerConnectionTracker::SOURCE_REMOTE
);
942 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
943 new rtc::RefCountedObject
<SetSessionDescriptionRequest
>(
944 base::ThreadTaskRunnerHandle::Get(), request
,
945 weak_factory_
.GetWeakPtr(), peer_connection_tracker_
,
946 PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION
));
947 signaling_thread()->PostTask(FROM_HERE
,
948 base::Bind(&RunClosureWithTrace
,
949 base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription
,
950 native_peer_connection_
, set_request
,
951 base::Unretained(native_desc
)),
952 "SetRemoteDescription"));
955 blink::WebRTCSessionDescription
956 RTCPeerConnectionHandler::localDescription() {
957 DCHECK(thread_checker_
.CalledOnValidThread());
958 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription");
960 // Since local_description returns a pointer to a non-reference-counted object
961 // that lives on the signaling thread, we cannot fetch a pointer to it and use
962 // it directly here. Instead, we access the object completely on the signaling
964 std::string sdp
, type
;
965 base::Callback
<const webrtc::SessionDescriptionInterface
*()> description_cb
=
966 base::Bind(&webrtc::PeerConnectionInterface::local_description
,
967 native_peer_connection_
);
968 RunSynchronousClosureOnSignalingThread(
969 base::Bind(&GetSdpAndTypeFromSessionDescription
, description_cb
,
970 base::Unretained(&sdp
), base::Unretained(&type
)),
973 return CreateWebKitSessionDescription(sdp
, type
);
976 blink::WebRTCSessionDescription
977 RTCPeerConnectionHandler::remoteDescription() {
978 DCHECK(thread_checker_
.CalledOnValidThread());
979 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::remoteDescription");
980 // Since local_description returns a pointer to a non-reference-counted object
981 // that lives on the signaling thread, we cannot fetch a pointer to it and use
982 // it directly here. Instead, we access the object completely on the signaling
984 std::string sdp
, type
;
985 base::Callback
<const webrtc::SessionDescriptionInterface
*()> description_cb
=
986 base::Bind(&webrtc::PeerConnectionInterface::remote_description
,
987 native_peer_connection_
);
988 RunSynchronousClosureOnSignalingThread(
989 base::Bind(&GetSdpAndTypeFromSessionDescription
, description_cb
,
990 base::Unretained(&sdp
), base::Unretained(&type
)),
991 "remoteDescription");
993 return CreateWebKitSessionDescription(sdp
, type
);
996 bool RTCPeerConnectionHandler::updateICE(
997 const blink::WebRTCConfiguration
& server_configuration
,
998 const blink::WebMediaConstraints
& options
) {
999 DCHECK(thread_checker_
.CalledOnValidThread());
1000 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
1001 webrtc::PeerConnectionInterface::RTCConfiguration config
;
1002 GetNativeRtcConfiguration(server_configuration
, &config
);
1003 RTCMediaConstraints
constraints(options
);
1005 if (peer_connection_tracker_
)
1006 peer_connection_tracker_
->TrackUpdateIce(this, config
, constraints
);
1008 return native_peer_connection_
->UpdateIce(config
.servers
, &constraints
);
1011 bool RTCPeerConnectionHandler::addICECandidate(
1012 const blink::WebRTCVoidRequest
& request
,
1013 const blink::WebRTCICECandidate
& candidate
) {
1014 DCHECK(thread_checker_
.CalledOnValidThread());
1015 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1016 // Libjingle currently does not accept callbacks for addICECandidate.
1017 // For that reason we are going to call callbacks from here.
1019 // TODO(tommi): Instead of calling addICECandidate here, we can do a
1020 // PostTaskAndReply kind of a thing.
1021 bool result
= addICECandidate(candidate
);
1022 base::MessageLoop::current()->PostTask(
1024 base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult
,
1025 weak_factory_
.GetWeakPtr(), request
, result
));
1026 // On failure callback will be triggered.
1030 bool RTCPeerConnectionHandler::addICECandidate(
1031 const blink::WebRTCICECandidate
& candidate
) {
1032 DCHECK(thread_checker_
.CalledOnValidThread());
1033 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
1034 scoped_ptr
<webrtc::IceCandidateInterface
> native_candidate(
1035 dependency_factory_
->CreateIceCandidate(
1036 base::UTF16ToUTF8(candidate
.sdpMid()),
1037 candidate
.sdpMLineIndex(),
1038 base::UTF16ToUTF8(candidate
.candidate())));
1039 bool return_value
= false;
1041 if (native_candidate
) {
1043 native_peer_connection_
->AddIceCandidate(native_candidate
.get());
1044 LOG_IF(ERROR
, !return_value
) << "Error processing ICE candidate.";
1046 LOG(ERROR
) << "Could not create native ICE candidate.";
1049 if (peer_connection_tracker_
) {
1050 peer_connection_tracker_
->TrackAddIceCandidate(
1051 this, candidate
, PeerConnectionTracker::SOURCE_REMOTE
, return_value
);
1053 return return_value
;
1056 void RTCPeerConnectionHandler::OnaddICECandidateResult(
1057 const blink::WebRTCVoidRequest
& webkit_request
, bool result
) {
1058 DCHECK(thread_checker_
.CalledOnValidThread());
1059 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult");
1061 // We don't have the actual error code from the libjingle, so for now
1062 // using a generic error string.
1063 return webkit_request
.requestFailed(
1064 base::UTF8ToUTF16("Error processing ICE candidate"));
1067 return webkit_request
.requestSucceeded();
1070 bool RTCPeerConnectionHandler::addStream(
1071 const blink::WebMediaStream
& stream
,
1072 const blink::WebMediaConstraints
& options
) {
1073 DCHECK(thread_checker_
.CalledOnValidThread());
1074 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addStream");
1075 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
1076 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
1078 if ((*adapter_it
)->IsEqual(stream
)) {
1079 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
1080 << "stream twice. id=" << stream
.id().utf8();
1085 if (peer_connection_tracker_
) {
1086 peer_connection_tracker_
->TrackAddStream(
1087 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
1090 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1092 WebRtcMediaStreamAdapter
* adapter
=
1093 new WebRtcMediaStreamAdapter(stream
, dependency_factory_
);
1094 local_streams_
.push_back(adapter
);
1096 webrtc::MediaStreamInterface
* webrtc_stream
= adapter
->webrtc_media_stream();
1097 track_metrics_
.AddStream(MediaStreamTrackMetrics::SENT_STREAM
,
1100 RTCMediaConstraints
constraints(options
);
1101 if (!constraints
.GetMandatory().empty() ||
1102 !constraints
.GetOptional().empty()) {
1103 // TODO(perkj): |mediaConstraints| is the name of the optional constraints
1104 // argument in RTCPeerConnection.idl. It has been removed from the spec and
1105 // should be removed from blink as well.
1107 << "mediaConstraints is not a supported argument to addStream.";
1110 return native_peer_connection_
->AddStream(webrtc_stream
);
1113 void RTCPeerConnectionHandler::removeStream(
1114 const blink::WebMediaStream
& stream
) {
1115 DCHECK(thread_checker_
.CalledOnValidThread());
1116 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::removeStream");
1117 // Find the webrtc stream.
1118 scoped_refptr
<webrtc::MediaStreamInterface
> webrtc_stream
;
1119 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
1120 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
1122 if ((*adapter_it
)->IsEqual(stream
)) {
1123 webrtc_stream
= (*adapter_it
)->webrtc_media_stream();
1124 local_streams_
.erase(adapter_it
);
1128 DCHECK(webrtc_stream
.get());
1129 // TODO(tommi): Make this async (PostTaskAndReply).
1130 native_peer_connection_
->RemoveStream(webrtc_stream
.get());
1132 if (peer_connection_tracker_
) {
1133 peer_connection_tracker_
->TrackRemoveStream(
1134 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
1136 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1137 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM
,
1138 webrtc_stream
.get());
1141 void RTCPeerConnectionHandler::getStats(
1142 const blink::WebRTCStatsRequest
& request
) {
1143 DCHECK(thread_checker_
.CalledOnValidThread());
1144 scoped_refptr
<LocalRTCStatsRequest
> inner_request(
1145 new rtc::RefCountedObject
<LocalRTCStatsRequest
>(request
));
1146 getStats(inner_request
);
1149 void RTCPeerConnectionHandler::getStats(
1150 const scoped_refptr
<LocalRTCStatsRequest
>& request
) {
1151 DCHECK(thread_checker_
.CalledOnValidThread());
1152 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats");
1155 rtc::scoped_refptr
<webrtc::StatsObserver
> observer(
1156 new rtc::RefCountedObject
<StatsResponse
>(request
));
1158 std::string track_id
;
1159 blink::WebMediaStreamSource::Type track_type
=
1160 blink::WebMediaStreamSource::TypeAudio
;
1161 if (request
->hasSelector()) {
1162 track_type
= request
->component().source().type();
1163 track_id
= request
->component().id().utf8();
1166 GetStats(observer
, webrtc::PeerConnectionInterface::kStatsOutputLevelStandard
,
1167 track_id
, track_type
);
1170 // TODO(tommi): It's weird to have three {g|G}etStats methods. Clean this up.
1171 void RTCPeerConnectionHandler::GetStats(
1172 webrtc::StatsObserver
* observer
,
1173 webrtc::PeerConnectionInterface::StatsOutputLevel level
,
1174 const std::string
& track_id
,
1175 blink::WebMediaStreamSource::Type track_type
) {
1176 DCHECK(thread_checker_
.CalledOnValidThread());
1177 signaling_thread()->PostTask(FROM_HERE
,
1178 base::Bind(&GetStatsOnSignalingThread
, native_peer_connection_
, level
,
1179 make_scoped_refptr(observer
), track_id
, track_type
));
1182 void RTCPeerConnectionHandler::CloseClientPeerConnection() {
1183 DCHECK(thread_checker_
.CalledOnValidThread());
1185 client_
->closePeerConnection();
1188 blink::WebRTCDataChannelHandler
* RTCPeerConnectionHandler::createDataChannel(
1189 const blink::WebString
& label
, const blink::WebRTCDataChannelInit
& init
) {
1190 DCHECK(thread_checker_
.CalledOnValidThread());
1191 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel");
1192 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label
);
1194 webrtc::DataChannelInit config
;
1195 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
1197 config
.reliable
= false;
1198 config
.id
= init
.id
;
1199 config
.ordered
= init
.ordered
;
1200 config
.negotiated
= init
.negotiated
;
1201 config
.maxRetransmits
= init
.maxRetransmits
;
1202 config
.maxRetransmitTime
= init
.maxRetransmitTime
;
1203 config
.protocol
= base::UTF16ToUTF8(init
.protocol
);
1205 rtc::scoped_refptr
<webrtc::DataChannelInterface
> webrtc_channel(
1206 native_peer_connection_
->CreateDataChannel(base::UTF16ToUTF8(label
),
1208 if (!webrtc_channel
) {
1209 DLOG(ERROR
) << "Could not create native data channel.";
1212 if (peer_connection_tracker_
) {
1213 peer_connection_tracker_
->TrackCreateDataChannel(
1214 this, webrtc_channel
.get(), PeerConnectionTracker::SOURCE_LOCAL
);
1217 ++num_data_channels_created_
;
1219 return new RtcDataChannelHandler(base::ThreadTaskRunnerHandle::Get(),
1223 blink::WebRTCDTMFSenderHandler
* RTCPeerConnectionHandler::createDTMFSender(
1224 const blink::WebMediaStreamTrack
& track
) {
1225 DCHECK(thread_checker_
.CalledOnValidThread());
1226 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
1227 DVLOG(1) << "createDTMFSender.";
1229 MediaStreamTrack
* native_track
= MediaStreamTrack::GetTrack(track
);
1230 if (!native_track
|| !native_track
->is_local_track() ||
1231 track
.source().type() != blink::WebMediaStreamSource::TypeAudio
) {
1232 DLOG(ERROR
) << "The DTMF sender requires a local audio track.";
1236 scoped_refptr
<webrtc::AudioTrackInterface
> audio_track
=
1237 native_track
->GetAudioAdapter();
1238 rtc::scoped_refptr
<webrtc::DtmfSenderInterface
> sender(
1239 native_peer_connection_
->CreateDtmfSender(audio_track
.get()));
1241 DLOG(ERROR
) << "Could not create native DTMF sender.";
1244 if (peer_connection_tracker_
)
1245 peer_connection_tracker_
->TrackCreateDTMFSender(this, track
);
1247 return new RtcDtmfSenderHandler(sender
);
1250 void RTCPeerConnectionHandler::stop() {
1251 DCHECK(thread_checker_
.CalledOnValidThread());
1252 DVLOG(1) << "RTCPeerConnectionHandler::stop";
1254 if (!client_
|| !native_peer_connection_
.get())
1255 return; // Already stopped.
1257 if (peer_connection_tracker_
)
1258 peer_connection_tracker_
->TrackStop(this);
1260 native_peer_connection_
->Close();
1262 // The client_ pointer is not considered valid after this point and no further
1263 // callbacks must be made.
1267 void RTCPeerConnectionHandler::OnSignalingChange(
1268 webrtc::PeerConnectionInterface::SignalingState new_state
) {
1269 DCHECK(thread_checker_
.CalledOnValidThread());
1270 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange");
1272 blink::WebRTCPeerConnectionHandlerClient::SignalingState state
=
1273 GetWebKitSignalingState(new_state
);
1274 if (peer_connection_tracker_
)
1275 peer_connection_tracker_
->TrackSignalingStateChange(this, state
);
1277 client_
->didChangeSignalingState(state
);
1280 // Called any time the IceConnectionState changes
1281 void RTCPeerConnectionHandler::OnIceConnectionChange(
1282 webrtc::PeerConnectionInterface::IceConnectionState new_state
) {
1283 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange");
1284 DCHECK(thread_checker_
.CalledOnValidThread());
1285 if (new_state
== webrtc::PeerConnectionInterface::kIceConnectionChecking
) {
1286 ice_connection_checking_start_
= base::TimeTicks::Now();
1287 } else if (new_state
==
1288 webrtc::PeerConnectionInterface::kIceConnectionConnected
) {
1289 // If the state becomes connected, send the time needed for PC to become
1290 // connected from checking to UMA. UMA data will help to know how much
1291 // time needed for PC to connect with remote peer.
1292 UMA_HISTOGRAM_MEDIUM_TIMES(
1293 "WebRTC.PeerConnection.TimeToConnect",
1294 base::TimeTicks::Now() - ice_connection_checking_start_
);
1297 track_metrics_
.IceConnectionChange(new_state
);
1298 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state
=
1299 GetWebKitIceConnectionState(new_state
);
1300 if (peer_connection_tracker_
)
1301 peer_connection_tracker_
->TrackIceConnectionStateChange(this, state
);
1303 client_
->didChangeICEConnectionState(state
);
1306 // Called any time the IceGatheringState changes
1307 void RTCPeerConnectionHandler::OnIceGatheringChange(
1308 webrtc::PeerConnectionInterface::IceGatheringState new_state
) {
1309 DCHECK(thread_checker_
.CalledOnValidThread());
1310 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange");
1312 if (new_state
== webrtc::PeerConnectionInterface::kIceGatheringComplete
) {
1313 // If ICE gathering is completed, generate a NULL ICE candidate,
1314 // to signal end of candidates.
1316 blink::WebRTCICECandidate null_candidate
;
1317 client_
->didGenerateICECandidate(null_candidate
);
1320 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4LocalCandidates",
1321 num_local_candidates_ipv4_
);
1323 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6LocalCandidates",
1324 num_local_candidates_ipv6_
);
1325 } else if (new_state
==
1326 webrtc::PeerConnectionInterface::kIceGatheringGathering
) {
1327 // ICE restarts will change gathering state back to "gathering",
1328 // reset the counter.
1329 num_local_candidates_ipv6_
= 0;
1330 num_local_candidates_ipv4_
= 0;
1333 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state
=
1334 GetWebKitIceGatheringState(new_state
);
1335 if (peer_connection_tracker_
)
1336 peer_connection_tracker_
->TrackIceGatheringStateChange(this, state
);
1338 client_
->didChangeICEGatheringState(state
);
1341 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
1342 DCHECK(thread_checker_
.CalledOnValidThread());
1343 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
1344 if (peer_connection_tracker_
)
1345 peer_connection_tracker_
->TrackOnRenegotiationNeeded(this);
1347 client_
->negotiationNeeded();
1350 void RTCPeerConnectionHandler::OnAddStream(
1351 scoped_ptr
<RemoteMediaStreamImpl
> stream
) {
1352 DCHECK(thread_checker_
.CalledOnValidThread());
1353 DCHECK(remote_streams_
.find(stream
->webrtc_stream().get()) ==
1354 remote_streams_
.end());
1355 DCHECK(stream
->webkit_stream().extraData()) << "Initialization not done";
1356 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
1358 // Ownership is with remote_streams_ now.
1359 RemoteMediaStreamImpl
* s
= stream
.release();
1360 remote_streams_
.insert(
1361 std::pair
<webrtc::MediaStreamInterface
*, RemoteMediaStreamImpl
*> (
1362 s
->webrtc_stream().get(), s
));
1364 if (peer_connection_tracker_
) {
1365 peer_connection_tracker_
->TrackAddStream(
1366 this, s
->webkit_stream(), PeerConnectionTracker::SOURCE_REMOTE
);
1369 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
1371 track_metrics_
.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
1372 s
->webrtc_stream().get());
1374 client_
->didAddRemoteStream(s
->webkit_stream());
1377 void RTCPeerConnectionHandler::OnRemoveStream(
1378 const scoped_refptr
<webrtc::MediaStreamInterface
>& stream
) {
1379 DCHECK(thread_checker_
.CalledOnValidThread());
1380 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveStreamImpl");
1381 RemoteStreamMap::iterator it
= remote_streams_
.find(stream
.get());
1382 if (it
== remote_streams_
.end()) {
1383 NOTREACHED() << "Stream not found";
1387 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
1389 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
1391 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(it
->second
);
1392 const blink::WebMediaStream
& webkit_stream
= remote_stream
->webkit_stream();
1393 DCHECK(!webkit_stream
.isNull());
1394 remote_streams_
.erase(it
);
1396 if (peer_connection_tracker_
) {
1397 peer_connection_tracker_
->TrackRemoveStream(
1398 this, webkit_stream
, PeerConnectionTracker::SOURCE_REMOTE
);
1402 client_
->didRemoveRemoteStream(webkit_stream
);
1405 void RTCPeerConnectionHandler::OnDataChannel(
1406 scoped_ptr
<RtcDataChannelHandler
> handler
) {
1407 DCHECK(thread_checker_
.CalledOnValidThread());
1408 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
1410 if (peer_connection_tracker_
) {
1411 peer_connection_tracker_
->TrackCreateDataChannel(
1412 this, handler
->channel().get(), PeerConnectionTracker::SOURCE_REMOTE
);
1416 client_
->didAddRemoteDataChannel(handler
.release());
1419 void RTCPeerConnectionHandler::OnIceCandidate(
1420 const std::string
& sdp
, const std::string
& sdp_mid
, int sdp_mline_index
,
1421 int component
, int address_family
) {
1422 DCHECK(thread_checker_
.CalledOnValidThread());
1423 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
1424 blink::WebRTCICECandidate web_candidate
;
1425 web_candidate
.initialize(base::UTF8ToUTF16(sdp
),
1426 base::UTF8ToUTF16(sdp_mid
),
1428 if (peer_connection_tracker_
) {
1429 peer_connection_tracker_
->TrackAddIceCandidate(
1430 this, web_candidate
, PeerConnectionTracker::SOURCE_LOCAL
, true);
1433 // Only the first m line's first component is tracked to avoid
1434 // miscounting when doing BUNDLE or rtcp mux.
1435 if (sdp_mline_index
== 0 && component
== 1) {
1436 if (address_family
== AF_INET
) {
1437 ++num_local_candidates_ipv4_
;
1438 } else if (address_family
== AF_INET6
) {
1439 ++num_local_candidates_ipv6_
;
1445 client_
->didGenerateICECandidate(web_candidate
);
1448 webrtc::SessionDescriptionInterface
*
1449 RTCPeerConnectionHandler::CreateNativeSessionDescription(
1450 const std::string
& sdp
, const std::string
& type
,
1451 webrtc::SdpParseError
* error
) {
1452 webrtc::SessionDescriptionInterface
* native_desc
=
1453 dependency_factory_
->CreateSessionDescription(type
, sdp
, error
);
1455 LOG_IF(ERROR
, !native_desc
) << "Failed to create native session description."
1456 << " Type: " << type
<< " SDP: " << sdp
;
1461 scoped_refptr
<base::SingleThreadTaskRunner
>
1462 RTCPeerConnectionHandler::signaling_thread() const {
1463 DCHECK(thread_checker_
.CalledOnValidThread());
1464 return dependency_factory_
->GetWebRtcSignalingThread();
1467 void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread(
1468 const base::Closure
& closure
,
1469 const char* trace_event_name
) {
1470 DCHECK(thread_checker_
.CalledOnValidThread());
1471 scoped_refptr
<base::SingleThreadTaskRunner
> thread(signaling_thread());
1472 if (!thread
.get() || thread
->BelongsToCurrentThread()) {
1473 TRACE_EVENT0("webrtc", trace_event_name
);
1476 base::WaitableEvent
event(false, false);
1477 thread
->PostTask(FROM_HERE
,
1478 base::Bind(&RunSynchronousClosure
, closure
,
1479 base::Unretained(trace_event_name
),
1480 base::Unretained(&event
)));
1485 } // namespace content