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, |
11 * this list of conditions and the following disclaimer in the documentation | 11 * this list of conditions and the following disclaimer in the documentation |
12 * and/or other materials provided with the distribution. | 12 * and/or other materials provided with the distribution. |
13 * 3. The name of the author may not be used to endorse or promote products | 13 * 3. The name of the author may not be used to endorse or promote products |
14 * derived from this software without specific prior written permission. | 14 * derived from this software without specific prior written permission. |
15 * | 15 * |
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include "talk/app/webrtc/peerconnection.h" | 28 #include "talk/app/webrtc/peerconnection.h" |
29 | 29 |
| 30 #include <algorithm> |
30 #include <vector> | 31 #include <vector> |
31 #include <cctype> // for isdigit | 32 #include <cctype> // for isdigit |
32 | 33 |
33 #include "talk/app/webrtc/audiotrack.h" | 34 #include "talk/app/webrtc/audiotrack.h" |
34 #include "talk/app/webrtc/dtmfsender.h" | 35 #include "talk/app/webrtc/dtmfsender.h" |
35 #include "talk/app/webrtc/jsepicecandidate.h" | 36 #include "talk/app/webrtc/jsepicecandidate.h" |
36 #include "talk/app/webrtc/jsepsessiondescription.h" | 37 #include "talk/app/webrtc/jsepsessiondescription.h" |
37 #include "talk/app/webrtc/mediaconstraintsinterface.h" | 38 #include "talk/app/webrtc/mediaconstraintsinterface.h" |
38 #include "talk/app/webrtc/mediastream.h" | 39 #include "talk/app/webrtc/mediastream.h" |
| 40 #include "talk/app/webrtc/mediastreamobserver.h" |
39 #include "talk/app/webrtc/mediastreamproxy.h" | 41 #include "talk/app/webrtc/mediastreamproxy.h" |
40 #include "talk/app/webrtc/mediastreamtrackproxy.h" | 42 #include "talk/app/webrtc/mediastreamtrackproxy.h" |
41 #include "talk/app/webrtc/remoteaudiosource.h" | 43 #include "talk/app/webrtc/remoteaudiosource.h" |
42 #include "talk/app/webrtc/remoteaudiotrack.h" | 44 #include "talk/app/webrtc/remoteaudiotrack.h" |
43 #include "talk/app/webrtc/remotevideocapturer.h" | 45 #include "talk/app/webrtc/remotevideocapturer.h" |
44 #include "talk/app/webrtc/rtpreceiver.h" | 46 #include "talk/app/webrtc/rtpreceiver.h" |
45 #include "talk/app/webrtc/rtpsender.h" | 47 #include "talk/app/webrtc/rtpsender.h" |
46 #include "talk/app/webrtc/streamcollection.h" | 48 #include "talk/app/webrtc/streamcollection.h" |
47 #include "talk/app/webrtc/videosource.h" | 49 #include "talk/app/webrtc/videosource.h" |
48 #include "talk/app/webrtc/videotrack.h" | 50 #include "talk/app/webrtc/videotrack.h" |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { | 735 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { |
734 TRACE_EVENT0("webrtc", "PeerConnection::AddStream"); | 736 TRACE_EVENT0("webrtc", "PeerConnection::AddStream"); |
735 if (IsClosed()) { | 737 if (IsClosed()) { |
736 return false; | 738 return false; |
737 } | 739 } |
738 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { | 740 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { |
739 return false; | 741 return false; |
740 } | 742 } |
741 | 743 |
742 local_streams_->AddStream(local_stream); | 744 local_streams_->AddStream(local_stream); |
| 745 MediaStreamObserver* observer = new MediaStreamObserver(local_stream); |
| 746 observer->SignalAudioTrackAdded.connect(this, |
| 747 &PeerConnection::OnAudioTrackAdded); |
| 748 observer->SignalAudioTrackRemoved.connect( |
| 749 this, &PeerConnection::OnAudioTrackRemoved); |
| 750 observer->SignalVideoTrackAdded.connect(this, |
| 751 &PeerConnection::OnVideoTrackAdded); |
| 752 observer->SignalVideoTrackRemoved.connect( |
| 753 this, &PeerConnection::OnVideoTrackRemoved); |
| 754 stream_observers_.push_back(rtc::scoped_ptr<MediaStreamObserver>(observer)); |
743 | 755 |
744 for (const auto& track : local_stream->GetAudioTracks()) { | 756 for (const auto& track : local_stream->GetAudioTracks()) { |
745 auto sender = FindSenderForTrack(track.get()); | 757 OnAudioTrackAdded(track.get(), local_stream); |
746 if (sender == senders_.end()) { | |
747 // Normal case; we've never seen this track before. | |
748 AudioRtpSender* new_sender = new AudioRtpSender( | |
749 track.get(), local_stream->label(), session_.get(), stats_.get()); | |
750 senders_.push_back(new_sender); | |
751 // If the sender has already been configured in SDP, we call SetSsrc, | |
752 // which will connect the sender to the underlying transport. This can | |
753 // occur if a local session description that contains the ID of the sender | |
754 // is set before AddStream is called. It can also occur if the local | |
755 // session description is not changed and RemoveStream is called, and | |
756 // later AddStream is called again with the same stream. | |
757 const TrackInfo* track_info = FindTrackInfo( | |
758 local_audio_tracks_, local_stream->label(), track->id()); | |
759 if (track_info) { | |
760 new_sender->SetSsrc(track_info->ssrc); | |
761 } | |
762 } else { | |
763 // We already have a sender for this track, so just change the stream_id | |
764 // so that it's correct in the next call to CreateOffer. | |
765 (*sender)->set_stream_id(local_stream->label()); | |
766 } | |
767 } | 758 } |
768 for (const auto& track : local_stream->GetVideoTracks()) { | 759 for (const auto& track : local_stream->GetVideoTracks()) { |
769 auto sender = FindSenderForTrack(track.get()); | 760 OnVideoTrackAdded(track.get(), local_stream); |
770 if (sender == senders_.end()) { | |
771 // Normal case; we've never seen this track before. | |
772 VideoRtpSender* new_sender = new VideoRtpSender( | |
773 track.get(), local_stream->label(), session_.get()); | |
774 senders_.push_back(new_sender); | |
775 const TrackInfo* track_info = FindTrackInfo( | |
776 local_video_tracks_, local_stream->label(), track->id()); | |
777 if (track_info) { | |
778 new_sender->SetSsrc(track_info->ssrc); | |
779 } | |
780 } else { | |
781 // We already have a sender for this track, so just change the stream_id | |
782 // so that it's correct in the next call to CreateOffer. | |
783 (*sender)->set_stream_id(local_stream->label()); | |
784 } | |
785 } | 761 } |
786 | 762 |
787 stats_->AddStream(local_stream); | 763 stats_->AddStream(local_stream); |
788 observer_->OnRenegotiationNeeded(); | 764 observer_->OnRenegotiationNeeded(); |
789 return true; | 765 return true; |
790 } | 766 } |
791 | 767 |
792 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around | |
793 // indefinitely, when we have unified plan SDP. | |
794 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { | 768 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { |
795 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream"); | 769 TRACE_EVENT0("webrtc", "PeerConnection::RemoveStream"); |
796 for (const auto& track : local_stream->GetAudioTracks()) { | 770 for (const auto& track : local_stream->GetAudioTracks()) { |
797 auto sender = FindSenderForTrack(track.get()); | 771 OnAudioTrackRemoved(track.get(), local_stream); |
798 if (sender == senders_.end()) { | |
799 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | |
800 << " doesn't exist."; | |
801 continue; | |
802 } | |
803 (*sender)->Stop(); | |
804 senders_.erase(sender); | |
805 } | 772 } |
806 for (const auto& track : local_stream->GetVideoTracks()) { | 773 for (const auto& track : local_stream->GetVideoTracks()) { |
807 auto sender = FindSenderForTrack(track.get()); | 774 OnVideoTrackRemoved(track.get(), local_stream); |
808 if (sender == senders_.end()) { | |
809 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | |
810 << " doesn't exist."; | |
811 continue; | |
812 } | |
813 (*sender)->Stop(); | |
814 senders_.erase(sender); | |
815 } | 775 } |
816 | 776 |
817 local_streams_->RemoveStream(local_stream); | 777 local_streams_->RemoveStream(local_stream); |
| 778 stream_observers_.erase( |
| 779 std::remove_if( |
| 780 stream_observers_.begin(), stream_observers_.end(), |
| 781 [local_stream](const rtc::scoped_ptr<MediaStreamObserver>& observer) { |
| 782 return observer->stream()->label().compare(local_stream->label()) == |
| 783 0; |
| 784 }), |
| 785 stream_observers_.end()); |
818 | 786 |
819 if (IsClosed()) { | 787 if (IsClosed()) { |
820 return; | 788 return; |
821 } | 789 } |
822 observer_->OnRenegotiationNeeded(); | 790 observer_->OnRenegotiationNeeded(); |
823 } | 791 } |
824 | 792 |
825 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( | 793 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( |
826 AudioTrackInterface* track) { | 794 AudioTrackInterface* track) { |
827 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender"); | 795 TRACE_EVENT0("webrtc", "PeerConnection::CreateDtmfSender"); |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1421 observer_->OnIceConnectionChange(ice_connection_state_); | 1389 observer_->OnIceConnectionChange(ice_connection_state_); |
1422 if (ice_gathering_state_ != kIceGatheringComplete) { | 1390 if (ice_gathering_state_ != kIceGatheringComplete) { |
1423 ice_gathering_state_ = kIceGatheringComplete; | 1391 ice_gathering_state_ = kIceGatheringComplete; |
1424 observer_->OnIceGatheringChange(ice_gathering_state_); | 1392 observer_->OnIceGatheringChange(ice_gathering_state_); |
1425 } | 1393 } |
1426 } | 1394 } |
1427 observer_->OnSignalingChange(signaling_state_); | 1395 observer_->OnSignalingChange(signaling_state_); |
1428 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); | 1396 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); |
1429 } | 1397 } |
1430 | 1398 |
| 1399 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track, |
| 1400 MediaStreamInterface* stream) { |
| 1401 auto sender = FindSenderForTrack(track); |
| 1402 if (sender != senders_.end()) { |
| 1403 // We already have a sender for this track, so just change the stream_id |
| 1404 // so that it's correct in the next call to CreateOffer. |
| 1405 (*sender)->set_stream_id(stream->label()); |
| 1406 return; |
| 1407 } |
| 1408 |
| 1409 // Normal case; we've never seen this track before. |
| 1410 AudioRtpSender* new_sender = |
| 1411 new AudioRtpSender(track, stream->label(), session_.get(), stats_.get()); |
| 1412 senders_.push_back(new_sender); |
| 1413 // If the sender has already been configured in SDP, we call SetSsrc, |
| 1414 // which will connect the sender to the underlying transport. This can |
| 1415 // occur if a local session description that contains the ID of the sender |
| 1416 // is set before AddStream is called. It can also occur if the local |
| 1417 // session description is not changed and RemoveStream is called, and |
| 1418 // later AddStream is called again with the same stream. |
| 1419 const TrackInfo* track_info = |
| 1420 FindTrackInfo(local_audio_tracks_, stream->label(), track->id()); |
| 1421 if (track_info) { |
| 1422 new_sender->SetSsrc(track_info->ssrc); |
| 1423 } |
| 1424 } |
| 1425 |
| 1426 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around |
| 1427 // indefinitely, when we have unified plan SDP. |
| 1428 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track, |
| 1429 MediaStreamInterface* stream) { |
| 1430 auto sender = FindSenderForTrack(track); |
| 1431 if (sender == senders_.end()) { |
| 1432 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() |
| 1433 << " doesn't exist."; |
| 1434 return; |
| 1435 } |
| 1436 (*sender)->Stop(); |
| 1437 senders_.erase(sender); |
| 1438 } |
| 1439 |
| 1440 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track, |
| 1441 MediaStreamInterface* stream) { |
| 1442 auto sender = FindSenderForTrack(track); |
| 1443 if (sender != senders_.end()) { |
| 1444 // We already have a sender for this track, so just change the stream_id |
| 1445 // so that it's correct in the next call to CreateOffer. |
| 1446 (*sender)->set_stream_id(stream->label()); |
| 1447 return; |
| 1448 } |
| 1449 |
| 1450 // Normal case; we've never seen this track before. |
| 1451 VideoRtpSender* new_sender = |
| 1452 new VideoRtpSender(track, stream->label(), session_.get()); |
| 1453 senders_.push_back(new_sender); |
| 1454 const TrackInfo* track_info = |
| 1455 FindTrackInfo(local_video_tracks_, stream->label(), track->id()); |
| 1456 if (track_info) { |
| 1457 new_sender->SetSsrc(track_info->ssrc); |
| 1458 } |
| 1459 } |
| 1460 |
| 1461 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track, |
| 1462 MediaStreamInterface* stream) { |
| 1463 auto sender = FindSenderForTrack(track); |
| 1464 if (sender == senders_.end()) { |
| 1465 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() |
| 1466 << " doesn't exist."; |
| 1467 return; |
| 1468 } |
| 1469 (*sender)->Stop(); |
| 1470 senders_.erase(sender); |
| 1471 } |
| 1472 |
1431 void PeerConnection::PostSetSessionDescriptionFailure( | 1473 void PeerConnection::PostSetSessionDescriptionFailure( |
1432 SetSessionDescriptionObserver* observer, | 1474 SetSessionDescriptionObserver* observer, |
1433 const std::string& error) { | 1475 const std::string& error) { |
1434 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | 1476 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); |
1435 msg->error = error; | 1477 msg->error = error; |
1436 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); | 1478 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); |
1437 } | 1479 } |
1438 | 1480 |
1439 void PeerConnection::PostCreateSessionDescriptionFailure( | 1481 void PeerConnection::PostCreateSessionDescriptionFailure( |
1440 CreateSessionDescriptionObserver* observer, | 1482 CreateSessionDescriptionObserver* observer, |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2020 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { | 2062 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { |
2021 for (const auto& channel : sctp_data_channels_) { | 2063 for (const auto& channel : sctp_data_channels_) { |
2022 if (channel->id() == sid) { | 2064 if (channel->id() == sid) { |
2023 return channel; | 2065 return channel; |
2024 } | 2066 } |
2025 } | 2067 } |
2026 return nullptr; | 2068 return nullptr; |
2027 } | 2069 } |
2028 | 2070 |
2029 } // namespace webrtc | 2071 } // namespace webrtc |
OLD | NEW |