| 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 |