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