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