1 /*
2  *  Copyright 2020 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/rtp_transmission_manager.h"
12 
13 #include <algorithm>
14 
15 #include "absl/types/optional.h"
16 #include "api/peer_connection_interface.h"
17 #include "api/rtp_transceiver_direction.h"
18 #include "pc/audio_rtp_receiver.h"
19 #include "pc/channel.h"
20 #include "pc/stats_collector_interface.h"
21 #include "pc/video_rtp_receiver.h"
22 #include "rtc_base/checks.h"
23 #include "rtc_base/helpers.h"
24 #include "rtc_base/logging.h"
25 
26 namespace webrtc {
27 
28 namespace {
29 
30 static const char kDefaultAudioSenderId[] = "defaulta0";
31 static const char kDefaultVideoSenderId[] = "defaultv0";
32 
33 }  // namespace
34 
RtpTransmissionManager(bool is_unified_plan,rtc::Thread * signaling_thread,rtc::Thread * worker_thread,cricket::ChannelManager * channel_manager,UsagePattern * usage_pattern,PeerConnectionObserver * observer,StatsCollectorInterface * stats,std::function<void ()> on_negotiation_needed)35 RtpTransmissionManager::RtpTransmissionManager(
36     bool is_unified_plan,
37     rtc::Thread* signaling_thread,
38     rtc::Thread* worker_thread,
39     cricket::ChannelManager* channel_manager,
40     UsagePattern* usage_pattern,
41     PeerConnectionObserver* observer,
42     StatsCollectorInterface* stats,
43     std::function<void()> on_negotiation_needed)
44     : is_unified_plan_(is_unified_plan),
45       signaling_thread_(signaling_thread),
46       worker_thread_(worker_thread),
47       channel_manager_(channel_manager),
48       usage_pattern_(usage_pattern),
49       observer_(observer),
50       stats_(stats),
51       on_negotiation_needed_(on_negotiation_needed),
52       weak_ptr_factory_(this) {}
53 
Close()54 void RtpTransmissionManager::Close() {
55   closed_ = true;
56   observer_ = nullptr;
57 }
58 
59 // Implementation of SetStreamsObserver
OnSetStreams()60 void RtpTransmissionManager::OnSetStreams() {
61   RTC_DCHECK_RUN_ON(signaling_thread());
62   if (IsUnifiedPlan())
63     OnNegotiationNeeded();
64 }
65 
66 // Function to call back to the PeerConnection when negotiation is needed
OnNegotiationNeeded()67 void RtpTransmissionManager::OnNegotiationNeeded() {
68   on_negotiation_needed_();
69 }
70 
71 // Function that returns the currently valid observer
Observer() const72 PeerConnectionObserver* RtpTransmissionManager::Observer() const {
73   RTC_DCHECK(!closed_);
74   RTC_DCHECK(observer_);
75   return observer_;
76 }
77 
voice_media_channel() const78 cricket::VoiceMediaChannel* RtpTransmissionManager::voice_media_channel()
79     const {
80   RTC_DCHECK_RUN_ON(signaling_thread());
81   RTC_DCHECK(!IsUnifiedPlan());
82   auto* voice_channel = static_cast<cricket::VoiceChannel*>(
83       GetAudioTransceiver()->internal()->channel());
84   if (voice_channel) {
85     return voice_channel->media_channel();
86   } else {
87     return nullptr;
88   }
89 }
90 
video_media_channel() const91 cricket::VideoMediaChannel* RtpTransmissionManager::video_media_channel()
92     const {
93   RTC_DCHECK_RUN_ON(signaling_thread());
94   RTC_DCHECK(!IsUnifiedPlan());
95   auto* video_channel = static_cast<cricket::VideoChannel*>(
96       GetVideoTransceiver()->internal()->channel());
97   if (video_channel) {
98     return video_channel->media_channel();
99   } else {
100     return nullptr;
101   }
102 }
103 
104 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
AddTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids)105 RtpTransmissionManager::AddTrack(
106     rtc::scoped_refptr<MediaStreamTrackInterface> track,
107     const std::vector<std::string>& stream_ids) {
108   RTC_DCHECK_RUN_ON(signaling_thread());
109 
110   return (IsUnifiedPlan() ? AddTrackUnifiedPlan(track, stream_ids)
111                           : AddTrackPlanB(track, stream_ids));
112 }
113 
114 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
AddTrackPlanB(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids)115 RtpTransmissionManager::AddTrackPlanB(
116     rtc::scoped_refptr<MediaStreamTrackInterface> track,
117     const std::vector<std::string>& stream_ids) {
118   RTC_DCHECK_RUN_ON(signaling_thread());
119   if (stream_ids.size() > 1u) {
120     LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
121                          "AddTrack with more than one stream is not "
122                          "supported with Plan B semantics.");
123   }
124   std::vector<std::string> adjusted_stream_ids = stream_ids;
125   if (adjusted_stream_ids.empty()) {
126     adjusted_stream_ids.push_back(rtc::CreateRandomUuid());
127   }
128   cricket::MediaType media_type =
129       (track->kind() == MediaStreamTrackInterface::kAudioKind
130            ? cricket::MEDIA_TYPE_AUDIO
131            : cricket::MEDIA_TYPE_VIDEO);
132   auto new_sender =
133       CreateSender(media_type, track->id(), track, adjusted_stream_ids, {});
134   if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
135     new_sender->internal()->SetMediaChannel(voice_media_channel());
136     GetAudioTransceiver()->internal()->AddSender(new_sender);
137     const RtpSenderInfo* sender_info =
138         FindSenderInfo(local_audio_sender_infos_,
139                        new_sender->internal()->stream_ids()[0], track->id());
140     if (sender_info) {
141       new_sender->internal()->SetSsrc(sender_info->first_ssrc);
142     }
143   } else {
144     RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
145     new_sender->internal()->SetMediaChannel(video_media_channel());
146     GetVideoTransceiver()->internal()->AddSender(new_sender);
147     const RtpSenderInfo* sender_info =
148         FindSenderInfo(local_video_sender_infos_,
149                        new_sender->internal()->stream_ids()[0], track->id());
150     if (sender_info) {
151       new_sender->internal()->SetSsrc(sender_info->first_ssrc);
152     }
153   }
154   return rtc::scoped_refptr<RtpSenderInterface>(new_sender);
155 }
156 
157 RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
AddTrackUnifiedPlan(rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids)158 RtpTransmissionManager::AddTrackUnifiedPlan(
159     rtc::scoped_refptr<MediaStreamTrackInterface> track,
160     const std::vector<std::string>& stream_ids) {
161   auto transceiver = FindFirstTransceiverForAddedTrack(track);
162   if (transceiver) {
163     RTC_LOG(LS_INFO) << "Reusing an existing "
164                      << cricket::MediaTypeToString(transceiver->media_type())
165                      << " transceiver for AddTrack.";
166     if (transceiver->stopping()) {
167       LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
168                            "The existing transceiver is stopping.");
169     }
170 
171     if (transceiver->direction() == RtpTransceiverDirection::kRecvOnly) {
172       transceiver->internal()->set_direction(
173           RtpTransceiverDirection::kSendRecv);
174     } else if (transceiver->direction() == RtpTransceiverDirection::kInactive) {
175       transceiver->internal()->set_direction(
176           RtpTransceiverDirection::kSendOnly);
177     }
178     transceiver->sender()->SetTrack(track);
179     transceiver->internal()->sender_internal()->set_stream_ids(stream_ids);
180     transceiver->internal()->set_reused_for_addtrack(true);
181   } else {
182     cricket::MediaType media_type =
183         (track->kind() == MediaStreamTrackInterface::kAudioKind
184              ? cricket::MEDIA_TYPE_AUDIO
185              : cricket::MEDIA_TYPE_VIDEO);
186     RTC_LOG(LS_INFO) << "Adding " << cricket::MediaTypeToString(media_type)
187                      << " transceiver in response to a call to AddTrack.";
188     std::string sender_id = track->id();
189     // Avoid creating a sender with an existing ID by generating a random ID.
190     // This can happen if this is the second time AddTrack has created a sender
191     // for this track.
192     if (FindSenderById(sender_id)) {
193       sender_id = rtc::CreateRandomUuid();
194     }
195     auto sender = CreateSender(media_type, sender_id, track, stream_ids, {});
196     auto receiver = CreateReceiver(media_type, rtc::CreateRandomUuid());
197     transceiver = CreateAndAddTransceiver(sender, receiver);
198     transceiver->internal()->set_created_by_addtrack(true);
199     transceiver->internal()->set_direction(RtpTransceiverDirection::kSendRecv);
200   }
201   return transceiver->sender();
202 }
203 
204 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
CreateSender(cricket::MediaType media_type,const std::string & id,rtc::scoped_refptr<MediaStreamTrackInterface> track,const std::vector<std::string> & stream_ids,const std::vector<RtpEncodingParameters> & send_encodings)205 RtpTransmissionManager::CreateSender(
206     cricket::MediaType media_type,
207     const std::string& id,
208     rtc::scoped_refptr<MediaStreamTrackInterface> track,
209     const std::vector<std::string>& stream_ids,
210     const std::vector<RtpEncodingParameters>& send_encodings) {
211   RTC_DCHECK_RUN_ON(signaling_thread());
212   rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender;
213   if (media_type == cricket::MEDIA_TYPE_AUDIO) {
214     RTC_DCHECK(!track ||
215                (track->kind() == MediaStreamTrackInterface::kAudioKind));
216     sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
217         signaling_thread(),
218         AudioRtpSender::Create(worker_thread(), id, stats_, this));
219     NoteUsageEvent(UsageEvent::AUDIO_ADDED);
220   } else {
221     RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
222     RTC_DCHECK(!track ||
223                (track->kind() == MediaStreamTrackInterface::kVideoKind));
224     sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
225         signaling_thread(), VideoRtpSender::Create(worker_thread(), id, this));
226     NoteUsageEvent(UsageEvent::VIDEO_ADDED);
227   }
228   bool set_track_succeeded = sender->SetTrack(track);
229   RTC_DCHECK(set_track_succeeded);
230   sender->internal()->set_stream_ids(stream_ids);
231   sender->internal()->set_init_send_encodings(send_encodings);
232   return sender;
233 }
234 
235 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
CreateReceiver(cricket::MediaType media_type,const std::string & receiver_id)236 RtpTransmissionManager::CreateReceiver(cricket::MediaType media_type,
237                                        const std::string& receiver_id) {
238   RTC_DCHECK_RUN_ON(signaling_thread());
239   rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
240       receiver;
241   if (media_type == cricket::MEDIA_TYPE_AUDIO) {
242     receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
243         signaling_thread(),
244         new AudioRtpReceiver(worker_thread(), receiver_id,
245                              std::vector<std::string>({}), IsUnifiedPlan()));
246     NoteUsageEvent(UsageEvent::AUDIO_ADDED);
247   } else {
248     RTC_DCHECK_EQ(media_type, cricket::MEDIA_TYPE_VIDEO);
249     receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
250         signaling_thread(), new VideoRtpReceiver(worker_thread(), receiver_id,
251                                                  std::vector<std::string>({})));
252     NoteUsageEvent(UsageEvent::VIDEO_ADDED);
253   }
254   return receiver;
255 }
256 
257 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
CreateAndAddTransceiver(rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>> receiver)258 RtpTransmissionManager::CreateAndAddTransceiver(
259     rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
260     rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
261         receiver) {
262   RTC_DCHECK_RUN_ON(signaling_thread());
263   // Ensure that the new sender does not have an ID that is already in use by
264   // another sender.
265   // Allow receiver IDs to conflict since those come from remote SDP (which
266   // could be invalid, but should not cause a crash).
267   RTC_DCHECK(!FindSenderById(sender->id()));
268   auto transceiver = RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
269       signaling_thread(),
270       new RtpTransceiver(
271           sender, receiver, channel_manager(),
272           sender->media_type() == cricket::MEDIA_TYPE_AUDIO
273               ? channel_manager()->GetSupportedAudioRtpHeaderExtensions()
274               : channel_manager()->GetSupportedVideoRtpHeaderExtensions(),
275           [this_weak_ptr = weak_ptr_factory_.GetWeakPtr()]() {
276             if (this_weak_ptr) {
277               this_weak_ptr->OnNegotiationNeeded();
278             }
279           }));
280   transceivers()->Add(transceiver);
281   return transceiver;
282 }
283 
284 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
FindFirstTransceiverForAddedTrack(rtc::scoped_refptr<MediaStreamTrackInterface> track)285 RtpTransmissionManager::FindFirstTransceiverForAddedTrack(
286     rtc::scoped_refptr<MediaStreamTrackInterface> track) {
287   RTC_DCHECK_RUN_ON(signaling_thread());
288   RTC_DCHECK(track);
289   for (auto transceiver : transceivers()->List()) {
290     if (!transceiver->sender()->track() &&
291         cricket::MediaTypeToString(transceiver->media_type()) ==
292             track->kind() &&
293         !transceiver->internal()->has_ever_been_used_to_send() &&
294         !transceiver->stopped()) {
295       return transceiver;
296     }
297   }
298   return nullptr;
299 }
300 
301 std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
GetSendersInternal() const302 RtpTransmissionManager::GetSendersInternal() const {
303   RTC_DCHECK_RUN_ON(signaling_thread());
304   std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
305       all_senders;
306   for (const auto& transceiver : transceivers_.List()) {
307     if (IsUnifiedPlan() && transceiver->internal()->stopped())
308       continue;
309 
310     auto senders = transceiver->internal()->senders();
311     all_senders.insert(all_senders.end(), senders.begin(), senders.end());
312   }
313   return all_senders;
314 }
315 
316 std::vector<
317     rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
GetReceiversInternal() const318 RtpTransmissionManager::GetReceiversInternal() const {
319   RTC_DCHECK_RUN_ON(signaling_thread());
320   std::vector<
321       rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
322       all_receivers;
323   for (const auto& transceiver : transceivers_.List()) {
324     if (IsUnifiedPlan() && transceiver->internal()->stopped())
325       continue;
326 
327     auto receivers = transceiver->internal()->receivers();
328     all_receivers.insert(all_receivers.end(), receivers.begin(),
329                          receivers.end());
330   }
331   return all_receivers;
332 }
333 
334 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
GetAudioTransceiver() const335 RtpTransmissionManager::GetAudioTransceiver() const {
336   RTC_DCHECK_RUN_ON(signaling_thread());
337   // This method only works with Plan B SDP, where there is a single
338   // audio/video transceiver.
339   RTC_DCHECK(!IsUnifiedPlan());
340   for (auto transceiver : transceivers_.List()) {
341     if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
342       return transceiver;
343     }
344   }
345   RTC_NOTREACHED();
346   return nullptr;
347 }
348 
349 rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
GetVideoTransceiver() const350 RtpTransmissionManager::GetVideoTransceiver() const {
351   RTC_DCHECK_RUN_ON(signaling_thread());
352   // This method only works with Plan B SDP, where there is a single
353   // audio/video transceiver.
354   RTC_DCHECK(!IsUnifiedPlan());
355   for (auto transceiver : transceivers_.List()) {
356     if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
357       return transceiver;
358     }
359   }
360   RTC_NOTREACHED();
361   return nullptr;
362 }
363 
AddAudioTrack(AudioTrackInterface * track,MediaStreamInterface * stream)364 void RtpTransmissionManager::AddAudioTrack(AudioTrackInterface* track,
365                                            MediaStreamInterface* stream) {
366   RTC_DCHECK_RUN_ON(signaling_thread());
367   RTC_DCHECK(track);
368   RTC_DCHECK(stream);
369   auto sender = FindSenderForTrack(track);
370   if (sender) {
371     // We already have a sender for this track, so just change the stream_id
372     // so that it's correct in the next call to CreateOffer.
373     sender->internal()->set_stream_ids({stream->id()});
374     return;
375   }
376 
377   // Normal case; we've never seen this track before.
378   auto new_sender = CreateSender(cricket::MEDIA_TYPE_AUDIO, track->id(), track,
379                                  {stream->id()}, {});
380   new_sender->internal()->SetMediaChannel(voice_media_channel());
381   GetAudioTransceiver()->internal()->AddSender(new_sender);
382   // If the sender has already been configured in SDP, we call SetSsrc,
383   // which will connect the sender to the underlying transport. This can
384   // occur if a local session description that contains the ID of the sender
385   // is set before AddStream is called. It can also occur if the local
386   // session description is not changed and RemoveStream is called, and
387   // later AddStream is called again with the same stream.
388   const RtpSenderInfo* sender_info =
389       FindSenderInfo(local_audio_sender_infos_, stream->id(), track->id());
390   if (sender_info) {
391     new_sender->internal()->SetSsrc(sender_info->first_ssrc);
392   }
393 }
394 
395 // TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
396 // indefinitely, when we have unified plan SDP.
RemoveAudioTrack(AudioTrackInterface * track,MediaStreamInterface * stream)397 void RtpTransmissionManager::RemoveAudioTrack(AudioTrackInterface* track,
398                                               MediaStreamInterface* stream) {
399   RTC_DCHECK_RUN_ON(signaling_thread());
400   RTC_DCHECK(!IsUnifiedPlan());
401   auto sender = FindSenderForTrack(track);
402   if (!sender) {
403     RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
404                         << " doesn't exist.";
405     return;
406   }
407   GetAudioTransceiver()->internal()->RemoveSender(sender);
408 }
409 
AddVideoTrack(VideoTrackInterface * track,MediaStreamInterface * stream)410 void RtpTransmissionManager::AddVideoTrack(VideoTrackInterface* track,
411                                            MediaStreamInterface* stream) {
412   RTC_DCHECK_RUN_ON(signaling_thread());
413   RTC_DCHECK(track);
414   RTC_DCHECK(stream);
415   auto sender = FindSenderForTrack(track);
416   if (sender) {
417     // We already have a sender for this track, so just change the stream_id
418     // so that it's correct in the next call to CreateOffer.
419     sender->internal()->set_stream_ids({stream->id()});
420     return;
421   }
422 
423   // Normal case; we've never seen this track before.
424   auto new_sender = CreateSender(cricket::MEDIA_TYPE_VIDEO, track->id(), track,
425                                  {stream->id()}, {});
426   new_sender->internal()->SetMediaChannel(video_media_channel());
427   GetVideoTransceiver()->internal()->AddSender(new_sender);
428   const RtpSenderInfo* sender_info =
429       FindSenderInfo(local_video_sender_infos_, stream->id(), track->id());
430   if (sender_info) {
431     new_sender->internal()->SetSsrc(sender_info->first_ssrc);
432   }
433 }
434 
RemoveVideoTrack(VideoTrackInterface * track,MediaStreamInterface * stream)435 void RtpTransmissionManager::RemoveVideoTrack(VideoTrackInterface* track,
436                                               MediaStreamInterface* stream) {
437   RTC_DCHECK_RUN_ON(signaling_thread());
438   RTC_DCHECK(!IsUnifiedPlan());
439   auto sender = FindSenderForTrack(track);
440   if (!sender) {
441     RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
442                         << " doesn't exist.";
443     return;
444   }
445   GetVideoTransceiver()->internal()->RemoveSender(sender);
446 }
447 
CreateAudioReceiver(MediaStreamInterface * stream,const RtpSenderInfo & remote_sender_info)448 void RtpTransmissionManager::CreateAudioReceiver(
449     MediaStreamInterface* stream,
450     const RtpSenderInfo& remote_sender_info) {
451   RTC_DCHECK(!closed_);
452   std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
453   streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
454   // TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
455   // the constructor taking stream IDs instead.
456   auto* audio_receiver = new AudioRtpReceiver(
457       worker_thread(), remote_sender_info.sender_id, streams, IsUnifiedPlan());
458   audio_receiver->SetMediaChannel(voice_media_channel());
459   if (remote_sender_info.sender_id == kDefaultAudioSenderId) {
460     audio_receiver->SetupUnsignaledMediaChannel();
461   } else {
462     audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
463   }
464   auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
465       signaling_thread(), audio_receiver);
466   GetAudioTransceiver()->internal()->AddReceiver(receiver);
467   Observer()->OnAddTrack(receiver, streams);
468   NoteUsageEvent(UsageEvent::AUDIO_ADDED);
469 }
470 
CreateVideoReceiver(MediaStreamInterface * stream,const RtpSenderInfo & remote_sender_info)471 void RtpTransmissionManager::CreateVideoReceiver(
472     MediaStreamInterface* stream,
473     const RtpSenderInfo& remote_sender_info) {
474   RTC_DCHECK(!closed_);
475   std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
476   streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
477   // TODO(https://crbug.com/webrtc/9480): When we remove remote_streams(), use
478   // the constructor taking stream IDs instead.
479   auto* video_receiver = new VideoRtpReceiver(
480       worker_thread(), remote_sender_info.sender_id, streams);
481   video_receiver->SetMediaChannel(video_media_channel());
482   if (remote_sender_info.sender_id == kDefaultVideoSenderId) {
483     video_receiver->SetupUnsignaledMediaChannel();
484   } else {
485     video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
486   }
487   auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
488       signaling_thread(), video_receiver);
489   GetVideoTransceiver()->internal()->AddReceiver(receiver);
490   Observer()->OnAddTrack(receiver, streams);
491   NoteUsageEvent(UsageEvent::VIDEO_ADDED);
492 }
493 
494 // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
495 // description.
496 rtc::scoped_refptr<RtpReceiverInterface>
RemoveAndStopReceiver(const RtpSenderInfo & remote_sender_info)497 RtpTransmissionManager::RemoveAndStopReceiver(
498     const RtpSenderInfo& remote_sender_info) {
499   auto receiver = FindReceiverById(remote_sender_info.sender_id);
500   if (!receiver) {
501     RTC_LOG(LS_WARNING) << "RtpReceiver for track with id "
502                         << remote_sender_info.sender_id << " doesn't exist.";
503     return nullptr;
504   }
505   if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
506     GetAudioTransceiver()->internal()->RemoveReceiver(receiver);
507   } else {
508     GetVideoTransceiver()->internal()->RemoveReceiver(receiver);
509   }
510   return receiver;
511 }
512 
OnRemoteSenderAdded(const RtpSenderInfo & sender_info,MediaStreamInterface * stream,cricket::MediaType media_type)513 void RtpTransmissionManager::OnRemoteSenderAdded(
514     const RtpSenderInfo& sender_info,
515     MediaStreamInterface* stream,
516     cricket::MediaType media_type) {
517   RTC_DCHECK_RUN_ON(signaling_thread());
518   RTC_LOG(LS_INFO) << "Creating " << cricket::MediaTypeToString(media_type)
519                    << " receiver for track_id=" << sender_info.sender_id
520                    << " and stream_id=" << sender_info.stream_id;
521 
522   if (media_type == cricket::MEDIA_TYPE_AUDIO) {
523     CreateAudioReceiver(stream, sender_info);
524   } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
525     CreateVideoReceiver(stream, sender_info);
526   } else {
527     RTC_NOTREACHED() << "Invalid media type";
528   }
529 }
530 
OnRemoteSenderRemoved(const RtpSenderInfo & sender_info,MediaStreamInterface * stream,cricket::MediaType media_type)531 void RtpTransmissionManager::OnRemoteSenderRemoved(
532     const RtpSenderInfo& sender_info,
533     MediaStreamInterface* stream,
534     cricket::MediaType media_type) {
535   RTC_DCHECK_RUN_ON(signaling_thread());
536   RTC_LOG(LS_INFO) << "Removing " << cricket::MediaTypeToString(media_type)
537                    << " receiver for track_id=" << sender_info.sender_id
538                    << " and stream_id=" << sender_info.stream_id;
539 
540   rtc::scoped_refptr<RtpReceiverInterface> receiver;
541   if (media_type == cricket::MEDIA_TYPE_AUDIO) {
542     // When the MediaEngine audio channel is destroyed, the RemoteAudioSource
543     // will be notified which will end the AudioRtpReceiver::track().
544     receiver = RemoveAndStopReceiver(sender_info);
545     rtc::scoped_refptr<AudioTrackInterface> audio_track =
546         stream->FindAudioTrack(sender_info.sender_id);
547     if (audio_track) {
548       stream->RemoveTrack(audio_track);
549     }
550   } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
551     // Stopping or destroying a VideoRtpReceiver will end the
552     // VideoRtpReceiver::track().
553     receiver = RemoveAndStopReceiver(sender_info);
554     rtc::scoped_refptr<VideoTrackInterface> video_track =
555         stream->FindVideoTrack(sender_info.sender_id);
556     if (video_track) {
557       // There's no guarantee the track is still available, e.g. the track may
558       // have been removed from the stream by an application.
559       stream->RemoveTrack(video_track);
560     }
561   } else {
562     RTC_NOTREACHED() << "Invalid media type";
563   }
564   if (receiver) {
565     RTC_DCHECK(!closed_);
566     Observer()->OnRemoveTrack(receiver);
567   }
568 }
569 
OnLocalSenderAdded(const RtpSenderInfo & sender_info,cricket::MediaType media_type)570 void RtpTransmissionManager::OnLocalSenderAdded(
571     const RtpSenderInfo& sender_info,
572     cricket::MediaType media_type) {
573   RTC_DCHECK_RUN_ON(signaling_thread());
574   RTC_DCHECK(!IsUnifiedPlan());
575   auto sender = FindSenderById(sender_info.sender_id);
576   if (!sender) {
577     RTC_LOG(LS_WARNING) << "An unknown RtpSender with id "
578                         << sender_info.sender_id
579                         << " has been configured in the local description.";
580     return;
581   }
582 
583   if (sender->media_type() != media_type) {
584     RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
585                            " description with an unexpected media type.";
586     return;
587   }
588 
589   sender->internal()->set_stream_ids({sender_info.stream_id});
590   sender->internal()->SetSsrc(sender_info.first_ssrc);
591 }
592 
OnLocalSenderRemoved(const RtpSenderInfo & sender_info,cricket::MediaType media_type)593 void RtpTransmissionManager::OnLocalSenderRemoved(
594     const RtpSenderInfo& sender_info,
595     cricket::MediaType media_type) {
596   RTC_DCHECK_RUN_ON(signaling_thread());
597   auto sender = FindSenderById(sender_info.sender_id);
598   if (!sender) {
599     // This is the normal case. I.e., RemoveStream has been called and the
600     // SessionDescriptions has been renegotiated.
601     return;
602   }
603 
604   // A sender has been removed from the SessionDescription but it's still
605   // associated with the PeerConnection. This only occurs if the SDP doesn't
606   // match with the calls to CreateSender, AddStream and RemoveStream.
607   if (sender->media_type() != media_type) {
608     RTC_LOG(LS_WARNING) << "An RtpSender has been configured in the local"
609                            " description with an unexpected media type.";
610     return;
611   }
612 
613   sender->internal()->SetSsrc(0);
614 }
615 
GetRemoteSenderInfos(cricket::MediaType media_type)616 std::vector<RtpSenderInfo>* RtpTransmissionManager::GetRemoteSenderInfos(
617     cricket::MediaType media_type) {
618   RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
619              media_type == cricket::MEDIA_TYPE_VIDEO);
620   return (media_type == cricket::MEDIA_TYPE_AUDIO)
621              ? &remote_audio_sender_infos_
622              : &remote_video_sender_infos_;
623 }
624 
GetLocalSenderInfos(cricket::MediaType media_type)625 std::vector<RtpSenderInfo>* RtpTransmissionManager::GetLocalSenderInfos(
626     cricket::MediaType media_type) {
627   RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
628              media_type == cricket::MEDIA_TYPE_VIDEO);
629   return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_sender_infos_
630                                                    : &local_video_sender_infos_;
631 }
632 
FindSenderInfo(const std::vector<RtpSenderInfo> & infos,const std::string & stream_id,const std::string sender_id) const633 const RtpSenderInfo* RtpTransmissionManager::FindSenderInfo(
634     const std::vector<RtpSenderInfo>& infos,
635     const std::string& stream_id,
636     const std::string sender_id) const {
637   for (const RtpSenderInfo& sender_info : infos) {
638     if (sender_info.stream_id == stream_id &&
639         sender_info.sender_id == sender_id) {
640       return &sender_info;
641     }
642   }
643   return nullptr;
644 }
645 
646 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
FindSenderForTrack(MediaStreamTrackInterface * track) const647 RtpTransmissionManager::FindSenderForTrack(
648     MediaStreamTrackInterface* track) const {
649   RTC_DCHECK_RUN_ON(signaling_thread());
650   for (const auto& transceiver : transceivers_.List()) {
651     for (auto sender : transceiver->internal()->senders()) {
652       if (sender->track() == track) {
653         return sender;
654       }
655     }
656   }
657   return nullptr;
658 }
659 
660 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>
FindSenderById(const std::string & sender_id) const661 RtpTransmissionManager::FindSenderById(const std::string& sender_id) const {
662   RTC_DCHECK_RUN_ON(signaling_thread());
663   for (const auto& transceiver : transceivers_.List()) {
664     for (auto sender : transceiver->internal()->senders()) {
665       if (sender->id() == sender_id) {
666         return sender;
667       }
668     }
669   }
670   return nullptr;
671 }
672 
673 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
FindReceiverById(const std::string & receiver_id) const674 RtpTransmissionManager::FindReceiverById(const std::string& receiver_id) const {
675   RTC_DCHECK_RUN_ON(signaling_thread());
676   for (const auto& transceiver : transceivers_.List()) {
677     for (auto receiver : transceiver->internal()->receivers()) {
678       if (receiver->id() == receiver_id) {
679         return receiver;
680       }
681     }
682   }
683   return nullptr;
684 }
685 
686 }  // namespace webrtc
687