1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/rtc_peer_connection_handler.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram.h"
17 #include "base/stl_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/renderer/media/media_stream_track.h"
21 #include "content/renderer/media/peer_connection_tracker.h"
22 #include "content/renderer/media/remote_media_stream_impl.h"
23 #include "content/renderer/media/rtc_data_channel_handler.h"
24 #include "content/renderer/media/rtc_dtmf_sender_handler.h"
25 #include "content/renderer/media/rtc_media_constraints.h"
26 #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
27 #include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
28 #include "content/renderer/media/webrtc_audio_capturer.h"
29 #include "content/renderer/media/webrtc_audio_device_impl.h"
30 #include "content/renderer/media/webrtc_uma_histograms.h"
31 #include "content/renderer/render_thread_impl.h"
32 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
33 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
34 #include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
35 #include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
36 #include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
37 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
38 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
39 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
40 #include "third_party/WebKit/public/platform/WebURL.h"
44 // Converter functions from libjingle types to WebKit types.
45 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState
46 GetWebKitIceGatheringState(
47 webrtc::PeerConnectionInterface::IceGatheringState state
) {
48 using blink::WebRTCPeerConnectionHandlerClient
;
50 case webrtc::PeerConnectionInterface::kIceGatheringNew
:
51 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
52 case webrtc::PeerConnectionInterface::kIceGatheringGathering
:
53 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateGathering
;
54 case webrtc::PeerConnectionInterface::kIceGatheringComplete
:
55 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateComplete
;
58 return WebRTCPeerConnectionHandlerClient::ICEGatheringStateNew
;
62 static blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState
63 GetWebKitIceConnectionState(
64 webrtc::PeerConnectionInterface::IceConnectionState ice_state
) {
65 using blink::WebRTCPeerConnectionHandlerClient
;
67 case webrtc::PeerConnectionInterface::kIceConnectionNew
:
68 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateStarting
;
69 case webrtc::PeerConnectionInterface::kIceConnectionChecking
:
70 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateChecking
;
71 case webrtc::PeerConnectionInterface::kIceConnectionConnected
:
72 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateConnected
;
73 case webrtc::PeerConnectionInterface::kIceConnectionCompleted
:
74 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateCompleted
;
75 case webrtc::PeerConnectionInterface::kIceConnectionFailed
:
76 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateFailed
;
77 case webrtc::PeerConnectionInterface::kIceConnectionDisconnected
:
78 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateDisconnected
;
79 case webrtc::PeerConnectionInterface::kIceConnectionClosed
:
80 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
83 return WebRTCPeerConnectionHandlerClient::ICEConnectionStateClosed
;
87 static blink::WebRTCPeerConnectionHandlerClient::SignalingState
88 GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state
) {
89 using blink::WebRTCPeerConnectionHandlerClient
;
91 case webrtc::PeerConnectionInterface::kStable
:
92 return WebRTCPeerConnectionHandlerClient::SignalingStateStable
;
93 case webrtc::PeerConnectionInterface::kHaveLocalOffer
:
94 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalOffer
;
95 case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer
:
96 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveLocalPrAnswer
;
97 case webrtc::PeerConnectionInterface::kHaveRemoteOffer
:
98 return WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemoteOffer
;
99 case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer
:
101 WebRTCPeerConnectionHandlerClient::SignalingStateHaveRemotePrAnswer
;
102 case webrtc::PeerConnectionInterface::kClosed
:
103 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
106 return WebRTCPeerConnectionHandlerClient::SignalingStateClosed
;
110 static blink::WebRTCSessionDescription
111 CreateWebKitSessionDescription(
112 const webrtc::SessionDescriptionInterface
* native_desc
) {
113 blink::WebRTCSessionDescription description
;
115 LOG(ERROR
) << "Native session description is null.";
120 if (!native_desc
->ToString(&sdp
)) {
121 LOG(ERROR
) << "Failed to get SDP string of native session description.";
125 description
.initialize(base::UTF8ToUTF16(native_desc
->type()),
126 base::UTF8ToUTF16(sdp
));
130 // Converter functions from WebKit types to libjingle types.
132 static void GetNativeIceServers(
133 const blink::WebRTCConfiguration
& server_configuration
,
134 webrtc::PeerConnectionInterface::IceServers
* servers
) {
135 if (server_configuration
.isNull() || !servers
)
137 for (size_t i
= 0; i
< server_configuration
.numberOfServers(); ++i
) {
138 webrtc::PeerConnectionInterface::IceServer server
;
139 const blink::WebRTCICEServer
& webkit_server
=
140 server_configuration
.server(i
);
141 server
.username
= base::UTF16ToUTF8(webkit_server
.username());
142 server
.password
= base::UTF16ToUTF8(webkit_server
.credential());
143 server
.uri
= webkit_server
.uri().spec();
144 servers
->push_back(server
);
148 class SessionDescriptionRequestTracker
{
150 SessionDescriptionRequestTracker(RTCPeerConnectionHandler
* handler
,
151 PeerConnectionTracker::Action action
)
152 : handler_(handler
), action_(action
) {}
154 void TrackOnSuccess(const webrtc::SessionDescriptionInterface
* desc
) {
157 desc
->ToString(&value
);
158 value
= "type: " + desc
->type() + ", sdp: " + value
;
160 if (handler_
->peer_connection_tracker())
161 handler_
->peer_connection_tracker()->TrackSessionDescriptionCallback(
162 handler_
, action_
, "OnSuccess", value
);
165 void TrackOnFailure(const std::string
& error
) {
166 if (handler_
->peer_connection_tracker())
167 handler_
->peer_connection_tracker()->TrackSessionDescriptionCallback(
168 handler_
, action_
, "OnFailure", error
);
172 RTCPeerConnectionHandler
* handler_
;
173 PeerConnectionTracker::Action action_
;
176 // Class mapping responses from calls to libjingle CreateOffer/Answer and
177 // the blink::WebRTCSessionDescriptionRequest.
178 class CreateSessionDescriptionRequest
179 : public webrtc::CreateSessionDescriptionObserver
{
181 explicit CreateSessionDescriptionRequest(
182 const blink::WebRTCSessionDescriptionRequest
& request
,
183 RTCPeerConnectionHandler
* handler
,
184 PeerConnectionTracker::Action action
)
185 : webkit_request_(request
), tracker_(handler
, action
) {}
187 virtual void OnSuccess(webrtc::SessionDescriptionInterface
* desc
) OVERRIDE
{
188 tracker_
.TrackOnSuccess(desc
);
189 webkit_request_
.requestSucceeded(CreateWebKitSessionDescription(desc
));
192 virtual void OnFailure(const std::string
& error
) OVERRIDE
{
193 tracker_
.TrackOnFailure(error
);
194 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
198 virtual ~CreateSessionDescriptionRequest() {}
201 blink::WebRTCSessionDescriptionRequest webkit_request_
;
202 SessionDescriptionRequestTracker tracker_
;
205 // Class mapping responses from calls to libjingle
206 // SetLocalDescription/SetRemoteDescription and a blink::WebRTCVoidRequest.
207 class SetSessionDescriptionRequest
208 : public webrtc::SetSessionDescriptionObserver
{
210 explicit SetSessionDescriptionRequest(
211 const blink::WebRTCVoidRequest
& request
,
212 RTCPeerConnectionHandler
* handler
,
213 PeerConnectionTracker::Action action
)
214 : webkit_request_(request
), tracker_(handler
, action
) {}
216 virtual void OnSuccess() OVERRIDE
{
217 tracker_
.TrackOnSuccess(NULL
);
218 webkit_request_
.requestSucceeded();
220 virtual void OnFailure(const std::string
& error
) OVERRIDE
{
221 tracker_
.TrackOnFailure(error
);
222 webkit_request_
.requestFailed(base::UTF8ToUTF16(error
));
226 virtual ~SetSessionDescriptionRequest() {}
229 blink::WebRTCVoidRequest webkit_request_
;
230 SessionDescriptionRequestTracker tracker_
;
233 // Class mapping responses from calls to libjingle
234 // GetStats into a blink::WebRTCStatsCallback.
235 class StatsResponse
: public webrtc::StatsObserver
{
237 explicit StatsResponse(const scoped_refptr
<LocalRTCStatsRequest
>& request
)
238 : request_(request
.get()), response_(request_
->createResponse().get()) {
239 // Measure the overall time it takes to satisfy a getStats request.
240 TRACE_EVENT_ASYNC_BEGIN0("webrtc", "getStats_Native", this);
243 virtual void OnComplete(
244 const std::vector
<webrtc::StatsReport
>& reports
) OVERRIDE
{
245 TRACE_EVENT0("webrtc", "StatsResponse::OnComplete")
246 for (std::vector
<webrtc::StatsReport
>::const_iterator it
= reports
.begin();
247 it
!= reports
.end(); ++it
) {
248 if (it
->values
.size() > 0) {
253 // Record the getSync operation as done before calling into Blink so that
254 // we don't skew the perf measurements of the native code with whatever the
255 // callback might be doing.
256 TRACE_EVENT_ASYNC_END0("webrtc", "getStats_Native", this);
258 request_
->requestSucceeded(response_
);
262 void AddReport(const webrtc::StatsReport
& report
) {
263 int idx
= response_
->addReport(blink::WebString::fromUTF8(report
.id
),
264 blink::WebString::fromUTF8(report
.type
),
266 for (webrtc::StatsReport::Values::const_iterator value_it
=
267 report
.values
.begin();
268 value_it
!= report
.values
.end(); ++value_it
) {
269 AddStatistic(idx
, value_it
->name
, value_it
->value
);
273 void AddStatistic(int idx
, const std::string
& name
,
274 const std::string
& value
) {
275 response_
->addStatistic(idx
,
276 blink::WebString::fromUTF8(name
),
277 blink::WebString::fromUTF8(value
));
280 talk_base::scoped_refptr
<LocalRTCStatsRequest
> request_
;
281 talk_base::scoped_refptr
<LocalRTCStatsResponse
> response_
;
284 // Implementation of LocalRTCStatsRequest.
285 LocalRTCStatsRequest::LocalRTCStatsRequest(blink::WebRTCStatsRequest impl
)
290 LocalRTCStatsRequest::LocalRTCStatsRequest() {}
291 LocalRTCStatsRequest::~LocalRTCStatsRequest() {}
293 bool LocalRTCStatsRequest::hasSelector() const {
294 return impl_
.hasSelector();
297 blink::WebMediaStreamTrack
LocalRTCStatsRequest::component() const {
298 return impl_
.component();
301 scoped_refptr
<LocalRTCStatsResponse
> LocalRTCStatsRequest::createResponse() {
303 response_
= new talk_base::RefCountedObject
<LocalRTCStatsResponse
>(
304 impl_
.createResponse());
305 return response_
.get();
308 void LocalRTCStatsRequest::requestSucceeded(
309 const LocalRTCStatsResponse
* response
) {
310 impl_
.requestSucceeded(response
->webKitStatsResponse());
313 // Implementation of LocalRTCStatsResponse.
314 blink::WebRTCStatsResponse
LocalRTCStatsResponse::webKitStatsResponse() const {
318 size_t LocalRTCStatsResponse::addReport(blink::WebString type
,
321 return impl_
.addReport(type
, id
, timestamp
);
324 void LocalRTCStatsResponse::addStatistic(size_t report
,
325 blink::WebString name
,
326 blink::WebString value
) {
327 impl_
.addStatistic(report
, name
, value
);
332 class PeerConnectionUMAObserver
: public webrtc::UMAObserver
{
334 PeerConnectionUMAObserver() {}
335 virtual ~PeerConnectionUMAObserver() {}
337 virtual void IncrementCounter(
338 webrtc::PeerConnectionUMAMetricsCounter counter
) OVERRIDE
{
339 UMA_HISTOGRAM_ENUMERATION("WebRTC.PeerConnection.IPMetrics",
344 virtual void AddHistogramSample(
345 webrtc::PeerConnectionUMAMetricsName type
, int value
) OVERRIDE
{
347 case webrtc::kTimeToConnect
:
348 UMA_HISTOGRAM_MEDIUM_TIMES(
349 "WebRTC.PeerConnection.TimeToConnect",
350 base::TimeDelta::FromMilliseconds(value
));
352 case webrtc::kNetworkInterfaces_IPv4
:
353 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces",
356 case webrtc::kNetworkInterfaces_IPv6
:
357 UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces",
366 base::LazyInstance
<std::set
<RTCPeerConnectionHandler
*> >::Leaky
367 g_peer_connection_handlers
= LAZY_INSTANCE_INITIALIZER
;
371 RTCPeerConnectionHandler::RTCPeerConnectionHandler(
372 blink::WebRTCPeerConnectionHandlerClient
* client
,
373 PeerConnectionDependencyFactory
* dependency_factory
)
375 dependency_factory_(dependency_factory
),
377 peer_connection_tracker_(NULL
),
378 num_data_channels_created_(0) {
379 g_peer_connection_handlers
.Get().insert(this);
382 RTCPeerConnectionHandler::~RTCPeerConnectionHandler() {
383 g_peer_connection_handlers
.Get().erase(this);
384 if (peer_connection_tracker_
)
385 peer_connection_tracker_
->UnregisterPeerConnection(this);
386 STLDeleteValues(&remote_streams_
);
388 UMA_HISTOGRAM_COUNTS_10000(
389 "WebRTC.NumDataChannelsPerPeerConnection", num_data_channels_created_
);
393 void RTCPeerConnectionHandler::DestructAllHandlers() {
394 std::set
<RTCPeerConnectionHandler
*> handlers(
395 g_peer_connection_handlers
.Get().begin(),
396 g_peer_connection_handlers
.Get().end());
397 for (std::set
<RTCPeerConnectionHandler
*>::iterator handler
= handlers
.begin();
398 handler
!= handlers
.end();
400 (*handler
)->client_
->releasePeerConnectionHandler();
404 void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame
* frame
) {
409 bool RTCPeerConnectionHandler::initialize(
410 const blink::WebRTCConfiguration
& server_configuration
,
411 const blink::WebMediaConstraints
& options
) {
414 peer_connection_tracker_
=
415 RenderThreadImpl::current()->peer_connection_tracker();
417 webrtc::PeerConnectionInterface::IceServers servers
;
418 GetNativeIceServers(server_configuration
, &servers
);
420 RTCMediaConstraints
constraints(options
);
422 native_peer_connection_
=
423 dependency_factory_
->CreatePeerConnection(
424 servers
, &constraints
, frame_
, this);
425 if (!native_peer_connection_
.get()) {
426 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
429 if (peer_connection_tracker_
)
430 peer_connection_tracker_
->RegisterPeerConnection(
431 this, servers
, constraints
, frame_
);
433 uma_observer_
= new talk_base::RefCountedObject
<PeerConnectionUMAObserver
>();
434 native_peer_connection_
->RegisterUMAObserver(uma_observer_
.get());
438 bool RTCPeerConnectionHandler::InitializeForTest(
439 const blink::WebRTCConfiguration
& server_configuration
,
440 const blink::WebMediaConstraints
& options
,
441 PeerConnectionTracker
* peer_connection_tracker
) {
442 webrtc::PeerConnectionInterface::IceServers servers
;
443 GetNativeIceServers(server_configuration
, &servers
);
445 RTCMediaConstraints
constraints(options
);
446 native_peer_connection_
=
447 dependency_factory_
->CreatePeerConnection(
448 servers
, &constraints
, NULL
, this);
449 if (!native_peer_connection_
.get()) {
450 LOG(ERROR
) << "Failed to initialize native PeerConnection.";
453 peer_connection_tracker_
= peer_connection_tracker
;
457 void RTCPeerConnectionHandler::createOffer(
458 const blink::WebRTCSessionDescriptionRequest
& request
,
459 const blink::WebMediaConstraints
& options
) {
460 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
461 new talk_base::RefCountedObject
<CreateSessionDescriptionRequest
>(
462 request
, this, PeerConnectionTracker::ACTION_CREATE_OFFER
));
463 RTCMediaConstraints
constraints(options
);
464 native_peer_connection_
->CreateOffer(description_request
.get(), &constraints
);
466 if (peer_connection_tracker_
)
467 peer_connection_tracker_
->TrackCreateOffer(this, constraints
);
470 void RTCPeerConnectionHandler::createAnswer(
471 const blink::WebRTCSessionDescriptionRequest
& request
,
472 const blink::WebMediaConstraints
& options
) {
473 scoped_refptr
<CreateSessionDescriptionRequest
> description_request(
474 new talk_base::RefCountedObject
<CreateSessionDescriptionRequest
>(
475 request
, this, PeerConnectionTracker::ACTION_CREATE_ANSWER
));
476 RTCMediaConstraints
constraints(options
);
477 native_peer_connection_
->CreateAnswer(description_request
.get(),
480 if (peer_connection_tracker_
)
481 peer_connection_tracker_
->TrackCreateAnswer(this, constraints
);
484 void RTCPeerConnectionHandler::setLocalDescription(
485 const blink::WebRTCVoidRequest
& request
,
486 const blink::WebRTCSessionDescription
& description
) {
487 webrtc::SdpParseError error
;
488 webrtc::SessionDescriptionInterface
* native_desc
=
489 CreateNativeSessionDescription(description
, &error
);
491 std::string reason_str
= "Failed to parse SessionDescription. ";
492 reason_str
.append(error
.line
);
493 reason_str
.append(" ");
494 reason_str
.append(error
.description
);
495 LOG(ERROR
) << reason_str
;
496 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
499 if (peer_connection_tracker_
)
500 peer_connection_tracker_
->TrackSetSessionDescription(
501 this, description
, PeerConnectionTracker::SOURCE_LOCAL
);
503 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
504 new talk_base::RefCountedObject
<SetSessionDescriptionRequest
>(
505 request
, this, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION
));
506 native_peer_connection_
->SetLocalDescription(set_request
.get(), native_desc
);
509 void RTCPeerConnectionHandler::setRemoteDescription(
510 const blink::WebRTCVoidRequest
& request
,
511 const blink::WebRTCSessionDescription
& description
) {
512 webrtc::SdpParseError error
;
513 webrtc::SessionDescriptionInterface
* native_desc
=
514 CreateNativeSessionDescription(description
, &error
);
516 std::string reason_str
= "Failed to parse SessionDescription. ";
517 reason_str
.append(error
.line
);
518 reason_str
.append(" ");
519 reason_str
.append(error
.description
);
520 LOG(ERROR
) << reason_str
;
521 request
.requestFailed(blink::WebString::fromUTF8(reason_str
));
524 if (peer_connection_tracker_
)
525 peer_connection_tracker_
->TrackSetSessionDescription(
526 this, description
, PeerConnectionTracker::SOURCE_REMOTE
);
528 scoped_refptr
<SetSessionDescriptionRequest
> set_request(
529 new talk_base::RefCountedObject
<SetSessionDescriptionRequest
>(
530 request
, this, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION
));
531 native_peer_connection_
->SetRemoteDescription(set_request
.get(), native_desc
);
534 blink::WebRTCSessionDescription
535 RTCPeerConnectionHandler::localDescription() {
536 const webrtc::SessionDescriptionInterface
* native_desc
=
537 native_peer_connection_
->local_description();
538 blink::WebRTCSessionDescription description
=
539 CreateWebKitSessionDescription(native_desc
);
543 blink::WebRTCSessionDescription
544 RTCPeerConnectionHandler::remoteDescription() {
545 const webrtc::SessionDescriptionInterface
* native_desc
=
546 native_peer_connection_
->remote_description();
547 blink::WebRTCSessionDescription description
=
548 CreateWebKitSessionDescription(native_desc
);
552 bool RTCPeerConnectionHandler::updateICE(
553 const blink::WebRTCConfiguration
& server_configuration
,
554 const blink::WebMediaConstraints
& options
) {
555 webrtc::PeerConnectionInterface::IceServers servers
;
556 GetNativeIceServers(server_configuration
, &servers
);
557 RTCMediaConstraints
constraints(options
);
559 if (peer_connection_tracker_
)
560 peer_connection_tracker_
->TrackUpdateIce(this, servers
, constraints
);
562 return native_peer_connection_
->UpdateIce(servers
,
566 bool RTCPeerConnectionHandler::addICECandidate(
567 const blink::WebRTCVoidRequest
& request
,
568 const blink::WebRTCICECandidate
& candidate
) {
569 // Libjingle currently does not accept callbacks for addICECandidate.
570 // For that reason we are going to call callbacks from here.
571 bool result
= addICECandidate(candidate
);
572 base::MessageLoop::current()->PostTask(
574 base::Bind(&RTCPeerConnectionHandler::OnaddICECandidateResult
,
575 base::Unretained(this), request
, result
));
576 // On failure callback will be triggered.
580 bool RTCPeerConnectionHandler::addICECandidate(
581 const blink::WebRTCICECandidate
& candidate
) {
582 scoped_ptr
<webrtc::IceCandidateInterface
> native_candidate(
583 dependency_factory_
->CreateIceCandidate(
584 base::UTF16ToUTF8(candidate
.sdpMid()),
585 candidate
.sdpMLineIndex(),
586 base::UTF16ToUTF8(candidate
.candidate())));
587 if (!native_candidate
) {
588 LOG(ERROR
) << "Could not create native ICE candidate.";
593 native_peer_connection_
->AddIceCandidate(native_candidate
.get());
594 LOG_IF(ERROR
, !return_value
) << "Error processing ICE candidate.";
596 if (peer_connection_tracker_
)
597 peer_connection_tracker_
->TrackAddIceCandidate(
598 this, candidate
, PeerConnectionTracker::SOURCE_REMOTE
);
603 void RTCPeerConnectionHandler::OnaddICECandidateResult(
604 const blink::WebRTCVoidRequest
& webkit_request
, bool result
) {
606 // We don't have the actual error code from the libjingle, so for now
607 // using a generic error string.
608 return webkit_request
.requestFailed(
609 base::UTF8ToUTF16("Error processing ICE candidate"));
612 return webkit_request
.requestSucceeded();
615 bool RTCPeerConnectionHandler::addStream(
616 const blink::WebMediaStream
& stream
,
617 const blink::WebMediaConstraints
& options
) {
619 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
620 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
622 if ((*adapter_it
)->IsEqual(stream
)) {
623 DVLOG(1) << "RTCPeerConnectionHandler::addStream called with the same "
624 << "stream twice. id=" << stream
.id().utf8();
629 if (peer_connection_tracker_
)
630 peer_connection_tracker_
->TrackAddStream(
631 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
633 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
635 WebRtcMediaStreamAdapter
* adapter
=
636 new WebRtcMediaStreamAdapter(stream
, dependency_factory_
);
637 local_streams_
.push_back(adapter
);
639 webrtc::MediaStreamInterface
* webrtc_stream
= adapter
->webrtc_media_stream();
640 track_metrics_
.AddStream(MediaStreamTrackMetrics::SENT_STREAM
,
643 RTCMediaConstraints
constraints(options
);
644 return native_peer_connection_
->AddStream(webrtc_stream
, &constraints
);
647 void RTCPeerConnectionHandler::removeStream(
648 const blink::WebMediaStream
& stream
) {
649 // Find the webrtc stream.
650 scoped_refptr
<webrtc::MediaStreamInterface
> webrtc_stream
;
651 for (ScopedVector
<WebRtcMediaStreamAdapter
>::iterator adapter_it
=
652 local_streams_
.begin(); adapter_it
!= local_streams_
.end();
654 if ((*adapter_it
)->IsEqual(stream
)) {
655 webrtc_stream
= (*adapter_it
)->webrtc_media_stream();
656 local_streams_
.erase(adapter_it
);
660 DCHECK(webrtc_stream
);
661 native_peer_connection_
->RemoveStream(webrtc_stream
);
663 if (peer_connection_tracker_
)
664 peer_connection_tracker_
->TrackRemoveStream(
665 this, stream
, PeerConnectionTracker::SOURCE_LOCAL
);
666 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
667 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM
,
671 void RTCPeerConnectionHandler::getStats(
672 const blink::WebRTCStatsRequest
& request
) {
673 scoped_refptr
<LocalRTCStatsRequest
> inner_request(
674 new talk_base::RefCountedObject
<LocalRTCStatsRequest
>(request
));
675 getStats(inner_request
.get());
678 void RTCPeerConnectionHandler::getStats(LocalRTCStatsRequest
* request
) {
679 talk_base::scoped_refptr
<webrtc::StatsObserver
> observer(
680 new talk_base::RefCountedObject
<StatsResponse
>(request
));
681 webrtc::MediaStreamTrackInterface
* track
= NULL
;
682 if (request
->hasSelector()) {
683 blink::WebMediaStreamSource::Type type
=
684 request
->component().source().type();
685 std::string track_id
= request
->component().id().utf8();
686 if (type
== blink::WebMediaStreamSource::TypeAudio
) {
688 native_peer_connection_
->local_streams()->FindAudioTrack(track_id
);
691 native_peer_connection_
->remote_streams()->FindAudioTrack(track_id
);
694 DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo
, type
);
696 native_peer_connection_
->local_streams()->FindVideoTrack(track_id
);
699 native_peer_connection_
->remote_streams()->FindVideoTrack(track_id
);
703 DVLOG(1) << "GetStats: Track not found.";
704 // TODO(hta): Consider how to get an error back.
705 std::vector
<webrtc::StatsReport
> no_reports
;
706 observer
->OnComplete(no_reports
);
712 webrtc::PeerConnectionInterface::kStatsOutputLevelStandard
);
715 void RTCPeerConnectionHandler::GetStats(
716 webrtc::StatsObserver
* observer
,
717 webrtc::MediaStreamTrackInterface
* track
,
718 webrtc::PeerConnectionInterface::StatsOutputLevel level
) {
719 TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::GetStats");
720 if (!native_peer_connection_
->GetStats(observer
, track
, level
)) {
721 DVLOG(1) << "GetStats failed.";
722 // TODO(hta): Consider how to get an error back.
723 std::vector
<webrtc::StatsReport
> no_reports
;
724 observer
->OnComplete(no_reports
);
729 blink::WebRTCDataChannelHandler
* RTCPeerConnectionHandler::createDataChannel(
730 const blink::WebString
& label
, const blink::WebRTCDataChannelInit
& init
) {
731 DVLOG(1) << "createDataChannel label " << base::UTF16ToUTF8(label
);
733 webrtc::DataChannelInit config
;
734 // TODO(jiayl): remove the deprecated reliable field once Libjingle is updated
736 config
.reliable
= false;
738 config
.ordered
= init
.ordered
;
739 config
.negotiated
= init
.negotiated
;
740 config
.maxRetransmits
= init
.maxRetransmits
;
741 config
.maxRetransmitTime
= init
.maxRetransmitTime
;
742 config
.protocol
= base::UTF16ToUTF8(init
.protocol
);
744 talk_base::scoped_refptr
<webrtc::DataChannelInterface
> webrtc_channel(
745 native_peer_connection_
->CreateDataChannel(base::UTF16ToUTF8(label
),
747 if (!webrtc_channel
) {
748 DLOG(ERROR
) << "Could not create native data channel.";
751 if (peer_connection_tracker_
)
752 peer_connection_tracker_
->TrackCreateDataChannel(
753 this, webrtc_channel
.get(), PeerConnectionTracker::SOURCE_LOCAL
);
755 ++num_data_channels_created_
;
757 return new RtcDataChannelHandler(webrtc_channel
);
760 blink::WebRTCDTMFSenderHandler
* RTCPeerConnectionHandler::createDTMFSender(
761 const blink::WebMediaStreamTrack
& track
) {
762 DVLOG(1) << "createDTMFSender.";
764 MediaStreamTrack
* native_track
= MediaStreamTrack::GetTrack(track
);
766 track
.source().type() != blink::WebMediaStreamSource::TypeAudio
) {
767 DLOG(ERROR
) << "Could not create DTMF sender from a non-audio track.";
771 webrtc::AudioTrackInterface
* audio_track
= native_track
->GetAudioAdapter();
772 talk_base::scoped_refptr
<webrtc::DtmfSenderInterface
> sender(
773 native_peer_connection_
->CreateDtmfSender(audio_track
));
775 DLOG(ERROR
) << "Could not create native DTMF sender.";
778 if (peer_connection_tracker_
)
779 peer_connection_tracker_
->TrackCreateDTMFSender(this, track
);
781 return new RtcDtmfSenderHandler(sender
);
784 void RTCPeerConnectionHandler::stop() {
785 DVLOG(1) << "RTCPeerConnectionHandler::stop";
787 if (peer_connection_tracker_
)
788 peer_connection_tracker_
->TrackStop(this);
789 native_peer_connection_
->Close();
792 void RTCPeerConnectionHandler::OnError() {
793 // TODO(perkj): Implement.
797 void RTCPeerConnectionHandler::OnSignalingChange(
798 webrtc::PeerConnectionInterface::SignalingState new_state
) {
799 blink::WebRTCPeerConnectionHandlerClient::SignalingState state
=
800 GetWebKitSignalingState(new_state
);
801 if (peer_connection_tracker_
)
802 peer_connection_tracker_
->TrackSignalingStateChange(this, state
);
803 client_
->didChangeSignalingState(state
);
806 // Called any time the IceConnectionState changes
807 void RTCPeerConnectionHandler::OnIceConnectionChange(
808 webrtc::PeerConnectionInterface::IceConnectionState new_state
) {
809 track_metrics_
.IceConnectionChange(new_state
);
810 blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state
=
811 GetWebKitIceConnectionState(new_state
);
812 if (peer_connection_tracker_
)
813 peer_connection_tracker_
->TrackIceConnectionStateChange(this, state
);
814 client_
->didChangeICEConnectionState(state
);
817 // Called any time the IceGatheringState changes
818 void RTCPeerConnectionHandler::OnIceGatheringChange(
819 webrtc::PeerConnectionInterface::IceGatheringState new_state
) {
820 if (new_state
== webrtc::PeerConnectionInterface::kIceGatheringComplete
) {
821 // If ICE gathering is completed, generate a NULL ICE candidate,
822 // to signal end of candidates.
823 blink::WebRTCICECandidate null_candidate
;
824 client_
->didGenerateICECandidate(null_candidate
);
827 blink::WebRTCPeerConnectionHandlerClient::ICEGatheringState state
=
828 GetWebKitIceGatheringState(new_state
);
829 if (peer_connection_tracker_
)
830 peer_connection_tracker_
->TrackIceGatheringStateChange(this, state
);
831 client_
->didChangeICEGatheringState(state
);
834 void RTCPeerConnectionHandler::OnAddStream(
835 webrtc::MediaStreamInterface
* stream_interface
) {
836 DCHECK(stream_interface
);
837 DCHECK(remote_streams_
.find(stream_interface
) == remote_streams_
.end());
839 RemoteMediaStreamImpl
* remote_stream
=
840 new RemoteMediaStreamImpl(stream_interface
);
841 remote_streams_
.insert(
842 std::pair
<webrtc::MediaStreamInterface
*, RemoteMediaStreamImpl
*> (
843 stream_interface
, remote_stream
));
845 if (peer_connection_tracker_
)
846 peer_connection_tracker_
->TrackAddStream(
847 this, remote_stream
->webkit_stream(),
848 PeerConnectionTracker::SOURCE_REMOTE
);
850 PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
852 track_metrics_
.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
855 client_
->didAddRemoteStream(remote_stream
->webkit_stream());
858 void RTCPeerConnectionHandler::OnRemoveStream(
859 webrtc::MediaStreamInterface
* stream_interface
) {
860 DCHECK(stream_interface
);
861 RemoteStreamMap::iterator it
= remote_streams_
.find(stream_interface
);
862 if (it
== remote_streams_
.end()) {
863 NOTREACHED() << "Stream not found";
867 track_metrics_
.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM
,
869 PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
871 scoped_ptr
<RemoteMediaStreamImpl
> remote_stream(it
->second
);
872 const blink::WebMediaStream
& webkit_stream
= remote_stream
->webkit_stream();
873 DCHECK(!webkit_stream
.isNull());
874 remote_streams_
.erase(it
);
876 if (peer_connection_tracker_
)
877 peer_connection_tracker_
->TrackRemoveStream(
878 this, webkit_stream
, PeerConnectionTracker::SOURCE_REMOTE
);
880 client_
->didRemoveRemoteStream(webkit_stream
);
883 void RTCPeerConnectionHandler::OnIceCandidate(
884 const webrtc::IceCandidateInterface
* candidate
) {
887 if (!candidate
->ToString(&sdp
)) {
888 NOTREACHED() << "OnIceCandidate: Could not get SDP string.";
891 blink::WebRTCICECandidate web_candidate
;
892 web_candidate
.initialize(base::UTF8ToUTF16(sdp
),
893 base::UTF8ToUTF16(candidate
->sdp_mid()),
894 candidate
->sdp_mline_index());
895 if (peer_connection_tracker_
)
896 peer_connection_tracker_
->TrackAddIceCandidate(
897 this, web_candidate
, PeerConnectionTracker::SOURCE_LOCAL
);
899 client_
->didGenerateICECandidate(web_candidate
);
902 void RTCPeerConnectionHandler::OnDataChannel(
903 webrtc::DataChannelInterface
* data_channel
) {
904 if (peer_connection_tracker_
)
905 peer_connection_tracker_
->TrackCreateDataChannel(
906 this, data_channel
, PeerConnectionTracker::SOURCE_REMOTE
);
908 DVLOG(1) << "RTCPeerConnectionHandler::OnDataChannel "
909 << data_channel
->label();
910 client_
->didAddRemoteDataChannel(new RtcDataChannelHandler(data_channel
));
913 void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
914 if (peer_connection_tracker_
)
915 peer_connection_tracker_
->TrackOnRenegotiationNeeded(this);
916 client_
->negotiationNeeded();
919 PeerConnectionTracker
* RTCPeerConnectionHandler::peer_connection_tracker() {
920 return peer_connection_tracker_
;
923 webrtc::SessionDescriptionInterface
*
924 RTCPeerConnectionHandler::CreateNativeSessionDescription(
925 const blink::WebRTCSessionDescription
& description
,
926 webrtc::SdpParseError
* error
) {
927 std::string sdp
= base::UTF16ToUTF8(description
.sdp());
928 std::string type
= base::UTF16ToUTF8(description
.type());
929 webrtc::SessionDescriptionInterface
* native_desc
=
930 dependency_factory_
->CreateSessionDescription(type
, sdp
, error
);
932 LOG_IF(ERROR
, !native_desc
) << "Failed to create native session description."
933 << " Type: " << type
<< " SDP: " << sdp
;
938 } // namespace content