Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 */ | 26 */ |
| 27 | 27 |
| 28 #include "talk/app/webrtc/peerconnection.h" | 28 #include "talk/app/webrtc/peerconnection.h" |
| 29 | 29 |
| 30 #include <vector> | 30 #include <vector> |
| 31 | 31 |
| 32 #include "talk/app/webrtc/audiotrack.h" | |
| 32 #include "talk/app/webrtc/dtmfsender.h" | 33 #include "talk/app/webrtc/dtmfsender.h" |
| 33 #include "talk/app/webrtc/jsepicecandidate.h" | 34 #include "talk/app/webrtc/jsepicecandidate.h" |
| 34 #include "talk/app/webrtc/jsepsessiondescription.h" | 35 #include "talk/app/webrtc/jsepsessiondescription.h" |
| 35 #include "talk/app/webrtc/mediaconstraintsinterface.h" | 36 #include "talk/app/webrtc/mediaconstraintsinterface.h" |
| 37 #include "talk/app/webrtc/mediastream.h" | |
| 38 #include "talk/app/webrtc/mediastreamproxy.h" | |
| 39 #include "talk/app/webrtc/mediastreamtrackproxy.h" | |
| 40 #include "talk/app/webrtc/remoteaudiosource.h" | |
| 41 #include "talk/app/webrtc/remotevideocapturer.h" | |
| 36 #include "talk/app/webrtc/rtpreceiver.h" | 42 #include "talk/app/webrtc/rtpreceiver.h" |
| 37 #include "talk/app/webrtc/rtpsender.h" | 43 #include "talk/app/webrtc/rtpsender.h" |
| 38 #include "talk/app/webrtc/streamcollection.h" | 44 #include "talk/app/webrtc/streamcollection.h" |
| 45 #include "talk/app/webrtc/videosource.h" | |
| 46 #include "talk/app/webrtc/videotrack.h" | |
| 47 #include "talk/media/sctp/sctpdataengine.h" | |
| 39 #include "webrtc/p2p/client/basicportallocator.h" | 48 #include "webrtc/p2p/client/basicportallocator.h" |
| 40 #include "talk/session/media/channelmanager.h" | 49 #include "talk/session/media/channelmanager.h" |
| 41 #include "webrtc/base/logging.h" | 50 #include "webrtc/base/logging.h" |
| 42 #include "webrtc/base/stringencode.h" | 51 #include "webrtc/base/stringencode.h" |
| 52 #include "webrtc/base/stringutils.h" | |
| 43 #include "webrtc/system_wrappers/interface/field_trial.h" | 53 #include "webrtc/system_wrappers/interface/field_trial.h" |
| 44 | 54 |
| 45 namespace { | 55 namespace { |
| 46 | 56 |
| 57 using webrtc::DataChannel; | |
| 58 using webrtc::MediaConstraintsInterface; | |
| 59 using webrtc::MediaStreamInterface; | |
| 47 using webrtc::PeerConnectionInterface; | 60 using webrtc::PeerConnectionInterface; |
| 61 using webrtc::StreamCollection; | |
| 62 | |
| 63 static const char kDefaultStreamLabel[] = "default"; | |
| 64 static const char kDefaultAudioTrackLabel[] = "defaulta0"; | |
| 65 static const char kDefaultVideoTrackLabel[] = "defaultv0"; | |
| 48 | 66 |
| 49 // The min number of tokens must present in Turn host uri. | 67 // The min number of tokens must present in Turn host uri. |
| 50 // e.g. user@turn.example.org | 68 // e.g. user@turn.example.org |
| 51 static const size_t kTurnHostTokensNum = 2; | 69 static const size_t kTurnHostTokensNum = 2; |
| 52 // Number of tokens must be preset when TURN uri has transport param. | 70 // Number of tokens must be preset when TURN uri has transport param. |
| 53 static const size_t kTurnTransportTokensNum = 2; | 71 static const size_t kTurnTransportTokensNum = 2; |
| 54 // The default stun port. | 72 // The default stun port. |
| 55 static const int kDefaultStunPort = 3478; | 73 static const int kDefaultStunPort = 3478; |
| 56 static const int kDefaultStunTlsPort = 5349; | 74 static const int kDefaultStunTlsPort = 5349; |
| 57 static const char kTransport[] = "transport"; | 75 static const char kTransport[] = "transport"; |
| 58 static const char kUdpTransportType[] = "udp"; | 76 static const char kUdpTransportType[] = "udp"; |
| 59 static const char kTcpTransportType[] = "tcp"; | 77 static const char kTcpTransportType[] = "tcp"; |
| 60 | 78 |
| 61 // NOTE: Must be in the same order as the ServiceType enum. | 79 // NOTE: Must be in the same order as the ServiceType enum. |
| 62 static const char* kValidIceServiceTypes[] = { | 80 static const char* kValidIceServiceTypes[] = { |
| 63 "stun", "stuns", "turn", "turns", "invalid" }; | 81 "stun", "stuns", "turn", "turns", "invalid" }; |
| 64 | 82 |
| 65 enum ServiceType { | 83 enum ServiceType { |
| 66 STUN, // Indicates a STUN server. | 84 STUN, // Indicates a STUN server. |
| 67 STUNS, // Indicates a STUN server used with a TLS session. | 85 STUNS, // Indicates a STUN server used with a TLS session. |
| 68 TURN, // Indicates a TURN server | 86 TURN, // Indicates a TURN server |
| 69 TURNS, // Indicates a TURN server used with a TLS session. | 87 TURNS, // Indicates a TURN server used with a TLS session. |
| 70 INVALID, // Unknown. | 88 INVALID, // Unknown. |
| 71 }; | 89 }; |
| 72 | 90 |
| 73 enum { | 91 enum { |
| 74 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, | 92 MSG_SET_SESSIONDESCRIPTION_SUCCESS = 0, |
| 75 MSG_SET_SESSIONDESCRIPTION_FAILED, | 93 MSG_SET_SESSIONDESCRIPTION_FAILED, |
| 94 MSG_CREATE_SESSIONDESCRIPTION_FAILED, | |
| 76 MSG_GETSTATS, | 95 MSG_GETSTATS, |
| 77 }; | 96 }; |
| 78 | 97 |
| 79 struct SetSessionDescriptionMsg : public rtc::MessageData { | 98 struct SetSessionDescriptionMsg : public rtc::MessageData { |
| 80 explicit SetSessionDescriptionMsg( | 99 explicit SetSessionDescriptionMsg( |
| 81 webrtc::SetSessionDescriptionObserver* observer) | 100 webrtc::SetSessionDescriptionObserver* observer) |
| 82 : observer(observer) { | 101 : observer(observer) { |
| 83 } | 102 } |
| 84 | 103 |
| 85 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer; | 104 rtc::scoped_refptr<webrtc::SetSessionDescriptionObserver> observer; |
| 86 std::string error; | 105 std::string error; |
| 87 }; | 106 }; |
| 88 | 107 |
| 108 struct CreateSessionDescriptionMsg : public rtc::MessageData { | |
| 109 explicit CreateSessionDescriptionMsg( | |
| 110 webrtc::CreateSessionDescriptionObserver* observer) | |
| 111 : observer(observer) {} | |
| 112 | |
| 113 rtc::scoped_refptr<webrtc::CreateSessionDescriptionObserver> observer; | |
| 114 std::string error; | |
| 115 }; | |
| 116 | |
| 89 struct GetStatsMsg : public rtc::MessageData { | 117 struct GetStatsMsg : public rtc::MessageData { |
| 90 GetStatsMsg(webrtc::StatsObserver* observer, | 118 GetStatsMsg(webrtc::StatsObserver* observer, |
| 91 webrtc::MediaStreamTrackInterface* track) | 119 webrtc::MediaStreamTrackInterface* track) |
| 92 : observer(observer), track(track) { | 120 : observer(observer), track(track) { |
| 93 } | 121 } |
| 94 rtc::scoped_refptr<webrtc::StatsObserver> observer; | 122 rtc::scoped_refptr<webrtc::StatsObserver> observer; |
| 95 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; | 123 rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track; |
| 96 }; | 124 }; |
| 97 | 125 |
| 98 // |in_str| should be of format | 126 // |in_str| should be of format |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 302 return false; | 330 return false; |
| 303 } | 331 } |
| 304 } else { | 332 } else { |
| 305 LOG(WARNING) << "Empty uri."; | 333 LOG(WARNING) << "Empty uri."; |
| 306 } | 334 } |
| 307 } | 335 } |
| 308 return true; | 336 return true; |
| 309 } | 337 } |
| 310 | 338 |
| 311 // Check if we can send |new_stream| on a PeerConnection. | 339 // Check if we can send |new_stream| on a PeerConnection. |
| 312 // Currently only one audio but multiple video track is supported per | |
| 313 // PeerConnection. | |
| 314 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, | 340 bool CanAddLocalMediaStream(webrtc::StreamCollectionInterface* current_streams, |
| 315 webrtc::MediaStreamInterface* new_stream) { | 341 webrtc::MediaStreamInterface* new_stream) { |
| 316 if (!new_stream || !current_streams) | 342 if (!new_stream || !current_streams) { |
| 317 return false; | 343 return false; |
| 318 if (current_streams->find(new_stream->label()) != NULL) { | 344 } |
| 345 if (current_streams->find(new_stream->label()) != nullptr) { | |
| 319 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() | 346 LOG(LS_ERROR) << "MediaStream with label " << new_stream->label() |
| 320 << " is already added."; | 347 << " is already added."; |
| 321 return false; | 348 return false; |
| 322 } | 349 } |
| 323 | |
| 324 return true; | 350 return true; |
| 325 } | 351 } |
| 326 | 352 |
| 353 bool MediaContentDirectionHasSend(cricket::MediaContentDirection dir) { | |
| 354 return dir == cricket::MD_SENDONLY || dir == cricket::MD_SENDRECV; | |
| 355 } | |
| 356 | |
| 357 bool IsValidOfferToReceiveMedia(int value) { | |
| 358 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; | |
| 359 return (value >= Options::kUndefined) && | |
| 360 (value <= Options::kMaxOfferToReceiveMedia); | |
| 361 } | |
| 362 | |
| 363 // Add the stream and RTP data channel info to |session_options|. | |
| 364 void SetStreams(cricket::MediaSessionOptions* session_options, | |
| 365 rtc::scoped_refptr<StreamCollection> streams, | |
| 366 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& | |
| 367 rtp_data_channels) { | |
| 368 session_options->streams.clear(); | |
| 369 if (streams != nullptr) { | |
| 370 for (size_t i = 0; i < streams->count(); ++i) { | |
| 371 MediaStreamInterface* stream = streams->at(i); | |
| 372 // For each audio track in the stream, add it to the MediaSessionOptions. | |
| 373 for (const auto& track : stream->GetAudioTracks()) { | |
| 374 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, track->id(), | |
| 375 stream->label()); | |
| 376 } | |
| 377 // For each video track in the stream, add it to the MediaSessionOptions. | |
| 378 for (const auto& track : stream->GetVideoTracks()) { | |
| 379 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, track->id(), | |
| 380 stream->label()); | |
| 381 } | |
| 382 } | |
| 383 } | |
| 384 | |
| 385 // Check for data channels. | |
| 386 for (const auto& kv : rtp_data_channels) { | |
| 387 const DataChannel* channel = kv.second; | |
| 388 if (channel->state() == DataChannel::kConnecting || | |
| 389 channel->state() == DataChannel::kOpen) { | |
| 390 // |streamid| and |sync_label| are both set to the DataChannel label | |
| 391 // here so they can be signaled the same way as MediaStreams and Tracks. | |
| 392 // For MediaStreams, the sync_label is the MediaStream label and the | |
| 393 // track label is the same as |streamid|. | |
| 394 const std::string& streamid = channel->label(); | |
| 395 const std::string& sync_label = channel->label(); | |
| 396 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid, | |
| 397 sync_label); | |
| 398 } | |
| 399 } | |
| 400 } | |
| 401 | |
| 327 } // namespace | 402 } // namespace |
| 328 | 403 |
| 329 namespace webrtc { | 404 namespace webrtc { |
| 330 | 405 |
| 406 // Factory class for creating remote MediaStreams and MediaStreamTracks. | |
| 407 class RemoteMediaStreamFactory { | |
| 408 public: | |
| 409 explicit RemoteMediaStreamFactory(rtc::Thread* signaling_thread, | |
| 410 cricket::ChannelManager* channel_manager) | |
| 411 : signaling_thread_(signaling_thread), | |
| 412 channel_manager_(channel_manager) {} | |
| 413 | |
| 414 rtc::scoped_refptr<MediaStreamInterface> CreateMediaStream( | |
| 415 const std::string& stream_label) { | |
| 416 return MediaStreamProxy::Create(signaling_thread_, | |
| 417 MediaStream::Create(stream_label)); | |
| 418 } | |
| 419 | |
| 420 AudioTrackInterface* AddAudioTrack(webrtc::MediaStreamInterface* stream, | |
| 421 const std::string& track_id) { | |
| 422 return AddTrack<AudioTrackInterface, AudioTrack, AudioTrackProxy>( | |
| 423 stream, track_id, RemoteAudioSource::Create().get()); | |
| 424 } | |
| 425 | |
| 426 VideoTrackInterface* AddVideoTrack(webrtc::MediaStreamInterface* stream, | |
| 427 const std::string& track_id) { | |
| 428 return AddTrack<VideoTrackInterface, VideoTrack, VideoTrackProxy>( | |
| 429 stream, track_id, | |
| 430 VideoSource::Create(channel_manager_, new RemoteVideoCapturer(), | |
| 431 nullptr) | |
| 432 .get()); | |
| 433 } | |
| 434 | |
| 435 private: | |
| 436 template <typename TI, typename T, typename TP, typename S> | |
| 437 TI* AddTrack(MediaStreamInterface* stream, | |
| 438 const std::string& track_id, | |
| 439 S* source) { | |
| 440 rtc::scoped_refptr<TI> track( | |
| 441 TP::Create(signaling_thread_, T::Create(track_id, source))); | |
| 442 track->set_state(webrtc::MediaStreamTrackInterface::kLive); | |
| 443 if (stream->AddTrack(track)) { | |
| 444 return track; | |
| 445 } | |
| 446 return nullptr; | |
| 447 } | |
| 448 | |
| 449 rtc::Thread* signaling_thread_; | |
| 450 cricket::ChannelManager* channel_manager_; | |
| 451 }; | |
| 452 | |
| 453 bool ConvertRtcOptionsForOffer( | |
| 454 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | |
| 455 cricket::MediaSessionOptions* session_options) { | |
| 456 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; | |
| 457 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) || | |
| 458 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) { | |
| 459 return false; | |
| 460 } | |
| 461 | |
| 462 // According to the spec, offer to receive audio/video if the constraint is | |
| 463 // not set and there are send streams. | |
| 464 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { | |
| 465 session_options->recv_audio = | |
| 466 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO); | |
| 467 } else { | |
| 468 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0); | |
| 469 } | |
| 470 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { | |
| 471 session_options->recv_video = | |
| 472 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO); | |
| 473 } else { | |
| 474 session_options->recv_video = (rtc_options.offer_to_receive_video > 0); | |
| 475 } | |
| 476 | |
| 477 session_options->vad_enabled = rtc_options.voice_activity_detection; | |
| 478 session_options->transport_options.ice_restart = rtc_options.ice_restart; | |
| 479 session_options->bundle_enabled = | |
| 480 rtc_options.use_rtp_mux && | |
| 481 (session_options->has_audio() || session_options->has_video() || | |
| 482 session_options->has_data()); | |
| 483 | |
| 484 return true; | |
| 485 } | |
| 486 | |
| 487 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, | |
| 488 cricket::MediaSessionOptions* session_options) { | |
| 489 bool value = false; | |
| 490 size_t mandatory_constraints_satisfied = 0; | |
| 491 | |
| 492 // kOfferToReceiveAudio defaults to true according to spec. | |
| 493 if (!FindConstraint(constraints, | |
| 494 MediaConstraintsInterface::kOfferToReceiveAudio, &value, | |
| 495 &mandatory_constraints_satisfied) || | |
| 496 value) { | |
| 497 session_options->recv_audio = true; | |
| 498 } | |
| 499 | |
| 500 // kOfferToReceiveVideo defaults to false according to spec. But | |
| 501 // if it is an answer and video is offered, we should still accept video | |
| 502 // per default. | |
| 503 value = false; | |
| 504 if (!FindConstraint(constraints, | |
| 505 MediaConstraintsInterface::kOfferToReceiveVideo, &value, | |
| 506 &mandatory_constraints_satisfied) || | |
| 507 value) { | |
| 508 session_options->recv_video = true; | |
| 509 } | |
| 510 | |
| 511 if (FindConstraint(constraints, | |
| 512 MediaConstraintsInterface::kVoiceActivityDetection, &value, | |
| 513 &mandatory_constraints_satisfied)) { | |
| 514 session_options->vad_enabled = value; | |
| 515 } | |
| 516 | |
| 517 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value, | |
| 518 &mandatory_constraints_satisfied)) { | |
| 519 session_options->bundle_enabled = value; | |
| 520 } else { | |
| 521 // kUseRtpMux defaults to true according to spec. | |
| 522 session_options->bundle_enabled = true; | |
| 523 } | |
| 524 session_options->bundle_enabled = | |
| 525 session_options->bundle_enabled && | |
| 526 (session_options->has_audio() || session_options->has_video() || | |
| 527 session_options->has_data()); | |
| 528 | |
| 529 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart, | |
| 530 &value, &mandatory_constraints_satisfied)) { | |
| 531 session_options->transport_options.ice_restart = value; | |
| 532 } else { | |
| 533 // kIceRestart defaults to false according to spec. | |
| 534 session_options->transport_options.ice_restart = false; | |
| 535 } | |
| 536 | |
| 537 if (!constraints) { | |
| 538 return true; | |
| 539 } | |
| 540 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); | |
| 541 } | |
| 542 | |
| 331 PeerConnection::PeerConnection(PeerConnectionFactory* factory) | 543 PeerConnection::PeerConnection(PeerConnectionFactory* factory) |
| 332 : factory_(factory), | 544 : factory_(factory), |
| 333 observer_(NULL), | 545 observer_(NULL), |
| 334 uma_observer_(NULL), | 546 uma_observer_(NULL), |
| 335 signaling_state_(kStable), | 547 signaling_state_(kStable), |
| 336 ice_state_(kIceNew), | 548 ice_state_(kIceNew), |
| 337 ice_connection_state_(kIceConnectionNew), | 549 ice_connection_state_(kIceConnectionNew), |
| 338 ice_gathering_state_(kIceGatheringNew) { | 550 ice_gathering_state_(kIceGatheringNew), |
| 339 } | 551 local_streams_(StreamCollection::Create()), |
| 552 remote_streams_(StreamCollection::Create()) {} | |
| 340 | 553 |
| 341 PeerConnection::~PeerConnection() { | 554 PeerConnection::~PeerConnection() { |
| 342 ASSERT(signaling_thread()->IsCurrent()); | 555 ASSERT(signaling_thread()->IsCurrent()); |
| 343 if (mediastream_signaling_) { | |
| 344 mediastream_signaling_->TearDown(); | |
| 345 } | |
|
Taylor Brandstetter
2015/10/07 00:26:19
The stuff previously done in mediastream_signaling
| |
| 346 // Need to detach RTP senders/receivers from WebRtcSession, | 556 // Need to detach RTP senders/receivers from WebRtcSession, |
| 347 // since it's about to be destroyed. | 557 // since it's about to be destroyed. |
| 348 for (const auto& sender : senders_) { | 558 for (const auto& sender : senders_) { |
| 349 sender->Stop(); | 559 sender->Stop(); |
| 350 } | 560 } |
| 351 for (const auto& receiver : receivers_) { | 561 for (const auto& receiver : receivers_) { |
| 352 receiver->Stop(); | 562 receiver->Stop(); |
| 353 } | 563 } |
| 354 } | 564 } |
| 355 | 565 |
| 356 bool PeerConnection::Initialize( | 566 bool PeerConnection::Initialize( |
| 357 const PeerConnectionInterface::RTCConfiguration& configuration, | 567 const PeerConnectionInterface::RTCConfiguration& configuration, |
| 358 const MediaConstraintsInterface* constraints, | 568 const MediaConstraintsInterface* constraints, |
| 359 PortAllocatorFactoryInterface* allocator_factory, | 569 PortAllocatorFactoryInterface* allocator_factory, |
| 360 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 570 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
| 361 PeerConnectionObserver* observer) { | 571 PeerConnectionObserver* observer) { |
| 362 ASSERT(observer != NULL); | 572 ASSERT(observer != nullptr); |
| 363 if (!observer) | 573 if (!observer) { |
| 364 return false; | 574 return false; |
| 575 } | |
| 365 observer_ = observer; | 576 observer_ = observer; |
| 366 | 577 |
| 367 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config; | 578 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stun_config; |
| 368 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config; | 579 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turn_config; |
| 369 if (!ParseIceServers(configuration.servers, &stun_config, &turn_config)) { | 580 if (!ParseIceServers(configuration.servers, &stun_config, &turn_config)) { |
| 370 return false; | 581 return false; |
| 371 } | 582 } |
| 372 port_allocator_.reset( | 583 port_allocator_.reset( |
| 373 allocator_factory->CreatePortAllocator(stun_config, turn_config)); | 584 allocator_factory->CreatePortAllocator(stun_config, turn_config)); |
| 374 | 585 |
| 375 // To handle both internal and externally created port allocator, we will | 586 // To handle both internal and externally created port allocator, we will |
| 376 // enable BUNDLE here. | 587 // enable BUNDLE here. |
| 377 int portallocator_flags = port_allocator_->flags(); | 588 int portallocator_flags = port_allocator_->flags(); |
| 378 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | | 589 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | |
| 379 cricket::PORTALLOCATOR_ENABLE_IPV6; | 590 cricket::PORTALLOCATOR_ENABLE_IPV6; |
| 380 bool value; | 591 bool value; |
| 381 // If IPv6 flag was specified, we'll not override it by experiment. | 592 // If IPv6 flag was specified, we'll not override it by experiment. |
| 382 if (FindConstraint( | 593 if (FindConstraint(constraints, MediaConstraintsInterface::kEnableIPv6, |
| 383 constraints, MediaConstraintsInterface::kEnableIPv6, &value, NULL)) { | 594 &value, nullptr)) { |
| 384 if (!value) { | 595 if (!value) { |
| 385 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); | 596 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); |
| 386 } | 597 } |
| 387 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == | 598 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == |
| 388 "Disabled") { | 599 "Disabled") { |
| 389 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); | 600 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); |
| 390 } | 601 } |
| 391 | 602 |
| 392 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { | 603 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { |
| 393 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; | 604 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; |
| 394 LOG(LS_INFO) << "TCP candidates are disabled."; | 605 LOG(LS_INFO) << "TCP candidates are disabled."; |
| 395 } | 606 } |
| 396 | 607 |
| 397 port_allocator_->set_flags(portallocator_flags); | 608 port_allocator_->set_flags(portallocator_flags); |
| 398 // No step delay is used while allocating ports. | 609 // No step delay is used while allocating ports. |
| 399 port_allocator_->set_step_delay(cricket::kMinimumStepDelay); | 610 port_allocator_->set_step_delay(cricket::kMinimumStepDelay); |
| 400 | 611 |
| 401 mediastream_signaling_.reset(new MediaStreamSignaling( | 612 remote_stream_factory_.reset(new RemoteMediaStreamFactory( |
| 402 factory_->signaling_thread(), this, factory_->channel_manager())); | 613 factory_->signaling_thread(), factory_->channel_manager())); |
| 403 | 614 |
| 404 session_.reset(new WebRtcSession(factory_->channel_manager(), | 615 session_.reset(new WebRtcSession( |
| 405 factory_->signaling_thread(), | 616 factory_->channel_manager(), factory_->signaling_thread(), |
| 406 factory_->worker_thread(), | 617 factory_->worker_thread(), port_allocator_.get())); |
| 407 port_allocator_.get(), | 618 stats_.reset(new StatsCollector(this, session_.get())); |
| 408 mediastream_signaling_.get())); | |
| 409 stats_.reset(new StatsCollector(session_.get())); | |
| 410 | 619 |
| 411 // Initialize the WebRtcSession. It creates transport channels etc. | 620 // Initialize the WebRtcSession. It creates transport channels etc. |
| 412 if (!session_->Initialize(factory_->options(), constraints, | 621 if (!session_->Initialize(factory_->options(), constraints, |
| 413 dtls_identity_store.Pass(), configuration)) | 622 dtls_identity_store.Pass(), configuration)) { |
| 414 return false; | 623 return false; |
| 624 } | |
| 415 | 625 |
| 416 // Register PeerConnection as receiver of local ice candidates. | 626 // Register PeerConnection as receiver of local ice candidates. |
| 417 // All the callbacks will be posted to the application from PeerConnection. | 627 // All the callbacks will be posted to the application from PeerConnection. |
| 418 session_->RegisterIceObserver(this); | 628 session_->RegisterIceObserver(this); |
| 419 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange); | 629 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange); |
| 630 session_->SignalVoiceChannelDestroyed.connect( | |
| 631 this, &PeerConnection::OnVoiceChannelDestroyed); | |
| 632 session_->SignalVideoChannelDestroyed.connect( | |
| 633 this, &PeerConnection::OnVideoChannelDestroyed); | |
| 634 session_->SignalDataChannelCreated.connect( | |
| 635 this, &PeerConnection::OnDataChannelCreated); | |
| 636 session_->SignalDataChannelDestroyed.connect( | |
| 637 this, &PeerConnection::OnDataChannelDestroyed); | |
| 638 session_->SignalDataChannelCreationRequested.connect( | |
| 639 this, &PeerConnection::OnDataChannelCreationRequested); | |
| 420 return true; | 640 return true; |
| 421 } | 641 } |
| 422 | 642 |
| 423 rtc::scoped_refptr<StreamCollectionInterface> | 643 rtc::scoped_refptr<StreamCollectionInterface> |
| 424 PeerConnection::local_streams() { | 644 PeerConnection::local_streams() { |
| 425 return mediastream_signaling_->local_streams(); | 645 return local_streams_; |
| 426 } | 646 } |
| 427 | 647 |
| 428 rtc::scoped_refptr<StreamCollectionInterface> | 648 rtc::scoped_refptr<StreamCollectionInterface> |
| 429 PeerConnection::remote_streams() { | 649 PeerConnection::remote_streams() { |
| 430 return mediastream_signaling_->remote_streams(); | 650 return remote_streams_; |
| 431 } | 651 } |
| 432 | 652 |
| 433 // TODO(deadbeef): Create RtpSenders immediately here, even if local | 653 // TODO(deadbeef): Create RtpSenders immediately here, even if local |
| 434 // description hasn't yet been set. | 654 // description hasn't yet been set. |
| 435 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { | 655 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { |
| 436 if (IsClosed()) { | 656 if (IsClosed()) { |
| 437 return false; | 657 return false; |
| 438 } | 658 } |
| 439 if (!CanAddLocalMediaStream(mediastream_signaling_->local_streams(), | 659 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { |
| 440 local_stream)) | |
| 441 return false; | |
| 442 | |
| 443 if (!mediastream_signaling_->AddLocalStream(local_stream)) { | |
| 444 return false; | 660 return false; |
| 445 } | 661 } |
| 662 | |
| 663 local_streams_->AddStream(local_stream); | |
| 664 | |
| 665 // Find tracks that have already been configured in SDP. This can occur if a | |
| 666 // local session description that contains the MSID of these tracks is set | |
| 667 // before AddLocalStream is called. It can also occur if the local session | |
| 668 // description is not changed and RemoveLocalStream is called and later | |
| 669 // AddLocalStream is called again with the same stream. | |
| 670 for (const auto& track : local_stream->GetAudioTracks()) { | |
| 671 const TrackInfo* track_info = | |
| 672 FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id()); | |
| 673 if (track_info) { | |
| 674 CreateAudioSender(local_stream, track.get(), track_info->ssrc); | |
| 675 } | |
| 676 } | |
| 677 for (const auto& track : local_stream->GetVideoTracks()) { | |
| 678 const TrackInfo* track_info = | |
| 679 FindTrackInfo(local_video_tracks_, local_stream->label(), track->id()); | |
| 680 if (track_info) { | |
| 681 CreateVideoSender(local_stream, track.get(), track_info->ssrc); | |
| 682 } | |
| 683 } | |
| 684 | |
| 446 stats_->AddStream(local_stream); | 685 stats_->AddStream(local_stream); |
| 447 observer_->OnRenegotiationNeeded(); | 686 observer_->OnRenegotiationNeeded(); |
| 448 return true; | 687 return true; |
| 449 } | 688 } |
| 450 | 689 |
| 690 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around | |
| 691 // indefinitely. | |
| 451 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { | 692 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { |
| 452 mediastream_signaling_->RemoveLocalStream(local_stream); | 693 for (const auto& track : local_stream->GetAudioTracks()) { |
| 694 const TrackInfo* track_info = | |
| 695 FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id()); | |
| 696 if (track_info) { | |
| 697 DestroyAudioSender(local_stream, track.get(), track_info->ssrc); | |
| 698 } | |
| 699 } | |
| 700 for (const auto& track : local_stream->GetVideoTracks()) { | |
| 701 const TrackInfo* track_info = | |
| 702 FindTrackInfo(local_video_tracks_, local_stream->label(), track->id()); | |
| 703 if (track_info) { | |
| 704 DestroyVideoSender(local_stream, track.get()); | |
| 705 } | |
| 706 } | |
| 707 | |
| 708 local_streams_->RemoveStream(local_stream); | |
| 709 | |
| 453 if (IsClosed()) { | 710 if (IsClosed()) { |
| 454 return; | 711 return; |
| 455 } | 712 } |
| 456 observer_->OnRenegotiationNeeded(); | 713 observer_->OnRenegotiationNeeded(); |
| 457 } | 714 } |
| 458 | 715 |
| 459 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( | 716 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( |
| 460 AudioTrackInterface* track) { | 717 AudioTrackInterface* track) { |
| 461 if (!track) { | 718 if (!track) { |
| 462 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL."; | 719 LOG(LS_ERROR) << "CreateDtmfSender - track is NULL."; |
| 463 return NULL; | 720 return NULL; |
| 464 } | 721 } |
| 465 if (!mediastream_signaling_->local_streams()->FindAudioTrack(track->id())) { | 722 if (!local_streams_->FindAudioTrack(track->id())) { |
| 466 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track."; | 723 LOG(LS_ERROR) << "CreateDtmfSender is called with a non local audio track."; |
| 467 return NULL; | 724 return NULL; |
| 468 } | 725 } |
| 469 | 726 |
| 470 rtc::scoped_refptr<DtmfSenderInterface> sender( | 727 rtc::scoped_refptr<DtmfSenderInterface> sender( |
| 471 DtmfSender::Create(track, signaling_thread(), session_.get())); | 728 DtmfSender::Create(track, signaling_thread(), session_.get())); |
| 472 if (!sender.get()) { | 729 if (!sender.get()) { |
| 473 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; | 730 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; |
| 474 return NULL; | 731 return NULL; |
| 475 } | 732 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 525 | 782 |
| 526 PeerConnectionInterface::IceGatheringState | 783 PeerConnectionInterface::IceGatheringState |
| 527 PeerConnection::ice_gathering_state() { | 784 PeerConnection::ice_gathering_state() { |
| 528 return ice_gathering_state_; | 785 return ice_gathering_state_; |
| 529 } | 786 } |
| 530 | 787 |
| 531 rtc::scoped_refptr<DataChannelInterface> | 788 rtc::scoped_refptr<DataChannelInterface> |
| 532 PeerConnection::CreateDataChannel( | 789 PeerConnection::CreateDataChannel( |
| 533 const std::string& label, | 790 const std::string& label, |
| 534 const DataChannelInit* config) { | 791 const DataChannelInit* config) { |
| 535 bool first_datachannel = !mediastream_signaling_->HasDataChannels(); | 792 bool first_datachannel = !HasDataChannels(); |
| 536 | 793 |
| 537 rtc::scoped_ptr<InternalDataChannelInit> internal_config; | 794 rtc::scoped_ptr<InternalDataChannelInit> internal_config; |
| 538 if (config) { | 795 if (config) { |
| 539 internal_config.reset(new InternalDataChannelInit(*config)); | 796 internal_config.reset(new InternalDataChannelInit(*config)); |
| 540 } | 797 } |
| 541 rtc::scoped_refptr<DataChannelInterface> channel( | 798 rtc::scoped_refptr<DataChannelInterface> channel( |
| 542 session_->CreateDataChannel(label, internal_config.get())); | 799 InternalCreateDataChannel(label, internal_config.get())); |
| 543 if (!channel.get()) | 800 if (!channel.get()) { |
| 544 return NULL; | 801 return nullptr; |
| 802 } | |
| 545 | 803 |
| 546 // Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or | 804 // Trigger the onRenegotiationNeeded event for every new RTP DataChannel, or |
| 547 // the first SCTP DataChannel. | 805 // the first SCTP DataChannel. |
| 548 if (session_->data_channel_type() == cricket::DCT_RTP || first_datachannel) { | 806 if (session_->data_channel_type() == cricket::DCT_RTP || first_datachannel) { |
| 549 observer_->OnRenegotiationNeeded(); | 807 observer_->OnRenegotiationNeeded(); |
| 550 } | 808 } |
| 551 | 809 |
| 552 return DataChannelProxy::Create(signaling_thread(), channel.get()); | 810 return DataChannelProxy::Create(signaling_thread(), channel.get()); |
| 553 } | 811 } |
| 554 | 812 |
| 555 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, | 813 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, |
| 556 const MediaConstraintsInterface* constraints) { | 814 const MediaConstraintsInterface* constraints) { |
| 557 if (!VERIFY(observer != NULL)) { | 815 if (!VERIFY(observer != nullptr)) { |
| 558 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; | 816 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; |
| 559 return; | 817 return; |
| 560 } | 818 } |
| 561 RTCOfferAnswerOptions options; | 819 RTCOfferAnswerOptions options; |
| 562 | 820 |
| 563 bool value; | 821 bool value; |
| 564 size_t mandatory_constraints = 0; | 822 size_t mandatory_constraints = 0; |
| 565 | 823 |
| 566 if (FindConstraint(constraints, | 824 if (FindConstraint(constraints, |
| 567 MediaConstraintsInterface::kOfferToReceiveAudio, | 825 MediaConstraintsInterface::kOfferToReceiveAudio, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 598 &value, | 856 &value, |
| 599 &mandatory_constraints)) { | 857 &mandatory_constraints)) { |
| 600 options.use_rtp_mux = value; | 858 options.use_rtp_mux = value; |
| 601 } | 859 } |
| 602 | 860 |
| 603 CreateOffer(observer, options); | 861 CreateOffer(observer, options); |
| 604 } | 862 } |
| 605 | 863 |
| 606 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, | 864 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, |
| 607 const RTCOfferAnswerOptions& options) { | 865 const RTCOfferAnswerOptions& options) { |
| 608 if (!VERIFY(observer != NULL)) { | 866 if (!VERIFY(observer != nullptr)) { |
| 609 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; | 867 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; |
| 610 return; | 868 return; |
| 611 } | 869 } |
| 612 session_->CreateOffer(observer, options); | 870 |
| 871 cricket::MediaSessionOptions session_options; | |
| 872 if (!GetOptionsForOffer(options, &session_options)) { | |
| 873 std::string error = "CreateOffer called with invalid options."; | |
| 874 LOG(LS_ERROR) << error; | |
| 875 PostCreateSessionDescriptionFailure(observer, error); | |
| 876 return; | |
| 877 } | |
| 878 | |
| 879 session_->CreateOffer(observer, options, session_options); | |
| 613 } | 880 } |
| 614 | 881 |
| 615 void PeerConnection::CreateAnswer( | 882 void PeerConnection::CreateAnswer( |
| 616 CreateSessionDescriptionObserver* observer, | 883 CreateSessionDescriptionObserver* observer, |
| 617 const MediaConstraintsInterface* constraints) { | 884 const MediaConstraintsInterface* constraints) { |
| 618 if (!VERIFY(observer != NULL)) { | 885 if (!VERIFY(observer != nullptr)) { |
| 619 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; | 886 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; |
| 620 return; | 887 return; |
| 621 } | 888 } |
| 622 session_->CreateAnswer(observer, constraints); | 889 |
| 890 cricket::MediaSessionOptions session_options; | |
| 891 if (!GetOptionsForAnswer(constraints, &session_options)) { | |
| 892 std::string error = "CreateAnswer called with invalid constraints."; | |
| 893 LOG(LS_ERROR) << error; | |
| 894 PostCreateSessionDescriptionFailure(observer, error); | |
| 895 return; | |
| 896 } | |
| 897 | |
| 898 session_->CreateAnswer(observer, constraints, session_options); | |
| 623 } | 899 } |
| 624 | 900 |
| 625 void PeerConnection::SetLocalDescription( | 901 void PeerConnection::SetLocalDescription( |
| 626 SetSessionDescriptionObserver* observer, | 902 SetSessionDescriptionObserver* observer, |
| 627 SessionDescriptionInterface* desc) { | 903 SessionDescriptionInterface* desc) { |
| 628 if (!VERIFY(observer != NULL)) { | 904 if (!VERIFY(observer != nullptr)) { |
| 629 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; | 905 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; |
| 630 return; | 906 return; |
| 631 } | 907 } |
| 632 if (!desc) { | 908 if (!desc) { |
| 633 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); | 909 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); |
| 634 return; | 910 return; |
| 635 } | 911 } |
| 636 // Update stats here so that we have the most recent stats for tracks and | 912 // Update stats here so that we have the most recent stats for tracks and |
| 637 // streams that might be removed by updating the session description. | 913 // streams that might be removed by updating the session description. |
| 638 stats_->UpdateStats(kStatsOutputLevelStandard); | 914 stats_->UpdateStats(kStatsOutputLevelStandard); |
| 639 std::string error; | 915 std::string error; |
| 640 if (!session_->SetLocalDescription(desc, &error)) { | 916 if (!session_->SetLocalDescription(desc, &error)) { |
| 641 PostSetSessionDescriptionFailure(observer, error); | 917 PostSetSessionDescriptionFailure(observer, error); |
| 642 return; | 918 return; |
| 643 } | 919 } |
| 644 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | 920 |
| 921 // If setting the description decided our SSL role, allocate any necessary | |
| 922 // SCTP sids. | |
| 923 rtc::SSLRole role; | |
| 924 if (session_->data_channel_type() == cricket::DCT_SCTP && | |
| 925 session_->GetSslRole(&role)) { | |
| 926 AllocateSctpSids(role); | |
| 927 } | |
| 928 | |
| 929 // Update state and SSRC of local MediaStreams and DataChannels based on the | |
| 930 // local session description. | |
| 931 const cricket::ContentInfo* audio_content = | |
| 932 GetFirstAudioContent(desc->description()); | |
| 933 if (audio_content) { | |
| 934 const cricket::AudioContentDescription* audio_desc = | |
| 935 static_cast<const cricket::AudioContentDescription*>( | |
| 936 audio_content->description); | |
| 937 UpdateLocalTracks(audio_desc->streams(), audio_desc->type()); | |
| 938 } | |
| 939 | |
| 940 const cricket::ContentInfo* video_content = | |
| 941 GetFirstVideoContent(desc->description()); | |
| 942 if (video_content) { | |
| 943 const cricket::VideoContentDescription* video_desc = | |
| 944 static_cast<const cricket::VideoContentDescription*>( | |
| 945 video_content->description); | |
| 946 UpdateLocalTracks(video_desc->streams(), video_desc->type()); | |
| 947 } | |
| 948 | |
| 949 const cricket::ContentInfo* data_content = | |
| 950 GetFirstDataContent(desc->description()); | |
| 951 if (data_content) { | |
| 952 const cricket::DataContentDescription* data_desc = | |
| 953 static_cast<const cricket::DataContentDescription*>( | |
| 954 data_content->description); | |
| 955 if (rtc::starts_with(data_desc->protocol().data(), | |
| 956 cricket::kMediaProtocolRtpPrefix)) { | |
| 957 UpdateLocalRtpDataChannels(data_desc->streams()); | |
| 958 } | |
| 959 } | |
| 960 | |
| 961 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | |
| 645 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); | 962 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); |
| 963 | |
| 646 // MaybeStartGathering needs to be called after posting | 964 // MaybeStartGathering needs to be called after posting |
| 647 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates | 965 // MSG_SET_SESSIONDESCRIPTION_SUCCESS, so that we don't signal any candidates |
| 648 // before signaling that SetLocalDescription completed. | 966 // before signaling that SetLocalDescription completed. |
| 649 session_->MaybeStartGathering(); | 967 session_->MaybeStartGathering(); |
| 650 } | 968 } |
| 651 | 969 |
| 652 void PeerConnection::SetRemoteDescription( | 970 void PeerConnection::SetRemoteDescription( |
| 653 SetSessionDescriptionObserver* observer, | 971 SetSessionDescriptionObserver* observer, |
| 654 SessionDescriptionInterface* desc) { | 972 SessionDescriptionInterface* desc) { |
| 655 if (!VERIFY(observer != NULL)) { | 973 if (!VERIFY(observer != nullptr)) { |
| 656 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL."; | 974 LOG(LS_ERROR) << "SetRemoteDescription - observer is NULL."; |
| 657 return; | 975 return; |
| 658 } | 976 } |
| 659 if (!desc) { | 977 if (!desc) { |
| 660 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); | 978 PostSetSessionDescriptionFailure(observer, "SessionDescription is NULL."); |
| 661 return; | 979 return; |
| 662 } | 980 } |
| 663 // Update stats here so that we have the most recent stats for tracks and | 981 // Update stats here so that we have the most recent stats for tracks and |
| 664 // streams that might be removed by updating the session description. | 982 // streams that might be removed by updating the session description. |
| 665 stats_->UpdateStats(kStatsOutputLevelStandard); | 983 stats_->UpdateStats(kStatsOutputLevelStandard); |
| 666 std::string error; | 984 std::string error; |
| 667 if (!session_->SetRemoteDescription(desc, &error)) { | 985 if (!session_->SetRemoteDescription(desc, &error)) { |
| 668 PostSetSessionDescriptionFailure(observer, error); | 986 PostSetSessionDescriptionFailure(observer, error); |
| 669 return; | 987 return; |
| 670 } | 988 } |
| 671 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | 989 |
| 990 // If setting the description decided our SSL role, allocate any necessary | |
| 991 // SCTP sids. | |
| 992 rtc::SSLRole role; | |
| 993 if (session_->data_channel_type() == cricket::DCT_SCTP && | |
| 994 session_->GetSslRole(&role)) { | |
| 995 AllocateSctpSids(role); | |
| 996 } | |
| 997 | |
| 998 const cricket::SessionDescription* remote_desc = desc->description(); | |
| 999 | |
| 1000 // We wait to signal new streams until we finish processing the description, | |
| 1001 // since only at that point will new streams have all their tracks. | |
| 1002 rtc::scoped_refptr<StreamCollection> new_streams(StreamCollection::Create()); | |
| 1003 | |
| 1004 // Find all audio rtp streams and create corresponding remote AudioTracks | |
| 1005 // and MediaStreams. | |
| 1006 const cricket::ContentInfo* audio_content = GetFirstAudioContent(remote_desc); | |
| 1007 if (audio_content) { | |
| 1008 const cricket::AudioContentDescription* desc = | |
| 1009 static_cast<const cricket::AudioContentDescription*>( | |
| 1010 audio_content->description); | |
| 1011 UpdateRemoteStreamsList(desc->streams(), desc->type(), new_streams); | |
| 1012 remote_info_.default_audio_track_needed = | |
| 1013 MediaContentDirectionHasSend(desc->direction()) && | |
| 1014 desc->streams().empty(); | |
| 1015 } | |
| 1016 | |
| 1017 // Find all video rtp streams and create corresponding remote VideoTracks | |
| 1018 // and MediaStreams. | |
| 1019 const cricket::ContentInfo* video_content = GetFirstVideoContent(remote_desc); | |
| 1020 if (video_content) { | |
| 1021 const cricket::VideoContentDescription* desc = | |
| 1022 static_cast<const cricket::VideoContentDescription*>( | |
| 1023 video_content->description); | |
| 1024 UpdateRemoteStreamsList(desc->streams(), desc->type(), new_streams); | |
| 1025 remote_info_.default_video_track_needed = | |
| 1026 MediaContentDirectionHasSend(desc->direction()) && | |
| 1027 desc->streams().empty(); | |
| 1028 } | |
| 1029 | |
| 1030 // Update the DataChannels with the information from the remote peer. | |
| 1031 const cricket::ContentInfo* data_content = GetFirstDataContent(remote_desc); | |
| 1032 if (data_content) { | |
| 1033 const cricket::DataContentDescription* data_desc = | |
| 1034 static_cast<const cricket::DataContentDescription*>( | |
| 1035 data_content->description); | |
| 1036 if (rtc::starts_with(data_desc->protocol().data(), | |
| 1037 cricket::kMediaProtocolRtpPrefix)) { | |
| 1038 UpdateRemoteRtpDataChannels(data_desc->streams()); | |
| 1039 } | |
| 1040 } | |
| 1041 | |
| 1042 // Iterate new_streams and notify the observer about new MediaStreams. | |
| 1043 for (size_t i = 0; i < new_streams->count(); ++i) { | |
| 1044 MediaStreamInterface* new_stream = new_streams->at(i); | |
| 1045 stats_->AddStream(new_stream); | |
| 1046 observer_->OnAddStream(new_stream); | |
| 1047 } | |
| 1048 | |
| 1049 // Find removed MediaStreams. | |
| 1050 if (remote_info_.IsDefaultMediaStreamNeeded() && | |
| 1051 remote_streams_->find(kDefaultStreamLabel) != nullptr) { | |
| 1052 // The default media stream already exists. No need to do anything. | |
| 1053 } else { | |
| 1054 UpdateEndedRemoteMediaStreams(); | |
| 1055 remote_info_.msid_supported |= remote_streams_->count() > 0; | |
| 1056 } | |
| 1057 MaybeCreateDefaultStream(); | |
| 1058 | |
| 1059 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | |
| 672 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); | 1060 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); |
| 673 } | 1061 } |
| 674 | 1062 |
| 675 void PeerConnection::PostSetSessionDescriptionFailure( | |
| 676 SetSessionDescriptionObserver* observer, | |
| 677 const std::string& error) { | |
| 678 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | |
| 679 msg->error = error; | |
| 680 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); | |
| 681 } | |
| 682 | |
| 683 bool PeerConnection::SetConfiguration(const RTCConfiguration& config) { | 1063 bool PeerConnection::SetConfiguration(const RTCConfiguration& config) { |
| 684 if (port_allocator_) { | 1064 if (port_allocator_) { |
| 685 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stuns; | 1065 std::vector<PortAllocatorFactoryInterface::StunConfiguration> stuns; |
| 686 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turns; | 1066 std::vector<PortAllocatorFactoryInterface::TurnConfiguration> turns; |
| 687 if (!ParseIceServers(config.servers, &stuns, &turns)) { | 1067 if (!ParseIceServers(config.servers, &stuns, &turns)) { |
| 688 return false; | 1068 return false; |
| 689 } | 1069 } |
| 690 | 1070 |
| 691 std::vector<rtc::SocketAddress> stun_hosts; | 1071 std::vector<rtc::SocketAddress> stun_hosts; |
| 692 typedef std::vector<StunConfiguration>::const_iterator StunIt; | 1072 typedef std::vector<StunConfiguration>::const_iterator StunIt; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 804 delete param; | 1184 delete param; |
| 805 break; | 1185 break; |
| 806 } | 1186 } |
| 807 case MSG_SET_SESSIONDESCRIPTION_FAILED: { | 1187 case MSG_SET_SESSIONDESCRIPTION_FAILED: { |
| 808 SetSessionDescriptionMsg* param = | 1188 SetSessionDescriptionMsg* param = |
| 809 static_cast<SetSessionDescriptionMsg*>(msg->pdata); | 1189 static_cast<SetSessionDescriptionMsg*>(msg->pdata); |
| 810 param->observer->OnFailure(param->error); | 1190 param->observer->OnFailure(param->error); |
| 811 delete param; | 1191 delete param; |
| 812 break; | 1192 break; |
| 813 } | 1193 } |
| 1194 case MSG_CREATE_SESSIONDESCRIPTION_FAILED: { | |
| 1195 CreateSessionDescriptionMsg* param = | |
| 1196 static_cast<CreateSessionDescriptionMsg*>(msg->pdata); | |
| 1197 param->observer->OnFailure(param->error); | |
| 1198 delete param; | |
| 1199 break; | |
| 1200 } | |
| 814 case MSG_GETSTATS: { | 1201 case MSG_GETSTATS: { |
| 815 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); | 1202 GetStatsMsg* param = static_cast<GetStatsMsg*>(msg->pdata); |
| 816 StatsReports reports; | 1203 StatsReports reports; |
| 817 stats_->GetStats(param->track, &reports); | 1204 stats_->GetStats(param->track, &reports); |
| 818 param->observer->OnComplete(reports); | 1205 param->observer->OnComplete(reports); |
| 819 delete param; | 1206 delete param; |
| 820 break; | 1207 break; |
| 821 } | 1208 } |
| 822 default: | 1209 default: |
| 823 ASSERT(false && "Not implemented"); | 1210 ASSERT(false && "Not implemented"); |
| 824 break; | 1211 break; |
| 825 } | 1212 } |
| 826 } | 1213 } |
| 827 | 1214 |
| 828 void PeerConnection::OnAddRemoteStream(MediaStreamInterface* stream) { | 1215 void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream, |
| 829 stats_->AddStream(stream); | 1216 AudioTrackInterface* audio_track, |
| 830 observer_->OnAddStream(stream); | 1217 uint32 ssrc) { |
| 831 } | |
| 832 | |
| 833 void PeerConnection::OnRemoveRemoteStream(MediaStreamInterface* stream) { | |
| 834 observer_->OnRemoveStream(stream); | |
| 835 } | |
| 836 | |
| 837 void PeerConnection::OnAddDataChannel(DataChannelInterface* data_channel) { | |
| 838 observer_->OnDataChannel(DataChannelProxy::Create(signaling_thread(), | |
| 839 data_channel)); | |
| 840 } | |
| 841 | |
| 842 void PeerConnection::OnAddRemoteAudioTrack(MediaStreamInterface* stream, | |
| 843 AudioTrackInterface* audio_track, | |
| 844 uint32 ssrc) { | |
| 845 receivers_.push_back(new AudioRtpReceiver(audio_track, ssrc, session_.get())); | 1218 receivers_.push_back(new AudioRtpReceiver(audio_track, ssrc, session_.get())); |
| 846 } | 1219 } |
| 847 | 1220 |
| 848 void PeerConnection::OnAddRemoteVideoTrack(MediaStreamInterface* stream, | 1221 void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream, |
| 849 VideoTrackInterface* video_track, | 1222 VideoTrackInterface* video_track, |
| 850 uint32 ssrc) { | 1223 uint32 ssrc) { |
| 851 receivers_.push_back(new VideoRtpReceiver(video_track, ssrc, session_.get())); | 1224 receivers_.push_back(new VideoRtpReceiver(video_track, ssrc, session_.get())); |
| 852 } | 1225 } |
| 853 | 1226 |
| 854 // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote | 1227 // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote |
| 855 // description. | 1228 // description. |
| 856 void PeerConnection::OnRemoveRemoteAudioTrack( | 1229 void PeerConnection::DestroyAudioReceiver(MediaStreamInterface* stream, |
| 857 MediaStreamInterface* stream, | 1230 AudioTrackInterface* audio_track) { |
| 858 AudioTrackInterface* audio_track) { | |
| 859 auto it = FindReceiverForTrack(audio_track); | 1231 auto it = FindReceiverForTrack(audio_track); |
| 860 if (it == receivers_.end()) { | 1232 if (it == receivers_.end()) { |
| 861 LOG(LS_WARNING) << "RtpReceiver for track with id " << audio_track->id() | 1233 LOG(LS_WARNING) << "RtpReceiver for track with id " << audio_track->id() |
| 862 << " doesn't exist."; | 1234 << " doesn't exist."; |
| 863 } else { | 1235 } else { |
| 864 (*it)->Stop(); | 1236 (*it)->Stop(); |
| 865 receivers_.erase(it); | 1237 receivers_.erase(it); |
| 866 } | 1238 } |
| 867 } | 1239 } |
| 868 | 1240 |
| 869 void PeerConnection::OnRemoveRemoteVideoTrack( | 1241 void PeerConnection::DestroyVideoReceiver(MediaStreamInterface* stream, |
| 870 MediaStreamInterface* stream, | 1242 VideoTrackInterface* video_track) { |
| 871 VideoTrackInterface* video_track) { | |
| 872 auto it = FindReceiverForTrack(video_track); | 1243 auto it = FindReceiverForTrack(video_track); |
| 873 if (it == receivers_.end()) { | 1244 if (it == receivers_.end()) { |
| 874 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() | 1245 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() |
| 875 << " doesn't exist."; | 1246 << " doesn't exist."; |
| 876 } else { | 1247 } else { |
| 877 (*it)->Stop(); | 1248 (*it)->Stop(); |
| 878 receivers_.erase(it); | 1249 receivers_.erase(it); |
| 879 } | 1250 } |
| 880 } | 1251 } |
| 881 | 1252 |
| 882 void PeerConnection::OnAddLocalAudioTrack(MediaStreamInterface* stream, | 1253 void PeerConnection::CreateAudioSender(MediaStreamInterface* stream, |
| 883 AudioTrackInterface* audio_track, | 1254 AudioTrackInterface* audio_track, |
| 884 uint32 ssrc) { | 1255 uint32 ssrc) { |
| 885 senders_.push_back(new AudioRtpSender(audio_track, ssrc, session_.get())); | 1256 senders_.push_back(new AudioRtpSender(audio_track, ssrc, session_.get())); |
| 886 stats_->AddLocalAudioTrack(audio_track, ssrc); | 1257 stats_->AddLocalAudioTrack(audio_track, ssrc); |
| 887 } | 1258 } |
| 888 | 1259 |
| 889 void PeerConnection::OnAddLocalVideoTrack(MediaStreamInterface* stream, | 1260 void PeerConnection::CreateVideoSender(MediaStreamInterface* stream, |
| 890 VideoTrackInterface* video_track, | 1261 VideoTrackInterface* video_track, |
| 891 uint32 ssrc) { | 1262 uint32 ssrc) { |
| 892 senders_.push_back(new VideoRtpSender(video_track, ssrc, session_.get())); | 1263 senders_.push_back(new VideoRtpSender(video_track, ssrc, session_.get())); |
| 893 } | 1264 } |
| 894 | 1265 |
| 895 // TODO(deadbeef): Keep RtpSenders around even if track goes away in local | 1266 // TODO(deadbeef): Keep RtpSenders around even if track goes away in local |
| 896 // description. | 1267 // description. |
| 897 void PeerConnection::OnRemoveLocalAudioTrack(MediaStreamInterface* stream, | 1268 void PeerConnection::DestroyAudioSender(MediaStreamInterface* stream, |
| 898 AudioTrackInterface* audio_track, | 1269 AudioTrackInterface* audio_track, |
| 899 uint32 ssrc) { | 1270 uint32 ssrc) { |
| 900 auto it = FindSenderForTrack(audio_track); | 1271 auto it = FindSenderForTrack(audio_track); |
| 901 if (it == senders_.end()) { | 1272 if (it == senders_.end()) { |
| 902 LOG(LS_WARNING) << "RtpSender for track with id " << audio_track->id() | 1273 LOG(LS_WARNING) << "RtpSender for track with id " << audio_track->id() |
| 903 << " doesn't exist."; | 1274 << " doesn't exist."; |
| 904 return; | 1275 return; |
| 905 } else { | 1276 } else { |
| 906 (*it)->Stop(); | 1277 (*it)->Stop(); |
| 907 senders_.erase(it); | 1278 senders_.erase(it); |
| 908 } | 1279 } |
| 909 stats_->RemoveLocalAudioTrack(audio_track, ssrc); | 1280 stats_->RemoveLocalAudioTrack(audio_track, ssrc); |
| 910 } | 1281 } |
| 911 | 1282 |
| 912 void PeerConnection::OnRemoveLocalVideoTrack(MediaStreamInterface* stream, | 1283 void PeerConnection::DestroyVideoSender(MediaStreamInterface* stream, |
| 913 VideoTrackInterface* video_track) { | 1284 VideoTrackInterface* video_track) { |
| 914 auto it = FindSenderForTrack(video_track); | 1285 auto it = FindSenderForTrack(video_track); |
| 915 if (it == senders_.end()) { | 1286 if (it == senders_.end()) { |
| 916 LOG(LS_WARNING) << "RtpSender for track with id " << video_track->id() | 1287 LOG(LS_WARNING) << "RtpSender for track with id " << video_track->id() |
| 917 << " doesn't exist."; | 1288 << " doesn't exist."; |
| 918 return; | 1289 return; |
| 919 } else { | 1290 } else { |
| 920 (*it)->Stop(); | 1291 (*it)->Stop(); |
| 921 senders_.erase(it); | 1292 senders_.erase(it); |
| 922 } | 1293 } |
| 923 } | 1294 } |
| 924 | 1295 |
| 925 void PeerConnection::OnRemoveLocalStream(MediaStreamInterface* stream) { | |
| 926 } | |
| 927 | |
| 928 void PeerConnection::OnIceConnectionChange( | 1296 void PeerConnection::OnIceConnectionChange( |
| 929 PeerConnectionInterface::IceConnectionState new_state) { | 1297 PeerConnectionInterface::IceConnectionState new_state) { |
| 930 ASSERT(signaling_thread()->IsCurrent()); | 1298 ASSERT(signaling_thread()->IsCurrent()); |
| 931 // After transitioning to "closed", ignore any additional states from | 1299 // After transitioning to "closed", ignore any additional states from |
| 932 // WebRtcSession (such as "disconnected"). | 1300 // WebRtcSession (such as "disconnected"). |
| 933 if (ice_connection_state_ == kIceConnectionClosed) { | 1301 if (IsClosed()) { |
| 934 return; | 1302 return; |
| 935 } | 1303 } |
| 936 ice_connection_state_ = new_state; | 1304 ice_connection_state_ = new_state; |
| 937 observer_->OnIceConnectionChange(ice_connection_state_); | 1305 observer_->OnIceConnectionChange(ice_connection_state_); |
| 938 } | 1306 } |
| 939 | 1307 |
| 940 void PeerConnection::OnIceGatheringChange( | 1308 void PeerConnection::OnIceGatheringChange( |
| 941 PeerConnectionInterface::IceGatheringState new_state) { | 1309 PeerConnectionInterface::IceGatheringState new_state) { |
| 942 ASSERT(signaling_thread()->IsCurrent()); | 1310 ASSERT(signaling_thread()->IsCurrent()); |
| 943 if (IsClosed()) { | 1311 if (IsClosed()) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 970 observer_->OnIceConnectionChange(ice_connection_state_); | 1338 observer_->OnIceConnectionChange(ice_connection_state_); |
| 971 if (ice_gathering_state_ != kIceGatheringComplete) { | 1339 if (ice_gathering_state_ != kIceGatheringComplete) { |
| 972 ice_gathering_state_ = kIceGatheringComplete; | 1340 ice_gathering_state_ = kIceGatheringComplete; |
| 973 observer_->OnIceGatheringChange(ice_gathering_state_); | 1341 observer_->OnIceGatheringChange(ice_gathering_state_); |
| 974 } | 1342 } |
| 975 } | 1343 } |
| 976 observer_->OnSignalingChange(signaling_state_); | 1344 observer_->OnSignalingChange(signaling_state_); |
| 977 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); | 1345 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); |
| 978 } | 1346 } |
| 979 | 1347 |
| 1348 void PeerConnection::PostSetSessionDescriptionFailure( | |
| 1349 SetSessionDescriptionObserver* observer, | |
| 1350 const std::string& error) { | |
| 1351 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | |
| 1352 msg->error = error; | |
| 1353 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); | |
| 1354 } | |
| 1355 | |
| 1356 void PeerConnection::PostCreateSessionDescriptionFailure( | |
| 1357 CreateSessionDescriptionObserver* observer, | |
| 1358 const std::string& error) { | |
| 1359 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); | |
| 1360 msg->error = error; | |
| 1361 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); | |
| 1362 } | |
| 1363 | |
| 1364 bool PeerConnection::GetOptionsForOffer( | |
| 1365 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | |
| 1366 cricket::MediaSessionOptions* session_options) { | |
| 1367 SetStreams(session_options, local_streams_, rtp_data_channels_); | |
| 1368 | |
| 1369 if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) { | |
| 1370 return false; | |
| 1371 } | |
| 1372 | |
| 1373 if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) { | |
| 1374 session_options->data_channel_type = cricket::DCT_SCTP; | |
| 1375 } | |
| 1376 return true; | |
| 1377 } | |
| 1378 | |
| 1379 bool PeerConnection::GetOptionsForAnswer( | |
| 1380 const MediaConstraintsInterface* constraints, | |
| 1381 cricket::MediaSessionOptions* session_options) { | |
| 1382 SetStreams(session_options, local_streams_, rtp_data_channels_); | |
| 1383 session_options->recv_audio = false; | |
| 1384 session_options->recv_video = false; | |
| 1385 | |
| 1386 if (!ParseConstraintsForAnswer(constraints, session_options)) { | |
| 1387 return false; | |
| 1388 } | |
| 1389 | |
| 1390 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams | |
| 1391 // are not signaled in the SDP so does not go through that path and must be | |
| 1392 // handled here. | |
| 1393 if (session_->data_channel_type() == cricket::DCT_SCTP) { | |
| 1394 session_options->data_channel_type = cricket::DCT_SCTP; | |
| 1395 } | |
| 1396 return true; | |
| 1397 } | |
| 1398 | |
| 1399 void PeerConnection::UpdateRemoteStreamsList( | |
| 1400 const cricket::StreamParamsVec& streams, | |
| 1401 cricket::MediaType media_type, | |
| 1402 StreamCollection* new_streams) { | |
| 1403 TrackInfos* current_tracks = GetRemoteTracks(media_type); | |
| 1404 | |
| 1405 // Find removed tracks. I.e., tracks where the track id or ssrc don't match | |
| 1406 // the | |
| 1407 // new StreamParam. | |
| 1408 auto track_it = current_tracks->begin(); | |
| 1409 while (track_it != current_tracks->end()) { | |
| 1410 const TrackInfo& info = *track_it; | |
| 1411 const cricket::StreamParams* params = | |
| 1412 cricket::GetStreamBySsrc(streams, info.ssrc); | |
| 1413 if (!params || params->id != info.track_id) { | |
| 1414 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); | |
| 1415 track_it = current_tracks->erase(track_it); | |
| 1416 } else { | |
| 1417 ++track_it; | |
| 1418 } | |
| 1419 } | |
| 1420 | |
| 1421 // Find new and active tracks. | |
| 1422 for (const cricket::StreamParams& params : streams) { | |
| 1423 // The sync_label is the MediaStream label and the |stream.id| is the | |
| 1424 // track id. | |
| 1425 const std::string& stream_label = params.sync_label; | |
| 1426 const std::string& track_id = params.id; | |
| 1427 uint32 ssrc = params.first_ssrc(); | |
| 1428 | |
| 1429 rtc::scoped_refptr<MediaStreamInterface> stream = | |
| 1430 remote_streams_->find(stream_label); | |
| 1431 if (!stream) { | |
| 1432 // This is a new MediaStream. Create a new remote MediaStream. | |
| 1433 stream = remote_stream_factory_->CreateMediaStream(stream_label); | |
| 1434 remote_streams_->AddStream(stream); | |
| 1435 new_streams->AddStream(stream); | |
| 1436 } | |
| 1437 | |
| 1438 const TrackInfo* track_info = | |
| 1439 FindTrackInfo(*current_tracks, stream_label, track_id); | |
| 1440 if (!track_info) { | |
| 1441 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); | |
| 1442 OnRemoteTrackSeen(stream_label, track_id, ssrc, media_type); | |
| 1443 } | |
| 1444 } | |
| 1445 } | |
| 1446 | |
| 1447 void PeerConnection::OnRemoteTrackSeen(const std::string& stream_label, | |
| 1448 const std::string& track_id, | |
| 1449 uint32 ssrc, | |
| 1450 cricket::MediaType media_type) { | |
| 1451 MediaStreamInterface* stream = remote_streams_->find(stream_label); | |
| 1452 | |
| 1453 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
| 1454 AudioTrackInterface* audio_track = | |
| 1455 remote_stream_factory_->AddAudioTrack(stream, track_id); | |
| 1456 CreateAudioReceiver(stream, audio_track, ssrc); | |
| 1457 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1458 VideoTrackInterface* video_track = | |
| 1459 remote_stream_factory_->AddVideoTrack(stream, track_id); | |
| 1460 CreateVideoReceiver(stream, video_track, ssrc); | |
| 1461 } else { | |
| 1462 RTC_DCHECK(false && "Invalid media type"); | |
| 1463 } | |
| 1464 } | |
| 1465 | |
| 1466 void PeerConnection::OnRemoteTrackRemoved(const std::string& stream_label, | |
| 1467 const std::string& track_id, | |
| 1468 cricket::MediaType media_type) { | |
| 1469 MediaStreamInterface* stream = remote_streams_->find(stream_label); | |
| 1470 | |
| 1471 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
| 1472 rtc::scoped_refptr<AudioTrackInterface> audio_track = | |
| 1473 stream->FindAudioTrack(track_id); | |
| 1474 if (audio_track) { | |
| 1475 audio_track->set_state(webrtc::MediaStreamTrackInterface::kEnded); | |
| 1476 stream->RemoveTrack(audio_track); | |
| 1477 DestroyAudioReceiver(stream, audio_track); | |
| 1478 } | |
| 1479 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1480 rtc::scoped_refptr<VideoTrackInterface> video_track = | |
| 1481 stream->FindVideoTrack(track_id); | |
| 1482 if (video_track) { | |
| 1483 video_track->set_state(webrtc::MediaStreamTrackInterface::kEnded); | |
| 1484 stream->RemoveTrack(video_track); | |
| 1485 DestroyVideoReceiver(stream, video_track); | |
| 1486 } | |
| 1487 } else { | |
| 1488 ASSERT(false && "Invalid media type"); | |
| 1489 } | |
| 1490 } | |
| 1491 | |
| 1492 void PeerConnection::UpdateEndedRemoteMediaStreams() { | |
| 1493 std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_to_remove; | |
| 1494 for (size_t i = 0; i < remote_streams_->count(); ++i) { | |
| 1495 MediaStreamInterface* stream = remote_streams_->at(i); | |
| 1496 if (stream->GetAudioTracks().empty() && stream->GetVideoTracks().empty()) { | |
| 1497 streams_to_remove.push_back(stream); | |
| 1498 } | |
| 1499 } | |
| 1500 | |
| 1501 for (const auto& stream : streams_to_remove) { | |
| 1502 remote_streams_->RemoveStream(stream); | |
| 1503 observer_->OnRemoveStream(stream); | |
| 1504 } | |
| 1505 } | |
| 1506 | |
| 1507 void PeerConnection::MaybeCreateDefaultStream() { | |
| 1508 if (!remote_info_.IsDefaultMediaStreamNeeded()) { | |
| 1509 return; | |
| 1510 } | |
| 1511 | |
| 1512 bool default_created = false; | |
| 1513 | |
| 1514 rtc::scoped_refptr<MediaStreamInterface> default_remote_stream = | |
| 1515 remote_streams_->find(kDefaultStreamLabel); | |
| 1516 if (default_remote_stream == nullptr) { | |
| 1517 default_created = true; | |
| 1518 default_remote_stream = | |
| 1519 remote_stream_factory_->CreateMediaStream(kDefaultStreamLabel); | |
| 1520 remote_streams_->AddStream(default_remote_stream); | |
| 1521 } | |
| 1522 if (remote_info_.default_audio_track_needed && | |
| 1523 default_remote_stream->GetAudioTracks().size() == 0) { | |
| 1524 remote_audio_tracks_.push_back( | |
| 1525 TrackInfo(kDefaultStreamLabel, kDefaultAudioTrackLabel, 0)); | |
| 1526 OnRemoteTrackSeen(kDefaultStreamLabel, kDefaultAudioTrackLabel, 0, | |
| 1527 cricket::MEDIA_TYPE_AUDIO); | |
| 1528 } | |
| 1529 if (remote_info_.default_video_track_needed && | |
| 1530 default_remote_stream->GetVideoTracks().size() == 0) { | |
| 1531 remote_video_tracks_.push_back( | |
| 1532 TrackInfo(kDefaultStreamLabel, kDefaultVideoTrackLabel, 0)); | |
| 1533 OnRemoteTrackSeen(kDefaultStreamLabel, kDefaultVideoTrackLabel, 0, | |
| 1534 cricket::MEDIA_TYPE_VIDEO); | |
| 1535 } | |
| 1536 if (default_created) { | |
| 1537 stats_->AddStream(default_remote_stream); | |
| 1538 observer_->OnAddStream(default_remote_stream); | |
| 1539 } | |
| 1540 } | |
| 1541 | |
| 1542 void PeerConnection::RejectRemoteTracks(cricket::MediaType media_type) { | |
|
pthatcher1
2015/10/08 05:23:54
Should this be called EndRemoteTracks? All it doe
Taylor Brandstetter
2015/10/09 19:54:09
I agree; done. Funny enough, I think we already ma
| |
| 1543 TrackInfos* current_tracks = GetRemoteTracks(media_type); | |
| 1544 for (TrackInfos::iterator track_it = current_tracks->begin(); | |
| 1545 track_it != current_tracks->end(); ++track_it) { | |
| 1546 const TrackInfo& info = *track_it; | |
| 1547 MediaStreamInterface* stream = remote_streams_->find(info.stream_label); | |
| 1548 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
| 1549 AudioTrackInterface* track = stream->FindAudioTrack(info.track_id); | |
| 1550 // There's no guarantee the track is still available, e.g. the track may | |
| 1551 // have been removed from the stream by javascript. | |
| 1552 if (track) { | |
| 1553 track->set_state(webrtc::MediaStreamTrackInterface::kEnded); | |
| 1554 } | |
| 1555 } | |
| 1556 if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1557 VideoTrackInterface* track = stream->FindVideoTrack(info.track_id); | |
| 1558 // There's no guarantee the track is still available, e.g. the track may | |
| 1559 // have been removed from the stream by javascript. | |
| 1560 if (track) { | |
| 1561 track->set_state(webrtc::MediaStreamTrackInterface::kEnded); | |
| 1562 } | |
| 1563 } | |
| 1564 } | |
| 1565 } | |
| 1566 | |
| 1567 void PeerConnection::UpdateLocalTracks( | |
| 1568 const std::vector<cricket::StreamParams>& streams, | |
| 1569 cricket::MediaType media_type) { | |
| 1570 TrackInfos* current_tracks = GetLocalTracks(media_type); | |
| 1571 | |
| 1572 // Find removed tracks. I.e., tracks where the track id, stream label or ssrc | |
| 1573 // don't match the new StreamParam. | |
| 1574 TrackInfos::iterator track_it = current_tracks->begin(); | |
| 1575 while (track_it != current_tracks->end()) { | |
| 1576 const TrackInfo& info = *track_it; | |
| 1577 const cricket::StreamParams* params = | |
| 1578 cricket::GetStreamBySsrc(streams, info.ssrc); | |
| 1579 if (!params || params->id != info.track_id || | |
| 1580 params->sync_label != info.stream_label) { | |
| 1581 OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc, | |
| 1582 media_type); | |
| 1583 track_it = current_tracks->erase(track_it); | |
| 1584 } else { | |
| 1585 ++track_it; | |
| 1586 } | |
| 1587 } | |
| 1588 | |
| 1589 // Find new and active tracks. | |
| 1590 for (const cricket::StreamParams& params : streams) { | |
| 1591 // The sync_label is the MediaStream label and the |stream.id| is the | |
| 1592 // track id. | |
| 1593 const std::string& stream_label = params.sync_label; | |
| 1594 const std::string& track_id = params.id; | |
| 1595 uint32 ssrc = params.first_ssrc(); | |
| 1596 const TrackInfo* track_info = | |
| 1597 FindTrackInfo(*current_tracks, stream_label, track_id); | |
| 1598 if (!track_info) { | |
| 1599 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); | |
| 1600 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); | |
| 1601 } | |
| 1602 } | |
| 1603 } | |
| 1604 | |
| 1605 void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, | |
| 1606 const std::string& track_id, | |
| 1607 uint32 ssrc, | |
| 1608 cricket::MediaType media_type) { | |
| 1609 MediaStreamInterface* stream = local_streams_->find(stream_label); | |
| 1610 if (!stream) { | |
| 1611 LOG(LS_WARNING) << "An unknown local MediaStream with label " | |
| 1612 << stream_label << " has been configured."; | |
| 1613 return; | |
| 1614 } | |
| 1615 | |
| 1616 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
| 1617 AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id); | |
| 1618 if (!audio_track) { | |
| 1619 LOG(LS_WARNING) << "An unknown local AudioTrack with id , " << track_id | |
| 1620 << " has been configured."; | |
| 1621 return; | |
| 1622 } | |
| 1623 CreateAudioSender(stream, audio_track, ssrc); | |
| 1624 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1625 VideoTrackInterface* video_track = stream->FindVideoTrack(track_id); | |
| 1626 if (!video_track) { | |
| 1627 LOG(LS_WARNING) << "An unknown local VideoTrack with id , " << track_id | |
| 1628 << " has been configured."; | |
| 1629 return; | |
| 1630 } | |
| 1631 CreateVideoSender(stream, video_track, ssrc); | |
| 1632 } else { | |
| 1633 RTC_DCHECK(false && "Invalid media type"); | |
| 1634 } | |
| 1635 } | |
| 1636 | |
| 1637 void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, | |
| 1638 const std::string& track_id, | |
| 1639 uint32 ssrc, | |
| 1640 cricket::MediaType media_type) { | |
| 1641 MediaStreamInterface* stream = local_streams_->find(stream_label); | |
| 1642 if (!stream) { | |
| 1643 // This is the normal case. I.e., RemoveLocalStream has been called and the | |
| 1644 // SessionDescriptions has been renegotiated. | |
| 1645 return; | |
| 1646 } | |
| 1647 // A track has been removed from the SessionDescription but the MediaStream | |
| 1648 // is still associated with PeerConnection. This only occurs if the SDP | |
| 1649 // doesn't match with the calls to AddLocalStream and RemoveLocalStream. | |
| 1650 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | |
| 1651 AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id); | |
| 1652 if (!audio_track) { | |
| 1653 return; | |
| 1654 } | |
| 1655 DestroyAudioSender(stream, audio_track, ssrc); | |
| 1656 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1657 VideoTrackInterface* video_track = stream->FindVideoTrack(track_id); | |
| 1658 if (!video_track) { | |
| 1659 return; | |
| 1660 } | |
| 1661 DestroyVideoSender(stream, video_track); | |
| 1662 } else { | |
| 1663 RTC_DCHECK(false && "Invalid media type."); | |
| 1664 } | |
| 1665 } | |
| 1666 | |
| 1667 void PeerConnection::UpdateLocalRtpDataChannels( | |
| 1668 const cricket::StreamParamsVec& streams) { | |
| 1669 std::vector<std::string> existing_channels; | |
| 1670 | |
| 1671 // Find new and active data channels. | |
| 1672 for (const cricket::StreamParams& params : streams) { | |
| 1673 // |it->sync_label| is actually the data channel label. The reason is that | |
| 1674 // we use the same naming of data channels as we do for | |
| 1675 // MediaStreams and Tracks. | |
| 1676 // For MediaStreams, the sync_label is the MediaStream label and the | |
| 1677 // track label is the same as |streamid|. | |
| 1678 const std::string& channel_label = params.sync_label; | |
| 1679 auto data_channel_it = rtp_data_channels_.find(channel_label); | |
| 1680 if (!VERIFY(data_channel_it != rtp_data_channels_.end())) { | |
| 1681 continue; | |
| 1682 } | |
| 1683 // Set the SSRC the data channel should use for sending. | |
| 1684 data_channel_it->second->SetSendSsrc(params.first_ssrc()); | |
| 1685 existing_channels.push_back(data_channel_it->first); | |
| 1686 } | |
| 1687 | |
| 1688 UpdateClosingRtpDataChannels(existing_channels, true); | |
| 1689 } | |
| 1690 | |
| 1691 void PeerConnection::UpdateRemoteRtpDataChannels( | |
| 1692 const cricket::StreamParamsVec& streams) { | |
| 1693 std::vector<std::string> existing_channels; | |
| 1694 | |
| 1695 // Find new and active data channels. | |
| 1696 for (const cricket::StreamParams& params : streams) { | |
| 1697 // The data channel label is either the mslabel or the SSRC if the mslabel | |
| 1698 // does not exist. Ex a=ssrc:444330170 mslabel:test1. | |
| 1699 std::string label = params.sync_label.empty() | |
| 1700 ? rtc::ToString(params.first_ssrc()) | |
| 1701 : params.sync_label; | |
| 1702 auto data_channel_it = rtp_data_channels_.find(label); | |
| 1703 if (data_channel_it == rtp_data_channels_.end()) { | |
| 1704 // This is a new data channel. | |
| 1705 CreateRemoteRtpDataChannel(label, params.first_ssrc()); | |
| 1706 } else { | |
| 1707 data_channel_it->second->SetReceiveSsrc(params.first_ssrc()); | |
| 1708 } | |
| 1709 existing_channels.push_back(label); | |
| 1710 } | |
| 1711 | |
| 1712 UpdateClosingRtpDataChannels(existing_channels, false); | |
| 1713 } | |
| 1714 | |
| 1715 void PeerConnection::UpdateClosingRtpDataChannels( | |
| 1716 const std::vector<std::string>& active_channels, | |
| 1717 bool is_local_update) { | |
| 1718 auto it = rtp_data_channels_.begin(); | |
| 1719 while (it != rtp_data_channels_.end()) { | |
| 1720 DataChannel* data_channel = it->second; | |
| 1721 if (std::find(active_channels.begin(), active_channels.end(), | |
| 1722 data_channel->label()) != active_channels.end()) { | |
| 1723 ++it; | |
| 1724 continue; | |
| 1725 } | |
| 1726 | |
| 1727 if (is_local_update) { | |
| 1728 data_channel->SetSendSsrc(0); | |
| 1729 } else { | |
| 1730 data_channel->RemotePeerRequestClose(); | |
| 1731 } | |
| 1732 | |
| 1733 if (data_channel->state() == DataChannel::kClosed) { | |
| 1734 it = rtp_data_channels_.erase(it); | |
| 1735 } else { | |
| 1736 ++it; | |
| 1737 } | |
| 1738 } | |
| 1739 } | |
| 1740 | |
| 1741 void PeerConnection::CreateRemoteRtpDataChannel(const std::string& label, | |
| 1742 uint32 remote_ssrc) { | |
| 1743 rtc::scoped_refptr<DataChannel> channel( | |
| 1744 InternalCreateDataChannel(label, nullptr)); | |
| 1745 if (!channel.get()) { | |
| 1746 LOG(LS_WARNING) << "Remote peer requested a DataChannel but" | |
| 1747 << "CreateDataChannel failed."; | |
| 1748 return; | |
| 1749 } | |
| 1750 channel->SetReceiveSsrc(remote_ssrc); | |
| 1751 observer_->OnDataChannel( | |
| 1752 DataChannelProxy::Create(signaling_thread(), channel)); | |
| 1753 } | |
| 1754 | |
| 1755 rtc::scoped_refptr<DataChannel> PeerConnection::InternalCreateDataChannel( | |
| 1756 const std::string& label, | |
| 1757 const InternalDataChannelInit* config) { | |
| 1758 if (IsClosed()) { | |
| 1759 return nullptr; | |
| 1760 } | |
| 1761 if (session_->data_channel_type() == cricket::DCT_NONE) { | |
| 1762 LOG(LS_ERROR) | |
| 1763 << "InternalCreateDataChannel: Data is not supported in this call."; | |
| 1764 return nullptr; | |
| 1765 } | |
| 1766 InternalDataChannelInit new_config = | |
| 1767 config ? (*config) : InternalDataChannelInit(); | |
| 1768 if (session_->data_channel_type() == cricket::DCT_SCTP) { | |
| 1769 if (new_config.id < 0) { | |
| 1770 rtc::SSLRole role; | |
| 1771 if (session_->GetSslRole(&role) && | |
| 1772 !sid_allocator_.AllocateSctpSid(role, &new_config.id)) { | |
| 1773 LOG(LS_ERROR) << "No id can be allocated for the SCTP data channel."; | |
| 1774 return nullptr; | |
| 1775 } | |
| 1776 } else if (!sid_allocator_.ReserveSctpSid(new_config.id)) { | |
| 1777 LOG(LS_ERROR) << "Failed to create a SCTP data channel " | |
| 1778 << "because the id is already in use or out of range."; | |
| 1779 return nullptr; | |
| 1780 } | |
| 1781 } | |
| 1782 | |
| 1783 rtc::scoped_refptr<DataChannel> channel(DataChannel::Create( | |
| 1784 session_.get(), session_->data_channel_type(), label, new_config)); | |
| 1785 if (!channel) { | |
| 1786 sid_allocator_.ReleaseSctpSid(new_config.id); | |
| 1787 return nullptr; | |
| 1788 } | |
| 1789 | |
| 1790 if (channel->data_channel_type() == cricket::DCT_RTP) { | |
| 1791 if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) { | |
| 1792 LOG(LS_ERROR) << "DataChannel with label " << channel->label() | |
| 1793 << " already exists."; | |
| 1794 return nullptr; | |
| 1795 } | |
| 1796 rtp_data_channels_[channel->label()] = channel; | |
| 1797 } else { | |
| 1798 RTC_DCHECK(channel->data_channel_type() == cricket::DCT_SCTP); | |
| 1799 sctp_data_channels_.push_back(channel); | |
| 1800 channel->SignalClosed.connect(this, | |
| 1801 &PeerConnection::OnSctpDataChannelClosed); | |
| 1802 } | |
| 1803 | |
| 1804 return channel; | |
| 1805 } | |
| 1806 | |
| 1807 bool PeerConnection::HasDataChannels() const { | |
| 1808 return !rtp_data_channels_.empty() || !sctp_data_channels_.empty(); | |
| 1809 } | |
| 1810 | |
| 1811 void PeerConnection::AllocateSctpSids(rtc::SSLRole role) { | |
| 1812 for (const auto& channel : sctp_data_channels_) { | |
| 1813 if (channel->id() < 0) { | |
| 1814 int sid; | |
| 1815 if (!sid_allocator_.AllocateSctpSid(role, &sid)) { | |
| 1816 LOG(LS_ERROR) << "Failed to allocate SCTP sid."; | |
| 1817 continue; | |
| 1818 } | |
| 1819 channel->SetSctpSid(sid); | |
| 1820 } | |
| 1821 } | |
| 1822 } | |
| 1823 | |
| 1824 void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) { | |
| 1825 for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end(); | |
| 1826 ++it) { | |
| 1827 if (it->get() == channel) { | |
| 1828 int sid = channel->id(); | |
| 1829 RTC_DCHECK(sid >= 0); | |
| 1830 sid_allocator_.ReleaseSctpSid(sid); | |
| 1831 sctp_data_channels_.erase(it); | |
| 1832 return; | |
| 1833 } | |
| 1834 } | |
| 1835 } | |
| 1836 | |
| 1837 void PeerConnection::OnVoiceChannelDestroyed() { | |
| 1838 RejectRemoteTracks(cricket::MEDIA_TYPE_AUDIO); | |
| 1839 } | |
| 1840 | |
| 1841 void PeerConnection::OnVideoChannelDestroyed() { | |
| 1842 RejectRemoteTracks(cricket::MEDIA_TYPE_VIDEO); | |
| 1843 } | |
| 1844 | |
| 1845 void PeerConnection::OnDataChannelCreated() { | |
| 1846 for (const auto& channel : sctp_data_channels_) { | |
| 1847 channel->OnTransportChannelCreated(); | |
| 1848 } | |
| 1849 } | |
| 1850 | |
| 1851 void PeerConnection::OnDataChannelDestroyed() { | |
| 1852 // Use a temporary copy of the RTP/SCTP DataChannel list because the | |
| 1853 // DataChannel may callback to us and try to modify the list. | |
| 1854 std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs; | |
| 1855 temp_rtp_dcs.swap(rtp_data_channels_); | |
| 1856 for (const auto& kv : temp_rtp_dcs) { | |
| 1857 kv.second->OnDataEngineClose(); | |
|
pthatcher1
2015/10/08 05:23:54
Can we rename these so they are consistent with on
Taylor Brandstetter
2015/10/09 19:54:09
Well, since the cricket::DataChannel actually IS b
pthatcher1
2015/10/09 21:12:26
Sounds good.
| |
| 1858 } | |
| 1859 | |
| 1860 std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs; | |
| 1861 temp_sctp_dcs.swap(sctp_data_channels_); | |
| 1862 for (const auto& channel : temp_sctp_dcs) { | |
| 1863 channel->OnDataEngineClose(); | |
| 1864 } | |
| 1865 } | |
| 1866 | |
| 1867 void PeerConnection::OnDataChannelCreationRequested( | |
| 1868 const std::string& label, | |
| 1869 const InternalDataChannelInit& config) { | |
| 1870 rtc::scoped_refptr<DataChannel> channel( | |
| 1871 InternalCreateDataChannel(label, &config)); | |
| 1872 if (!channel.get()) { | |
| 1873 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; | |
| 1874 return; | |
| 1875 } | |
| 1876 | |
| 1877 observer_->OnDataChannel( | |
| 1878 DataChannelProxy::Create(signaling_thread(), channel)); | |
| 1879 } | |
| 1880 | |
| 980 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator | 1881 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator |
| 981 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { | 1882 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { |
| 982 return std::find_if( | 1883 return std::find_if( |
| 983 senders_.begin(), senders_.end(), | 1884 senders_.begin(), senders_.end(), |
| 984 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { | 1885 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { |
| 985 return sender->track() == track; | 1886 return sender->track() == track; |
| 986 }); | 1887 }); |
| 987 } | 1888 } |
| 988 | 1889 |
| 989 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator | 1890 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator |
| 990 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) { | 1891 PeerConnection::FindReceiverForTrack(MediaStreamTrackInterface* track) { |
| 991 return std::find_if( | 1892 return std::find_if( |
| 992 receivers_.begin(), receivers_.end(), | 1893 receivers_.begin(), receivers_.end(), |
| 993 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) { | 1894 [track](const rtc::scoped_refptr<RtpReceiverInterface>& receiver) { |
| 994 return receiver->track() == track; | 1895 return receiver->track() == track; |
| 995 }); | 1896 }); |
| 996 } | 1897 } |
| 997 | 1898 |
| 1899 PeerConnection::TrackInfos* PeerConnection::GetRemoteTracks( | |
| 1900 cricket::MediaType media_type) { | |
| 1901 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || | |
| 1902 media_type == cricket::MEDIA_TYPE_VIDEO); | |
| 1903 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &remote_audio_tracks_ | |
| 1904 : &remote_video_tracks_; | |
| 1905 } | |
| 1906 | |
| 1907 PeerConnection::TrackInfos* PeerConnection::GetLocalTracks( | |
| 1908 cricket::MediaType media_type) { | |
| 1909 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || | |
| 1910 media_type == cricket::MEDIA_TYPE_VIDEO); | |
| 1911 return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_tracks_ | |
| 1912 : &local_video_tracks_; | |
| 1913 } | |
| 1914 | |
| 1915 const PeerConnection::TrackInfo* PeerConnection::FindTrackInfo( | |
| 1916 const PeerConnection::TrackInfos& infos, | |
| 1917 const std::string& stream_label, | |
| 1918 const std::string track_id) const { | |
| 1919 for (const TrackInfo& track_info : infos) { | |
| 1920 if (track_info.stream_label == stream_label && | |
| 1921 track_info.track_id == track_id) { | |
| 1922 return &track_info; | |
| 1923 } | |
| 1924 } | |
| 1925 return nullptr; | |
| 1926 } | |
| 1927 | |
| 1928 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { | |
| 1929 for (const auto& channel : sctp_data_channels_) { | |
| 1930 if (channel->id() == sid) { | |
| 1931 return channel; | |
| 1932 } | |
| 1933 } | |
| 1934 return nullptr; | |
| 1935 } | |
| 1936 | |
| 998 } // namespace webrtc | 1937 } // namespace webrtc |
| OLD | NEW |