Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: webrtc/api/peerconnection.cc

Issue 1975453002: Add PeerConnection IsClosed check. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Inject the TransportController to PeerConnection. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | webrtc/api/peerconnectionfactory.h » ('j') | webrtc/api/peerconnectionfactory.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 return false; 584 return false;
585 } 585 }
586 586
587 media_controller_.reset( 587 media_controller_.reset(
588 factory_->CreateMediaController(configuration.media_config)); 588 factory_->CreateMediaController(configuration.media_config));
589 589
590 session_.reset( 590 session_.reset(
591 new WebRtcSession(media_controller_.get(), factory_->network_thread(), 591 new WebRtcSession(media_controller_.get(), factory_->network_thread(),
592 factory_->worker_thread(), factory_->signaling_thread(), 592 factory_->worker_thread(), factory_->signaling_thread(),
593 port_allocator_.get())); 593 port_allocator_.get()));
594
595 session_->SetTransportController(
596 factory_->CreateTransportController(port_allocator_.get()));
594 stats_.reset(new StatsCollector(this)); 597 stats_.reset(new StatsCollector(this));
595 598
596 // Initialize the WebRtcSession. It creates transport channels etc. 599 // Initialize the WebRtcSession. It creates transport channels etc.
597 if (!session_->Initialize(factory_->options(), std::move(dtls_identity_store), 600 if (!session_->Initialize(factory_->options(), std::move(dtls_identity_store),
598 configuration)) { 601 configuration)) {
599 return false; 602 return false;
600 } 603 }
601 604
602 // Register PeerConnection as receiver of local ice candidates. 605 // Register PeerConnection as receiver of local ice candidates.
603 // All the callbacks will be posted to the application from PeerConnection. 606 // All the callbacks will be posted to the application from PeerConnection.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 (*it)->Stop(); 757 (*it)->Stop();
755 senders_.erase(it); 758 senders_.erase(it);
756 759
757 observer_->OnRenegotiationNeeded(); 760 observer_->OnRenegotiationNeeded();
758 return true; 761 return true;
759 } 762 }
760 763
761 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( 764 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
762 AudioTrackInterface* track) { 765 AudioTrackInterface* track) {
763 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender"); 766 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
767 if (IsClosed()) {
768 return nullptr;
769 }
764 if (!track) { 770 if (!track) {
765 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL."; 771 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL.";
766 return NULL; 772 return NULL;
767 } 773 }
768 if (!local_streams_->FindAudioTrack(track->id())) { 774 if (!local_streams_->FindAudioTrack(track->id())) {
769 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track."; 775 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track.";
770 return NULL; 776 return NULL;
771 } 777 }
772 778
773 rtc::scoped_refptr<DtmfSenderInterface> sender( 779 rtc::scoped_refptr<DtmfSenderInterface> sender(
774 DtmfSender::Create(track, signaling_thread(), session_.get())); 780 DtmfSender::Create(track, signaling_thread(), session_.get()));
775 if (!sender.get()) { 781 if (!sender.get()) {
776 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; 782 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create.";
777 return NULL; 783 return NULL;
778 } 784 }
779 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); 785 return DtmfSenderProxy::Create(signaling_thread(), sender.get());
780 } 786 }
781 787
782 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender( 788 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
783 const std::string& kind, 789 const std::string& kind,
784 const std::string& stream_id) { 790 const std::string& stream_id) {
785 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender"); 791 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
792 if (IsClosed()) {
793 return nullptr;
794 }
786 rtc::scoped_refptr<RtpSenderInterface> new_sender; 795 rtc::scoped_refptr<RtpSenderInterface> new_sender;
787 if (kind == MediaStreamTrackInterface::kAudioKind) { 796 if (kind == MediaStreamTrackInterface::kAudioKind) {
788 new_sender = RtpSenderProxy::Create( 797 new_sender = RtpSenderProxy::Create(
789 signaling_thread(), new AudioRtpSender(session_.get(), stats_.get())); 798 signaling_thread(), new AudioRtpSender(session_.get(), stats_.get()));
790 } else if (kind == MediaStreamTrackInterface::kVideoKind) { 799 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
791 new_sender = RtpSenderProxy::Create(signaling_thread(), 800 new_sender = RtpSenderProxy::Create(signaling_thread(),
792 new VideoRtpSender(session_.get())); 801 new VideoRtpSender(session_.get()));
793 } else { 802 } else {
794 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind; 803 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
795 return new_sender; 804 return new_sender;
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 return; 987 return;
979 } 988 }
980 989
981 session_->CreateAnswer(observer, session_options); 990 session_->CreateAnswer(observer, session_options);
982 } 991 }
983 992
984 void PeerConnection::SetLocalDescription( 993 void PeerConnection::SetLocalDescription(
985 SetSessionDescriptionObserver* observer, 994 SetSessionDescriptionObserver* observer,
986 SessionDescriptionInterface* desc) { 995 SessionDescriptionInterface* desc) {
987 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); 996 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
997 if (IsClosed()) {
998 return;
999 }
988 if (!VERIFY(observer != nullptr)) { 1000 if (!VERIFY(observer != nullptr)) {
989 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; 1001 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL.";
990 return; 1002 return;
991 } 1003 }
992 if (!desc) { 1004 if (!desc) {
993 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); 1005 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
994 return; 1006 return;
995 } 1007 }
996 // Update stats here so that we have the most recent stats for tracks and 1008 // Update stats here so that we have the most recent stats for tracks and
997 // streams that might be removed by updating the session description. 1009 // streams that might be removed by updating the session description.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 // MaybeStartGathering needs to be called after posting 1068 // MaybeStartGathering needs to be called after posting
1057 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates 1069 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
1058 // before signaling that SetLocalDescription completed. 1070 // before signaling that SetLocalDescription completed.
1059 session_->MaybeStartGathering(); 1071 session_->MaybeStartGathering();
1060 } 1072 }
1061 1073
1062 void PeerConnection::SetRemoteDescription( 1074 void PeerConnection::SetRemoteDescription(
1063 SetSessionDescriptionObserver* observer, 1075 SetSessionDescriptionObserver* observer,
1064 SessionDescriptionInterface* desc) { 1076 SessionDescriptionInterface* desc) {
1065 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription"); 1077 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription");
1078 if (IsClosed()) {
1079 return;
1080 }
1066 if (!VERIFY(observer != nullptr)) { 1081 if (!VERIFY(observer != nullptr)) {
1067 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL."; 1082 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL.";
1068 return; 1083 return;
1069 } 1084 }
1070 if (!desc) { 1085 if (!desc) {
1071 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); 1086 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
1072 return; 1087 return;
1073 } 1088 }
1074 // Update stats here so that we have the most recent stats for tracks and 1089 // Update stats here so that we have the most recent stats for tracks and
1075 // streams that might be removed by updating the session description. 1090 // streams that might be removed by updating the session description.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 } 1187 }
1173 1188
1174 // TODO(deadbeef): Shouldn't have to hop to the worker thread twice... 1189 // TODO(deadbeef): Shouldn't have to hop to the worker thread twice...
1175 session_->SetIceConfig(session_->ParseIceConfig(configuration)); 1190 session_->SetIceConfig(session_->ParseIceConfig(configuration));
1176 return true; 1191 return true;
1177 } 1192 }
1178 1193
1179 bool PeerConnection::AddIceCandidate( 1194 bool PeerConnection::AddIceCandidate(
1180 const IceCandidateInterface* ice_candidate) { 1195 const IceCandidateInterface* ice_candidate) {
1181 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate"); 1196 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate");
1197 if (IsClosed()) {
1198 return false;
1199 }
1182 return session_->ProcessIceMessage(ice_candidate); 1200 return session_->ProcessIceMessage(ice_candidate);
1183 } 1201 }
1184 1202
1185 bool PeerConnection::RemoveIceCandidates( 1203 bool PeerConnection::RemoveIceCandidates(
1186 const std::vector<cricket::Candidate>& candidates) { 1204 const std::vector<cricket::Candidate>& candidates) {
1187 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates"); 1205 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
1188 return session_->RemoveRemoteIceCandidates(candidates); 1206 return session_->RemoveRemoteIceCandidates(candidates);
1189 } 1207 }
1190 1208
1191 void PeerConnection::RegisterUMAObserver(UMAObserver* observer) { 1209 void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
(...skipping 24 matching lines...) Expand all
1216 1234
1217 const SessionDescriptionInterface* PeerConnection::remote_description() const { 1235 const SessionDescriptionInterface* PeerConnection::remote_description() const {
1218 return session_->remote_description(); 1236 return session_->remote_description();
1219 } 1237 }
1220 1238
1221 void PeerConnection::Close() { 1239 void PeerConnection::Close() {
1222 TRACE_EVENT0("webrtc", "PeerConnection::Close"); 1240 TRACE_EVENT0("webrtc", "PeerConnection::Close");
1223 // Update stats here so that we have the most recent stats for tracks and 1241 // Update stats here so that we have the most recent stats for tracks and
1224 // streams before the channels are closed. 1242 // streams before the channels are closed.
1225 stats_->UpdateStats(kStatsOutputLevelStandard); 1243 stats_->UpdateStats(kStatsOutputLevelStandard);
1226
1227 session_->Close(); 1244 session_->Close();
1228 } 1245 }
1229 1246
1230 void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/, 1247 void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
1231 WebRtcSession::State state) { 1248 WebRtcSession::State state) {
1232 switch (state) { 1249 switch (state) {
1233 case WebRtcSession::STATE_INIT: 1250 case WebRtcSession::STATE_INIT:
1234 ChangeSignalingState(PeerConnectionInterface::kStable); 1251 ChangeSignalingState(PeerConnectionInterface::kStable);
1235 break; 1252 break;
1236 case WebRtcSession::STATE_SENTOFFER: 1253 case WebRtcSession::STATE_SENTOFFER:
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 RTC_DCHECK(signaling_thread()->IsCurrent()); 1374 RTC_DCHECK(signaling_thread()->IsCurrent());
1358 if (IsClosed()) { 1375 if (IsClosed()) {
1359 return; 1376 return;
1360 } 1377 }
1361 ice_gathering_state_ = new_state; 1378 ice_gathering_state_ = new_state;
1362 observer_->OnIceGatheringChange(ice_gathering_state_); 1379 observer_->OnIceGatheringChange(ice_gathering_state_);
1363 } 1380 }
1364 1381
1365 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) { 1382 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
1366 RTC_DCHECK(signaling_thread()->IsCurrent()); 1383 RTC_DCHECK(signaling_thread()->IsCurrent());
1384 if (IsClosed()) {
1385 return;
1386 }
1367 observer_->OnIceCandidate(candidate); 1387 observer_->OnIceCandidate(candidate);
1368 } 1388 }
1369 1389
1370 void PeerConnection::OnIceCandidatesRemoved( 1390 void PeerConnection::OnIceCandidatesRemoved(
1371 const std::vector<cricket::Candidate>& candidates) { 1391 const std::vector<cricket::Candidate>& candidates) {
1372 RTC_DCHECK(signaling_thread()->IsCurrent()); 1392 RTC_DCHECK(signaling_thread()->IsCurrent());
1393 if (IsClosed()) {
1394 return;
1395 }
1373 observer_->OnIceCandidatesRemoved(candidates); 1396 observer_->OnIceCandidatesRemoved(candidates);
1374 } 1397 }
1375 1398
1376 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) { 1399 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
1377 RTC_DCHECK(signaling_thread()->IsCurrent()); 1400 RTC_DCHECK(signaling_thread()->IsCurrent());
1401 if (IsClosed()) {
1402 return;
1403 }
1378 observer_->OnIceConnectionReceivingChange(receiving); 1404 observer_->OnIceConnectionReceivingChange(receiving);
1379 } 1405 }
1380 1406
1381 void PeerConnection::ChangeSignalingState( 1407 void PeerConnection::ChangeSignalingState(
1382 PeerConnectionInterface::SignalingState signaling_state) { 1408 PeerConnectionInterface::SignalingState signaling_state) {
1383 signaling_state_ = signaling_state; 1409 signaling_state_ = signaling_state;
1384 if (signaling_state == kClosed) { 1410 if (signaling_state == kClosed) {
1385 ice_connection_state_ = kIceConnectionClosed; 1411 ice_connection_state_ = kIceConnectionClosed;
1386 observer_->OnIceConnectionChange(ice_connection_state_); 1412 observer_->OnIceConnectionChange(ice_connection_state_);
1387 if (ice_gathering_state_ != kIceGatheringComplete) { 1413 if (ice_gathering_state_ != kIceGatheringComplete) {
1388 ice_gathering_state_ = kIceGatheringComplete; 1414 ice_gathering_state_ = kIceGatheringComplete;
1389 observer_->OnIceGatheringChange(ice_gathering_state_); 1415 observer_->OnIceGatheringChange(ice_gathering_state_);
1390 } 1416 }
1391 } 1417 }
1392 observer_->OnSignalingChange(signaling_state_); 1418 observer_->OnSignalingChange(signaling_state_);
1393 } 1419 }
1394 1420
1395 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track, 1421 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
1396 MediaStreamInterface* stream) { 1422 MediaStreamInterface* stream) {
1423 if (IsClosed()) {
1424 return;
1425 }
1397 auto sender = FindSenderForTrack(track); 1426 auto sender = FindSenderForTrack(track);
1398 if (sender != senders_.end()) { 1427 if (sender != senders_.end()) {
1399 // We already have a sender for this track, so just change the stream_id 1428 // We already have a sender for this track, so just change the stream_id
1400 // so that it's correct in the next call to CreateOffer. 1429 // so that it's correct in the next call to CreateOffer.
1401 (*sender)->set_stream_id(stream->label()); 1430 (*sender)->set_stream_id(stream->label());
1402 return; 1431 return;
1403 } 1432 }
1404 1433
1405 // Normal case; we've never seen this track before. 1434 // Normal case; we've never seen this track before.
1406 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create( 1435 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
(...skipping 10 matching lines...) Expand all
1417 FindTrackInfo(local_audio_tracks_, stream->label(), track->id()); 1446 FindTrackInfo(local_audio_tracks_, stream->label(), track->id());
1418 if (track_info) { 1447 if (track_info) {
1419 new_sender->SetSsrc(track_info->ssrc); 1448 new_sender->SetSsrc(track_info->ssrc);
1420 } 1449 }
1421 } 1450 }
1422 1451
1423 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around 1452 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
1424 // indefinitely, when we have unified plan SDP. 1453 // indefinitely, when we have unified plan SDP.
1425 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track, 1454 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
1426 MediaStreamInterface* stream) { 1455 MediaStreamInterface* stream) {
1456 if (IsClosed()) {
1457 return;
1458 }
1427 auto sender = FindSenderForTrack(track); 1459 auto sender = FindSenderForTrack(track);
1428 if (sender == senders_.end()) { 1460 if (sender == senders_.end()) {
1429 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() 1461 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1430 << " doesn't exist."; 1462 << " doesn't exist.";
1431 return; 1463 return;
1432 } 1464 }
1433 (*sender)->Stop(); 1465 (*sender)->Stop();
1434 senders_.erase(sender); 1466 senders_.erase(sender);
1435 } 1467 }
1436 1468
1437 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track, 1469 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
1438 MediaStreamInterface* stream) { 1470 MediaStreamInterface* stream) {
1471 if (IsClosed()) {
1472 return;
1473 }
1439 auto sender = FindSenderForTrack(track); 1474 auto sender = FindSenderForTrack(track);
1440 if (sender != senders_.end()) { 1475 if (sender != senders_.end()) {
1441 // We already have a sender for this track, so just change the stream_id 1476 // We already have a sender for this track, so just change the stream_id
1442 // so that it's correct in the next call to CreateOffer. 1477 // so that it's correct in the next call to CreateOffer.
1443 (*sender)->set_stream_id(stream->label()); 1478 (*sender)->set_stream_id(stream->label());
1444 return; 1479 return;
1445 } 1480 }
1446 1481
1447 // Normal case; we've never seen this track before. 1482 // Normal case; we've never seen this track before.
1448 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create( 1483 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
1449 signaling_thread(), 1484 signaling_thread(),
1450 new VideoRtpSender(track, stream->label(), session_.get())); 1485 new VideoRtpSender(track, stream->label(), session_.get()));
1451 senders_.push_back(new_sender); 1486 senders_.push_back(new_sender);
1452 const TrackInfo* track_info = 1487 const TrackInfo* track_info =
1453 FindTrackInfo(local_video_tracks_, stream->label(), track->id()); 1488 FindTrackInfo(local_video_tracks_, stream->label(), track->id());
1454 if (track_info) { 1489 if (track_info) {
1455 new_sender->SetSsrc(track_info->ssrc); 1490 new_sender->SetSsrc(track_info->ssrc);
1456 } 1491 }
1457 } 1492 }
1458 1493
1459 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track, 1494 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
1460 MediaStreamInterface* stream) { 1495 MediaStreamInterface* stream) {
1496 if (IsClosed()) {
1497 return;
1498 }
1461 auto sender = FindSenderForTrack(track); 1499 auto sender = FindSenderForTrack(track);
1462 if (sender == senders_.end()) { 1500 if (sender == senders_.end()) {
1463 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() 1501 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1464 << " doesn't exist."; 1502 << " doesn't exist.";
1465 return; 1503 return;
1466 } 1504 }
1467 (*sender)->Stop(); 1505 (*sender)->Stop();
1468 senders_.erase(sender); 1506 senders_.erase(sender);
1469 } 1507 }
1470 1508
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
2138 port_allocator_->set_candidate_filter( 2176 port_allocator_->set_candidate_filter(
2139 ConvertIceTransportTypeToCandidateFilter(configuration.type)); 2177 ConvertIceTransportTypeToCandidateFilter(configuration.type));
2140 // Call this last since it may create pooled allocator sessions using the 2178 // Call this last since it may create pooled allocator sessions using the
2141 // candidate filter set above. 2179 // candidate filter set above.
2142 port_allocator_->SetConfiguration(stun_servers, turn_servers, 2180 port_allocator_->SetConfiguration(stun_servers, turn_servers,
2143 configuration.ice_candidate_pool_size); 2181 configuration.ice_candidate_pool_size);
2144 return true; 2182 return true;
2145 } 2183 }
2146 2184
2147 } // namespace webrtc 2185 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | webrtc/api/peerconnectionfactory.h » ('j') | webrtc/api/peerconnectionfactory.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698