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 |