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

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: Minor Changes. 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 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 return false; 583 return false;
584 } 584 }
585 585
586 media_controller_.reset( 586 media_controller_.reset(
587 factory_->CreateMediaController(configuration.media_config)); 587 factory_->CreateMediaController(configuration.media_config));
588 588
589 session_.reset( 589 session_.reset(
590 new WebRtcSession(media_controller_.get(), factory_->network_thread(), 590 new WebRtcSession(media_controller_.get(), factory_->network_thread(),
591 factory_->worker_thread(), factory_->signaling_thread(), 591 factory_->worker_thread(), factory_->signaling_thread(),
592 port_allocator_.get())); 592 port_allocator_.get()));
593
594 session_->SetTransportController(
595 factory_->CreateTransportController(port_allocator_.get()));
593 stats_.reset(new StatsCollector(this)); 596 stats_.reset(new StatsCollector(this));
594 597
595 // Initialize the WebRtcSession. It creates transport channels etc. 598 // Initialize the WebRtcSession. It creates transport channels etc.
596 if (!session_->Initialize(factory_->options(), std::move(cert_generator), 599 if (!session_->Initialize(factory_->options(), std::move(cert_generator),
597 configuration)) { 600 configuration)) {
598 return false; 601 return false;
599 } 602 }
600 603
601 // Register PeerConnection as receiver of local ice candidates. 604 // Register PeerConnection as receiver of local ice candidates.
602 // All the callbacks will be posted to the application from PeerConnection. 605 // All the callbacks will be posted to the application from PeerConnection.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 (*it)->Stop(); 756 (*it)->Stop();
754 senders_.erase(it); 757 senders_.erase(it);
755 758
756 observer_->OnRenegotiationNeeded(); 759 observer_->OnRenegotiationNeeded();
757 return true; 760 return true;
758 } 761 }
759 762
760 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( 763 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
761 AudioTrackInterface* track) { 764 AudioTrackInterface* track) {
762 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender"); 765 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender");
766 if (IsClosed()) {
767 return nullptr;
768 }
763 if (!track) { 769 if (!track) {
764 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL."; 770 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL.";
765 return NULL; 771 return NULL;
766 } 772 }
767 if (!local_streams_->FindAudioTrack(track->id())) { 773 if (!local_streams_->FindAudioTrack(track->id())) {
768 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track."; 774 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track.";
769 return NULL; 775 return NULL;
770 } 776 }
771 777
772 rtc::scoped_refptr<DtmfSenderInterface> sender( 778 rtc::scoped_refptr<DtmfSenderInterface> sender(
773 DtmfSender::Create(track, signaling_thread(), session_.get())); 779 DtmfSender::Create(track, signaling_thread(), session_.get()));
774 if (!sender.get()) { 780 if (!sender.get()) {
775 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; 781 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create.";
776 return NULL; 782 return NULL;
777 } 783 }
778 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); 784 return DtmfSenderProxy::Create(signaling_thread(), sender.get());
779 } 785 }
780 786
781 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender( 787 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
782 const std::string& kind, 788 const std::string& kind,
783 const std::string& stream_id) { 789 const std::string& stream_id) {
784 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender"); 790 TRACE_EVENT0("webrtc", "PeerConnection::CreateSender");
791 if (IsClosed()) {
792 return nullptr;
793 }
785 rtc::scoped_refptr<RtpSenderInterface> new_sender; 794 rtc::scoped_refptr<RtpSenderInterface> new_sender;
786 if (kind == MediaStreamTrackInterface::kAudioKind) { 795 if (kind == MediaStreamTrackInterface::kAudioKind) {
787 new_sender = RtpSenderProxy::Create( 796 new_sender = RtpSenderProxy::Create(
788 signaling_thread(), new AudioRtpSender(session_.get(), stats_.get())); 797 signaling_thread(), new AudioRtpSender(session_.get(), stats_.get()));
789 } else if (kind == MediaStreamTrackInterface::kVideoKind) { 798 } else if (kind == MediaStreamTrackInterface::kVideoKind) {
790 new_sender = RtpSenderProxy::Create(signaling_thread(), 799 new_sender = RtpSenderProxy::Create(signaling_thread(),
791 new VideoRtpSender(session_.get())); 800 new VideoRtpSender(session_.get()));
792 } else { 801 } else {
793 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind; 802 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind;
794 return new_sender; 803 return new_sender;
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 return; 986 return;
978 } 987 }
979 988
980 session_->CreateAnswer(observer, session_options); 989 session_->CreateAnswer(observer, session_options);
981 } 990 }
982 991
983 void PeerConnection::SetLocalDescription( 992 void PeerConnection::SetLocalDescription(
984 SetSessionDescriptionObserver* observer, 993 SetSessionDescriptionObserver* observer,
985 SessionDescriptionInterface* desc) { 994 SessionDescriptionInterface* desc) {
986 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); 995 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
996 if (IsClosed()) {
997 return;
998 }
987 if (!VERIFY(observer != nullptr)) { 999 if (!VERIFY(observer != nullptr)) {
988 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; 1000 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL.";
989 return; 1001 return;
990 } 1002 }
991 if (!desc) { 1003 if (!desc) {
992 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); 1004 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
993 return; 1005 return;
994 } 1006 }
995 // Update stats here so that we have the most recent stats for tracks and 1007 // Update stats here so that we have the most recent stats for tracks and
996 // streams that might be removed by updating the session description. 1008 // streams that might be removed by updating the session description.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 // MaybeStartGathering needs to be called after posting 1067 // MaybeStartGathering needs to be called after posting
1056 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates 1068 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates
1057 // before signaling that SetLocalDescription completed. 1069 // before signaling that SetLocalDescription completed.
1058 session_->MaybeStartGathering(); 1070 session_->MaybeStartGathering();
1059 } 1071 }
1060 1072
1061 void PeerConnection::SetRemoteDescription( 1073 void PeerConnection::SetRemoteDescription(
1062 SetSessionDescriptionObserver* observer, 1074 SetSessionDescriptionObserver* observer,
1063 SessionDescriptionInterface* desc) { 1075 SessionDescriptionInterface* desc) {
1064 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription"); 1076 TRACE_EVENT0("webrtc", "PeerConnection::SetRemoteDescription");
1077 if (IsClosed()) {
1078 return;
1079 }
1065 if (!VERIFY(observer != nullptr)) { 1080 if (!VERIFY(observer != nullptr)) {
1066 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL."; 1081 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL.";
1067 return; 1082 return;
1068 } 1083 }
1069 if (!desc) { 1084 if (!desc) {
1070 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); 1085 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL.");
1071 return; 1086 return;
1072 } 1087 }
1073 // Update stats here so that we have the most recent stats for tracks and 1088 // Update stats here so that we have the most recent stats for tracks and
1074 // streams that might be removed by updating the session description. 1089 // streams that might be removed by updating the session description.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1175 } 1190 }
1176 1191
1177 // TODO(deadbeef): Shouldn't have to hop to the worker thread twice... 1192 // TODO(deadbeef): Shouldn't have to hop to the worker thread twice...
1178 session_->SetIceConfig(session_->ParseIceConfig(configuration)); 1193 session_->SetIceConfig(session_->ParseIceConfig(configuration));
1179 return true; 1194 return true;
1180 } 1195 }
1181 1196
1182 bool PeerConnection::AddIceCandidate( 1197 bool PeerConnection::AddIceCandidate(
1183 const IceCandidateInterface* ice_candidate) { 1198 const IceCandidateInterface* ice_candidate) {
1184 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate"); 1199 TRACE_EVENT0("webrtc", "PeerConnection::AddIceCandidate");
1200 if (IsClosed()) {
1201 return false;
1202 }
1185 return session_->ProcessIceMessage(ice_candidate); 1203 return session_->ProcessIceMessage(ice_candidate);
1186 } 1204 }
1187 1205
1188 bool PeerConnection::RemoveIceCandidates( 1206 bool PeerConnection::RemoveIceCandidates(
1189 const std::vector<cricket::Candidate>& candidates) { 1207 const std::vector<cricket::Candidate>& candidates) {
1190 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates"); 1208 TRACE_EVENT0("webrtc", "PeerConnection::RemoveIceCandidates");
1191 return session_->RemoveRemoteIceCandidates(candidates); 1209 return session_->RemoveRemoteIceCandidates(candidates);
1192 } 1210 }
1193 1211
1194 void PeerConnection::RegisterUMAObserver(UMAObserver* observer) { 1212 void PeerConnection::RegisterUMAObserver(UMAObserver* observer) {
(...skipping 24 matching lines...) Expand all
1219 1237
1220 const SessionDescriptionInterface* PeerConnection::remote_description() const { 1238 const SessionDescriptionInterface* PeerConnection::remote_description() const {
1221 return session_->remote_description(); 1239 return session_->remote_description();
1222 } 1240 }
1223 1241
1224 void PeerConnection::Close() { 1242 void PeerConnection::Close() {
1225 TRACE_EVENT0("webrtc", "PeerConnection::Close"); 1243 TRACE_EVENT0("webrtc", "PeerConnection::Close");
1226 // Update stats here so that we have the most recent stats for tracks and 1244 // Update stats here so that we have the most recent stats for tracks and
1227 // streams before the channels are closed. 1245 // streams before the channels are closed.
1228 stats_->UpdateStats(kStatsOutputLevelStandard); 1246 stats_->UpdateStats(kStatsOutputLevelStandard);
1229
1230 session_->Close(); 1247 session_->Close();
1231 } 1248 }
1232 1249
1233 void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/, 1250 void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
1234 WebRtcSession::State state) { 1251 WebRtcSession::State state) {
1235 switch (state) { 1252 switch (state) {
1236 case WebRtcSession::STATE_INIT: 1253 case WebRtcSession::STATE_INIT:
1237 ChangeSignalingState(PeerConnectionInterface::kStable); 1254 ChangeSignalingState(PeerConnectionInterface::kStable);
1238 break; 1255 break;
1239 case WebRtcSession::STATE_SENTOFFER: 1256 case WebRtcSession::STATE_SENTOFFER:
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 RTC_DCHECK(signaling_thread()->IsCurrent()); 1377 RTC_DCHECK(signaling_thread()->IsCurrent());
1361 if (IsClosed()) { 1378 if (IsClosed()) {
1362 return; 1379 return;
1363 } 1380 }
1364 ice_gathering_state_ = new_state; 1381 ice_gathering_state_ = new_state;
1365 observer_->OnIceGatheringChange(ice_gathering_state_); 1382 observer_->OnIceGatheringChange(ice_gathering_state_);
1366 } 1383 }
1367 1384
1368 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) { 1385 void PeerConnection::OnIceCandidate(const IceCandidateInterface* candidate) {
1369 RTC_DCHECK(signaling_thread()->IsCurrent()); 1386 RTC_DCHECK(signaling_thread()->IsCurrent());
1387 if (IsClosed()) {
1388 return;
1389 }
1370 observer_->OnIceCandidate(candidate); 1390 observer_->OnIceCandidate(candidate);
1371 } 1391 }
1372 1392
1373 void PeerConnection::OnIceCandidatesRemoved( 1393 void PeerConnection::OnIceCandidatesRemoved(
1374 const std::vector<cricket::Candidate>& candidates) { 1394 const std::vector<cricket::Candidate>& candidates) {
1375 RTC_DCHECK(signaling_thread()->IsCurrent()); 1395 RTC_DCHECK(signaling_thread()->IsCurrent());
1396 if (IsClosed()) {
1397 return;
1398 }
1376 observer_->OnIceCandidatesRemoved(candidates); 1399 observer_->OnIceCandidatesRemoved(candidates);
1377 } 1400 }
1378 1401
1379 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) { 1402 void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
1380 RTC_DCHECK(signaling_thread()->IsCurrent()); 1403 RTC_DCHECK(signaling_thread()->IsCurrent());
1404 if (IsClosed()) {
1405 return;
1406 }
1381 observer_->OnIceConnectionReceivingChange(receiving); 1407 observer_->OnIceConnectionReceivingChange(receiving);
1382 } 1408 }
1383 1409
1384 void PeerConnection::ChangeSignalingState( 1410 void PeerConnection::ChangeSignalingState(
1385 PeerConnectionInterface::SignalingState signaling_state) { 1411 PeerConnectionInterface::SignalingState signaling_state) {
1386 signaling_state_ = signaling_state; 1412 signaling_state_ = signaling_state;
1387 if (signaling_state == kClosed) { 1413 if (signaling_state == kClosed) {
1388 ice_connection_state_ = kIceConnectionClosed; 1414 ice_connection_state_ = kIceConnectionClosed;
1389 observer_->OnIceConnectionChange(ice_connection_state_); 1415 observer_->OnIceConnectionChange(ice_connection_state_);
1390 if (ice_gathering_state_ != kIceGatheringComplete) { 1416 if (ice_gathering_state_ != kIceGatheringComplete) {
1391 ice_gathering_state_ = kIceGatheringComplete; 1417 ice_gathering_state_ = kIceGatheringComplete;
1392 observer_->OnIceGatheringChange(ice_gathering_state_); 1418 observer_->OnIceGatheringChange(ice_gathering_state_);
1393 } 1419 }
1394 } 1420 }
1395 observer_->OnSignalingChange(signaling_state_); 1421 observer_->OnSignalingChange(signaling_state_);
1396 } 1422 }
1397 1423
1398 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track, 1424 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track,
1399 MediaStreamInterface* stream) { 1425 MediaStreamInterface* stream) {
1426 if (IsClosed()) {
1427 return;
1428 }
1400 auto sender = FindSenderForTrack(track); 1429 auto sender = FindSenderForTrack(track);
1401 if (sender != senders_.end()) { 1430 if (sender != senders_.end()) {
1402 // We already have a sender for this track, so just change the stream_id 1431 // We already have a sender for this track, so just change the stream_id
1403 // so that it's correct in the next call to CreateOffer. 1432 // so that it's correct in the next call to CreateOffer.
1404 (*sender)->set_stream_id(stream->label()); 1433 (*sender)->set_stream_id(stream->label());
1405 return; 1434 return;
1406 } 1435 }
1407 1436
1408 // Normal case; we've never seen this track before. 1437 // Normal case; we've never seen this track before.
1409 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create( 1438 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
(...skipping 10 matching lines...) Expand all
1420 FindTrackInfo(local_audio_tracks_, stream->label(), track->id()); 1449 FindTrackInfo(local_audio_tracks_, stream->label(), track->id());
1421 if (track_info) { 1450 if (track_info) {
1422 new_sender->SetSsrc(track_info->ssrc); 1451 new_sender->SetSsrc(track_info->ssrc);
1423 } 1452 }
1424 } 1453 }
1425 1454
1426 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around 1455 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
1427 // indefinitely, when we have unified plan SDP. 1456 // indefinitely, when we have unified plan SDP.
1428 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track, 1457 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track,
1429 MediaStreamInterface* stream) { 1458 MediaStreamInterface* stream) {
1459 if (IsClosed()) {
1460 return;
1461 }
1430 auto sender = FindSenderForTrack(track); 1462 auto sender = FindSenderForTrack(track);
1431 if (sender == senders_.end()) { 1463 if (sender == senders_.end()) {
1432 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() 1464 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1433 << " doesn't exist."; 1465 << " doesn't exist.";
1434 return; 1466 return;
1435 } 1467 }
1436 (*sender)->Stop(); 1468 (*sender)->Stop();
1437 senders_.erase(sender); 1469 senders_.erase(sender);
1438 } 1470 }
1439 1471
1440 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track, 1472 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track,
1441 MediaStreamInterface* stream) { 1473 MediaStreamInterface* stream) {
1474 if (IsClosed()) {
1475 return;
1476 }
1442 auto sender = FindSenderForTrack(track); 1477 auto sender = FindSenderForTrack(track);
1443 if (sender != senders_.end()) { 1478 if (sender != senders_.end()) {
1444 // We already have a sender for this track, so just change the stream_id 1479 // We already have a sender for this track, so just change the stream_id
1445 // so that it's correct in the next call to CreateOffer. 1480 // so that it's correct in the next call to CreateOffer.
1446 (*sender)->set_stream_id(stream->label()); 1481 (*sender)->set_stream_id(stream->label());
1447 return; 1482 return;
1448 } 1483 }
1449 1484
1450 // Normal case; we've never seen this track before. 1485 // Normal case; we've never seen this track before.
1451 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create( 1486 rtc::scoped_refptr<RtpSenderInterface> new_sender = RtpSenderProxy::Create(
1452 signaling_thread(), 1487 signaling_thread(),
1453 new VideoRtpSender(track, stream->label(), session_.get())); 1488 new VideoRtpSender(track, stream->label(), session_.get()));
1454 senders_.push_back(new_sender); 1489 senders_.push_back(new_sender);
1455 const TrackInfo* track_info = 1490 const TrackInfo* track_info =
1456 FindTrackInfo(local_video_tracks_, stream->label(), track->id()); 1491 FindTrackInfo(local_video_tracks_, stream->label(), track->id());
1457 if (track_info) { 1492 if (track_info) {
1458 new_sender->SetSsrc(track_info->ssrc); 1493 new_sender->SetSsrc(track_info->ssrc);
1459 } 1494 }
1460 } 1495 }
1461 1496
1462 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track, 1497 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track,
1463 MediaStreamInterface* stream) { 1498 MediaStreamInterface* stream) {
1499 if (IsClosed()) {
1500 return;
1501 }
1464 auto sender = FindSenderForTrack(track); 1502 auto sender = FindSenderForTrack(track);
1465 if (sender == senders_.end()) { 1503 if (sender == senders_.end()) {
1466 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() 1504 LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
1467 << " doesn't exist."; 1505 << " doesn't exist.";
1468 return; 1506 return;
1469 } 1507 }
1470 (*sender)->Stop(); 1508 (*sender)->Stop();
1471 senders_.erase(sender); 1509 senders_.erase(sender);
1472 } 1510 }
1473 1511
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
2156 port_allocator_->set_candidate_filter( 2194 port_allocator_->set_candidate_filter(
2157 ConvertIceTransportTypeToCandidateFilter(configuration.type)); 2195 ConvertIceTransportTypeToCandidateFilter(configuration.type));
2158 // Call this last since it may create pooled allocator sessions using the 2196 // Call this last since it may create pooled allocator sessions using the
2159 // candidate filter set above. 2197 // candidate filter set above.
2160 port_allocator_->SetConfiguration(stun_servers, turn_servers, 2198 port_allocator_->SetConfiguration(stun_servers, turn_servers,
2161 configuration.ice_candidate_pool_size); 2199 configuration.ice_candidate_pool_size);
2162 return true; 2200 return true;
2163 } 2201 }
2164 2202
2165 } // namespace webrtc 2203 } // 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