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