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