blob: ca57b911426c3817ff420678d55459d6eb6f837b [file] [log] [blame]
Steve Anton6e634bf2017-11-13 10:44:53 -08001/*
2 * Copyright 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/rtp_transceiver.h"
Steve Anton6e634bf2017-11-13 10:44:53 -080012
13#include <string>
Markus Handell0357b3e2020-03-16 13:40:51 +010014#include <utility>
Steve Anton6e634bf2017-11-13 10:44:53 -080015
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "absl/algorithm/container.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010017#include "api/rtp_parameters.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020018#include "pc/channel_manager.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "pc/rtp_media_utils.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020020#include "pc/rtp_parameters_conversion.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "rtc_base/checks.h"
22#include "rtc_base/logging.h"
Steve Antondcc3c022017-12-22 16:02:54 -080023
Steve Anton6e634bf2017-11-13 10:44:53 -080024namespace webrtc {
25
26RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
27 : unified_plan_(false), media_type_(media_type) {
28 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
29 media_type == cricket::MEDIA_TYPE_VIDEO);
30}
31
Steve Anton79e79602017-11-20 10:25:56 -080032RtpTransceiver::RtpTransceiver(
33 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
34 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +020035 receiver,
Markus Handell0357b3e2020-03-16 13:40:51 +010036 cricket::ChannelManager* channel_manager,
37 std::vector<RtpHeaderExtensionCapability> header_extensions_offered)
Florent Castelli2d9d82e2019-04-23 19:25:51 +020038 : unified_plan_(true),
39 media_type_(sender->media_type()),
Markus Handell0357b3e2020-03-16 13:40:51 +010040 channel_manager_(channel_manager),
41 HeaderExtensionsToOffer_(std::move(header_extensions_offered)) {
Steve Anton79e79602017-11-20 10:25:56 -080042 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
43 media_type_ == cricket::MEDIA_TYPE_VIDEO);
44 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
45 senders_.push_back(sender);
46 receivers_.push_back(receiver);
47}
48
Steve Anton6e634bf2017-11-13 10:44:53 -080049RtpTransceiver::~RtpTransceiver() {
50 Stop();
51}
52
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080053void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
54 // Cannot set a non-null channel on a stopped transceiver.
55 if (stopped_ && channel) {
56 return;
57 }
58
Steve Anton6e634bf2017-11-13 10:44:53 -080059 if (channel) {
60 RTC_DCHECK_EQ(media_type(), channel->media_type());
61 }
Steve Anton60776752018-01-10 11:51:34 -080062
63 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080064 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 11:51:34 -080065 }
66
Steve Anton6e634bf2017-11-13 10:44:53 -080067 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -080068
69 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080070 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 11:51:34 -080071 this, &RtpTransceiver::OnFirstPacketReceived);
72 }
73
Mirko Bonadei739baf02019-01-27 17:29:42 +010074 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080075 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
76 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -080077 }
Steve Anton60776752018-01-10 11:51:34 -080078
Mirko Bonadei739baf02019-01-27 17:29:42 +010079 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080080 if (!channel_) {
Steve Anton6e634bf2017-11-13 10:44:53 -080081 receiver->internal()->Stop();
82 }
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080083
84 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
85 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -080086 }
87}
88
89void RtpTransceiver::AddSender(
90 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080091 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -080092 RTC_DCHECK(!unified_plan_);
93 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -080094 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -080095 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -080096 senders_.push_back(sender);
97}
98
99bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
100 RTC_DCHECK(!unified_plan_);
101 if (sender) {
102 RTC_DCHECK_EQ(media_type(), sender->media_type());
103 }
Steve Anton64b626b2019-01-28 17:25:26 -0800104 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800105 if (it == senders_.end()) {
106 return false;
107 }
108 (*it)->internal()->Stop();
109 senders_.erase(it);
110 return true;
111}
112
113void RtpTransceiver::AddReceiver(
114 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
115 receiver) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800116 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800117 RTC_DCHECK(!unified_plan_);
118 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800119 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800120 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800121 receivers_.push_back(receiver);
122}
123
124bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
125 RTC_DCHECK(!unified_plan_);
126 if (receiver) {
127 RTC_DCHECK_EQ(media_type(), receiver->media_type());
128 }
Steve Anton64b626b2019-01-28 17:25:26 -0800129 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800130 if (it == receivers_.end()) {
131 return false;
132 }
133 (*it)->internal()->Stop();
Markus Handell43e62fc2020-01-07 19:46:15 +0100134 // After the receiver has been removed, there's no guarantee that the
135 // contained media channel isn't deleted shortly after this. To make sure that
136 // the receiver doesn't spontaneously try to use it's (potentially stale)
137 // media channel reference, we clear it out.
138 (*it)->internal()->SetMediaChannel(nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800139 receivers_.erase(it);
140 return true;
141}
142
Steve Antonf9381f02017-12-14 10:23:57 -0800143rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
144 RTC_DCHECK(unified_plan_);
145 RTC_CHECK_EQ(1u, senders_.size());
146 return senders_[0]->internal();
147}
148
149rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
150 const {
151 RTC_DCHECK(unified_plan_);
152 RTC_CHECK_EQ(1u, receivers_.size());
153 return receivers_[0]->internal();
154}
155
Steve Anton69470252018-02-09 11:43:08 -0800156cricket::MediaType RtpTransceiver::media_type() const {
157 return media_type_;
158}
159
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200160absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800161 return mid_;
162}
163
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800164void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100165 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800166 receiver->internal()->NotifyFirstPacketReceived();
167 }
168}
169
Steve Anton6e634bf2017-11-13 10:44:53 -0800170rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
171 RTC_DCHECK(unified_plan_);
172 RTC_CHECK_EQ(1u, senders_.size());
173 return senders_[0];
174}
175
176rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
177 RTC_DCHECK(unified_plan_);
178 RTC_CHECK_EQ(1u, receivers_.size());
179 return receivers_[0];
180}
181
Steve Antondcc3c022017-12-22 16:02:54 -0800182void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700183 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
184 << ") current direction from "
185 << (current_direction_ ? RtpTransceiverDirectionToString(
186 *current_direction_)
187 : "<not set>")
188 << " to " << RtpTransceiverDirectionToString(direction)
189 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800190 current_direction_ = direction;
191 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
192 has_ever_been_used_to_send_ = true;
193 }
194}
195
Steve Anton0f5400a2018-07-17 14:25:36 -0700196void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
197 fired_direction_ = direction;
198}
199
Steve Anton6e634bf2017-11-13 10:44:53 -0800200bool RtpTransceiver::stopped() const {
201 return stopped_;
202}
203
204RtpTransceiverDirection RtpTransceiver::direction() const {
205 return direction_;
206}
207
208void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
Steve Anton52d86772018-02-20 15:48:12 -0800209 if (stopped()) {
210 return;
211 }
212 if (new_direction == direction_) {
213 return;
214 }
215 direction_ = new_direction;
216 SignalNegotiationNeeded();
Steve Anton6e634bf2017-11-13 10:44:53 -0800217}
218
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200219absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800220 const {
221 return current_direction_;
222}
223
Steve Anton0f5400a2018-07-17 14:25:36 -0700224absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
225 const {
226 return fired_direction_;
227}
228
Steve Anton6e634bf2017-11-13 10:44:53 -0800229void RtpTransceiver::Stop() {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100230 for (const auto& sender : senders_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800231 sender->internal()->Stop();
232 }
Mirko Bonadei739baf02019-01-27 17:29:42 +0100233 for (const auto& receiver : receivers_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800234 receiver->internal()->Stop();
235 }
236 stopped_ = true;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200237 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800238}
239
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200240RTCError RtpTransceiver::SetCodecPreferences(
241 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
242 RTC_DCHECK(unified_plan_);
243
244 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
245 // to codecs and abort these steps.
246 if (codec_capabilities.empty()) {
247 codec_preferences_.clear();
248 return RTCError::OK();
249 }
250
251 // 4. Remove any duplicate values in codecs.
252 std::vector<RtpCodecCapability> codecs;
253 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
254 [&codecs](const RtpCodecCapability& codec) {
255 return absl::c_linear_search(codecs, codec);
256 });
257
258 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
Johannes Kron8e8b36a2020-02-07 14:23:45 +0000259 std::vector<cricket::AudioCodec> audio_codecs;
260
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200261 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
262 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
263 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
264
Johannes Kron8e8b36a2020-02-07 14:23:45 +0000265 // 6. If the intersection between codecs and
266 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
267 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
268 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
269 // This ensures that we always have something to offer, regardless of
270 // transceiver.direction.
271
272 if (!absl::c_any_of(
273 codecs, [&recv_codecs](const RtpCodecCapability& codec) {
274 return codec.name != cricket::kRtxCodecName &&
275 codec.name != cricket::kRedCodecName &&
276 codec.name != cricket::kFlexfecCodecName &&
277 absl::c_any_of(
278 recv_codecs,
279 [&codec](const cricket::AudioCodec& recv_codec) {
280 return recv_codec.MatchesCapability(codec);
281 });
282 })) {
283 return RTCError(RTCErrorType::INVALID_MODIFICATION,
284 "Invalid codec preferences: Missing codec from recv "
285 "codec capabilities.");
286 }
287
288 if (!absl::c_any_of(
289 codecs, [&send_codecs](const RtpCodecCapability& codec) {
290 return codec.name != cricket::kRtxCodecName &&
291 codec.name != cricket::kRedCodecName &&
292 codec.name != cricket::kFlexfecCodecName &&
293 absl::c_any_of(
294 send_codecs,
295 [&codec](const cricket::AudioCodec& send_codec) {
296 return send_codec.MatchesCapability(codec);
297 });
298 })) {
299 return RTCError(RTCErrorType::INVALID_MODIFICATION,
300 "Invalid codec preferences: Missing codec from send "
301 "codec capabilities.");
302 }
303
304 // 7. Let codecCapabilities be the union of
305 // RTCRtpSender.getCapabilities(kind).codecs and
306 // RTCRtpReceiver.getCapabilities(kind).codecs. 8.1 For each codec in
307 // codecs, If codec is not in codecCapabilities, throw
308 // InvalidModificationError.
309 for (const auto& codec_preference : codecs) {
310 bool is_recv_codec = absl::c_any_of(
311 recv_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
312 return codec.MatchesCapability(codec_preference);
313 });
314
315 bool is_send_codec = absl::c_any_of(
316 send_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
317 return codec.MatchesCapability(codec_preference);
318 });
319
320 if (!is_recv_codec && !is_send_codec) {
321 return RTCError(
322 RTCErrorType::INVALID_MODIFICATION,
323 std::string(
324 "Invalid codec preferences: invalid codec with name \"") +
325 codec_preference.name + "\".");
326 }
327 }
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200328 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
Johannes Kron8e8b36a2020-02-07 14:23:45 +0000329 std::vector<cricket::VideoCodec> video_codecs;
330 // Video codecs are both for the receive and send side, so the checks are
331 // simpler than the audio ones.
332 channel_manager_->GetSupportedVideoCodecs(&video_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200333
Johannes Kron8e8b36a2020-02-07 14:23:45 +0000334 // Validate codecs
335 for (const auto& codec_preference : codecs) {
336 if (!absl::c_any_of(video_codecs, [&codec_preference](
337 const cricket::VideoCodec& codec) {
338 return codec.MatchesCapability(codec_preference);
339 })) {
340 return RTCError(
341 RTCErrorType::INVALID_MODIFICATION,
342 std::string(
343 "Invalid codec preferences: invalid codec with name \"") +
344 codec_preference.name + "\".");
345 }
346 }
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200347 }
348
Johannes Kron8e8b36a2020-02-07 14:23:45 +0000349 // Check we have a real codec (not just rtx, red or fec)
350 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
351 return codec.name == cricket::kRtxCodecName ||
352 codec.name == cricket::kRedCodecName ||
353 codec.name == cricket::kUlpfecCodecName;
354 })) {
355 return RTCError(RTCErrorType::INVALID_MODIFICATION,
356 "Invalid codec preferences: codec list must have a non "
357 "RTX, RED or FEC entry.");
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200358 }
359
Johannes Kron8e8b36a2020-02-07 14:23:45 +0000360 codec_preferences_ = codecs;
361
362 return RTCError::OK();
Steve Anton6e634bf2017-11-13 10:44:53 -0800363}
364
Markus Handell0357b3e2020-03-16 13:40:51 +0100365std::vector<RtpHeaderExtensionCapability>
366RtpTransceiver::HeaderExtensionsToOffer() const {
367 return HeaderExtensionsToOffer_;
368}
369
Steve Anton6e634bf2017-11-13 10:44:53 -0800370} // namespace webrtc