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 |