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