| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 #include "webrtc/base/stringutils.h" | 53 #include "webrtc/base/stringutils.h" |
| 54 #include "webrtc/p2p/client/basicportallocator.h" | 54 #include "webrtc/p2p/client/basicportallocator.h" |
| 55 #include "webrtc/system_wrappers/include/field_trial.h" | 55 #include "webrtc/system_wrappers/include/field_trial.h" |
| 56 | 56 |
| 57 namespace { | 57 namespace { |
| 58 | 58 |
| 59 using webrtc::DataChannel; | 59 using webrtc::DataChannel; |
| 60 using webrtc::MediaConstraintsInterface; | 60 using webrtc::MediaConstraintsInterface; |
| 61 using webrtc::MediaStreamInterface; | 61 using webrtc::MediaStreamInterface; |
| 62 using webrtc::PeerConnectionInterface; | 62 using webrtc::PeerConnectionInterface; |
| 63 using webrtc::RtpSenderInterface; |
| 63 using webrtc::StreamCollection; | 64 using webrtc::StreamCollection; |
| 64 using webrtc::StunConfigurations; | 65 using webrtc::StunConfigurations; |
| 65 using webrtc::TurnConfigurations; | 66 using webrtc::TurnConfigurations; |
| 66 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration | 67 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration |
| 67 StunConfiguration; | 68 StunConfiguration; |
| 68 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration | 69 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration |
| 69 TurnConfiguration; | 70 TurnConfiguration; |
| 70 | 71 |
| 71 static const char kDefaultStreamLabel[] = "default"; | 72 static const char kDefaultStreamLabel[] = "default"; |
| 72 static const char kDefaultAudioTrackLabel[] = "defaulta0"; | 73 static const char kDefaultAudioTrackLabel[] = "defaulta0"; |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 : std::vector<cricket::StreamParams>(); | 394 : std::vector<cricket::StreamParams>(); |
| 394 } | 395 } |
| 395 | 396 |
| 396 bool IsValidOfferToReceiveMedia(int value) { | 397 bool IsValidOfferToReceiveMedia(int value) { |
| 397 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; | 398 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; |
| 398 return (value >= Options::kUndefined) && | 399 return (value >= Options::kUndefined) && |
| 399 (value <= Options::kMaxOfferToReceiveMedia); | 400 (value <= Options::kMaxOfferToReceiveMedia); |
| 400 } | 401 } |
| 401 | 402 |
| 402 // Add the stream and RTP data channel info to |session_options|. | 403 // Add the stream and RTP data channel info to |session_options|. |
| 403 void SetStreams(cricket::MediaSessionOptions* session_options, | 404 void AddSendStreams( |
| 404 rtc::scoped_refptr<StreamCollection> streams, | 405 cricket::MediaSessionOptions* session_options, |
| 405 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& | 406 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders, |
| 406 rtp_data_channels) { | 407 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& |
| 408 rtp_data_channels) { |
| 407 session_options->streams.clear(); | 409 session_options->streams.clear(); |
| 408 if (streams != nullptr) { | 410 for (const auto& sender : senders) { |
| 409 for (size_t i = 0; i < streams->count(); ++i) { | 411 session_options->AddSendStream(sender->media_type(), sender->id(), |
| 410 MediaStreamInterface* stream = streams->at(i); | 412 sender->stream_id()); |
| 411 // For each audio track in the stream, add it to the MediaSessionOptions. | |
| 412 for (const auto& track : stream->GetAudioTracks()) { | |
| 413 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, track->id(), | |
| 414 stream->label()); | |
| 415 } | |
| 416 // For each video track in the stream, add it to the MediaSessionOptions. | |
| 417 for (const auto& track : stream->GetVideoTracks()) { | |
| 418 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, track->id(), | |
| 419 stream->label()); | |
| 420 } | |
| 421 } | |
| 422 } | 413 } |
| 423 | 414 |
| 424 // Check for data channels. | 415 // Check for data channels. |
| 425 for (const auto& kv : rtp_data_channels) { | 416 for (const auto& kv : rtp_data_channels) { |
| 426 const DataChannel* channel = kv.second; | 417 const DataChannel* channel = kv.second; |
| 427 if (channel->state() == DataChannel::kConnecting || | 418 if (channel->state() == DataChannel::kConnecting || |
| 428 channel->state() == DataChannel::kOpen) { | 419 channel->state() == DataChannel::kOpen) { |
| 429 // |streamid| and |sync_label| are both set to the DataChannel label | 420 // |streamid| and |sync_label| are both set to the DataChannel label |
| 430 // here so they can be signaled the same way as MediaStreams and Tracks. | 421 // here so they can be signaled the same way as MediaStreams and Tracks. |
| 431 // For MediaStreams, the sync_label is the MediaStream label and the | 422 // For MediaStreams, the sync_label is the MediaStream label and the |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 726 rtc::scoped_refptr<StreamCollectionInterface> | 717 rtc::scoped_refptr<StreamCollectionInterface> |
| 727 PeerConnection::local_streams() { | 718 PeerConnection::local_streams() { |
| 728 return local_streams_; | 719 return local_streams_; |
| 729 } | 720 } |
| 730 | 721 |
| 731 rtc::scoped_refptr<StreamCollectionInterface> | 722 rtc::scoped_refptr<StreamCollectionInterface> |
| 732 PeerConnection::remote_streams() { | 723 PeerConnection::remote_streams() { |
| 733 return remote_streams_; | 724 return remote_streams_; |
| 734 } | 725 } |
| 735 | 726 |
| 736 // TODO(deadbeef): Create RtpSenders immediately here, even if local | |
| 737 // description hasn't yet been set. | |
| 738 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { | 727 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { |
| 739 if (IsClosed()) { | 728 if (IsClosed()) { |
| 740 return false; | 729 return false; |
| 741 } | 730 } |
| 742 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { | 731 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { |
| 743 return false; | 732 return false; |
| 744 } | 733 } |
| 745 | 734 |
| 746 local_streams_->AddStream(local_stream); | 735 local_streams_->AddStream(local_stream); |
| 747 | 736 |
| 748 // Find tracks that have already been configured in SDP. This can occur if a | |
| 749 // local session description that contains the MSID of these tracks is set | |
| 750 // before AddLocalStream is called. It can also occur if the local session | |
| 751 // description is not changed and RemoveLocalStream is called and later | |
| 752 // AddLocalStream is called again with the same stream. | |
| 753 for (const auto& track : local_stream->GetAudioTracks()) { | 737 for (const auto& track : local_stream->GetAudioTracks()) { |
| 754 const TrackInfo* track_info = | 738 auto sender = FindSenderForTrack(track.get()); |
| 755 FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id()); | 739 if (sender == senders_.end()) { |
| 756 if (track_info) { | 740 // Normal case; we've never seen this track before. |
| 757 CreateAudioSender(local_stream, track.get(), track_info->ssrc); | 741 AudioRtpSender* new_sender = new AudioRtpSender( |
| 742 track.get(), local_stream->label(), session_.get(), stats_.get()); |
| 743 senders_.push_back(new_sender); |
| 744 // If the sender has already been configured in SDP, we call SetSsrc, |
| 745 // which will connect the sender to the underlying transport. This can |
| 746 // occur if a local session description that contains the ID of the sender |
| 747 // is set before AddStream is called. It can also occur if the local |
| 748 // session description is not changed and RemoveStream is called, and |
| 749 // later AddStream is called again with the same stream. |
| 750 const TrackInfo* track_info = FindTrackInfo( |
| 751 local_audio_tracks_, local_stream->label(), track->id()); |
| 752 if (track_info) { |
| 753 new_sender->SetSsrc(track_info->ssrc); |
| 754 } |
| 755 } else { |
| 756 // We already have a sender for this track, so just change the stream_id |
| 757 // so that it's correct in the next call to CreateOffer. |
| 758 (*sender)->set_stream_id(local_stream->label()); |
| 758 } | 759 } |
| 759 } | 760 } |
| 760 for (const auto& track : local_stream->GetVideoTracks()) { | 761 for (const auto& track : local_stream->GetVideoTracks()) { |
| 761 const TrackInfo* track_info = | 762 auto sender = FindSenderForTrack(track.get()); |
| 762 FindTrackInfo(local_video_tracks_, local_stream->label(), track->id()); | 763 if (sender == senders_.end()) { |
| 763 if (track_info) { | 764 // Normal case; we've never seen this track before. |
| 764 CreateVideoSender(local_stream, track.get(), track_info->ssrc); | 765 VideoRtpSender* new_sender = new VideoRtpSender( |
| 766 track.get(), local_stream->label(), session_.get()); |
| 767 senders_.push_back(new_sender); |
| 768 const TrackInfo* track_info = FindTrackInfo( |
| 769 local_video_tracks_, local_stream->label(), track->id()); |
| 770 if (track_info) { |
| 771 new_sender->SetSsrc(track_info->ssrc); |
| 772 } |
| 773 } else { |
| 774 // We already have a sender for this track, so just change the stream_id |
| 775 // so that it's correct in the next call to CreateOffer. |
| 776 (*sender)->set_stream_id(local_stream->label()); |
| 765 } | 777 } |
| 766 } | 778 } |
| 767 | 779 |
| 768 stats_->AddStream(local_stream); | 780 stats_->AddStream(local_stream); |
| 769 observer_->OnRenegotiationNeeded(); | 781 observer_->OnRenegotiationNeeded(); |
| 770 return true; | 782 return true; |
| 771 } | 783 } |
| 772 | 784 |
| 773 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around | 785 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around |
| 774 // indefinitely. | 786 // indefinitely, when we have unified plan SDP. |
| 775 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { | 787 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { |
| 776 for (const auto& track : local_stream->GetAudioTracks()) { | 788 for (const auto& track : local_stream->GetAudioTracks()) { |
| 777 const TrackInfo* track_info = | 789 auto sender = FindSenderForTrack(track.get()); |
| 778 FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id()); | 790 if (sender == senders_.end()) { |
| 779 if (track_info) { | 791 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() |
| 780 DestroyAudioSender(local_stream, track.get(), track_info->ssrc); | 792 << " doesn't exist."; |
| 793 continue; |
| 781 } | 794 } |
| 795 (*sender)->Stop(); |
| 796 senders_.erase(sender); |
| 782 } | 797 } |
| 783 for (const auto& track : local_stream->GetVideoTracks()) { | 798 for (const auto& track : local_stream->GetVideoTracks()) { |
| 784 const TrackInfo* track_info = | 799 auto sender = FindSenderForTrack(track.get()); |
| 785 FindTrackInfo(local_video_tracks_, local_stream->label(), track->id()); | 800 if (sender == senders_.end()) { |
| 786 if (track_info) { | 801 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() |
| 787 DestroyVideoSender(local_stream, track.get()); | 802 << " doesn't exist."; |
| 803 continue; |
| 788 } | 804 } |
| 805 (*sender)->Stop(); |
| 806 senders_.erase(sender); |
| 789 } | 807 } |
| 790 | 808 |
| 791 local_streams_->RemoveStream(local_stream); | 809 local_streams_->RemoveStream(local_stream); |
| 792 | 810 |
| 793 if (IsClosed()) { | 811 if (IsClosed()) { |
| 794 return; | 812 return; |
| 795 } | 813 } |
| 796 observer_->OnRenegotiationNeeded(); | 814 observer_->OnRenegotiationNeeded(); |
| 797 } | 815 } |
| 798 | 816 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 809 | 827 |
| 810 rtc::scoped_refptr<DtmfSenderInterface> sender( | 828 rtc::scoped_refptr<DtmfSenderInterface> sender( |
| 811 DtmfSender::Create(track, signaling_thread(), session_.get())); | 829 DtmfSender::Create(track, signaling_thread(), session_.get())); |
| 812 if (!sender.get()) { | 830 if (!sender.get()) { |
| 813 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; | 831 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; |
| 814 return NULL; | 832 return NULL; |
| 815 } | 833 } |
| 816 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); | 834 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); |
| 817 } | 835 } |
| 818 | 836 |
| 837 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender( |
| 838 const std::string& kind) { |
| 839 RtpSenderInterface* new_sender; |
| 840 if (kind == MediaStreamTrackInterface::kAudioKind) { |
| 841 new_sender = new AudioRtpSender(session_.get(), stats_.get()); |
| 842 } else if (kind == MediaStreamTrackInterface::kVideoKind) { |
| 843 new_sender = new VideoRtpSender(session_.get()); |
| 844 } else { |
| 845 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind; |
| 846 return rtc::scoped_refptr<RtpSenderInterface>(); |
| 847 } |
| 848 senders_.push_back(new_sender); |
| 849 return RtpSenderProxy::Create(signaling_thread(), new_sender); |
| 850 } |
| 851 |
| 819 std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders() | 852 std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders() |
| 820 const { | 853 const { |
| 821 std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders; | 854 std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders; |
| 822 for (const auto& sender : senders_) { | 855 for (const auto& sender : senders_) { |
| 823 senders.push_back(RtpSenderProxy::Create(signaling_thread(), sender.get())); | 856 senders.push_back(RtpSenderProxy::Create(signaling_thread(), sender.get())); |
| 824 } | 857 } |
| 825 return senders; | 858 return senders; |
| 826 } | 859 } |
| 827 | 860 |
| 828 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> | 861 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 auto it = FindReceiverForTrack(video_track); | 1350 auto it = FindReceiverForTrack(video_track); |
| 1318 if (it == receivers_.end()) { | 1351 if (it == receivers_.end()) { |
| 1319 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() | 1352 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() |
| 1320 << " doesn't exist."; | 1353 << " doesn't exist."; |
| 1321 } else { | 1354 } else { |
| 1322 (*it)->Stop(); | 1355 (*it)->Stop(); |
| 1323 receivers_.erase(it); | 1356 receivers_.erase(it); |
| 1324 } | 1357 } |
| 1325 } | 1358 } |
| 1326 | 1359 |
| 1327 void PeerConnection::CreateAudioSender(MediaStreamInterface* stream, | |
| 1328 AudioTrackInterface* audio_track, | |
| 1329 uint32_t ssrc) { | |
| 1330 senders_.push_back(new AudioRtpSender(audio_track, ssrc, session_.get())); | |
| 1331 stats_->AddLocalAudioTrack(audio_track, ssrc); | |
| 1332 } | |
| 1333 | |
| 1334 void PeerConnection::CreateVideoSender(MediaStreamInterface* stream, | |
| 1335 VideoTrackInterface* video_track, | |
| 1336 uint32_t ssrc) { | |
| 1337 senders_.push_back(new VideoRtpSender(video_track, ssrc, session_.get())); | |
| 1338 } | |
| 1339 | |
| 1340 // TODO(deadbeef): Keep RtpSenders around even if track goes away in local | |
| 1341 // description. | |
| 1342 void PeerConnection::DestroyAudioSender(MediaStreamInterface* stream, | |
| 1343 AudioTrackInterface* audio_track, | |
| 1344 uint32_t ssrc) { | |
| 1345 auto it = FindSenderForTrack(audio_track); | |
| 1346 if (it == senders_.end()) { | |
| 1347 LOG(LS_WARNING) << "RtpSender for track with id " << audio_track->id() | |
| 1348 << " doesn't exist."; | |
| 1349 return; | |
| 1350 } else { | |
| 1351 (*it)->Stop(); | |
| 1352 senders_.erase(it); | |
| 1353 } | |
| 1354 stats_->RemoveLocalAudioTrack(audio_track, ssrc); | |
| 1355 } | |
| 1356 | |
| 1357 void PeerConnection::DestroyVideoSender(MediaStreamInterface* stream, | |
| 1358 VideoTrackInterface* video_track) { | |
| 1359 auto it = FindSenderForTrack(video_track); | |
| 1360 if (it == senders_.end()) { | |
| 1361 LOG(LS_WARNING) << "RtpSender for track with id " << video_track->id() | |
| 1362 << " doesn't exist."; | |
| 1363 return; | |
| 1364 } else { | |
| 1365 (*it)->Stop(); | |
| 1366 senders_.erase(it); | |
| 1367 } | |
| 1368 } | |
| 1369 | |
| 1370 void PeerConnection::OnIceConnectionChange( | 1360 void PeerConnection::OnIceConnectionChange( |
| 1371 PeerConnectionInterface::IceConnectionState new_state) { | 1361 PeerConnectionInterface::IceConnectionState new_state) { |
| 1372 RTC_DCHECK(signaling_thread()->IsCurrent()); | 1362 RTC_DCHECK(signaling_thread()->IsCurrent()); |
| 1373 // After transitioning to "closed", ignore any additional states from | 1363 // After transitioning to "closed", ignore any additional states from |
| 1374 // WebRtcSession (such as "disconnected"). | 1364 // WebRtcSession (such as "disconnected"). |
| 1375 if (IsClosed()) { | 1365 if (IsClosed()) { |
| 1376 return; | 1366 return; |
| 1377 } | 1367 } |
| 1378 ice_connection_state_ = new_state; | 1368 ice_connection_state_ = new_state; |
| 1379 observer_->OnIceConnectionChange(ice_connection_state_); | 1369 observer_->OnIceConnectionChange(ice_connection_state_); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); | 1425 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); |
| 1436 } | 1426 } |
| 1437 | 1427 |
| 1438 bool PeerConnection::GetOptionsForOffer( | 1428 bool PeerConnection::GetOptionsForOffer( |
| 1439 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 1429 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
| 1440 cricket::MediaSessionOptions* session_options) { | 1430 cricket::MediaSessionOptions* session_options) { |
| 1441 if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) { | 1431 if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) { |
| 1442 return false; | 1432 return false; |
| 1443 } | 1433 } |
| 1444 | 1434 |
| 1445 SetStreams(session_options, local_streams_, rtp_data_channels_); | 1435 AddSendStreams(session_options, senders_, rtp_data_channels_); |
| 1446 // Offer to receive audio/video if the constraint is not set and there are | 1436 // Offer to receive audio/video if the constraint is not set and there are |
| 1447 // send streams, or we're currently receiving. | 1437 // send streams, or we're currently receiving. |
| 1448 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { | 1438 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { |
| 1449 session_options->recv_audio = | 1439 session_options->recv_audio = |
| 1450 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || | 1440 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || |
| 1451 !remote_audio_tracks_.empty(); | 1441 !remote_audio_tracks_.empty(); |
| 1452 } | 1442 } |
| 1453 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { | 1443 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { |
| 1454 session_options->recv_video = | 1444 session_options->recv_video = |
| 1455 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || | 1445 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1468 | 1458 |
| 1469 bool PeerConnection::GetOptionsForAnswer( | 1459 bool PeerConnection::GetOptionsForAnswer( |
| 1470 const MediaConstraintsInterface* constraints, | 1460 const MediaConstraintsInterface* constraints, |
| 1471 cricket::MediaSessionOptions* session_options) { | 1461 cricket::MediaSessionOptions* session_options) { |
| 1472 session_options->recv_audio = false; | 1462 session_options->recv_audio = false; |
| 1473 session_options->recv_video = false; | 1463 session_options->recv_video = false; |
| 1474 if (!ParseConstraintsForAnswer(constraints, session_options)) { | 1464 if (!ParseConstraintsForAnswer(constraints, session_options)) { |
| 1475 return false; | 1465 return false; |
| 1476 } | 1466 } |
| 1477 | 1467 |
| 1478 SetStreams(session_options, local_streams_, rtp_data_channels_); | 1468 AddSendStreams(session_options, senders_, rtp_data_channels_); |
| 1479 session_options->bundle_enabled = | 1469 session_options->bundle_enabled = |
| 1480 session_options->bundle_enabled && | 1470 session_options->bundle_enabled && |
| 1481 (session_options->has_audio() || session_options->has_video() || | 1471 (session_options->has_audio() || session_options->has_video() || |
| 1482 session_options->has_data()); | 1472 session_options->has_data()); |
| 1483 | 1473 |
| 1484 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams | 1474 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams |
| 1485 // are not signaled in the SDP so does not go through that path and must be | 1475 // are not signaled in the SDP so does not go through that path and must be |
| 1486 // handled here. | 1476 // handled here. |
| 1487 if (session_->data_channel_type() == cricket::DCT_SCTP) { | 1477 if (session_->data_channel_type() == cricket::DCT_SCTP) { |
| 1488 session_options->data_channel_type = cricket::DCT_SCTP; | 1478 session_options->data_channel_type = cricket::DCT_SCTP; |
| 1489 } | 1479 } |
| 1490 return true; | 1480 return true; |
| 1491 } | 1481 } |
| 1492 | 1482 |
| 1493 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { | 1483 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { |
| 1494 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); | 1484 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); |
| 1495 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), media_type, | 1485 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), media_type, |
| 1496 nullptr); | 1486 nullptr); |
| 1497 } | 1487 } |
| 1498 | 1488 |
| 1499 void PeerConnection::UpdateRemoteStreamsList( | 1489 void PeerConnection::UpdateRemoteStreamsList( |
| 1500 const cricket::StreamParamsVec& streams, | 1490 const cricket::StreamParamsVec& streams, |
| 1501 cricket::MediaType media_type, | 1491 cricket::MediaType media_type, |
| 1502 StreamCollection* new_streams) { | 1492 StreamCollection* new_streams) { |
| 1503 TrackInfos* current_tracks = GetRemoteTracks(media_type); | 1493 TrackInfos* current_tracks = GetRemoteTracks(media_type); |
| 1504 | 1494 |
| 1505 // Find removed tracks. I.e., tracks where the track id or ssrc don't match | 1495 // Find removed tracks. I.e., tracks where the track id or ssrc don't match |
| 1506 // the | 1496 // the new StreamParam. |
| 1507 // new StreamParam. | |
| 1508 auto track_it = current_tracks->begin(); | 1497 auto track_it = current_tracks->begin(); |
| 1509 while (track_it != current_tracks->end()) { | 1498 while (track_it != current_tracks->end()) { |
| 1510 const TrackInfo& info = *track_it; | 1499 const TrackInfo& info = *track_it; |
| 1511 const cricket::StreamParams* params = | 1500 const cricket::StreamParams* params = |
| 1512 cricket::GetStreamBySsrc(streams, info.ssrc); | 1501 cricket::GetStreamBySsrc(streams, info.ssrc); |
| 1513 if (!params || params->id != info.track_id) { | 1502 if (!params || params->id != info.track_id) { |
| 1514 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); | 1503 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); |
| 1515 track_it = current_tracks->erase(track_it); | 1504 track_it = current_tracks->erase(track_it); |
| 1516 } else { | 1505 } else { |
| 1517 ++track_it; | 1506 ++track_it; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); | 1688 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); |
| 1700 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); | 1689 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); |
| 1701 } | 1690 } |
| 1702 } | 1691 } |
| 1703 } | 1692 } |
| 1704 | 1693 |
| 1705 void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, | 1694 void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, |
| 1706 const std::string& track_id, | 1695 const std::string& track_id, |
| 1707 uint32_t ssrc, | 1696 uint32_t ssrc, |
| 1708 cricket::MediaType media_type) { | 1697 cricket::MediaType media_type) { |
| 1709 MediaStreamInterface* stream = local_streams_->find(stream_label); | 1698 RtpSenderInterface* sender = FindSenderById(track_id); |
| 1710 if (!stream) { | 1699 if (!sender) { |
| 1711 LOG(LS_WARNING) << "An unknown local MediaStream with label " | 1700 LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id |
| 1712 << stream_label << " has been configured."; | 1701 << " has been configured in the local description."; |
| 1713 return; | 1702 return; |
| 1714 } | 1703 } |
| 1715 | 1704 |
| 1716 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | 1705 if (sender->media_type() != media_type) { |
| 1717 AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id); | 1706 LOG(LS_WARNING) << "An RtpSender has been configured in the local" |
| 1718 if (!audio_track) { | 1707 << " description with an unexpected media type."; |
| 1719 LOG(LS_WARNING) << "An unknown local AudioTrack with id , " << track_id | 1708 return; |
| 1720 << " has been configured."; | |
| 1721 return; | |
| 1722 } | |
| 1723 CreateAudioSender(stream, audio_track, ssrc); | |
| 1724 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1725 VideoTrackInterface* video_track = stream->FindVideoTrack(track_id); | |
| 1726 if (!video_track) { | |
| 1727 LOG(LS_WARNING) << "An unknown local VideoTrack with id , " << track_id | |
| 1728 << " has been configured."; | |
| 1729 return; | |
| 1730 } | |
| 1731 CreateVideoSender(stream, video_track, ssrc); | |
| 1732 } else { | |
| 1733 RTC_DCHECK(false && "Invalid media type"); | |
| 1734 } | 1709 } |
| 1710 |
| 1711 sender->set_stream_id(stream_label); |
| 1712 sender->SetSsrc(ssrc); |
| 1735 } | 1713 } |
| 1736 | 1714 |
| 1737 void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, | 1715 void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, |
| 1738 const std::string& track_id, | 1716 const std::string& track_id, |
| 1739 uint32_t ssrc, | 1717 uint32_t ssrc, |
| 1740 cricket::MediaType media_type) { | 1718 cricket::MediaType media_type) { |
| 1741 MediaStreamInterface* stream = local_streams_->find(stream_label); | 1719 RtpSenderInterface* sender = FindSenderById(track_id); |
| 1742 if (!stream) { | 1720 if (!sender) { |
| 1743 // This is the normal case. I.e., RemoveLocalStream has been called and the | 1721 // This is the normal case. I.e., RemoveStream has been called and the |
| 1744 // SessionDescriptions has been renegotiated. | 1722 // SessionDescriptions has been renegotiated. |
| 1745 return; | 1723 return; |
| 1746 } | 1724 } |
| 1747 // A track has been removed from the SessionDescription but the MediaStream | 1725 |
| 1748 // is still associated with PeerConnection. This only occurs if the SDP | 1726 // A sender has been removed from the SessionDescription but it's still |
| 1749 // doesn't match with the calls to AddLocalStream and RemoveLocalStream. | 1727 // associated with the PeerConnection. This only occurs if the SDP doesn't |
| 1750 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | 1728 // match with the calls to CreateSender, AddStream and RemoveStream. |
| 1751 AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id); | 1729 if (sender->media_type() != media_type) { |
| 1752 if (!audio_track) { | 1730 LOG(LS_WARNING) << "An RtpSender has been configured in the local" |
| 1753 return; | 1731 << " description with an unexpected media type."; |
| 1754 } | 1732 return; |
| 1755 DestroyAudioSender(stream, audio_track, ssrc); | |
| 1756 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | |
| 1757 VideoTrackInterface* video_track = stream->FindVideoTrack(track_id); | |
| 1758 if (!video_track) { | |
| 1759 return; | |
| 1760 } | |
| 1761 DestroyVideoSender(stream, video_track); | |
| 1762 } else { | |
| 1763 RTC_DCHECK(false && "Invalid media type."); | |
| 1764 } | 1733 } |
| 1734 |
| 1735 sender->SetSsrc(0); |
| 1765 } | 1736 } |
| 1766 | 1737 |
| 1767 void PeerConnection::UpdateLocalRtpDataChannels( | 1738 void PeerConnection::UpdateLocalRtpDataChannels( |
| 1768 const cricket::StreamParamsVec& streams) { | 1739 const cricket::StreamParamsVec& streams) { |
| 1769 std::vector<std::string> existing_channels; | 1740 std::vector<std::string> existing_channels; |
| 1770 | 1741 |
| 1771 // Find new and active data channels. | 1742 // Find new and active data channels. |
| 1772 for (const cricket::StreamParams& params : streams) { | 1743 for (const cricket::StreamParams& params : streams) { |
| 1773 // |it->sync_label| is actually the data channel label. The reason is that | 1744 // |it->sync_label| is actually the data channel label. The reason is that |
| 1774 // we use the same naming of data channels as we do for | 1745 // we use the same naming of data channels as we do for |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1972 InternalCreateDataChannel(label, &config)); | 1943 InternalCreateDataChannel(label, &config)); |
| 1973 if (!channel.get()) { | 1944 if (!channel.get()) { |
| 1974 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; | 1945 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; |
| 1975 return; | 1946 return; |
| 1976 } | 1947 } |
| 1977 | 1948 |
| 1978 observer_->OnDataChannel( | 1949 observer_->OnDataChannel( |
| 1979 DataChannelProxy::Create(signaling_thread(), channel)); | 1950 DataChannelProxy::Create(signaling_thread(), channel)); |
| 1980 } | 1951 } |
| 1981 | 1952 |
| 1953 RtpSenderInterface* PeerConnection::FindSenderById(const std::string& id) { |
| 1954 auto it = |
| 1955 std::find_if(senders_.begin(), senders_.end(), |
| 1956 [id](const rtc::scoped_refptr<RtpSenderInterface>& sender) { |
| 1957 return sender->id() == id; |
| 1958 }); |
| 1959 return it != senders_.end() ? it->get() : nullptr; |
| 1960 } |
| 1961 |
| 1982 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator | 1962 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator |
| 1983 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { | 1963 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { |
| 1984 return std::find_if( | 1964 return std::find_if( |
| 1985 senders_.begin(), senders_.end(), | 1965 senders_.begin(), senders_.end(), |
| 1986 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { | 1966 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { |
| 1987 return sender->track() == track; | 1967 return sender->track() == track; |
| 1988 }); | 1968 }); |
| 1989 } | 1969 } |
| 1990 | 1970 |
| 1991 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator | 1971 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2029 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { | 2009 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { |
| 2030 for (const auto& channel : sctp_data_channels_) { | 2010 for (const auto& channel : sctp_data_channels_) { |
| 2031 if (channel->id() == sid) { | 2011 if (channel->id() == sid) { |
| 2032 return channel; | 2012 return channel; |
| 2033 } | 2013 } |
| 2034 } | 2014 } |
| 2035 return nullptr; | 2015 return nullptr; |
| 2036 } | 2016 } |
| 2037 | 2017 |
| 2038 } // namespace webrtc | 2018 } // namespace webrtc |
| OLD | NEW |