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/remotevideocapturer.h" | 44 #include "talk/app/webrtc/remotevideocapturer.h" |
43 #include "talk/app/webrtc/rtpreceiver.h" | 45 #include "talk/app/webrtc/rtpreceiver.h" |
44 #include "talk/app/webrtc/rtpsender.h" | 46 #include "talk/app/webrtc/rtpsender.h" |
45 #include "talk/app/webrtc/streamcollection.h" | 47 #include "talk/app/webrtc/streamcollection.h" |
46 #include "talk/app/webrtc/videosource.h" | 48 #include "talk/app/webrtc/videosource.h" |
47 #include "talk/app/webrtc/videotrack.h" | 49 #include "talk/app/webrtc/videotrack.h" |
48 #include "talk/media/sctp/sctpdataengine.h" | 50 #include "talk/media/sctp/sctpdataengine.h" |
(...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 | 728 |
727 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { | 729 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { |
728 if (IsClosed()) { | 730 if (IsClosed()) { |
729 return false; | 731 return false; |
730 } | 732 } |
731 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { | 733 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { |
732 return false; | 734 return false; |
733 } | 735 } |
734 | 736 |
735 local_streams_->AddStream(local_stream); | 737 local_streams_->AddStream(local_stream); |
738 MediaStreamObserver* observer = new MediaStreamObserver(local_stream); | |
739 observer->SignalAudioTrackAdded.connect(this, | |
740 &PeerConnection::OnAudioTrackAdded); | |
741 observer->SignalAudioTrackRemoved.connect( | |
742 this, &PeerConnection::OnAudioTrackRemoved); | |
743 observer->SignalVideoTrackAdded.connect(this, | |
744 &PeerConnection::OnVideoTrackAdded); | |
745 observer->SignalVideoTrackRemoved.connect( | |
746 this, &PeerConnection::OnVideoTrackRemoved); | |
747 stream_observers_.push_back(rtc::scoped_ptr<MediaStreamObserver>(observer)); | |
736 | 748 |
737 for (const auto& track : local_stream->GetAudioTracks()) { | 749 for (const auto& track : local_stream->GetAudioTracks()) { |
738 auto sender = FindSenderForTrack(track.get()); | 750 OnAudioTrackAdded(track.get(), local_stream); |
739 if (sender == senders_.end()) { | |
740 // Normal case; we've never seen this track before. | |
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()); | |
759 } | |
760 } | 751 } |
761 for (const auto& track : local_stream->GetVideoTracks()) { | 752 for (const auto& track : local_stream->GetVideoTracks()) { |
762 auto sender = FindSenderForTrack(track.get()); | 753 OnVideoTrackAdded(track.get(), local_stream); |
763 if (sender == senders_.end()) { | |
764 // Normal case; we've never seen this track before. | |
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()); | |
777 } | |
778 } | 754 } |
779 | 755 |
780 stats_->AddStream(local_stream); | 756 stats_->AddStream(local_stream); |
781 observer_->OnRenegotiationNeeded(); | 757 observer_->OnRenegotiationNeeded(); |
782 return true; | 758 return true; |
783 } | 759 } |
784 | 760 |
785 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around | |
786 // indefinitely, when we have unified plan SDP. | |
787 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { | 761 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { |
788 for (const auto& track : local_stream->GetAudioTracks()) { | 762 for (const auto& track : local_stream->GetAudioTracks()) { |
789 auto sender = FindSenderForTrack(track.get()); | 763 OnAudioTrackRemoved(track.get(), local_stream); |
790 if (sender == senders_.end()) { | |
791 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | |
792 << " doesn't exist."; | |
793 continue; | |
794 } | |
795 (*sender)->Stop(); | |
796 senders_.erase(sender); | |
797 } | 764 } |
798 for (const auto& track : local_stream->GetVideoTracks()) { | 765 for (const auto& track : local_stream->GetVideoTracks()) { |
799 auto sender = FindSenderForTrack(track.get()); | 766 OnVideoTrackRemoved(track.get(), local_stream); |
800 if (sender == senders_.end()) { | |
801 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | |
802 << " doesn't exist."; | |
803 continue; | |
804 } | |
805 (*sender)->Stop(); | |
806 senders_.erase(sender); | |
807 } | 767 } |
808 | 768 |
809 local_streams_->RemoveStream(local_stream); | 769 local_streams_->RemoveStream(local_stream); |
770 auto it = std::find_if( | |
771 stream_observers_.begin(), stream_observers_.end(), | |
772 [local_stream]( | |
773 const rtc::scoped_ptr<MediaStreamObserver>& observer) -> bool { | |
pthatcher1
2015/12/08 21:31:05
I think you can leave off the "-> bool" (it can be
Taylor Brandstetter
2015/12/09 00:36:02
Done.
| |
774 return observer->stream()->label().compare(local_stream->label()) == 0; | |
775 }); | |
776 if (it != stream_observers_.end()) { | |
777 stream_observers_.erase(it); | |
778 } | |
pthatcher1
2015/12/08 21:31:05
I think you can use std::remove_if to save a few l
Taylor Brandstetter
2015/12/09 00:36:02
Done.
| |
810 | 779 |
811 if (IsClosed()) { | 780 if (IsClosed()) { |
812 return; | 781 return; |
813 } | 782 } |
814 observer_->OnRenegotiationNeeded(); | 783 observer_->OnRenegotiationNeeded(); |
815 } | 784 } |
816 | 785 |
817 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( | 786 rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender( |
818 AudioTrackInterface* track) { | 787 AudioTrackInterface* track) { |
819 if (!track) { | 788 if (!track) { |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1402 observer_->OnIceConnectionChange(ice_connection_state_); | 1371 observer_->OnIceConnectionChange(ice_connection_state_); |
1403 if (ice_gathering_state_ != kIceGatheringComplete) { | 1372 if (ice_gathering_state_ != kIceGatheringComplete) { |
1404 ice_gathering_state_ = kIceGatheringComplete; | 1373 ice_gathering_state_ = kIceGatheringComplete; |
1405 observer_->OnIceGatheringChange(ice_gathering_state_); | 1374 observer_->OnIceGatheringChange(ice_gathering_state_); |
1406 } | 1375 } |
1407 } | 1376 } |
1408 observer_->OnSignalingChange(signaling_state_); | 1377 observer_->OnSignalingChange(signaling_state_); |
1409 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); | 1378 observer_->OnStateChange(PeerConnectionObserver::kSignalingState); |
1410 } | 1379 } |
1411 | 1380 |
1381 void PeerConnection::OnAudioTrackAdded(AudioTrackInterface* track, | |
1382 MediaStreamInterface* stream) { | |
1383 auto sender = FindSenderForTrack(track); | |
1384 if (sender == senders_.end()) { | |
pthatcher1
2015/12/08 21:31:05
Might as well use an early return, here and in OnV
Taylor Brandstetter
2015/12/09 00:36:02
Done.
| |
1385 // Normal case; we've never seen this track before. | |
1386 AudioRtpSender* new_sender = new AudioRtpSender( | |
1387 track, stream->label(), session_.get(), stats_.get()); | |
1388 senders_.push_back(new_sender); | |
1389 // If the sender has already been configured in SDP, we call SetSsrc, | |
1390 // which will connect the sender to the underlying transport. This can | |
1391 // occur if a local session description that contains the ID of the sender | |
1392 // is set before AddStream is called. It can also occur if the local | |
1393 // session description is not changed and RemoveStream is called, and | |
1394 // later AddStream is called again with the same stream. | |
1395 const TrackInfo* track_info = | |
1396 FindTrackInfo(local_audio_tracks_, stream->label(), track->id()); | |
1397 if (track_info) { | |
1398 new_sender->SetSsrc(track_info->ssrc); | |
1399 } | |
1400 } else { | |
1401 // We already have a sender for this track, so just change the stream_id | |
1402 // so that it's correct in the next call to CreateOffer. | |
1403 (*sender)->set_stream_id(stream->label()); | |
1404 } | |
1405 } | |
1406 | |
1407 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around | |
1408 // indefinitely, when we have unified plan SDP. | |
1409 void PeerConnection::OnAudioTrackRemoved(AudioTrackInterface* track, | |
1410 MediaStreamInterface* stream) { | |
1411 auto sender = FindSenderForTrack(track); | |
1412 if (sender == senders_.end()) { | |
1413 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | |
1414 << " doesn't exist."; | |
1415 return; | |
1416 } | |
1417 (*sender)->Stop(); | |
1418 senders_.erase(sender); | |
1419 } | |
1420 | |
1421 void PeerConnection::OnVideoTrackAdded(VideoTrackInterface* track, | |
1422 MediaStreamInterface* stream) { | |
1423 auto sender = FindSenderForTrack(track); | |
1424 if (sender == senders_.end()) { | |
1425 // Normal case; we've never seen this track before. | |
1426 VideoRtpSender* new_sender = | |
1427 new VideoRtpSender(track, stream->label(), session_.get()); | |
1428 senders_.push_back(new_sender); | |
1429 const TrackInfo* track_info = | |
1430 FindTrackInfo(local_video_tracks_, stream->label(), track->id()); | |
1431 if (track_info) { | |
1432 new_sender->SetSsrc(track_info->ssrc); | |
1433 } | |
1434 } else { | |
1435 // We already have a sender for this track, so just change the stream_id | |
1436 // so that it's correct in the next call to CreateOffer. | |
1437 (*sender)->set_stream_id(stream->label()); | |
1438 } | |
1439 } | |
1440 | |
1441 void PeerConnection::OnVideoTrackRemoved(VideoTrackInterface* track, | |
1442 MediaStreamInterface* stream) { | |
1443 auto sender = FindSenderForTrack(track); | |
1444 if (sender == senders_.end()) { | |
1445 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | |
1446 << " doesn't exist."; | |
1447 return; | |
1448 } | |
1449 (*sender)->Stop(); | |
1450 senders_.erase(sender); | |
1451 } | |
1452 | |
1412 void PeerConnection::PostSetSessionDescriptionFailure( | 1453 void PeerConnection::PostSetSessionDescriptionFailure( |
1413 SetSessionDescriptionObserver* observer, | 1454 SetSessionDescriptionObserver* observer, |
1414 const std::string& error) { | 1455 const std::string& error) { |
1415 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); | 1456 SetSessionDescriptionMsg* msg = new SetSessionDescriptionMsg(observer); |
1416 msg->error = error; | 1457 msg->error = error; |
1417 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); | 1458 signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_FAILED, msg); |
1418 } | 1459 } |
1419 | 1460 |
1420 void PeerConnection::PostCreateSessionDescriptionFailure( | 1461 void PeerConnection::PostCreateSessionDescriptionFailure( |
1421 CreateSessionDescriptionObserver* observer, | 1462 CreateSessionDescriptionObserver* observer, |
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2009 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { | 2050 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { |
2010 for (const auto& channel : sctp_data_channels_) { | 2051 for (const auto& channel : sctp_data_channels_) { |
2011 if (channel->id() == sid) { | 2052 if (channel->id() == sid) { |
2012 return channel; | 2053 return channel; |
2013 } | 2054 } |
2014 } | 2055 } |
2015 return nullptr; | 2056 return nullptr; |
2016 } | 2057 } |
2017 | 2058 |
2018 } // namespace webrtc | 2059 } // namespace webrtc |
OLD | NEW |