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