blob: b4e500bbc8d1ddc4f01d175d700c5566ed58fd49 [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 {
Johannes Kron3e983682020-03-29 22:17:00 +020025namespace {
26template <class T>
27RTCError VerifyCodecPreferences(const std::vector<RtpCodecCapability>& codecs,
28 const std::vector<T>& send_codecs,
29 const std::vector<T>& recv_codecs) {
30 // If the intersection between codecs and
31 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
32 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
33 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
34 // This ensures that we always have something to offer, regardless of
35 // transceiver.direction.
36
37 if (!absl::c_any_of(codecs, [&recv_codecs](const RtpCodecCapability& codec) {
38 return codec.name != cricket::kRtxCodecName &&
39 codec.name != cricket::kRedCodecName &&
40 codec.name != cricket::kFlexfecCodecName &&
41 absl::c_any_of(recv_codecs, [&codec](const T& recv_codec) {
42 return recv_codec.MatchesCapability(codec);
43 });
44 })) {
45 return RTCError(RTCErrorType::INVALID_MODIFICATION,
46 "Invalid codec preferences: Missing codec from recv "
47 "codec capabilities.");
48 }
49
50 if (!absl::c_any_of(codecs, [&send_codecs](const RtpCodecCapability& codec) {
51 return codec.name != cricket::kRtxCodecName &&
52 codec.name != cricket::kRedCodecName &&
53 codec.name != cricket::kFlexfecCodecName &&
54 absl::c_any_of(send_codecs, [&codec](const T& send_codec) {
55 return send_codec.MatchesCapability(codec);
56 });
57 })) {
58 return RTCError(RTCErrorType::INVALID_MODIFICATION,
59 "Invalid codec preferences: Missing codec from send "
60 "codec capabilities.");
61 }
62
63 // Let codecCapabilities be the union of
64 // RTCRtpSender.getCapabilities(kind).codecs and
65 // RTCRtpReceiver.getCapabilities(kind).codecs. For each codec in codecs, If
66 // codec is not in codecCapabilities, throw InvalidModificationError.
67 for (const auto& codec_preference : codecs) {
68 bool is_recv_codec =
69 absl::c_any_of(recv_codecs, [&codec_preference](const T& codec) {
70 return codec.MatchesCapability(codec_preference);
71 });
72
73 bool is_send_codec =
74 absl::c_any_of(send_codecs, [&codec_preference](const T& codec) {
75 return codec.MatchesCapability(codec_preference);
76 });
77
78 if (!is_recv_codec && !is_send_codec) {
79 return RTCError(
80 RTCErrorType::INVALID_MODIFICATION,
81 std::string("Invalid codec preferences: invalid codec with name \"") +
82 codec_preference.name + "\".");
83 }
84 }
85
86 // Check we have a real codec (not just rtx, red or fec)
87 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
88 return codec.name == cricket::kRtxCodecName ||
89 codec.name == cricket::kRedCodecName ||
90 codec.name == cricket::kUlpfecCodecName;
91 })) {
92 return RTCError(RTCErrorType::INVALID_MODIFICATION,
93 "Invalid codec preferences: codec list must have a non "
94 "RTX, RED or FEC entry.");
95 }
96
97 return RTCError::OK();
98}
99
100} // namespace
Steve Anton6e634bf2017-11-13 10:44:53 -0800101
102RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
103 : unified_plan_(false), media_type_(media_type) {
104 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
105 media_type == cricket::MEDIA_TYPE_VIDEO);
106}
107
Steve Anton79e79602017-11-20 10:25:56 -0800108RtpTransceiver::RtpTransceiver(
109 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
110 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200111 receiver,
Markus Handell0357b3e2020-03-16 13:40:51 +0100112 cricket::ChannelManager* channel_manager,
113 std::vector<RtpHeaderExtensionCapability> header_extensions_offered)
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200114 : unified_plan_(true),
115 media_type_(sender->media_type()),
Markus Handell0357b3e2020-03-16 13:40:51 +0100116 channel_manager_(channel_manager),
Markus Handell755c65d2020-06-24 01:06:10 +0200117 header_extensions_to_offer_(std::move(header_extensions_offered)) {
Steve Anton79e79602017-11-20 10:25:56 -0800118 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
119 media_type_ == cricket::MEDIA_TYPE_VIDEO);
120 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
121 senders_.push_back(sender);
122 receivers_.push_back(receiver);
123}
124
Steve Anton6e634bf2017-11-13 10:44:53 -0800125RtpTransceiver::~RtpTransceiver() {
126 Stop();
127}
128
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800129void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
130 // Cannot set a non-null channel on a stopped transceiver.
131 if (stopped_ && channel) {
132 return;
133 }
134
Steve Anton6e634bf2017-11-13 10:44:53 -0800135 if (channel) {
136 RTC_DCHECK_EQ(media_type(), channel->media_type());
137 }
Steve Anton60776752018-01-10 11:51:34 -0800138
139 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800140 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 11:51:34 -0800141 }
142
Steve Anton6e634bf2017-11-13 10:44:53 -0800143 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -0800144
145 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800146 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 11:51:34 -0800147 this, &RtpTransceiver::OnFirstPacketReceived);
148 }
149
Mirko Bonadei739baf02019-01-27 17:29:42 +0100150 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800151 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
152 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800153 }
Steve Anton60776752018-01-10 11:51:34 -0800154
Mirko Bonadei739baf02019-01-27 17:29:42 +0100155 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800156 if (!channel_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800157 receiver->internal()->Stop();
158 }
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800159
160 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
161 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800162 }
163}
164
165void RtpTransceiver::AddSender(
166 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800167 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800168 RTC_DCHECK(!unified_plan_);
169 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -0800170 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800171 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -0800172 senders_.push_back(sender);
173}
174
175bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
176 RTC_DCHECK(!unified_plan_);
177 if (sender) {
178 RTC_DCHECK_EQ(media_type(), sender->media_type());
179 }
Steve Anton64b626b2019-01-28 17:25:26 -0800180 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800181 if (it == senders_.end()) {
182 return false;
183 }
184 (*it)->internal()->Stop();
185 senders_.erase(it);
186 return true;
187}
188
189void RtpTransceiver::AddReceiver(
190 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
191 receiver) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800192 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800193 RTC_DCHECK(!unified_plan_);
194 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800195 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800196 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800197 receivers_.push_back(receiver);
198}
199
200bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
201 RTC_DCHECK(!unified_plan_);
202 if (receiver) {
203 RTC_DCHECK_EQ(media_type(), receiver->media_type());
204 }
Steve Anton64b626b2019-01-28 17:25:26 -0800205 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800206 if (it == receivers_.end()) {
207 return false;
208 }
209 (*it)->internal()->Stop();
Markus Handell43e62fc2020-01-07 19:46:15 +0100210 // After the receiver has been removed, there's no guarantee that the
211 // contained media channel isn't deleted shortly after this. To make sure that
212 // the receiver doesn't spontaneously try to use it's (potentially stale)
213 // media channel reference, we clear it out.
214 (*it)->internal()->SetMediaChannel(nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800215 receivers_.erase(it);
216 return true;
217}
218
Steve Antonf9381f02017-12-14 10:23:57 -0800219rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
220 RTC_DCHECK(unified_plan_);
221 RTC_CHECK_EQ(1u, senders_.size());
222 return senders_[0]->internal();
223}
224
225rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
226 const {
227 RTC_DCHECK(unified_plan_);
228 RTC_CHECK_EQ(1u, receivers_.size());
229 return receivers_[0]->internal();
230}
231
Steve Anton69470252018-02-09 11:43:08 -0800232cricket::MediaType RtpTransceiver::media_type() const {
233 return media_type_;
234}
235
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200236absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800237 return mid_;
238}
239
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800240void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100241 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800242 receiver->internal()->NotifyFirstPacketReceived();
243 }
244}
245
Steve Anton6e634bf2017-11-13 10:44:53 -0800246rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
247 RTC_DCHECK(unified_plan_);
248 RTC_CHECK_EQ(1u, senders_.size());
249 return senders_[0];
250}
251
252rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
253 RTC_DCHECK(unified_plan_);
254 RTC_CHECK_EQ(1u, receivers_.size());
255 return receivers_[0];
256}
257
Steve Antondcc3c022017-12-22 16:02:54 -0800258void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700259 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
260 << ") current direction from "
261 << (current_direction_ ? RtpTransceiverDirectionToString(
262 *current_direction_)
263 : "<not set>")
264 << " to " << RtpTransceiverDirectionToString(direction)
265 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800266 current_direction_ = direction;
267 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
268 has_ever_been_used_to_send_ = true;
269 }
270}
271
Steve Anton0f5400a2018-07-17 14:25:36 -0700272void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
273 fired_direction_ = direction;
274}
275
Steve Anton6e634bf2017-11-13 10:44:53 -0800276bool RtpTransceiver::stopped() const {
277 return stopped_;
278}
279
280RtpTransceiverDirection RtpTransceiver::direction() const {
281 return direction_;
282}
283
284void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
Steve Anton52d86772018-02-20 15:48:12 -0800285 if (stopped()) {
286 return;
287 }
288 if (new_direction == direction_) {
289 return;
290 }
291 direction_ = new_direction;
292 SignalNegotiationNeeded();
Steve Anton6e634bf2017-11-13 10:44:53 -0800293}
294
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200295absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800296 const {
297 return current_direction_;
298}
299
Steve Anton0f5400a2018-07-17 14:25:36 -0700300absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
301 const {
302 return fired_direction_;
303}
304
Steve Anton6e634bf2017-11-13 10:44:53 -0800305void RtpTransceiver::Stop() {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100306 for (const auto& sender : senders_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800307 sender->internal()->Stop();
308 }
Mirko Bonadei739baf02019-01-27 17:29:42 +0100309 for (const auto& receiver : receivers_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800310 receiver->internal()->Stop();
311 }
312 stopped_ = true;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200313 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800314}
315
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200316RTCError RtpTransceiver::SetCodecPreferences(
317 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
318 RTC_DCHECK(unified_plan_);
319
320 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
321 // to codecs and abort these steps.
322 if (codec_capabilities.empty()) {
323 codec_preferences_.clear();
324 return RTCError::OK();
325 }
326
327 // 4. Remove any duplicate values in codecs.
328 std::vector<RtpCodecCapability> codecs;
329 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
330 [&codecs](const RtpCodecCapability& codec) {
331 return absl::c_linear_search(codecs, codec);
332 });
333
Johannes Kron3e983682020-03-29 22:17:00 +0200334 // 6. to 8.
335 RTCError result;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200336 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200337 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
338 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
339 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
340
Johannes Kron3e983682020-03-29 22:17:00 +0200341 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200342 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
Johannes Kron3e983682020-03-29 22:17:00 +0200343 std::vector<cricket::VideoCodec> recv_codecs, send_codecs;
344 channel_manager_->GetSupportedVideoReceiveCodecs(&recv_codecs);
345 channel_manager_->GetSupportedVideoSendCodecs(&send_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200346
Johannes Kron3e983682020-03-29 22:17:00 +0200347 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200348 }
349
Johannes Kron3e983682020-03-29 22:17:00 +0200350 if (result.ok()) {
351 codec_preferences_ = codecs;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200352 }
353
Johannes Kron3e983682020-03-29 22:17:00 +0200354 return result;
Steve Anton6e634bf2017-11-13 10:44:53 -0800355}
356
Markus Handell0357b3e2020-03-16 13:40:51 +0100357std::vector<RtpHeaderExtensionCapability>
358RtpTransceiver::HeaderExtensionsToOffer() const {
Markus Handell755c65d2020-06-24 01:06:10 +0200359 return header_extensions_to_offer_;
360}
361
362RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
363 rtc::ArrayView<const RtpHeaderExtensionCapability>
364 header_extensions_to_offer) {
365 for (const auto& entry : header_extensions_to_offer) {
366 // Handle unsupported requests for mandatory extensions as per
367 // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
368 // Note:
369 // - We do not handle setOfferedRtpHeaderExtensions algorithm step 2.1,
370 // this has to be checked on a higher level. We naturally error out
371 // in the handling of Step 2.2 if an unset URI is encountered.
372
373 // Step 2.2.
374 // Handle unknown extensions.
375 auto it = std::find_if(
376 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
377 [&entry](const auto& offered) { return entry.uri == offered.uri; });
378 if (it == header_extensions_to_offer_.end()) {
379 return RTCError(RTCErrorType::INVALID_PARAMETER,
380 "Attempted to modify an unoffered extension.");
381 }
382
383 // Step 2.4-2.5.
384 // - Use of the transceiver interface indicates unified plan is in effect,
385 // hence the MID extension needs to be enabled.
386 // - Also handle the mandatory video orientation extensions.
387 if ((entry.uri == RtpExtension::kMidUri ||
388 entry.uri == RtpExtension::kVideoRotationUri) &&
389 entry.direction != RtpTransceiverDirection::kSendRecv) {
390 return RTCError(RTCErrorType::INVALID_MODIFICATION,
391 "Attempted to stop a mandatory extension.");
392 }
393 }
394
395 // Apply mutation after error checking.
396 for (const auto& entry : header_extensions_to_offer) {
397 auto it = std::find_if(
398 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
399 [&entry](const auto& offered) { return entry.uri == offered.uri; });
400 it->direction = entry.direction;
401 }
402
403 return RTCError::OK();
Markus Handell0357b3e2020-03-16 13:40:51 +0100404}
405
Steve Anton6e634bf2017-11-13 10:44:53 -0800406} // namespace webrtc