blob: f8c5bd5ec844696c058dc2414afbade77bc69325 [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"
Harald Alvestrand5761e7b2021-01-29 14:45:08 +000028#include "rtc_base/thread.h"
Steve Antondcc3c022017-12-22 16:02:54 -080029
Steve Anton6e634bf2017-11-13 10:44:53 -080030namespace webrtc {
Johannes Kron3e983682020-03-29 22:17:00 +020031namespace {
32template <class T>
33RTCError VerifyCodecPreferences(const std::vector<RtpCodecCapability>& codecs,
34 const std::vector<T>& send_codecs,
35 const std::vector<T>& recv_codecs) {
36 // If the intersection between codecs and
37 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
38 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
39 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
40 // This ensures that we always have something to offer, regardless of
41 // transceiver.direction.
42
43 if (!absl::c_any_of(codecs, [&recv_codecs](const RtpCodecCapability& codec) {
44 return codec.name != cricket::kRtxCodecName &&
45 codec.name != cricket::kRedCodecName &&
46 codec.name != cricket::kFlexfecCodecName &&
47 absl::c_any_of(recv_codecs, [&codec](const T& recv_codec) {
48 return recv_codec.MatchesCapability(codec);
49 });
50 })) {
51 return RTCError(RTCErrorType::INVALID_MODIFICATION,
52 "Invalid codec preferences: Missing codec from recv "
53 "codec capabilities.");
54 }
55
56 if (!absl::c_any_of(codecs, [&send_codecs](const RtpCodecCapability& codec) {
57 return codec.name != cricket::kRtxCodecName &&
58 codec.name != cricket::kRedCodecName &&
59 codec.name != cricket::kFlexfecCodecName &&
60 absl::c_any_of(send_codecs, [&codec](const T& send_codec) {
61 return send_codec.MatchesCapability(codec);
62 });
63 })) {
64 return RTCError(RTCErrorType::INVALID_MODIFICATION,
65 "Invalid codec preferences: Missing codec from send "
66 "codec capabilities.");
67 }
68
69 // Let codecCapabilities be the union of
70 // RTCRtpSender.getCapabilities(kind).codecs and
71 // RTCRtpReceiver.getCapabilities(kind).codecs. For each codec in codecs, If
72 // codec is not in codecCapabilities, throw InvalidModificationError.
73 for (const auto& codec_preference : codecs) {
74 bool is_recv_codec =
75 absl::c_any_of(recv_codecs, [&codec_preference](const T& codec) {
76 return codec.MatchesCapability(codec_preference);
77 });
78
79 bool is_send_codec =
80 absl::c_any_of(send_codecs, [&codec_preference](const T& codec) {
81 return codec.MatchesCapability(codec_preference);
82 });
83
84 if (!is_recv_codec && !is_send_codec) {
85 return RTCError(
86 RTCErrorType::INVALID_MODIFICATION,
87 std::string("Invalid codec preferences: invalid codec with name \"") +
88 codec_preference.name + "\".");
89 }
90 }
91
92 // Check we have a real codec (not just rtx, red or fec)
93 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
94 return codec.name == cricket::kRtxCodecName ||
95 codec.name == cricket::kRedCodecName ||
96 codec.name == cricket::kUlpfecCodecName;
97 })) {
98 return RTCError(RTCErrorType::INVALID_MODIFICATION,
99 "Invalid codec preferences: codec list must have a non "
100 "RTX, RED or FEC entry.");
101 }
102
103 return RTCError::OK();
104}
105
Harald Alvestrand6060df52020-08-11 09:54:02 +0200106TaskQueueBase* GetCurrentTaskQueueOrThread() {
107 TaskQueueBase* current = TaskQueueBase::Current();
108 if (!current)
109 current = rtc::ThreadManager::Instance()->CurrentThread();
110 return current;
111}
112
Johannes Kron3e983682020-03-29 22:17:00 +0200113} // namespace
Steve Anton6e634bf2017-11-13 10:44:53 -0800114
115RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
Harald Alvestrand6060df52020-08-11 09:54:02 +0200116 : thread_(GetCurrentTaskQueueOrThread()),
117 unified_plan_(false),
118 media_type_(media_type) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800119 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
120 media_type == cricket::MEDIA_TYPE_VIDEO);
121}
122
Steve Anton79e79602017-11-20 10:25:56 -0800123RtpTransceiver::RtpTransceiver(
124 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
125 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200126 receiver,
Markus Handell0357b3e2020-03-16 13:40:51 +0100127 cricket::ChannelManager* channel_manager,
Harald Alvestrand280054f2020-11-10 13:12:53 +0000128 std::vector<RtpHeaderExtensionCapability> header_extensions_offered,
129 std::function<void()> on_negotiation_needed)
Harald Alvestrand6060df52020-08-11 09:54:02 +0200130 : thread_(GetCurrentTaskQueueOrThread()),
131 unified_plan_(true),
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200132 media_type_(sender->media_type()),
Markus Handell0357b3e2020-03-16 13:40:51 +0100133 channel_manager_(channel_manager),
Harald Alvestrand280054f2020-11-10 13:12:53 +0000134 header_extensions_to_offer_(std::move(header_extensions_offered)),
135 on_negotiation_needed_(std::move(on_negotiation_needed)) {
Steve Anton79e79602017-11-20 10:25:56 -0800136 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
137 media_type_ == cricket::MEDIA_TYPE_VIDEO);
138 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
139 senders_.push_back(sender);
140 receivers_.push_back(receiver);
141}
142
Steve Anton6e634bf2017-11-13 10:44:53 -0800143RtpTransceiver::~RtpTransceiver() {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200144 StopInternal();
Steve Anton6e634bf2017-11-13 10:44:53 -0800145}
146
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800147void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
148 // Cannot set a non-null channel on a stopped transceiver.
149 if (stopped_ && channel) {
150 return;
151 }
152
Steve Anton6e634bf2017-11-13 10:44:53 -0800153 if (channel) {
154 RTC_DCHECK_EQ(media_type(), channel->media_type());
155 }
Steve Anton60776752018-01-10 11:51:34 -0800156
157 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800158 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 11:51:34 -0800159 }
160
Steve Anton6e634bf2017-11-13 10:44:53 -0800161 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -0800162
163 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800164 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 11:51:34 -0800165 this, &RtpTransceiver::OnFirstPacketReceived);
166 }
167
Mirko Bonadei739baf02019-01-27 17:29:42 +0100168 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800169 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
170 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800171 }
Steve Anton60776752018-01-10 11:51:34 -0800172
Mirko Bonadei739baf02019-01-27 17:29:42 +0100173 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800174 if (!channel_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800175 receiver->internal()->Stop();
176 }
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800177
178 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
179 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800180 }
181}
182
183void RtpTransceiver::AddSender(
184 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800185 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800186 RTC_DCHECK(!unified_plan_);
187 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -0800188 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800189 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -0800190 senders_.push_back(sender);
191}
192
193bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
194 RTC_DCHECK(!unified_plan_);
195 if (sender) {
196 RTC_DCHECK_EQ(media_type(), sender->media_type());
197 }
Steve Anton64b626b2019-01-28 17:25:26 -0800198 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800199 if (it == senders_.end()) {
200 return false;
201 }
202 (*it)->internal()->Stop();
203 senders_.erase(it);
204 return true;
205}
206
207void RtpTransceiver::AddReceiver(
208 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
209 receiver) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800210 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800211 RTC_DCHECK(!unified_plan_);
212 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800213 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800214 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800215 receivers_.push_back(receiver);
216}
217
218bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
219 RTC_DCHECK(!unified_plan_);
220 if (receiver) {
221 RTC_DCHECK_EQ(media_type(), receiver->media_type());
222 }
Steve Anton64b626b2019-01-28 17:25:26 -0800223 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800224 if (it == receivers_.end()) {
225 return false;
226 }
227 (*it)->internal()->Stop();
Markus Handell43e62fc2020-01-07 19:46:15 +0100228 // After the receiver has been removed, there's no guarantee that the
229 // contained media channel isn't deleted shortly after this. To make sure that
230 // the receiver doesn't spontaneously try to use it's (potentially stale)
231 // media channel reference, we clear it out.
232 (*it)->internal()->SetMediaChannel(nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800233 receivers_.erase(it);
234 return true;
235}
236
Steve Antonf9381f02017-12-14 10:23:57 -0800237rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
238 RTC_DCHECK(unified_plan_);
239 RTC_CHECK_EQ(1u, senders_.size());
240 return senders_[0]->internal();
241}
242
243rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
244 const {
245 RTC_DCHECK(unified_plan_);
246 RTC_CHECK_EQ(1u, receivers_.size());
247 return receivers_[0]->internal();
248}
249
Steve Anton69470252018-02-09 11:43:08 -0800250cricket::MediaType RtpTransceiver::media_type() const {
251 return media_type_;
252}
253
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200254absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800255 return mid_;
256}
257
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800258void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100259 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800260 receiver->internal()->NotifyFirstPacketReceived();
261 }
262}
263
Steve Anton6e634bf2017-11-13 10:44:53 -0800264rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
265 RTC_DCHECK(unified_plan_);
266 RTC_CHECK_EQ(1u, senders_.size());
267 return senders_[0];
268}
269
270rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
271 RTC_DCHECK(unified_plan_);
272 RTC_CHECK_EQ(1u, receivers_.size());
273 return receivers_[0];
274}
275
Steve Antondcc3c022017-12-22 16:02:54 -0800276void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700277 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
278 << ") current direction from "
279 << (current_direction_ ? RtpTransceiverDirectionToString(
280 *current_direction_)
281 : "<not set>")
282 << " to " << RtpTransceiverDirectionToString(direction)
283 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800284 current_direction_ = direction;
285 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
286 has_ever_been_used_to_send_ = true;
287 }
288}
289
Steve Anton0f5400a2018-07-17 14:25:36 -0700290void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
291 fired_direction_ = direction;
292}
293
Steve Anton6e634bf2017-11-13 10:44:53 -0800294bool RtpTransceiver::stopped() const {
295 return stopped_;
296}
297
Harald Alvestrand6060df52020-08-11 09:54:02 +0200298bool RtpTransceiver::stopping() const {
299 RTC_DCHECK_RUN_ON(thread_);
300 return stopping_;
301}
302
Steve Anton6e634bf2017-11-13 10:44:53 -0800303RtpTransceiverDirection RtpTransceiver::direction() const {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200304 if (unified_plan_ && stopping())
305 return webrtc::RtpTransceiverDirection::kStopped;
306
Steve Anton6e634bf2017-11-13 10:44:53 -0800307 return direction_;
308}
309
Harald Alvestrand6060df52020-08-11 09:54:02 +0200310RTCError RtpTransceiver::SetDirectionWithError(
311 RtpTransceiverDirection new_direction) {
312 if (unified_plan_ && stopping()) {
313 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
314 "Cannot set direction on a stopping transceiver.");
Steve Anton52d86772018-02-20 15:48:12 -0800315 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200316 if (new_direction == direction_)
317 return RTCError::OK();
318
319 if (new_direction == RtpTransceiverDirection::kStopped) {
320 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
321 "The set direction 'stopped' is invalid.");
Steve Anton52d86772018-02-20 15:48:12 -0800322 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200323
Steve Anton52d86772018-02-20 15:48:12 -0800324 direction_ = new_direction;
Harald Alvestrand280054f2020-11-10 13:12:53 +0000325 on_negotiation_needed_();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200326
327 return RTCError::OK();
Steve Anton6e634bf2017-11-13 10:44:53 -0800328}
329
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200330absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800331 const {
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000332 if (unified_plan_ && stopped())
Harald Alvestrand6060df52020-08-11 09:54:02 +0200333 return webrtc::RtpTransceiverDirection::kStopped;
334
Steve Anton6e634bf2017-11-13 10:44:53 -0800335 return current_direction_;
336}
337
Steve Anton0f5400a2018-07-17 14:25:36 -0700338absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
339 const {
340 return fired_direction_;
341}
342
Harald Alvestrand6060df52020-08-11 09:54:02 +0200343void RtpTransceiver::StopSendingAndReceiving() {
344 // 1. Let sender be transceiver.[[Sender]].
345 // 2. Let receiver be transceiver.[[Receiver]].
346 //
347 // 3. Stop sending media with sender.
348 //
349 // 4. Send an RTCP BYE for each RTP stream that was being sent by sender, as
350 // specified in [RFC3550].
351 RTC_DCHECK_RUN_ON(thread_);
352 for (const auto& sender : senders_)
Steve Anton6e634bf2017-11-13 10:44:53 -0800353 sender->internal()->Stop();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200354
355 // 5. Stop receiving media with receiver.
356 for (const auto& receiver : receivers_)
Harald Alvestrand1ee33252020-09-24 13:31:15 +0000357 receiver->internal()->StopAndEndTrack();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200358
359 stopping_ = true;
360 direction_ = webrtc::RtpTransceiverDirection::kInactive;
361}
362
363RTCError RtpTransceiver::StopStandard() {
364 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000365 // If we're on Plan B, do what Stop() used to do there.
366 if (!unified_plan_) {
367 StopInternal();
368 return RTCError::OK();
369 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200370 // 1. Let transceiver be the RTCRtpTransceiver object on which the method is
371 // invoked.
372 //
373 // 2. Let connection be the RTCPeerConnection object associated with
374 // transceiver.
375 //
376 // 3. If connection.[[IsClosed]] is true, throw an InvalidStateError.
377 if (is_pc_closed_) {
378 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
379 "PeerConnection is closed.");
Harald Alvestranda88c9772020-08-10 18:06:09 +0000380 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200381
382 // 4. If transceiver.[[Stopping]] is true, abort these steps.
383 if (stopping_)
384 return RTCError::OK();
385
386 // 5. Stop sending and receiving given transceiver, and update the
387 // negotiation-needed flag for connection.
388 StopSendingAndReceiving();
Harald Alvestrand280054f2020-11-10 13:12:53 +0000389 on_negotiation_needed_();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200390
391 return RTCError::OK();
392}
393
394void RtpTransceiver::StopInternal() {
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000395 StopTransceiverProcedure();
396}
397
398void RtpTransceiver::StopTransceiverProcedure() {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200399 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000400 // As specified in the "Stop the RTCRtpTransceiver" procedure
Harald Alvestrand6060df52020-08-11 09:54:02 +0200401 // 1. If transceiver.[[Stopping]] is false, stop sending and receiving given
402 // transceiver.
403 if (!stopping_)
404 StopSendingAndReceiving();
405
406 // 2. Set transceiver.[[Stopped]] to true.
Steve Anton6e634bf2017-11-13 10:44:53 -0800407 stopped_ = true;
Harald Alvestrand6060df52020-08-11 09:54:02 +0200408
409 // Signal the updated change to the senders.
410 for (const auto& sender : senders_)
411 sender->internal()->SetTransceiverAsStopped();
412
413 // 3. Set transceiver.[[Receptive]] to false.
414 // 4. Set transceiver.[[CurrentDirection]] to null.
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200415 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800416}
417
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200418RTCError RtpTransceiver::SetCodecPreferences(
419 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
420 RTC_DCHECK(unified_plan_);
421
422 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
423 // to codecs and abort these steps.
424 if (codec_capabilities.empty()) {
425 codec_preferences_.clear();
426 return RTCError::OK();
427 }
428
429 // 4. Remove any duplicate values in codecs.
430 std::vector<RtpCodecCapability> codecs;
431 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
432 [&codecs](const RtpCodecCapability& codec) {
433 return absl::c_linear_search(codecs, codec);
434 });
435
Johannes Kron3e983682020-03-29 22:17:00 +0200436 // 6. to 8.
437 RTCError result;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200438 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200439 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
440 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
441 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
442
Johannes Kron3e983682020-03-29 22:17:00 +0200443 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200444 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
Johannes Kron3e983682020-03-29 22:17:00 +0200445 std::vector<cricket::VideoCodec> recv_codecs, send_codecs;
446 channel_manager_->GetSupportedVideoReceiveCodecs(&recv_codecs);
447 channel_manager_->GetSupportedVideoSendCodecs(&send_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200448
Johannes Kron3e983682020-03-29 22:17:00 +0200449 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200450 }
451
Johannes Kron3e983682020-03-29 22:17:00 +0200452 if (result.ok()) {
453 codec_preferences_ = codecs;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200454 }
455
Johannes Kron3e983682020-03-29 22:17:00 +0200456 return result;
Steve Anton6e634bf2017-11-13 10:44:53 -0800457}
458
Markus Handell0357b3e2020-03-16 13:40:51 +0100459std::vector<RtpHeaderExtensionCapability>
460RtpTransceiver::HeaderExtensionsToOffer() const {
Markus Handell755c65d2020-06-24 01:06:10 +0200461 return header_extensions_to_offer_;
462}
463
Markus Handell5932fe12020-12-17 22:19:40 +0100464std::vector<RtpHeaderExtensionCapability>
465RtpTransceiver::HeaderExtensionsNegotiated() const {
466 if (!channel_)
467 return {};
468 std::vector<RtpHeaderExtensionCapability> result;
469 for (const auto& ext : channel_->GetNegotiatedRtpHeaderExtensions()) {
470 result.emplace_back(ext.uri, ext.id, RtpTransceiverDirection::kSendRecv);
471 }
472 return result;
473}
474
Markus Handell755c65d2020-06-24 01:06:10 +0200475RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
476 rtc::ArrayView<const RtpHeaderExtensionCapability>
477 header_extensions_to_offer) {
478 for (const auto& entry : header_extensions_to_offer) {
479 // Handle unsupported requests for mandatory extensions as per
480 // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
481 // Note:
482 // - We do not handle setOfferedRtpHeaderExtensions algorithm step 2.1,
483 // this has to be checked on a higher level. We naturally error out
484 // in the handling of Step 2.2 if an unset URI is encountered.
485
486 // Step 2.2.
487 // Handle unknown extensions.
488 auto it = std::find_if(
489 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
490 [&entry](const auto& offered) { return entry.uri == offered.uri; });
491 if (it == header_extensions_to_offer_.end()) {
Markus Handellc17bca72021-01-14 17:08:01 +0100492 return RTCError(RTCErrorType::UNSUPPORTED_PARAMETER,
Markus Handell755c65d2020-06-24 01:06:10 +0200493 "Attempted to modify an unoffered extension.");
494 }
495
496 // Step 2.4-2.5.
497 // - Use of the transceiver interface indicates unified plan is in effect,
498 // hence the MID extension needs to be enabled.
499 // - Also handle the mandatory video orientation extensions.
500 if ((entry.uri == RtpExtension::kMidUri ||
501 entry.uri == RtpExtension::kVideoRotationUri) &&
502 entry.direction != RtpTransceiverDirection::kSendRecv) {
503 return RTCError(RTCErrorType::INVALID_MODIFICATION,
504 "Attempted to stop a mandatory extension.");
505 }
506 }
507
508 // Apply mutation after error checking.
509 for (const auto& entry : header_extensions_to_offer) {
510 auto it = std::find_if(
511 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
512 [&entry](const auto& offered) { return entry.uri == offered.uri; });
513 it->direction = entry.direction;
514 }
515
516 return RTCError::OK();
Markus Handell0357b3e2020-03-16 13:40:51 +0100517}
518
Harald Alvestrand6060df52020-08-11 09:54:02 +0200519void RtpTransceiver::SetPeerConnectionClosed() {
520 is_pc_closed_ = true;
521}
522
Steve Anton6e634bf2017-11-13 10:44:53 -0800523} // namespace webrtc