blob: 013277fa5376b6d69dbc0698914aa53467275433 [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
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000013#include <iterator>
Steve Anton6e634bf2017-11-13 10:44:53 -080014#include <string>
Markus Handell0357b3e2020-03-16 13:40:51 +010015#include <utility>
Markus Handell5932fe12020-12-17 22:19:40 +010016#include <vector>
Steve Anton6e634bf2017-11-13 10:44:53 -080017
Steve Anton64b626b2019-01-28 17:25:26 -080018#include "absl/algorithm/container.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010019#include "api/rtp_parameters.h"
Artem Titovd15a5752021-02-10 14:31:24 +010020#include "api/sequence_checker.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000021#include "media/base/codec.h"
22#include "media/base/media_constants.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020023#include "pc/channel_manager.h"
Steve Anton10542f22019-01-11 09:11:00 -080024#include "pc/rtp_media_utils.h"
Markus Handell5932fe12020-12-17 22:19:40 +010025#include "pc/session_description.h"
Yves Gerey3e707812018-11-28 16:47:49 +010026#include "rtc_base/checks.h"
27#include "rtc_base/logging.h"
Tommi99c8a802021-04-27 15:00:00 +020028#include "rtc_base/task_utils/to_queued_task.h"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000029#include "rtc_base/thread.h"
Steve Antondcc3c022017-12-22 16:02:54 -080030
Steve Anton6e634bf2017-11-13 10:44:53 -080031namespace webrtc {
Johannes Kron3e983682020-03-29 22:17:00 +020032namespace {
33template <class T>
34RTCError VerifyCodecPreferences(const std::vector<RtpCodecCapability>& codecs,
35 const std::vector<T>& send_codecs,
36 const std::vector<T>& recv_codecs) {
37 // If the intersection between codecs and
38 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
39 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
40 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
41 // This ensures that we always have something to offer, regardless of
42 // transceiver.direction.
43
44 if (!absl::c_any_of(codecs, [&recv_codecs](const RtpCodecCapability& codec) {
45 return codec.name != cricket::kRtxCodecName &&
46 codec.name != cricket::kRedCodecName &&
47 codec.name != cricket::kFlexfecCodecName &&
48 absl::c_any_of(recv_codecs, [&codec](const T& recv_codec) {
49 return recv_codec.MatchesCapability(codec);
50 });
51 })) {
52 return RTCError(RTCErrorType::INVALID_MODIFICATION,
53 "Invalid codec preferences: Missing codec from recv "
54 "codec capabilities.");
55 }
56
57 if (!absl::c_any_of(codecs, [&send_codecs](const RtpCodecCapability& codec) {
58 return codec.name != cricket::kRtxCodecName &&
59 codec.name != cricket::kRedCodecName &&
60 codec.name != cricket::kFlexfecCodecName &&
61 absl::c_any_of(send_codecs, [&codec](const T& send_codec) {
62 return send_codec.MatchesCapability(codec);
63 });
64 })) {
65 return RTCError(RTCErrorType::INVALID_MODIFICATION,
66 "Invalid codec preferences: Missing codec from send "
67 "codec capabilities.");
68 }
69
70 // Let codecCapabilities be the union of
71 // RTCRtpSender.getCapabilities(kind).codecs and
72 // RTCRtpReceiver.getCapabilities(kind).codecs. For each codec in codecs, If
73 // codec is not in codecCapabilities, throw InvalidModificationError.
74 for (const auto& codec_preference : codecs) {
75 bool is_recv_codec =
76 absl::c_any_of(recv_codecs, [&codec_preference](const T& codec) {
77 return codec.MatchesCapability(codec_preference);
78 });
79
80 bool is_send_codec =
81 absl::c_any_of(send_codecs, [&codec_preference](const T& codec) {
82 return codec.MatchesCapability(codec_preference);
83 });
84
85 if (!is_recv_codec && !is_send_codec) {
86 return RTCError(
87 RTCErrorType::INVALID_MODIFICATION,
88 std::string("Invalid codec preferences: invalid codec with name \"") +
89 codec_preference.name + "\".");
90 }
91 }
92
93 // Check we have a real codec (not just rtx, red or fec)
94 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
95 return codec.name == cricket::kRtxCodecName ||
96 codec.name == cricket::kRedCodecName ||
97 codec.name == cricket::kUlpfecCodecName;
98 })) {
99 return RTCError(RTCErrorType::INVALID_MODIFICATION,
100 "Invalid codec preferences: codec list must have a non "
101 "RTX, RED or FEC entry.");
102 }
103
104 return RTCError::OK();
105}
106
Harald Alvestrand6060df52020-08-11 09:54:02 +0200107TaskQueueBase* GetCurrentTaskQueueOrThread() {
108 TaskQueueBase* current = TaskQueueBase::Current();
109 if (!current)
110 current = rtc::ThreadManager::Instance()->CurrentThread();
111 return current;
112}
113
Johannes Kron3e983682020-03-29 22:17:00 +0200114} // namespace
Steve Anton6e634bf2017-11-13 10:44:53 -0800115
Tommi99c8a802021-04-27 15:00:00 +0200116RtpTransceiver::RtpTransceiver(
117 cricket::MediaType media_type,
118 cricket::ChannelManager* channel_manager /* = nullptr*/)
Harald Alvestrand6060df52020-08-11 09:54:02 +0200119 : thread_(GetCurrentTaskQueueOrThread()),
120 unified_plan_(false),
Tommi99c8a802021-04-27 15:00:00 +0200121 media_type_(media_type),
122 channel_manager_(channel_manager) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800123 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
124 media_type == cricket::MEDIA_TYPE_VIDEO);
Tommi99c8a802021-04-27 15:00:00 +0200125 RTC_DCHECK(channel_manager_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800126}
127
Steve Anton79e79602017-11-20 10:25:56 -0800128RtpTransceiver::RtpTransceiver(
129 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
130 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200131 receiver,
Markus Handell0357b3e2020-03-16 13:40:51 +0100132 cricket::ChannelManager* channel_manager,
Harald Alvestrand280054f2020-11-10 13:12:53 +0000133 std::vector<RtpHeaderExtensionCapability> header_extensions_offered,
134 std::function<void()> on_negotiation_needed)
Harald Alvestrand6060df52020-08-11 09:54:02 +0200135 : thread_(GetCurrentTaskQueueOrThread()),
136 unified_plan_(true),
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200137 media_type_(sender->media_type()),
Markus Handell0357b3e2020-03-16 13:40:51 +0100138 channel_manager_(channel_manager),
Harald Alvestrand280054f2020-11-10 13:12:53 +0000139 header_extensions_to_offer_(std::move(header_extensions_offered)),
140 on_negotiation_needed_(std::move(on_negotiation_needed)) {
Steve Anton79e79602017-11-20 10:25:56 -0800141 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
142 media_type_ == cricket::MEDIA_TYPE_VIDEO);
143 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
Tommi99c8a802021-04-27 15:00:00 +0200144 RTC_DCHECK(channel_manager_);
Steve Anton79e79602017-11-20 10:25:56 -0800145 senders_.push_back(sender);
146 receivers_.push_back(receiver);
147}
148
Steve Anton6e634bf2017-11-13 10:44:53 -0800149RtpTransceiver::~RtpTransceiver() {
Tommi99c8a802021-04-27 15:00:00 +0200150 // TODO(tommi): On Android, when running PeerConnectionClientTest (e.g.
151 // PeerConnectionClientTest#testCameraSwitch), the instance doesn't get
152 // deleted on `thread_`. See if we can fix that.
Harald Alvestrand85466662021-04-19 21:21:36 +0000153 if (!stopped_) {
154 RTC_DCHECK_RUN_ON(thread_);
155 StopInternal();
156 }
Tomas Gunnarsson16de2162022-01-26 10:21:57 +0100157
158 RTC_CHECK(!channel_) << "Missing call to SetChannel(nullptr)?";
Steve Anton6e634bf2017-11-13 10:44:53 -0800159}
160
Tomas Gunnarsson4f8a58c2022-01-19 11:36:23 +0100161void RtpTransceiver::SetChannel(
162 cricket::ChannelInterface* channel,
163 std::function<RtpTransportInternal*(const std::string&)> transport_lookup) {
Tommi99c8a802021-04-27 15:00:00 +0200164 RTC_DCHECK_RUN_ON(thread_);
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800165 // Cannot set a non-null channel on a stopped transceiver.
Tomas Gunnarsson16de2162022-01-26 10:21:57 +0100166 if ((stopped_ && channel) || channel == channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800167 return;
168 }
169
Tommi99c8a802021-04-27 15:00:00 +0200170 RTC_DCHECK(channel || channel_);
Tomas Gunnarsson4f8a58c2022-01-19 11:36:23 +0100171 RTC_DCHECK(!channel || transport_lookup) << "lookup function not supplied";
Tommi99c8a802021-04-27 15:00:00 +0200172
Tommife041642021-04-07 10:08:28 +0200173 RTC_LOG_THREAD_BLOCK_COUNT();
174
Tommi99c8a802021-04-27 15:00:00 +0200175 if (channel_) {
176 signaling_thread_safety_->SetNotAlive();
177 signaling_thread_safety_ = nullptr;
178 }
179
Steve Anton6e634bf2017-11-13 10:44:53 -0800180 if (channel) {
181 RTC_DCHECK_EQ(media_type(), channel->media_type());
Tommi99c8a802021-04-27 15:00:00 +0200182 signaling_thread_safety_ = PendingTaskSafetyFlag::Create();
Steve Anton6e634bf2017-11-13 10:44:53 -0800183 }
Steve Anton60776752018-01-10 11:51:34 -0800184
Tomas Gunnarsson16de2162022-01-26 10:21:57 +0100185 cricket::ChannelInterface* channel_to_delete = nullptr;
186
Tommi99c8a802021-04-27 15:00:00 +0200187 // An alternative to this, could be to require SetChannel to be called
188 // on the network thread. The channel object operates for the most part
189 // on the network thread, as part of its initialization being on the network
190 // thread is required, so setting a channel object as part of the construction
191 // (without thread hopping) might be the more efficient thing to do than
192 // how SetChannel works today.
193 // Similarly, if the channel() accessor is limited to the network thread, that
194 // helps with keeping the channel implementation requirements being met and
195 // avoids synchronization for accessing the pointer or network related state.
196 channel_manager_->network_thread()->Invoke<void>(RTC_FROM_HERE, [&]() {
197 if (channel_) {
198 channel_->SetFirstPacketReceivedCallback(nullptr);
Tomas Gunnarsson4f8a58c2022-01-19 11:36:23 +0100199 channel_->SetRtpTransport(nullptr);
Tomas Gunnarsson16de2162022-01-26 10:21:57 +0100200 channel_to_delete = channel_;
Tommi99c8a802021-04-27 15:00:00 +0200201 }
Steve Anton60776752018-01-10 11:51:34 -0800202
Tommi99c8a802021-04-27 15:00:00 +0200203 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -0800204
Tommi99c8a802021-04-27 15:00:00 +0200205 if (channel_) {
Tomas Gunnarsson5411b172022-01-24 08:45:26 +0100206 channel_->SetRtpTransport(transport_lookup(channel_->mid()));
Tommi99c8a802021-04-27 15:00:00 +0200207 channel_->SetFirstPacketReceivedCallback(
208 [thread = thread_, flag = signaling_thread_safety_, this]() mutable {
209 thread->PostTask(ToQueuedTask(
210 std::move(flag), [this]() { OnFirstPacketReceived(); }));
211 });
212 }
213 });
Steve Anton60776752018-01-10 11:51:34 -0800214
Tommi99c8a802021-04-27 15:00:00 +0200215 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);
Tommife041642021-04-07 10:08:28 +0200216
Tommi6589def2022-02-17 23:36:47 +0100217 if (!channel_) {
218 for (const auto& receiver : receivers_)
219 receiver->internal()->SetSourceEnded();
220 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1); // There should not be an invoke.
Steve Anton6e634bf2017-11-13 10:44:53 -0800221 }
Tomas Gunnarsson16de2162022-01-26 10:21:57 +0100222
Tommi6589def2022-02-17 23:36:47 +0100223 if (channel_to_delete || !senders_.empty() || !receivers_.empty()) {
224 channel_manager_->worker_thread()->Invoke<void>(RTC_FROM_HERE, [&]() {
225 auto* media_channel = channel_ ? channel_->media_channel() : nullptr;
226 for (const auto& sender : senders_) {
227 sender->internal()->SetMediaChannel(media_channel);
228 }
229
230 for (const auto& receiver : receivers_) {
231 receiver->internal()->SetMediaChannel(media_channel);
232 }
233
234 // Destroy the channel, if we had one, now _after_ updating the receivers
235 // who might have had references to the previous channel.
236 if (channel_to_delete) {
237 channel_manager_->DestroyChannel(channel_to_delete);
238 }
239 });
Tomas Gunnarsson16de2162022-01-26 10:21:57 +0100240 }
Tommi6589def2022-02-17 23:36:47 +0100241
242 RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(2);
Steve Anton6e634bf2017-11-13 10:44:53 -0800243}
244
245void RtpTransceiver::AddSender(
246 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Tommi99c8a802021-04-27 15:00:00 +0200247 RTC_DCHECK_RUN_ON(thread_);
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800248 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800249 RTC_DCHECK(!unified_plan_);
250 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -0800251 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800252 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -0800253 senders_.push_back(sender);
254}
255
256bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
257 RTC_DCHECK(!unified_plan_);
258 if (sender) {
259 RTC_DCHECK_EQ(media_type(), sender->media_type());
260 }
Steve Anton64b626b2019-01-28 17:25:26 -0800261 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800262 if (it == senders_.end()) {
263 return false;
264 }
265 (*it)->internal()->Stop();
266 senders_.erase(it);
267 return true;
268}
269
270void RtpTransceiver::AddReceiver(
271 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
272 receiver) {
Tommi99c8a802021-04-27 15:00:00 +0200273 RTC_DCHECK_RUN_ON(thread_);
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800274 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800275 RTC_DCHECK(!unified_plan_);
276 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800277 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800278 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800279 receivers_.push_back(receiver);
280}
281
282bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
Tommi6589def2022-02-17 23:36:47 +0100283 RTC_DCHECK_RUN_ON(thread_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800284 RTC_DCHECK(!unified_plan_);
285 if (receiver) {
286 RTC_DCHECK_EQ(media_type(), receiver->media_type());
287 }
Steve Anton64b626b2019-01-28 17:25:26 -0800288 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800289 if (it == receivers_.end()) {
290 return false;
291 }
Tommi6589def2022-02-17 23:36:47 +0100292
Steve Anton6e634bf2017-11-13 10:44:53 -0800293 (*it)->internal()->Stop();
Tommi6589def2022-02-17 23:36:47 +0100294 channel_manager_->worker_thread()->Invoke<void>(RTC_FROM_HERE, [&]() {
295 // `Stop()` will clear the receiver's pointer to the media channel.
296 (*it)->internal()->SetMediaChannel(nullptr);
297 });
298
Steve Anton6e634bf2017-11-13 10:44:53 -0800299 receivers_.erase(it);
300 return true;
301}
302
Steve Antonf9381f02017-12-14 10:23:57 -0800303rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
304 RTC_DCHECK(unified_plan_);
305 RTC_CHECK_EQ(1u, senders_.size());
Niels Möllere7cc8832022-01-04 15:20:03 +0100306 return rtc::scoped_refptr<RtpSenderInternal>(senders_[0]->internal());
Steve Antonf9381f02017-12-14 10:23:57 -0800307}
308
309rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
310 const {
311 RTC_DCHECK(unified_plan_);
312 RTC_CHECK_EQ(1u, receivers_.size());
Niels Möllere7cc8832022-01-04 15:20:03 +0100313 return rtc::scoped_refptr<RtpReceiverInternal>(receivers_[0]->internal());
Steve Antonf9381f02017-12-14 10:23:57 -0800314}
315
Steve Anton69470252018-02-09 11:43:08 -0800316cricket::MediaType RtpTransceiver::media_type() const {
317 return media_type_;
318}
319
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200320absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800321 return mid_;
322}
323
Tommi99c8a802021-04-27 15:00:00 +0200324void RtpTransceiver::OnFirstPacketReceived() {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100325 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800326 receiver->internal()->NotifyFirstPacketReceived();
327 }
328}
329
Steve Anton6e634bf2017-11-13 10:44:53 -0800330rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
331 RTC_DCHECK(unified_plan_);
332 RTC_CHECK_EQ(1u, senders_.size());
333 return senders_[0];
334}
335
336rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
337 RTC_DCHECK(unified_plan_);
338 RTC_CHECK_EQ(1u, receivers_.size());
339 return receivers_[0];
340}
341
Steve Antondcc3c022017-12-22 16:02:54 -0800342void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700343 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
344 << ") current direction from "
345 << (current_direction_ ? RtpTransceiverDirectionToString(
346 *current_direction_)
347 : "<not set>")
348 << " to " << RtpTransceiverDirectionToString(direction)
349 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800350 current_direction_ = direction;
351 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
352 has_ever_been_used_to_send_ = true;
353 }
354}
355
Steve Anton0f5400a2018-07-17 14:25:36 -0700356void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
357 fired_direction_ = direction;
358}
359
Steve Anton6e634bf2017-11-13 10:44:53 -0800360bool RtpTransceiver::stopped() const {
Tommi99c8a802021-04-27 15:00:00 +0200361 RTC_DCHECK_RUN_ON(thread_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800362 return stopped_;
363}
364
Harald Alvestrand6060df52020-08-11 09:54:02 +0200365bool RtpTransceiver::stopping() const {
366 RTC_DCHECK_RUN_ON(thread_);
367 return stopping_;
368}
369
Steve Anton6e634bf2017-11-13 10:44:53 -0800370RtpTransceiverDirection RtpTransceiver::direction() const {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200371 if (unified_plan_ && stopping())
372 return webrtc::RtpTransceiverDirection::kStopped;
373
Steve Anton6e634bf2017-11-13 10:44:53 -0800374 return direction_;
375}
376
Harald Alvestrand6060df52020-08-11 09:54:02 +0200377RTCError RtpTransceiver::SetDirectionWithError(
378 RtpTransceiverDirection new_direction) {
379 if (unified_plan_ && stopping()) {
380 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
381 "Cannot set direction on a stopping transceiver.");
Steve Anton52d86772018-02-20 15:48:12 -0800382 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200383 if (new_direction == direction_)
384 return RTCError::OK();
385
386 if (new_direction == RtpTransceiverDirection::kStopped) {
387 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
388 "The set direction 'stopped' is invalid.");
Steve Anton52d86772018-02-20 15:48:12 -0800389 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200390
Steve Anton52d86772018-02-20 15:48:12 -0800391 direction_ = new_direction;
Harald Alvestrand280054f2020-11-10 13:12:53 +0000392 on_negotiation_needed_();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200393
394 return RTCError::OK();
Steve Anton6e634bf2017-11-13 10:44:53 -0800395}
396
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200397absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800398 const {
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000399 if (unified_plan_ && stopped())
Harald Alvestrand6060df52020-08-11 09:54:02 +0200400 return webrtc::RtpTransceiverDirection::kStopped;
401
Steve Anton6e634bf2017-11-13 10:44:53 -0800402 return current_direction_;
403}
404
Steve Anton0f5400a2018-07-17 14:25:36 -0700405absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
406 const {
407 return fired_direction_;
408}
409
Harald Alvestrand6060df52020-08-11 09:54:02 +0200410void RtpTransceiver::StopSendingAndReceiving() {
411 // 1. Let sender be transceiver.[[Sender]].
412 // 2. Let receiver be transceiver.[[Receiver]].
413 //
414 // 3. Stop sending media with sender.
415 //
Tommi6589def2022-02-17 23:36:47 +0100416 RTC_DCHECK_RUN_ON(thread_);
417
Harald Alvestrand6060df52020-08-11 09:54:02 +0200418 // 4. Send an RTCP BYE for each RTP stream that was being sent by sender, as
419 // specified in [RFC3550].
Harald Alvestrand6060df52020-08-11 09:54:02 +0200420 for (const auto& sender : senders_)
Steve Anton6e634bf2017-11-13 10:44:53 -0800421 sender->internal()->Stop();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200422
Tommi6589def2022-02-17 23:36:47 +0100423 // Signal to receiver sources that we're stopping.
Harald Alvestrand6060df52020-08-11 09:54:02 +0200424 for (const auto& receiver : receivers_)
Tommi6589def2022-02-17 23:36:47 +0100425 receiver->internal()->Stop();
426
427 channel_manager_->worker_thread()->Invoke<void>(RTC_FROM_HERE, [&]() {
428 // 5 Stop receiving media with receiver.
429 for (const auto& receiver : receivers_)
430 receiver->internal()->SetMediaChannel(nullptr);
431 });
Harald Alvestrand6060df52020-08-11 09:54:02 +0200432
433 stopping_ = true;
434 direction_ = webrtc::RtpTransceiverDirection::kInactive;
435}
436
437RTCError RtpTransceiver::StopStandard() {
438 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000439 // If we're on Plan B, do what Stop() used to do there.
440 if (!unified_plan_) {
441 StopInternal();
442 return RTCError::OK();
443 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200444 // 1. Let transceiver be the RTCRtpTransceiver object on which the method is
445 // invoked.
446 //
447 // 2. Let connection be the RTCPeerConnection object associated with
448 // transceiver.
449 //
450 // 3. If connection.[[IsClosed]] is true, throw an InvalidStateError.
451 if (is_pc_closed_) {
452 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
453 "PeerConnection is closed.");
Harald Alvestranda88c9772020-08-10 18:06:09 +0000454 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200455
456 // 4. If transceiver.[[Stopping]] is true, abort these steps.
457 if (stopping_)
458 return RTCError::OK();
459
460 // 5. Stop sending and receiving given transceiver, and update the
461 // negotiation-needed flag for connection.
462 StopSendingAndReceiving();
Harald Alvestrand280054f2020-11-10 13:12:53 +0000463 on_negotiation_needed_();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200464
465 return RTCError::OK();
466}
467
468void RtpTransceiver::StopInternal() {
Harald Alvestrand85466662021-04-19 21:21:36 +0000469 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000470 StopTransceiverProcedure();
471}
472
473void RtpTransceiver::StopTransceiverProcedure() {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200474 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000475 // As specified in the "Stop the RTCRtpTransceiver" procedure
Harald Alvestrand6060df52020-08-11 09:54:02 +0200476 // 1. If transceiver.[[Stopping]] is false, stop sending and receiving given
477 // transceiver.
478 if (!stopping_)
479 StopSendingAndReceiving();
480
481 // 2. Set transceiver.[[Stopped]] to true.
Steve Anton6e634bf2017-11-13 10:44:53 -0800482 stopped_ = true;
Harald Alvestrand6060df52020-08-11 09:54:02 +0200483
484 // Signal the updated change to the senders.
485 for (const auto& sender : senders_)
486 sender->internal()->SetTransceiverAsStopped();
487
488 // 3. Set transceiver.[[Receptive]] to false.
489 // 4. Set transceiver.[[CurrentDirection]] to null.
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200490 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800491}
492
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200493RTCError RtpTransceiver::SetCodecPreferences(
494 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
495 RTC_DCHECK(unified_plan_);
496
497 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
498 // to codecs and abort these steps.
499 if (codec_capabilities.empty()) {
500 codec_preferences_.clear();
501 return RTCError::OK();
502 }
503
504 // 4. Remove any duplicate values in codecs.
505 std::vector<RtpCodecCapability> codecs;
506 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
507 [&codecs](const RtpCodecCapability& codec) {
508 return absl::c_linear_search(codecs, codec);
509 });
510
Johannes Kron3e983682020-03-29 22:17:00 +0200511 // 6. to 8.
512 RTCError result;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200513 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200514 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
515 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
516 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
517
Johannes Kron3e983682020-03-29 22:17:00 +0200518 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200519 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
Johannes Kron3e983682020-03-29 22:17:00 +0200520 std::vector<cricket::VideoCodec> recv_codecs, send_codecs;
521 channel_manager_->GetSupportedVideoReceiveCodecs(&recv_codecs);
522 channel_manager_->GetSupportedVideoSendCodecs(&send_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200523
Johannes Kron3e983682020-03-29 22:17:00 +0200524 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200525 }
526
Johannes Kron3e983682020-03-29 22:17:00 +0200527 if (result.ok()) {
528 codec_preferences_ = codecs;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200529 }
530
Johannes Kron3e983682020-03-29 22:17:00 +0200531 return result;
Steve Anton6e634bf2017-11-13 10:44:53 -0800532}
533
Markus Handell0357b3e2020-03-16 13:40:51 +0100534std::vector<RtpHeaderExtensionCapability>
535RtpTransceiver::HeaderExtensionsToOffer() const {
Markus Handell755c65d2020-06-24 01:06:10 +0200536 return header_extensions_to_offer_;
537}
538
Markus Handell5932fe12020-12-17 22:19:40 +0100539std::vector<RtpHeaderExtensionCapability>
540RtpTransceiver::HeaderExtensionsNegotiated() const {
Tommicc7a3682021-05-04 14:59:38 +0200541 RTC_DCHECK_RUN_ON(thread_);
Markus Handell5932fe12020-12-17 22:19:40 +0100542 std::vector<RtpHeaderExtensionCapability> result;
Tommicc7a3682021-05-04 14:59:38 +0200543 for (const auto& ext : negotiated_header_extensions_) {
Markus Handell5932fe12020-12-17 22:19:40 +0100544 result.emplace_back(ext.uri, ext.id, RtpTransceiverDirection::kSendRecv);
545 }
546 return result;
547}
548
Markus Handell755c65d2020-06-24 01:06:10 +0200549RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
550 rtc::ArrayView<const RtpHeaderExtensionCapability>
551 header_extensions_to_offer) {
552 for (const auto& entry : header_extensions_to_offer) {
553 // Handle unsupported requests for mandatory extensions as per
554 // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
555 // Note:
556 // - We do not handle setOfferedRtpHeaderExtensions algorithm step 2.1,
557 // this has to be checked on a higher level. We naturally error out
558 // in the handling of Step 2.2 if an unset URI is encountered.
559
560 // Step 2.2.
561 // Handle unknown extensions.
562 auto it = std::find_if(
563 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
564 [&entry](const auto& offered) { return entry.uri == offered.uri; });
565 if (it == header_extensions_to_offer_.end()) {
Markus Handellc17bca72021-01-14 17:08:01 +0100566 return RTCError(RTCErrorType::UNSUPPORTED_PARAMETER,
Markus Handell755c65d2020-06-24 01:06:10 +0200567 "Attempted to modify an unoffered extension.");
568 }
569
570 // Step 2.4-2.5.
571 // - Use of the transceiver interface indicates unified plan is in effect,
572 // hence the MID extension needs to be enabled.
573 // - Also handle the mandatory video orientation extensions.
574 if ((entry.uri == RtpExtension::kMidUri ||
575 entry.uri == RtpExtension::kVideoRotationUri) &&
576 entry.direction != RtpTransceiverDirection::kSendRecv) {
577 return RTCError(RTCErrorType::INVALID_MODIFICATION,
578 "Attempted to stop a mandatory extension.");
579 }
580 }
581
582 // Apply mutation after error checking.
583 for (const auto& entry : header_extensions_to_offer) {
584 auto it = std::find_if(
585 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
586 [&entry](const auto& offered) { return entry.uri == offered.uri; });
587 it->direction = entry.direction;
588 }
589
590 return RTCError::OK();
Markus Handell0357b3e2020-03-16 13:40:51 +0100591}
592
Tommicc7a3682021-05-04 14:59:38 +0200593void RtpTransceiver::OnNegotiationUpdate(
594 SdpType sdp_type,
595 const cricket::MediaContentDescription* content) {
596 RTC_DCHECK_RUN_ON(thread_);
597 RTC_DCHECK(content);
598 if (sdp_type == SdpType::kAnswer)
599 negotiated_header_extensions_ = content->rtp_header_extensions();
600}
601
Harald Alvestrand6060df52020-08-11 09:54:02 +0200602void RtpTransceiver::SetPeerConnectionClosed() {
603 is_pc_closed_ = true;
604}
605
Steve Anton6e634bf2017-11-13 10:44:53 -0800606} // namespace webrtc