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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 #include "webrtc/base/stringencode.h" | 52 #include "webrtc/base/stringencode.h" |
53 #include "webrtc/base/stringutils.h" | 53 #include "webrtc/base/stringutils.h" |
54 #include "webrtc/system_wrappers/interface/field_trial.h" | 54 #include "webrtc/system_wrappers/interface/field_trial.h" |
55 | 55 |
56 namespace { | 56 namespace { |
57 | 57 |
58 using webrtc::DataChannel; | 58 using webrtc::DataChannel; |
59 using webrtc::MediaConstraintsInterface; | 59 using webrtc::MediaConstraintsInterface; |
60 using webrtc::MediaStreamInterface; | 60 using webrtc::MediaStreamInterface; |
61 using webrtc::PeerConnectionInterface; | 61 using webrtc::PeerConnectionInterface; |
62 using webrtc::RtpSenderInterface; | |
63 using webrtc::StreamCollection; | 62 using webrtc::StreamCollection; |
64 using webrtc::StunConfigurations; | 63 using webrtc::StunConfigurations; |
65 using webrtc::TurnConfigurations; | 64 using webrtc::TurnConfigurations; |
66 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration | 65 typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration |
67 StunConfiguration; | 66 StunConfiguration; |
68 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration | 67 typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration |
69 TurnConfiguration; | 68 TurnConfiguration; |
70 | 69 |
71 static const char kDefaultStreamLabel[] = "default"; | 70 static const char kDefaultStreamLabel[] = "default"; |
72 static const char kDefaultAudioTrackLabel[] = "defaulta0"; | 71 static const char kDefaultAudioTrackLabel[] = "defaulta0"; |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 : std::vector<cricket::StreamParams>(); | 358 : std::vector<cricket::StreamParams>(); |
360 } | 359 } |
361 | 360 |
362 bool IsValidOfferToReceiveMedia(int value) { | 361 bool IsValidOfferToReceiveMedia(int value) { |
363 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; | 362 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; |
364 return (value >= Options::kUndefined) && | 363 return (value >= Options::kUndefined) && |
365 (value <= Options::kMaxOfferToReceiveMedia); | 364 (value <= Options::kMaxOfferToReceiveMedia); |
366 } | 365 } |
367 | 366 |
368 // Add the stream and RTP data channel info to |session_options|. | 367 // Add the stream and RTP data channel info to |session_options|. |
369 void AddSendStreams( | 368 void SetStreams(cricket::MediaSessionOptions* session_options, |
370 cricket::MediaSessionOptions* session_options, | 369 rtc::scoped_refptr<StreamCollection> streams, |
371 const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders, | 370 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& |
372 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& | 371 rtp_data_channels) { |
373 rtp_data_channels) { | |
374 session_options->streams.clear(); | 372 session_options->streams.clear(); |
375 for (const auto& sender : senders) { | 373 if (streams != nullptr) { |
376 session_options->AddSendStream(sender->media_type(), sender->id(), | 374 for (size_t i = 0; i < streams->count(); ++i) { |
377 sender->stream_id()); | 375 MediaStreamInterface* stream = streams->at(i); |
| 376 // For each audio track in the stream, add it to the MediaSessionOptions. |
| 377 for (const auto& track : stream->GetAudioTracks()) { |
| 378 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, track->id(), |
| 379 stream->label()); |
| 380 } |
| 381 // For each video track in the stream, add it to the MediaSessionOptions. |
| 382 for (const auto& track : stream->GetVideoTracks()) { |
| 383 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, track->id(), |
| 384 stream->label()); |
| 385 } |
| 386 } |
378 } | 387 } |
379 | 388 |
380 // Check for data channels. | 389 // Check for data channels. |
381 for (const auto& kv : rtp_data_channels) { | 390 for (const auto& kv : rtp_data_channels) { |
382 const DataChannel* channel = kv.second; | 391 const DataChannel* channel = kv.second; |
383 if (channel->state() == DataChannel::kConnecting || | 392 if (channel->state() == DataChannel::kConnecting || |
384 channel->state() == DataChannel::kOpen) { | 393 channel->state() == DataChannel::kOpen) { |
385 // |streamid| and |sync_label| are both set to the DataChannel label | 394 // |streamid| and |sync_label| are both set to the DataChannel label |
386 // here so they can be signaled the same way as MediaStreams and Tracks. | 395 // here so they can be signaled the same way as MediaStreams and Tracks. |
387 // For MediaStreams, the sync_label is the MediaStream label and the | 396 // For MediaStreams, the sync_label is the MediaStream label and the |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 rtc::scoped_refptr<StreamCollectionInterface> | 661 rtc::scoped_refptr<StreamCollectionInterface> |
653 PeerConnection::local_streams() { | 662 PeerConnection::local_streams() { |
654 return local_streams_; | 663 return local_streams_; |
655 } | 664 } |
656 | 665 |
657 rtc::scoped_refptr<StreamCollectionInterface> | 666 rtc::scoped_refptr<StreamCollectionInterface> |
658 PeerConnection::remote_streams() { | 667 PeerConnection::remote_streams() { |
659 return remote_streams_; | 668 return remote_streams_; |
660 } | 669 } |
661 | 670 |
| 671 // TODO(deadbeef): Create RtpSenders immediately here, even if local |
| 672 // description hasn't yet been set. |
662 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { | 673 bool PeerConnection::AddStream(MediaStreamInterface* local_stream) { |
663 if (IsClosed()) { | 674 if (IsClosed()) { |
664 return false; | 675 return false; |
665 } | 676 } |
666 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { | 677 if (!CanAddLocalMediaStream(local_streams_, local_stream)) { |
667 return false; | 678 return false; |
668 } | 679 } |
669 | 680 |
670 local_streams_->AddStream(local_stream); | 681 local_streams_->AddStream(local_stream); |
671 | 682 |
| 683 // Find tracks that have already been configured in SDP. This can occur if a |
| 684 // local session description that contains the MSID of these tracks is set |
| 685 // before AddLocalStream is called. It can also occur if the local session |
| 686 // description is not changed and RemoveLocalStream is called and later |
| 687 // AddLocalStream is called again with the same stream. |
672 for (const auto& track : local_stream->GetAudioTracks()) { | 688 for (const auto& track : local_stream->GetAudioTracks()) { |
673 auto sender = FindSenderForTrack(track.get()); | 689 const TrackInfo* track_info = |
674 if (sender == senders_.end()) { | 690 FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id()); |
675 // Normal case; we've never seen this track before. | 691 if (track_info) { |
676 AudioRtpSender* new_sender = new AudioRtpSender( | 692 CreateAudioSender(local_stream, track.get(), track_info->ssrc); |
677 track.get(), local_stream->label(), session_.get(), stats_.get()); | |
678 senders_.push_back(new_sender); | |
679 // If the sender has already been configured in SDP, we call SetSsrc, | |
680 // which will connect the sender to the underlying transport. This can | |
681 // occur if a local session description that contains the ID of the sender | |
682 // is set before AddStream is called. It can also occur if the local | |
683 // session description is not changed and RemoveStream is called, and | |
684 // later AddStream is called again with the same stream. | |
685 const TrackInfo* track_info = FindTrackInfo( | |
686 local_audio_tracks_, local_stream->label(), track->id()); | |
687 if (track_info) { | |
688 new_sender->SetSsrc(track_info->ssrc); | |
689 } | |
690 } else { | |
691 // We already have a sender for this track, so just change the stream_id | |
692 // so that it's correct in the next call to CreateOffer. | |
693 (*sender)->set_stream_id(local_stream->label()); | |
694 } | 693 } |
695 } | 694 } |
696 for (const auto& track : local_stream->GetVideoTracks()) { | 695 for (const auto& track : local_stream->GetVideoTracks()) { |
697 auto sender = FindSenderForTrack(track.get()); | 696 const TrackInfo* track_info = |
698 if (sender == senders_.end()) { | 697 FindTrackInfo(local_video_tracks_, local_stream->label(), track->id()); |
699 // Normal case; we've never seen this track before. | 698 if (track_info) { |
700 VideoRtpSender* new_sender = new VideoRtpSender( | 699 CreateVideoSender(local_stream, track.get(), track_info->ssrc); |
701 track.get(), local_stream->label(), session_.get()); | |
702 senders_.push_back(new_sender); | |
703 const TrackInfo* track_info = FindTrackInfo( | |
704 local_video_tracks_, local_stream->label(), track->id()); | |
705 if (track_info) { | |
706 new_sender->SetSsrc(track_info->ssrc); | |
707 } | |
708 } else { | |
709 // We already have a sender for this track, so just change the stream_id | |
710 // so that it's correct in the next call to CreateOffer. | |
711 (*sender)->set_stream_id(local_stream->label()); | |
712 } | 700 } |
713 } | 701 } |
714 | 702 |
715 stats_->AddStream(local_stream); | 703 stats_->AddStream(local_stream); |
716 observer_->OnRenegotiationNeeded(); | 704 observer_->OnRenegotiationNeeded(); |
717 return true; | 705 return true; |
718 } | 706 } |
719 | 707 |
720 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around | 708 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around |
721 // indefinitely, when we have unified plan SDP. | 709 // indefinitely. |
722 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { | 710 void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) { |
723 for (const auto& track : local_stream->GetAudioTracks()) { | 711 for (const auto& track : local_stream->GetAudioTracks()) { |
724 auto sender = FindSenderForTrack(track.get()); | 712 const TrackInfo* track_info = |
725 if (sender == senders_.end()) { | 713 FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id()); |
726 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | 714 if (track_info) { |
727 << " doesn't exist."; | 715 DestroyAudioSender(local_stream, track.get(), track_info->ssrc); |
728 continue; | |
729 } | 716 } |
730 (*sender)->Stop(); | |
731 senders_.erase(sender); | |
732 } | 717 } |
733 for (const auto& track : local_stream->GetVideoTracks()) { | 718 for (const auto& track : local_stream->GetVideoTracks()) { |
734 auto sender = FindSenderForTrack(track.get()); | 719 const TrackInfo* track_info = |
735 if (sender == senders_.end()) { | 720 FindTrackInfo(local_video_tracks_, local_stream->label(), track->id()); |
736 LOG(LS_WARNING) << "RtpSender for track with id " << track->id() | 721 if (track_info) { |
737 << " doesn't exist."; | 722 DestroyVideoSender(local_stream, track.get()); |
738 continue; | |
739 } | 723 } |
740 (*sender)->Stop(); | |
741 senders_.erase(sender); | |
742 } | 724 } |
743 | 725 |
744 local_streams_->RemoveStream(local_stream); | 726 local_streams_->RemoveStream(local_stream); |
745 | 727 |
746 if (IsClosed()) { | 728 if (IsClosed()) { |
747 return; | 729 return; |
748 } | 730 } |
749 observer_->OnRenegotiationNeeded(); | 731 observer_->OnRenegotiationNeeded(); |
750 } | 732 } |
751 | 733 |
(...skipping 10 matching lines...) Expand all Loading... |
762 | 744 |
763 rtc::scoped_refptr<DtmfSenderInterface> sender( | 745 rtc::scoped_refptr<DtmfSenderInterface> sender( |
764 DtmfSender::Create(track, signaling_thread(), session_.get())); | 746 DtmfSender::Create(track, signaling_thread(), session_.get())); |
765 if (!sender.get()) { | 747 if (!sender.get()) { |
766 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; | 748 LOG(LS_ERROR) << "CreateDtmfSender failed on DtmfSender::Create."; |
767 return NULL; | 749 return NULL; |
768 } | 750 } |
769 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); | 751 return DtmfSenderProxy::Create(signaling_thread(), sender.get()); |
770 } | 752 } |
771 | 753 |
772 rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender( | |
773 const std::string& kind) { | |
774 RtpSenderInterface* new_sender; | |
775 if (kind == MediaStreamTrackInterface::kAudioTrackKind) { | |
776 new_sender = new AudioRtpSender(session_.get(), stats_.get()); | |
777 } else if (kind == MediaStreamTrackInterface::kVideoTrackKind) { | |
778 new_sender = new VideoRtpSender(session_.get()); | |
779 } else { | |
780 LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind; | |
781 return rtc::scoped_refptr<RtpSenderInterface>(); | |
782 } | |
783 senders_.push_back(new_sender); | |
784 return RtpSenderProxy::Create(signaling_thread(), new_sender); | |
785 } | |
786 | |
787 std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders() | 754 std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders() |
788 const { | 755 const { |
789 std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders; | 756 std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders; |
790 for (const auto& sender : senders_) { | 757 for (const auto& sender : senders_) { |
791 senders.push_back(RtpSenderProxy::Create(signaling_thread(), sender.get())); | 758 senders.push_back(RtpSenderProxy::Create(signaling_thread(), sender.get())); |
792 } | 759 } |
793 return senders; | 760 return senders; |
794 } | 761 } |
795 | 762 |
796 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> | 763 std::vector<rtc::scoped_refptr<RtpReceiverInterface>> |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 auto it = FindReceiverForTrack(video_track); | 1260 auto it = FindReceiverForTrack(video_track); |
1294 if (it == receivers_.end()) { | 1261 if (it == receivers_.end()) { |
1295 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() | 1262 LOG(LS_WARNING) << "RtpReceiver for track with id " << video_track->id() |
1296 << " doesn't exist."; | 1263 << " doesn't exist."; |
1297 } else { | 1264 } else { |
1298 (*it)->Stop(); | 1265 (*it)->Stop(); |
1299 receivers_.erase(it); | 1266 receivers_.erase(it); |
1300 } | 1267 } |
1301 } | 1268 } |
1302 | 1269 |
| 1270 void PeerConnection::CreateAudioSender(MediaStreamInterface* stream, |
| 1271 AudioTrackInterface* audio_track, |
| 1272 uint32_t ssrc) { |
| 1273 senders_.push_back(new AudioRtpSender(audio_track, ssrc, session_.get())); |
| 1274 stats_->AddLocalAudioTrack(audio_track, ssrc); |
| 1275 } |
| 1276 |
| 1277 void PeerConnection::CreateVideoSender(MediaStreamInterface* stream, |
| 1278 VideoTrackInterface* video_track, |
| 1279 uint32_t ssrc) { |
| 1280 senders_.push_back(new VideoRtpSender(video_track, ssrc, session_.get())); |
| 1281 } |
| 1282 |
| 1283 // TODO(deadbeef): Keep RtpSenders around even if track goes away in local |
| 1284 // description. |
| 1285 void PeerConnection::DestroyAudioSender(MediaStreamInterface* stream, |
| 1286 AudioTrackInterface* audio_track, |
| 1287 uint32_t ssrc) { |
| 1288 auto it = FindSenderForTrack(audio_track); |
| 1289 if (it == senders_.end()) { |
| 1290 LOG(LS_WARNING) << "RtpSender for track with id " << audio_track->id() |
| 1291 << " doesn't exist."; |
| 1292 return; |
| 1293 } else { |
| 1294 (*it)->Stop(); |
| 1295 senders_.erase(it); |
| 1296 } |
| 1297 stats_->RemoveLocalAudioTrack(audio_track, ssrc); |
| 1298 } |
| 1299 |
| 1300 void PeerConnection::DestroyVideoSender(MediaStreamInterface* stream, |
| 1301 VideoTrackInterface* video_track) { |
| 1302 auto it = FindSenderForTrack(video_track); |
| 1303 if (it == senders_.end()) { |
| 1304 LOG(LS_WARNING) << "RtpSender for track with id " << video_track->id() |
| 1305 << " doesn't exist."; |
| 1306 return; |
| 1307 } else { |
| 1308 (*it)->Stop(); |
| 1309 senders_.erase(it); |
| 1310 } |
| 1311 } |
| 1312 |
1303 void PeerConnection::OnIceConnectionChange( | 1313 void PeerConnection::OnIceConnectionChange( |
1304 PeerConnectionInterface::IceConnectionState new_state) { | 1314 PeerConnectionInterface::IceConnectionState new_state) { |
1305 RTC_DCHECK(signaling_thread()->IsCurrent()); | 1315 RTC_DCHECK(signaling_thread()->IsCurrent()); |
1306 // After transitioning to "closed", ignore any additional states from | 1316 // After transitioning to "closed", ignore any additional states from |
1307 // WebRtcSession (such as "disconnected"). | 1317 // WebRtcSession (such as "disconnected"). |
1308 if (IsClosed()) { | 1318 if (IsClosed()) { |
1309 return; | 1319 return; |
1310 } | 1320 } |
1311 ice_connection_state_ = new_state; | 1321 ice_connection_state_ = new_state; |
1312 observer_->OnIceConnectionChange(ice_connection_state_); | 1322 observer_->OnIceConnectionChange(ice_connection_state_); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1368 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); | 1378 signaling_thread()->Post(this, MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); |
1369 } | 1379 } |
1370 | 1380 |
1371 bool PeerConnection::GetOptionsForOffer( | 1381 bool PeerConnection::GetOptionsForOffer( |
1372 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 1382 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
1373 cricket::MediaSessionOptions* session_options) { | 1383 cricket::MediaSessionOptions* session_options) { |
1374 if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) { | 1384 if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) { |
1375 return false; | 1385 return false; |
1376 } | 1386 } |
1377 | 1387 |
1378 AddSendStreams(session_options, senders_, rtp_data_channels_); | 1388 SetStreams(session_options, local_streams_, rtp_data_channels_); |
1379 // Offer to receive audio/video if the constraint is not set and there are | 1389 // Offer to receive audio/video if the constraint is not set and there are |
1380 // send streams, or we're currently receiving. | 1390 // send streams, or we're currently receiving. |
1381 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { | 1391 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { |
1382 session_options->recv_audio = | 1392 session_options->recv_audio = |
1383 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || | 1393 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || |
1384 !remote_audio_tracks_.empty(); | 1394 !remote_audio_tracks_.empty(); |
1385 } | 1395 } |
1386 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { | 1396 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { |
1387 session_options->recv_video = | 1397 session_options->recv_video = |
1388 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || | 1398 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || |
(...skipping 12 matching lines...) Expand all Loading... |
1401 | 1411 |
1402 bool PeerConnection::GetOptionsForAnswer( | 1412 bool PeerConnection::GetOptionsForAnswer( |
1403 const MediaConstraintsInterface* constraints, | 1413 const MediaConstraintsInterface* constraints, |
1404 cricket::MediaSessionOptions* session_options) { | 1414 cricket::MediaSessionOptions* session_options) { |
1405 session_options->recv_audio = false; | 1415 session_options->recv_audio = false; |
1406 session_options->recv_video = false; | 1416 session_options->recv_video = false; |
1407 if (!ParseConstraintsForAnswer(constraints, session_options)) { | 1417 if (!ParseConstraintsForAnswer(constraints, session_options)) { |
1408 return false; | 1418 return false; |
1409 } | 1419 } |
1410 | 1420 |
1411 AddSendStreams(session_options, senders_, rtp_data_channels_); | 1421 SetStreams(session_options, local_streams_, rtp_data_channels_); |
1412 session_options->bundle_enabled = | 1422 session_options->bundle_enabled = |
1413 session_options->bundle_enabled && | 1423 session_options->bundle_enabled && |
1414 (session_options->has_audio() || session_options->has_video() || | 1424 (session_options->has_audio() || session_options->has_video() || |
1415 session_options->has_data()); | 1425 session_options->has_data()); |
1416 | 1426 |
1417 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams | 1427 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams |
1418 // are not signaled in the SDP so does not go through that path and must be | 1428 // are not signaled in the SDP so does not go through that path and must be |
1419 // handled here. | 1429 // handled here. |
1420 if (session_->data_channel_type() == cricket::DCT_SCTP) { | 1430 if (session_->data_channel_type() == cricket::DCT_SCTP) { |
1421 session_options->data_channel_type = cricket::DCT_SCTP; | 1431 session_options->data_channel_type = cricket::DCT_SCTP; |
1422 } | 1432 } |
1423 return true; | 1433 return true; |
1424 } | 1434 } |
1425 | 1435 |
1426 void PeerConnection::UpdateRemoteStreamsList( | 1436 void PeerConnection::UpdateRemoteStreamsList( |
1427 const cricket::StreamParamsVec& streams, | 1437 const cricket::StreamParamsVec& streams, |
1428 cricket::MediaType media_type, | 1438 cricket::MediaType media_type, |
1429 StreamCollection* new_streams) { | 1439 StreamCollection* new_streams) { |
1430 TrackInfos* current_tracks = GetRemoteTracks(media_type); | 1440 TrackInfos* current_tracks = GetRemoteTracks(media_type); |
1431 | 1441 |
1432 // Find removed tracks. I.e., tracks where the track id or ssrc don't match | 1442 // Find removed tracks. I.e., tracks where the track id or ssrc don't match |
1433 // the new StreamParam. | 1443 // the |
| 1444 // new StreamParam. |
1434 auto track_it = current_tracks->begin(); | 1445 auto track_it = current_tracks->begin(); |
1435 while (track_it != current_tracks->end()) { | 1446 while (track_it != current_tracks->end()) { |
1436 const TrackInfo& info = *track_it; | 1447 const TrackInfo& info = *track_it; |
1437 const cricket::StreamParams* params = | 1448 const cricket::StreamParams* params = |
1438 cricket::GetStreamBySsrc(streams, info.ssrc); | 1449 cricket::GetStreamBySsrc(streams, info.ssrc); |
1439 if (!params || params->id != info.track_id) { | 1450 if (!params || params->id != info.track_id) { |
1440 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); | 1451 OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); |
1441 track_it = current_tracks->erase(track_it); | 1452 track_it = current_tracks->erase(track_it); |
1442 } else { | 1453 } else { |
1443 ++track_it; | 1454 ++track_it; |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); | 1636 current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); |
1626 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); | 1637 OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); |
1627 } | 1638 } |
1628 } | 1639 } |
1629 } | 1640 } |
1630 | 1641 |
1631 void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, | 1642 void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, |
1632 const std::string& track_id, | 1643 const std::string& track_id, |
1633 uint32_t ssrc, | 1644 uint32_t ssrc, |
1634 cricket::MediaType media_type) { | 1645 cricket::MediaType media_type) { |
1635 RtpSenderInterface* sender = FindSenderById(track_id); | 1646 MediaStreamInterface* stream = local_streams_->find(stream_label); |
1636 if (!sender) { | 1647 if (!stream) { |
1637 LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id | 1648 LOG(LS_WARNING) << "An unknown local MediaStream with label " |
1638 << " has been configured in the local description."; | 1649 << stream_label << " has been configured."; |
1639 return; | 1650 return; |
1640 } | 1651 } |
1641 | 1652 |
1642 if (sender->media_type() != media_type) { | 1653 if (media_type == cricket::MEDIA_TYPE_AUDIO) { |
1643 LOG(LS_WARNING) << "An RtpSender has been configured in the local" | 1654 AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id); |
1644 << " description with an unexpected media type."; | 1655 if (!audio_track) { |
1645 return; | 1656 LOG(LS_WARNING) << "An unknown local AudioTrack with id , " << track_id |
| 1657 << " has been configured."; |
| 1658 return; |
| 1659 } |
| 1660 CreateAudioSender(stream, audio_track, ssrc); |
| 1661 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
| 1662 VideoTrackInterface* video_track = stream->FindVideoTrack(track_id); |
| 1663 if (!video_track) { |
| 1664 LOG(LS_WARNING) << "An unknown local VideoTrack with id , " << track_id |
| 1665 << " has been configured."; |
| 1666 return; |
| 1667 } |
| 1668 CreateVideoSender(stream, video_track, ssrc); |
| 1669 } else { |
| 1670 RTC_DCHECK(false && "Invalid media type"); |
1646 } | 1671 } |
1647 | |
1648 sender->set_stream_id(stream_label); | |
1649 sender->SetSsrc(ssrc); | |
1650 } | 1672 } |
1651 | 1673 |
1652 void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, | 1674 void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, |
1653 const std::string& track_id, | 1675 const std::string& track_id, |
1654 uint32_t ssrc, | 1676 uint32_t ssrc, |
1655 cricket::MediaType media_type) { | 1677 cricket::MediaType media_type) { |
1656 RtpSenderInterface* sender = FindSenderById(track_id); | 1678 MediaStreamInterface* stream = local_streams_->find(stream_label); |
1657 if (!sender) { | 1679 if (!stream) { |
1658 // This is the normal case. I.e., RemoveStream has been called and the | 1680 // This is the normal case. I.e., RemoveLocalStream has been called and the |
1659 // SessionDescriptions has been renegotiated. | 1681 // SessionDescriptions has been renegotiated. |
1660 return; | 1682 return; |
1661 } | 1683 } |
1662 | 1684 // A track has been removed from the SessionDescription but the MediaStream |
1663 // A sender has been removed from the SessionDescription but it's still | 1685 // is still associated with PeerConnection. This only occurs if the SDP |
1664 // associated with the PeerConnection. This only occurs if the SDP doesn't | 1686 // doesn't match with the calls to AddLocalStream and RemoveLocalStream. |
1665 // match with the calls to CreateSender, AddStream and RemoveStream. | 1687 if (media_type == cricket::MEDIA_TYPE_AUDIO) { |
1666 if (sender->media_type() != media_type) { | 1688 AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id); |
1667 LOG(LS_WARNING) << "An RtpSender has been configured in the local" | 1689 if (!audio_track) { |
1668 << " description with an unexpected media type."; | 1690 return; |
1669 return; | 1691 } |
| 1692 DestroyAudioSender(stream, audio_track, ssrc); |
| 1693 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
| 1694 VideoTrackInterface* video_track = stream->FindVideoTrack(track_id); |
| 1695 if (!video_track) { |
| 1696 return; |
| 1697 } |
| 1698 DestroyVideoSender(stream, video_track); |
| 1699 } else { |
| 1700 RTC_DCHECK(false && "Invalid media type."); |
1670 } | 1701 } |
1671 | |
1672 sender->SetSsrc(0); | |
1673 } | 1702 } |
1674 | 1703 |
1675 void PeerConnection::UpdateLocalRtpDataChannels( | 1704 void PeerConnection::UpdateLocalRtpDataChannels( |
1676 const cricket::StreamParamsVec& streams) { | 1705 const cricket::StreamParamsVec& streams) { |
1677 std::vector<std::string> existing_channels; | 1706 std::vector<std::string> existing_channels; |
1678 | 1707 |
1679 // Find new and active data channels. | 1708 // Find new and active data channels. |
1680 for (const cricket::StreamParams& params : streams) { | 1709 for (const cricket::StreamParams& params : streams) { |
1681 // |it->sync_label| is actually the data channel label. The reason is that | 1710 // |it->sync_label| is actually the data channel label. The reason is that |
1682 // we use the same naming of data channels as we do for | 1711 // 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... |
1880 InternalCreateDataChannel(label, &config)); | 1909 InternalCreateDataChannel(label, &config)); |
1881 if (!channel.get()) { | 1910 if (!channel.get()) { |
1882 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; | 1911 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; |
1883 return; | 1912 return; |
1884 } | 1913 } |
1885 | 1914 |
1886 observer_->OnDataChannel( | 1915 observer_->OnDataChannel( |
1887 DataChannelProxy::Create(signaling_thread(), channel)); | 1916 DataChannelProxy::Create(signaling_thread(), channel)); |
1888 } | 1917 } |
1889 | 1918 |
1890 RtpSenderInterface* PeerConnection::FindSenderById(const std::string& id) { | |
1891 auto it = | |
1892 std::find_if(senders_.begin(), senders_.end(), | |
1893 [id](const rtc::scoped_refptr<RtpSenderInterface>& sender) { | |
1894 return sender->id() == id; | |
1895 }); | |
1896 return it != senders_.end() ? it->get() : nullptr; | |
1897 } | |
1898 | |
1899 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator | 1919 std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator |
1900 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { | 1920 PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { |
1901 return std::find_if( | 1921 return std::find_if( |
1902 senders_.begin(), senders_.end(), | 1922 senders_.begin(), senders_.end(), |
1903 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { | 1923 [track](const rtc::scoped_refptr<RtpSenderInterface>& sender) { |
1904 return sender->track() == track; | 1924 return sender->track() == track; |
1905 }); | 1925 }); |
1906 } | 1926 } |
1907 | 1927 |
1908 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator | 1928 std::vector<rtc::scoped_refptr<RtpReceiverInterface>>::iterator |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1946 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { | 1966 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { |
1947 for (const auto& channel : sctp_data_channels_) { | 1967 for (const auto& channel : sctp_data_channels_) { |
1948 if (channel->id() == sid) { | 1968 if (channel->id() == sid) { |
1949 return channel; | 1969 return channel; |
1950 } | 1970 } |
1951 } | 1971 } |
1952 return nullptr; | 1972 return nullptr; |
1953 } | 1973 } |
1954 | 1974 |
1955 } // namespace webrtc | 1975 } // namespace webrtc |
OLD | NEW |