blob: 9e62f95dd89f43860dea52f15878207f4819a3a1 [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>
Markus Handell5932fe12020-12-17 22:19:40 +010015#include <vector>
Steve Anton6e634bf2017-11-13 10:44:53 -080016
Steve Anton64b626b2019-01-28 17:25:26 -080017#include "absl/algorithm/container.h"
Markus Handell0357b3e2020-03-16 13:40:51 +010018#include "api/rtp_parameters.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020019#include "pc/channel_manager.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "pc/rtp_media_utils.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020021#include "pc/rtp_parameters_conversion.h"
Markus Handell5932fe12020-12-17 22:19:40 +010022#include "pc/session_description.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "rtc_base/checks.h"
24#include "rtc_base/logging.h"
Steve Antondcc3c022017-12-22 16:02:54 -080025
Steve Anton6e634bf2017-11-13 10:44:53 -080026namespace webrtc {
Johannes Kron3e983682020-03-29 22:17:00 +020027namespace {
28template <class T>
29RTCError VerifyCodecPreferences(const std::vector<RtpCodecCapability>& codecs,
30 const std::vector<T>& send_codecs,
31 const std::vector<T>& recv_codecs) {
32 // If the intersection between codecs and
33 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
34 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
35 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
36 // This ensures that we always have something to offer, regardless of
37 // transceiver.direction.
38
39 if (!absl::c_any_of(codecs, [&recv_codecs](const RtpCodecCapability& codec) {
40 return codec.name != cricket::kRtxCodecName &&
41 codec.name != cricket::kRedCodecName &&
42 codec.name != cricket::kFlexfecCodecName &&
43 absl::c_any_of(recv_codecs, [&codec](const T& recv_codec) {
44 return recv_codec.MatchesCapability(codec);
45 });
46 })) {
47 return RTCError(RTCErrorType::INVALID_MODIFICATION,
48 "Invalid codec preferences: Missing codec from recv "
49 "codec capabilities.");
50 }
51
52 if (!absl::c_any_of(codecs, [&send_codecs](const RtpCodecCapability& codec) {
53 return codec.name != cricket::kRtxCodecName &&
54 codec.name != cricket::kRedCodecName &&
55 codec.name != cricket::kFlexfecCodecName &&
56 absl::c_any_of(send_codecs, [&codec](const T& send_codec) {
57 return send_codec.MatchesCapability(codec);
58 });
59 })) {
60 return RTCError(RTCErrorType::INVALID_MODIFICATION,
61 "Invalid codec preferences: Missing codec from send "
62 "codec capabilities.");
63 }
64
65 // Let codecCapabilities be the union of
66 // RTCRtpSender.getCapabilities(kind).codecs and
67 // RTCRtpReceiver.getCapabilities(kind).codecs. For each codec in codecs, If
68 // codec is not in codecCapabilities, throw InvalidModificationError.
69 for (const auto& codec_preference : codecs) {
70 bool is_recv_codec =
71 absl::c_any_of(recv_codecs, [&codec_preference](const T& codec) {
72 return codec.MatchesCapability(codec_preference);
73 });
74
75 bool is_send_codec =
76 absl::c_any_of(send_codecs, [&codec_preference](const T& codec) {
77 return codec.MatchesCapability(codec_preference);
78 });
79
80 if (!is_recv_codec && !is_send_codec) {
81 return RTCError(
82 RTCErrorType::INVALID_MODIFICATION,
83 std::string("Invalid codec preferences: invalid codec with name \"") +
84 codec_preference.name + "\".");
85 }
86 }
87
88 // Check we have a real codec (not just rtx, red or fec)
89 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
90 return codec.name == cricket::kRtxCodecName ||
91 codec.name == cricket::kRedCodecName ||
92 codec.name == cricket::kUlpfecCodecName;
93 })) {
94 return RTCError(RTCErrorType::INVALID_MODIFICATION,
95 "Invalid codec preferences: codec list must have a non "
96 "RTX, RED or FEC entry.");
97 }
98
99 return RTCError::OK();
100}
101
Harald Alvestrand6060df52020-08-11 09:54:02 +0200102TaskQueueBase* GetCurrentTaskQueueOrThread() {
103 TaskQueueBase* current = TaskQueueBase::Current();
104 if (!current)
105 current = rtc::ThreadManager::Instance()->CurrentThread();
106 return current;
107}
108
Johannes Kron3e983682020-03-29 22:17:00 +0200109} // namespace
Steve Anton6e634bf2017-11-13 10:44:53 -0800110
111RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
Harald Alvestrand6060df52020-08-11 09:54:02 +0200112 : thread_(GetCurrentTaskQueueOrThread()),
113 unified_plan_(false),
114 media_type_(media_type) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800115 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
116 media_type == cricket::MEDIA_TYPE_VIDEO);
117}
118
Steve Anton79e79602017-11-20 10:25:56 -0800119RtpTransceiver::RtpTransceiver(
120 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
121 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200122 receiver,
Markus Handell0357b3e2020-03-16 13:40:51 +0100123 cricket::ChannelManager* channel_manager,
Harald Alvestrand280054f2020-11-10 13:12:53 +0000124 std::vector<RtpHeaderExtensionCapability> header_extensions_offered,
125 std::function<void()> on_negotiation_needed)
Harald Alvestrand6060df52020-08-11 09:54:02 +0200126 : thread_(GetCurrentTaskQueueOrThread()),
127 unified_plan_(true),
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200128 media_type_(sender->media_type()),
Markus Handell0357b3e2020-03-16 13:40:51 +0100129 channel_manager_(channel_manager),
Harald Alvestrand280054f2020-11-10 13:12:53 +0000130 header_extensions_to_offer_(std::move(header_extensions_offered)),
131 on_negotiation_needed_(std::move(on_negotiation_needed)) {
Steve Anton79e79602017-11-20 10:25:56 -0800132 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
133 media_type_ == cricket::MEDIA_TYPE_VIDEO);
134 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
135 senders_.push_back(sender);
136 receivers_.push_back(receiver);
137}
138
Steve Anton6e634bf2017-11-13 10:44:53 -0800139RtpTransceiver::~RtpTransceiver() {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200140 StopInternal();
Steve Anton6e634bf2017-11-13 10:44:53 -0800141}
142
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800143void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
144 // Cannot set a non-null channel on a stopped transceiver.
145 if (stopped_ && channel) {
146 return;
147 }
148
Steve Anton6e634bf2017-11-13 10:44:53 -0800149 if (channel) {
150 RTC_DCHECK_EQ(media_type(), channel->media_type());
151 }
Steve Anton60776752018-01-10 11:51:34 -0800152
153 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800154 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 11:51:34 -0800155 }
156
Steve Anton6e634bf2017-11-13 10:44:53 -0800157 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -0800158
159 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800160 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 11:51:34 -0800161 this, &RtpTransceiver::OnFirstPacketReceived);
162 }
163
Mirko Bonadei739baf02019-01-27 17:29:42 +0100164 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800165 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
166 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800167 }
Steve Anton60776752018-01-10 11:51:34 -0800168
Mirko Bonadei739baf02019-01-27 17:29:42 +0100169 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800170 if (!channel_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800171 receiver->internal()->Stop();
172 }
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800173
174 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
175 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800176 }
177}
178
179void RtpTransceiver::AddSender(
180 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800181 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800182 RTC_DCHECK(!unified_plan_);
183 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -0800184 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800185 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -0800186 senders_.push_back(sender);
187}
188
189bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
190 RTC_DCHECK(!unified_plan_);
191 if (sender) {
192 RTC_DCHECK_EQ(media_type(), sender->media_type());
193 }
Steve Anton64b626b2019-01-28 17:25:26 -0800194 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800195 if (it == senders_.end()) {
196 return false;
197 }
198 (*it)->internal()->Stop();
199 senders_.erase(it);
200 return true;
201}
202
203void RtpTransceiver::AddReceiver(
204 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
205 receiver) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800206 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800207 RTC_DCHECK(!unified_plan_);
208 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800209 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800210 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800211 receivers_.push_back(receiver);
212}
213
214bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
215 RTC_DCHECK(!unified_plan_);
216 if (receiver) {
217 RTC_DCHECK_EQ(media_type(), receiver->media_type());
218 }
Steve Anton64b626b2019-01-28 17:25:26 -0800219 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800220 if (it == receivers_.end()) {
221 return false;
222 }
223 (*it)->internal()->Stop();
Markus Handell43e62fc2020-01-07 19:46:15 +0100224 // After the receiver has been removed, there's no guarantee that the
225 // contained media channel isn't deleted shortly after this. To make sure that
226 // the receiver doesn't spontaneously try to use it's (potentially stale)
227 // media channel reference, we clear it out.
228 (*it)->internal()->SetMediaChannel(nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800229 receivers_.erase(it);
230 return true;
231}
232
Steve Antonf9381f02017-12-14 10:23:57 -0800233rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
234 RTC_DCHECK(unified_plan_);
235 RTC_CHECK_EQ(1u, senders_.size());
236 return senders_[0]->internal();
237}
238
239rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
240 const {
241 RTC_DCHECK(unified_plan_);
242 RTC_CHECK_EQ(1u, receivers_.size());
243 return receivers_[0]->internal();
244}
245
Steve Anton69470252018-02-09 11:43:08 -0800246cricket::MediaType RtpTransceiver::media_type() const {
247 return media_type_;
248}
249
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200250absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800251 return mid_;
252}
253
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800254void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100255 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800256 receiver->internal()->NotifyFirstPacketReceived();
257 }
258}
259
Steve Anton6e634bf2017-11-13 10:44:53 -0800260rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
261 RTC_DCHECK(unified_plan_);
262 RTC_CHECK_EQ(1u, senders_.size());
263 return senders_[0];
264}
265
266rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
267 RTC_DCHECK(unified_plan_);
268 RTC_CHECK_EQ(1u, receivers_.size());
269 return receivers_[0];
270}
271
Steve Antondcc3c022017-12-22 16:02:54 -0800272void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700273 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
274 << ") current direction from "
275 << (current_direction_ ? RtpTransceiverDirectionToString(
276 *current_direction_)
277 : "<not set>")
278 << " to " << RtpTransceiverDirectionToString(direction)
279 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800280 current_direction_ = direction;
281 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
282 has_ever_been_used_to_send_ = true;
283 }
284}
285
Steve Anton0f5400a2018-07-17 14:25:36 -0700286void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
287 fired_direction_ = direction;
288}
289
Steve Anton6e634bf2017-11-13 10:44:53 -0800290bool RtpTransceiver::stopped() const {
291 return stopped_;
292}
293
Harald Alvestrand6060df52020-08-11 09:54:02 +0200294bool RtpTransceiver::stopping() const {
295 RTC_DCHECK_RUN_ON(thread_);
296 return stopping_;
297}
298
Steve Anton6e634bf2017-11-13 10:44:53 -0800299RtpTransceiverDirection RtpTransceiver::direction() const {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200300 if (unified_plan_ && stopping())
301 return webrtc::RtpTransceiverDirection::kStopped;
302
Steve Anton6e634bf2017-11-13 10:44:53 -0800303 return direction_;
304}
305
Harald Alvestrand6060df52020-08-11 09:54:02 +0200306RTCError RtpTransceiver::SetDirectionWithError(
307 RtpTransceiverDirection new_direction) {
308 if (unified_plan_ && stopping()) {
309 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
310 "Cannot set direction on a stopping transceiver.");
Steve Anton52d86772018-02-20 15:48:12 -0800311 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200312 if (new_direction == direction_)
313 return RTCError::OK();
314
315 if (new_direction == RtpTransceiverDirection::kStopped) {
316 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
317 "The set direction 'stopped' is invalid.");
Steve Anton52d86772018-02-20 15:48:12 -0800318 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200319
Steve Anton52d86772018-02-20 15:48:12 -0800320 direction_ = new_direction;
Harald Alvestrand280054f2020-11-10 13:12:53 +0000321 on_negotiation_needed_();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200322
323 return RTCError::OK();
Steve Anton6e634bf2017-11-13 10:44:53 -0800324}
325
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200326absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800327 const {
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000328 if (unified_plan_ && stopped())
Harald Alvestrand6060df52020-08-11 09:54:02 +0200329 return webrtc::RtpTransceiverDirection::kStopped;
330
Steve Anton6e634bf2017-11-13 10:44:53 -0800331 return current_direction_;
332}
333
Steve Anton0f5400a2018-07-17 14:25:36 -0700334absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
335 const {
336 return fired_direction_;
337}
338
Harald Alvestrand6060df52020-08-11 09:54:02 +0200339void RtpTransceiver::StopSendingAndReceiving() {
340 // 1. Let sender be transceiver.[[Sender]].
341 // 2. Let receiver be transceiver.[[Receiver]].
342 //
343 // 3. Stop sending media with sender.
344 //
345 // 4. Send an RTCP BYE for each RTP stream that was being sent by sender, as
346 // specified in [RFC3550].
347 RTC_DCHECK_RUN_ON(thread_);
348 for (const auto& sender : senders_)
Steve Anton6e634bf2017-11-13 10:44:53 -0800349 sender->internal()->Stop();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200350
351 // 5. Stop receiving media with receiver.
352 for (const auto& receiver : receivers_)
Harald Alvestrand1ee33252020-09-24 13:31:15 +0000353 receiver->internal()->StopAndEndTrack();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200354
355 stopping_ = true;
356 direction_ = webrtc::RtpTransceiverDirection::kInactive;
357}
358
359RTCError RtpTransceiver::StopStandard() {
360 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000361 // If we're on Plan B, do what Stop() used to do there.
362 if (!unified_plan_) {
363 StopInternal();
364 return RTCError::OK();
365 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200366 // 1. Let transceiver be the RTCRtpTransceiver object on which the method is
367 // invoked.
368 //
369 // 2. Let connection be the RTCPeerConnection object associated with
370 // transceiver.
371 //
372 // 3. If connection.[[IsClosed]] is true, throw an InvalidStateError.
373 if (is_pc_closed_) {
374 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_STATE,
375 "PeerConnection is closed.");
Harald Alvestranda88c9772020-08-10 18:06:09 +0000376 }
Harald Alvestrand6060df52020-08-11 09:54:02 +0200377
378 // 4. If transceiver.[[Stopping]] is true, abort these steps.
379 if (stopping_)
380 return RTCError::OK();
381
382 // 5. Stop sending and receiving given transceiver, and update the
383 // negotiation-needed flag for connection.
384 StopSendingAndReceiving();
Harald Alvestrand280054f2020-11-10 13:12:53 +0000385 on_negotiation_needed_();
Harald Alvestrand6060df52020-08-11 09:54:02 +0200386
387 return RTCError::OK();
388}
389
390void RtpTransceiver::StopInternal() {
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000391 StopTransceiverProcedure();
392}
393
394void RtpTransceiver::StopTransceiverProcedure() {
Harald Alvestrand6060df52020-08-11 09:54:02 +0200395 RTC_DCHECK_RUN_ON(thread_);
Harald Alvestrandc75c4282020-08-26 12:17:54 +0000396 // As specified in the "Stop the RTCRtpTransceiver" procedure
Harald Alvestrand6060df52020-08-11 09:54:02 +0200397 // 1. If transceiver.[[Stopping]] is false, stop sending and receiving given
398 // transceiver.
399 if (!stopping_)
400 StopSendingAndReceiving();
401
402 // 2. Set transceiver.[[Stopped]] to true.
Steve Anton6e634bf2017-11-13 10:44:53 -0800403 stopped_ = true;
Harald Alvestrand6060df52020-08-11 09:54:02 +0200404
405 // Signal the updated change to the senders.
406 for (const auto& sender : senders_)
407 sender->internal()->SetTransceiverAsStopped();
408
409 // 3. Set transceiver.[[Receptive]] to false.
410 // 4. Set transceiver.[[CurrentDirection]] to null.
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200411 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800412}
413
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200414RTCError RtpTransceiver::SetCodecPreferences(
415 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
416 RTC_DCHECK(unified_plan_);
417
418 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
419 // to codecs and abort these steps.
420 if (codec_capabilities.empty()) {
421 codec_preferences_.clear();
422 return RTCError::OK();
423 }
424
425 // 4. Remove any duplicate values in codecs.
426 std::vector<RtpCodecCapability> codecs;
427 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
428 [&codecs](const RtpCodecCapability& codec) {
429 return absl::c_linear_search(codecs, codec);
430 });
431
Johannes Kron3e983682020-03-29 22:17:00 +0200432 // 6. to 8.
433 RTCError result;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200434 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200435 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
436 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
437 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
438
Johannes Kron3e983682020-03-29 22:17:00 +0200439 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200440 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
Johannes Kron3e983682020-03-29 22:17:00 +0200441 std::vector<cricket::VideoCodec> recv_codecs, send_codecs;
442 channel_manager_->GetSupportedVideoReceiveCodecs(&recv_codecs);
443 channel_manager_->GetSupportedVideoSendCodecs(&send_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200444
Johannes Kron3e983682020-03-29 22:17:00 +0200445 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200446 }
447
Johannes Kron3e983682020-03-29 22:17:00 +0200448 if (result.ok()) {
449 codec_preferences_ = codecs;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200450 }
451
Johannes Kron3e983682020-03-29 22:17:00 +0200452 return result;
Steve Anton6e634bf2017-11-13 10:44:53 -0800453}
454
Markus Handell0357b3e2020-03-16 13:40:51 +0100455std::vector<RtpHeaderExtensionCapability>
456RtpTransceiver::HeaderExtensionsToOffer() const {
Markus Handell755c65d2020-06-24 01:06:10 +0200457 return header_extensions_to_offer_;
458}
459
Markus Handell5932fe12020-12-17 22:19:40 +0100460std::vector<RtpHeaderExtensionCapability>
461RtpTransceiver::HeaderExtensionsNegotiated() const {
462 if (!channel_)
463 return {};
464 std::vector<RtpHeaderExtensionCapability> result;
465 for (const auto& ext : channel_->GetNegotiatedRtpHeaderExtensions()) {
466 result.emplace_back(ext.uri, ext.id, RtpTransceiverDirection::kSendRecv);
467 }
468 return result;
469}
470
Markus Handell755c65d2020-06-24 01:06:10 +0200471RTCError RtpTransceiver::SetOfferedRtpHeaderExtensions(
472 rtc::ArrayView<const RtpHeaderExtensionCapability>
473 header_extensions_to_offer) {
474 for (const auto& entry : header_extensions_to_offer) {
475 // Handle unsupported requests for mandatory extensions as per
476 // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface.
477 // Note:
478 // - We do not handle setOfferedRtpHeaderExtensions algorithm step 2.1,
479 // this has to be checked on a higher level. We naturally error out
480 // in the handling of Step 2.2 if an unset URI is encountered.
481
482 // Step 2.2.
483 // Handle unknown extensions.
484 auto it = std::find_if(
485 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
486 [&entry](const auto& offered) { return entry.uri == offered.uri; });
487 if (it == header_extensions_to_offer_.end()) {
488 return RTCError(RTCErrorType::INVALID_PARAMETER,
489 "Attempted to modify an unoffered extension.");
490 }
491
492 // Step 2.4-2.5.
493 // - Use of the transceiver interface indicates unified plan is in effect,
494 // hence the MID extension needs to be enabled.
495 // - Also handle the mandatory video orientation extensions.
496 if ((entry.uri == RtpExtension::kMidUri ||
497 entry.uri == RtpExtension::kVideoRotationUri) &&
498 entry.direction != RtpTransceiverDirection::kSendRecv) {
499 return RTCError(RTCErrorType::INVALID_MODIFICATION,
500 "Attempted to stop a mandatory extension.");
501 }
502 }
503
504 // Apply mutation after error checking.
505 for (const auto& entry : header_extensions_to_offer) {
506 auto it = std::find_if(
507 header_extensions_to_offer_.begin(), header_extensions_to_offer_.end(),
508 [&entry](const auto& offered) { return entry.uri == offered.uri; });
509 it->direction = entry.direction;
510 }
511
512 return RTCError::OK();
Markus Handell0357b3e2020-03-16 13:40:51 +0100513}
514
Harald Alvestrand6060df52020-08-11 09:54:02 +0200515void RtpTransceiver::SetPeerConnectionClosed() {
516 is_pc_closed_ = true;
517}
518
Steve Anton6e634bf2017-11-13 10:44:53 -0800519} // namespace webrtc