blob: fcb54b54c24fb80553ccac279eca18751f0d2a8d [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>
14
Steve Anton64b626b2019-01-28 17:25:26 -080015#include "absl/algorithm/container.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020016#include "pc/channel_manager.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "pc/rtp_media_utils.h"
Florent Castelli2d9d82e2019-04-23 19:25:51 +020018#include "pc/rtp_parameters_conversion.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "rtc_base/checks.h"
20#include "rtc_base/logging.h"
Steve Antondcc3c022017-12-22 16:02:54 -080021
Steve Anton6e634bf2017-11-13 10:44:53 -080022namespace webrtc {
Johannes Kron184ea662020-01-29 12:43:36 +010023namespace {
24template <class T>
25RTCError VerifyCodecPreferences(const std::vector<RtpCodecCapability>& codecs,
26 const std::vector<T>& send_codecs,
27 const std::vector<T>& recv_codecs) {
28 // 6. If the intersection between codecs and
29 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
30 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
31 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
32 // This ensures that we always have something to offer, regardless of
33 // transceiver.direction.
34
35 if (!absl::c_any_of(codecs, [&recv_codecs](const RtpCodecCapability& codec) {
36 return codec.name != cricket::kRtxCodecName &&
37 codec.name != cricket::kRedCodecName &&
38 codec.name != cricket::kFlexfecCodecName &&
39 absl::c_any_of(recv_codecs, [&codec](const T& recv_codec) {
40 return recv_codec.MatchesCapability(codec);
41 });
42 })) {
43 return RTCError(RTCErrorType::INVALID_MODIFICATION,
44 "Invalid codec preferences: Missing codec from recv "
45 "codec capabilities.");
46 }
47
48 if (!absl::c_any_of(codecs, [&send_codecs](const RtpCodecCapability& codec) {
49 return codec.name != cricket::kRtxCodecName &&
50 codec.name != cricket::kRedCodecName &&
51 codec.name != cricket::kFlexfecCodecName &&
52 absl::c_any_of(send_codecs, [&codec](const T& send_codec) {
53 return send_codec.MatchesCapability(codec);
54 });
55 })) {
56 return RTCError(RTCErrorType::INVALID_MODIFICATION,
57 "Invalid codec preferences: Missing codec from send "
58 "codec capabilities.");
59 }
60
61 // 7. Let codecCapabilities be the union of
62 // RTCRtpSender.getCapabilities(kind).codecs and
63 // RTCRtpReceiver.getCapabilities(kind).codecs. 8.1 For each codec in
64 // codecs, If codec is not in codecCapabilities, throw
65 // InvalidModificationError.
66 for (const auto& codec_preference : codecs) {
67 bool is_recv_codec =
68 absl::c_any_of(recv_codecs, [&codec_preference](const T& codec) {
69 return codec.MatchesCapability(codec_preference);
70 });
71
72 bool is_send_codec =
73 absl::c_any_of(send_codecs, [&codec_preference](const T& codec) {
74 return codec.MatchesCapability(codec_preference);
75 });
76
77 if (!is_recv_codec && !is_send_codec) {
78 return RTCError(
79 RTCErrorType::INVALID_MODIFICATION,
80 std::string("Invalid codec preferences: invalid codec with name \"") +
81 codec_preference.name + "\".");
82 }
83 }
84
85 // Check we have a real codec (not just rtx, red or fec)
86 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
87 return codec.name == cricket::kRtxCodecName ||
88 codec.name == cricket::kRedCodecName ||
89 codec.name == cricket::kUlpfecCodecName;
90 })) {
91 return RTCError(RTCErrorType::INVALID_MODIFICATION,
92 "Invalid codec preferences: codec list must have a non "
93 "RTX, RED or FEC entry.");
94 }
95
96 return RTCError::OK();
97}
98
99} // namespace
Steve Anton6e634bf2017-11-13 10:44:53 -0800100
101RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
102 : unified_plan_(false), media_type_(media_type) {
103 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
104 media_type == cricket::MEDIA_TYPE_VIDEO);
105}
106
Steve Anton79e79602017-11-20 10:25:56 -0800107RtpTransceiver::RtpTransceiver(
108 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
109 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200110 receiver,
111 cricket::ChannelManager* channel_manager)
112 : unified_plan_(true),
113 media_type_(sender->media_type()),
114 channel_manager_(channel_manager) {
Steve Anton79e79602017-11-20 10:25:56 -0800115 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
116 media_type_ == cricket::MEDIA_TYPE_VIDEO);
117 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
118 senders_.push_back(sender);
119 receivers_.push_back(receiver);
120}
121
Steve Anton6e634bf2017-11-13 10:44:53 -0800122RtpTransceiver::~RtpTransceiver() {
123 Stop();
124}
125
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800126void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
127 // Cannot set a non-null channel on a stopped transceiver.
128 if (stopped_ && channel) {
129 return;
130 }
131
Steve Anton6e634bf2017-11-13 10:44:53 -0800132 if (channel) {
133 RTC_DCHECK_EQ(media_type(), channel->media_type());
134 }
Steve Anton60776752018-01-10 11:51:34 -0800135
136 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800137 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 11:51:34 -0800138 }
139
Steve Anton6e634bf2017-11-13 10:44:53 -0800140 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -0800141
142 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800143 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 11:51:34 -0800144 this, &RtpTransceiver::OnFirstPacketReceived);
145 }
146
Mirko Bonadei739baf02019-01-27 17:29:42 +0100147 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800148 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
149 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800150 }
Steve Anton60776752018-01-10 11:51:34 -0800151
Mirko Bonadei739baf02019-01-27 17:29:42 +0100152 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800153 if (!channel_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800154 receiver->internal()->Stop();
155 }
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800156
157 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
158 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800159 }
160}
161
162void RtpTransceiver::AddSender(
163 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800164 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800165 RTC_DCHECK(!unified_plan_);
166 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -0800167 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800168 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -0800169 senders_.push_back(sender);
170}
171
172bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
173 RTC_DCHECK(!unified_plan_);
174 if (sender) {
175 RTC_DCHECK_EQ(media_type(), sender->media_type());
176 }
Steve Anton64b626b2019-01-28 17:25:26 -0800177 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800178 if (it == senders_.end()) {
179 return false;
180 }
181 (*it)->internal()->Stop();
182 senders_.erase(it);
183 return true;
184}
185
186void RtpTransceiver::AddReceiver(
187 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
188 receiver) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800189 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800190 RTC_DCHECK(!unified_plan_);
191 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800192 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800193 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800194 receivers_.push_back(receiver);
195}
196
197bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
198 RTC_DCHECK(!unified_plan_);
199 if (receiver) {
200 RTC_DCHECK_EQ(media_type(), receiver->media_type());
201 }
Steve Anton64b626b2019-01-28 17:25:26 -0800202 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800203 if (it == receivers_.end()) {
204 return false;
205 }
206 (*it)->internal()->Stop();
Markus Handell43e62fc2020-01-07 19:46:15 +0100207 // After the receiver has been removed, there's no guarantee that the
208 // contained media channel isn't deleted shortly after this. To make sure that
209 // the receiver doesn't spontaneously try to use it's (potentially stale)
210 // media channel reference, we clear it out.
211 (*it)->internal()->SetMediaChannel(nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800212 receivers_.erase(it);
213 return true;
214}
215
Steve Antonf9381f02017-12-14 10:23:57 -0800216rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
217 RTC_DCHECK(unified_plan_);
218 RTC_CHECK_EQ(1u, senders_.size());
219 return senders_[0]->internal();
220}
221
222rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
223 const {
224 RTC_DCHECK(unified_plan_);
225 RTC_CHECK_EQ(1u, receivers_.size());
226 return receivers_[0]->internal();
227}
228
Steve Anton69470252018-02-09 11:43:08 -0800229cricket::MediaType RtpTransceiver::media_type() const {
230 return media_type_;
231}
232
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200233absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800234 return mid_;
235}
236
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800237void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100238 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800239 receiver->internal()->NotifyFirstPacketReceived();
240 }
241}
242
Steve Anton6e634bf2017-11-13 10:44:53 -0800243rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
244 RTC_DCHECK(unified_plan_);
245 RTC_CHECK_EQ(1u, senders_.size());
246 return senders_[0];
247}
248
249rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
250 RTC_DCHECK(unified_plan_);
251 RTC_CHECK_EQ(1u, receivers_.size());
252 return receivers_[0];
253}
254
Steve Antondcc3c022017-12-22 16:02:54 -0800255void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700256 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
257 << ") current direction from "
258 << (current_direction_ ? RtpTransceiverDirectionToString(
259 *current_direction_)
260 : "<not set>")
261 << " to " << RtpTransceiverDirectionToString(direction)
262 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800263 current_direction_ = direction;
264 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
265 has_ever_been_used_to_send_ = true;
266 }
267}
268
Steve Anton0f5400a2018-07-17 14:25:36 -0700269void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
270 fired_direction_ = direction;
271}
272
Steve Anton6e634bf2017-11-13 10:44:53 -0800273bool RtpTransceiver::stopped() const {
274 return stopped_;
275}
276
277RtpTransceiverDirection RtpTransceiver::direction() const {
278 return direction_;
279}
280
281void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
Steve Anton52d86772018-02-20 15:48:12 -0800282 if (stopped()) {
283 return;
284 }
285 if (new_direction == direction_) {
286 return;
287 }
288 direction_ = new_direction;
289 SignalNegotiationNeeded();
Steve Anton6e634bf2017-11-13 10:44:53 -0800290}
291
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200292absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800293 const {
294 return current_direction_;
295}
296
Steve Anton0f5400a2018-07-17 14:25:36 -0700297absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
298 const {
299 return fired_direction_;
300}
301
Steve Anton6e634bf2017-11-13 10:44:53 -0800302void RtpTransceiver::Stop() {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100303 for (const auto& sender : senders_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800304 sender->internal()->Stop();
305 }
Mirko Bonadei739baf02019-01-27 17:29:42 +0100306 for (const auto& receiver : receivers_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800307 receiver->internal()->Stop();
308 }
309 stopped_ = true;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200310 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800311}
312
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200313RTCError RtpTransceiver::SetCodecPreferences(
314 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
315 RTC_DCHECK(unified_plan_);
316
317 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
318 // to codecs and abort these steps.
319 if (codec_capabilities.empty()) {
320 codec_preferences_.clear();
321 return RTCError::OK();
322 }
323
324 // 4. Remove any duplicate values in codecs.
325 std::vector<RtpCodecCapability> codecs;
326 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
327 [&codecs](const RtpCodecCapability& codec) {
328 return absl::c_linear_search(codecs, codec);
329 });
330
Johannes Kron184ea662020-01-29 12:43:36 +0100331 RTCError result;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200332 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200333 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
334 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
335 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
336
Johannes Kron184ea662020-01-29 12:43:36 +0100337 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200338 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
Johannes Kron184ea662020-01-29 12:43:36 +0100339 std::vector<cricket::VideoCodec> recv_codecs, send_codecs;
340 channel_manager_->GetSupportedVideoReceiveCodecs(&recv_codecs);
341 channel_manager_->GetSupportedVideoSendCodecs(&send_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200342
Johannes Kron184ea662020-01-29 12:43:36 +0100343 result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs);
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200344 }
345
Johannes Kron184ea662020-01-29 12:43:36 +0100346 if (result.ok()) {
347 codec_preferences_ = codecs;
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200348 }
349
Johannes Kron184ea662020-01-29 12:43:36 +0100350 return result;
Steve Anton6e634bf2017-11-13 10:44:53 -0800351}
352
353} // namespace webrtc