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