blob: d3281d5e6ed577eb6a01b028bfcb51c1564be2c6 [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 {
23
24RtpTransceiver::RtpTransceiver(cricket::MediaType media_type)
25 : unified_plan_(false), media_type_(media_type) {
26 RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO ||
27 media_type == cricket::MEDIA_TYPE_VIDEO);
28}
29
Steve Anton79e79602017-11-20 10:25:56 -080030RtpTransceiver::RtpTransceiver(
31 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
32 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 19:25:51 +020033 receiver,
34 cricket::ChannelManager* channel_manager)
35 : unified_plan_(true),
36 media_type_(sender->media_type()),
37 channel_manager_(channel_manager) {
Steve Anton79e79602017-11-20 10:25:56 -080038 RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO ||
39 media_type_ == cricket::MEDIA_TYPE_VIDEO);
40 RTC_DCHECK_EQ(sender->media_type(), receiver->media_type());
41 senders_.push_back(sender);
42 receivers_.push_back(receiver);
43}
44
Steve Anton6e634bf2017-11-13 10:44:53 -080045RtpTransceiver::~RtpTransceiver() {
46 Stop();
47}
48
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080049void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
50 // Cannot set a non-null channel on a stopped transceiver.
51 if (stopped_ && channel) {
52 return;
53 }
54
Steve Anton6e634bf2017-11-13 10:44:53 -080055 if (channel) {
56 RTC_DCHECK_EQ(media_type(), channel->media_type());
57 }
Steve Anton60776752018-01-10 11:51:34 -080058
59 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080060 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 11:51:34 -080061 }
62
Steve Anton6e634bf2017-11-13 10:44:53 -080063 channel_ = channel;
Steve Anton60776752018-01-10 11:51:34 -080064
65 if (channel_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080066 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 11:51:34 -080067 this, &RtpTransceiver::OnFirstPacketReceived);
68 }
69
Mirko Bonadei739baf02019-01-27 17:29:42 +010070 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080071 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
72 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -080073 }
Steve Anton60776752018-01-10 11:51:34 -080074
Mirko Bonadei739baf02019-01-27 17:29:42 +010075 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080076 if (!channel_) {
Steve Anton6e634bf2017-11-13 10:44:53 -080077 receiver->internal()->Stop();
78 }
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080079
80 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
81 : nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -080082 }
83}
84
85void RtpTransceiver::AddSender(
86 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -080087 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -080088 RTC_DCHECK(!unified_plan_);
89 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 11:43:08 -080090 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -080091 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 10:44:53 -080092 senders_.push_back(sender);
93}
94
95bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) {
96 RTC_DCHECK(!unified_plan_);
97 if (sender) {
98 RTC_DCHECK_EQ(media_type(), sender->media_type());
99 }
Steve Anton64b626b2019-01-28 17:25:26 -0800100 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 10:44:53 -0800101 if (it == senders_.end()) {
102 return false;
103 }
104 (*it)->internal()->Stop();
105 senders_.erase(it);
106 return true;
107}
108
109void RtpTransceiver::AddReceiver(
110 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
111 receiver) {
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800112 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 10:44:53 -0800113 RTC_DCHECK(!unified_plan_);
114 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 11:43:08 -0800115 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-28 17:25:26 -0800116 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 10:44:53 -0800117 receivers_.push_back(receiver);
118}
119
120bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) {
121 RTC_DCHECK(!unified_plan_);
122 if (receiver) {
123 RTC_DCHECK_EQ(media_type(), receiver->media_type());
124 }
Steve Anton64b626b2019-01-28 17:25:26 -0800125 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 10:44:53 -0800126 if (it == receivers_.end()) {
127 return false;
128 }
129 (*it)->internal()->Stop();
Markus Handell43e62fc2020-01-07 19:46:15 +0100130 // After the receiver has been removed, there's no guarantee that the
131 // contained media channel isn't deleted shortly after this. To make sure that
132 // the receiver doesn't spontaneously try to use it's (potentially stale)
133 // media channel reference, we clear it out.
134 (*it)->internal()->SetMediaChannel(nullptr);
Steve Anton6e634bf2017-11-13 10:44:53 -0800135 receivers_.erase(it);
136 return true;
137}
138
Steve Antonf9381f02017-12-14 10:23:57 -0800139rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
140 RTC_DCHECK(unified_plan_);
141 RTC_CHECK_EQ(1u, senders_.size());
142 return senders_[0]->internal();
143}
144
145rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
146 const {
147 RTC_DCHECK(unified_plan_);
148 RTC_CHECK_EQ(1u, receivers_.size());
149 return receivers_[0]->internal();
150}
151
Steve Anton69470252018-02-09 11:43:08 -0800152cricket::MediaType RtpTransceiver::media_type() const {
153 return media_type_;
154}
155
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200156absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 10:44:53 -0800157 return mid_;
158}
159
Amit Hilbuchdd9390c2018-11-13 16:26:05 -0800160void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100161 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 11:51:34 -0800162 receiver->internal()->NotifyFirstPacketReceived();
163 }
164}
165
Steve Anton6e634bf2017-11-13 10:44:53 -0800166rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
167 RTC_DCHECK(unified_plan_);
168 RTC_CHECK_EQ(1u, senders_.size());
169 return senders_[0];
170}
171
172rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
173 RTC_DCHECK(unified_plan_);
174 RTC_CHECK_EQ(1u, receivers_.size());
175 return receivers_[0];
176}
177
Steve Antondcc3c022017-12-22 16:02:54 -0800178void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 11:27:23 -0700179 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
180 << ") current direction from "
181 << (current_direction_ ? RtpTransceiverDirectionToString(
182 *current_direction_)
183 : "<not set>")
184 << " to " << RtpTransceiverDirectionToString(direction)
185 << ".";
Steve Antondcc3c022017-12-22 16:02:54 -0800186 current_direction_ = direction;
187 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
188 has_ever_been_used_to_send_ = true;
189 }
190}
191
Steve Anton0f5400a2018-07-17 14:25:36 -0700192void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
193 fired_direction_ = direction;
194}
195
Steve Anton6e634bf2017-11-13 10:44:53 -0800196bool RtpTransceiver::stopped() const {
197 return stopped_;
198}
199
200RtpTransceiverDirection RtpTransceiver::direction() const {
201 return direction_;
202}
203
204void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
Steve Anton52d86772018-02-20 15:48:12 -0800205 if (stopped()) {
206 return;
207 }
208 if (new_direction == direction_) {
209 return;
210 }
211 direction_ = new_direction;
212 SignalNegotiationNeeded();
Steve Anton6e634bf2017-11-13 10:44:53 -0800213}
214
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200215absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 10:44:53 -0800216 const {
217 return current_direction_;
218}
219
Steve Anton0f5400a2018-07-17 14:25:36 -0700220absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
221 const {
222 return fired_direction_;
223}
224
Steve Anton6e634bf2017-11-13 10:44:53 -0800225void RtpTransceiver::Stop() {
Mirko Bonadei739baf02019-01-27 17:29:42 +0100226 for (const auto& sender : senders_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800227 sender->internal()->Stop();
228 }
Mirko Bonadei739baf02019-01-27 17:29:42 +0100229 for (const auto& receiver : receivers_) {
Steve Anton6e634bf2017-11-13 10:44:53 -0800230 receiver->internal()->Stop();
231 }
232 stopped_ = true;
Danil Chapovalov66cadcc2018-06-19 16:47:43 +0200233 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 10:44:53 -0800234}
235
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200236RTCError RtpTransceiver::SetCodecPreferences(
237 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
238 RTC_DCHECK(unified_plan_);
239
240 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
241 // to codecs and abort these steps.
242 if (codec_capabilities.empty()) {
243 codec_preferences_.clear();
244 return RTCError::OK();
245 }
246
247 // 4. Remove any duplicate values in codecs.
248 std::vector<RtpCodecCapability> codecs;
249 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
250 [&codecs](const RtpCodecCapability& codec) {
251 return absl::c_linear_search(codecs, codec);
252 });
253
254 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
255 std::vector<cricket::AudioCodec> audio_codecs;
256
257 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
258 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
259 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
260
261 // 6. If the intersection between codecs and
262 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
263 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
264 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
265 // This ensures that we always have something to offer, regardless of
266 // transceiver.direction.
267
268 if (!absl::c_any_of(
269 codecs, [&recv_codecs](const RtpCodecCapability& codec) {
270 return codec.name != cricket::kRtxCodecName &&
271 codec.name != cricket::kRedCodecName &&
272 codec.name != cricket::kFlexfecCodecName &&
273 absl::c_any_of(
274 recv_codecs,
275 [&codec](const cricket::AudioCodec& recv_codec) {
276 return recv_codec.MatchesCapability(codec);
277 });
278 })) {
279 return RTCError(RTCErrorType::INVALID_MODIFICATION,
280 "Invalid codec preferences: Missing codec from recv "
281 "codec capabilities.");
282 }
283
284 if (!absl::c_any_of(
285 codecs, [&send_codecs](const RtpCodecCapability& codec) {
286 return codec.name != cricket::kRtxCodecName &&
287 codec.name != cricket::kRedCodecName &&
288 codec.name != cricket::kFlexfecCodecName &&
289 absl::c_any_of(
290 send_codecs,
291 [&codec](const cricket::AudioCodec& send_codec) {
292 return send_codec.MatchesCapability(codec);
293 });
294 })) {
295 return RTCError(RTCErrorType::INVALID_MODIFICATION,
296 "Invalid codec preferences: Missing codec from send "
297 "codec capabilities.");
298 }
299
300 // 7. Let codecCapabilities be the union of
301 // RTCRtpSender.getCapabilities(kind).codecs and
302 // RTCRtpReceiver.getCapabilities(kind).codecs. 8.1 For each codec in
303 // codecs, If codec is not in codecCapabilities, throw
304 // InvalidModificationError.
305 for (const auto& codec_preference : codecs) {
306 bool is_recv_codec = absl::c_any_of(
307 recv_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
308 return codec.MatchesCapability(codec_preference);
309 });
310
311 bool is_send_codec = absl::c_any_of(
312 send_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
313 return codec.MatchesCapability(codec_preference);
314 });
315
316 if (!is_recv_codec && !is_send_codec) {
317 return RTCError(
318 RTCErrorType::INVALID_MODIFICATION,
319 std::string(
320 "Invalid codec preferences: invalid codec with name \"") +
321 codec_preference.name + "\".");
322 }
323 }
324 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
325 std::vector<cricket::VideoCodec> video_codecs;
326 // Video codecs are both for the receive and send side, so the checks are
327 // simpler than the audio ones.
328 channel_manager_->GetSupportedVideoCodecs(&video_codecs);
329
330 // Validate codecs
331 for (const auto& codec_preference : codecs) {
332 if (!absl::c_any_of(video_codecs, [&codec_preference](
333 const cricket::VideoCodec& codec) {
334 return codec.MatchesCapability(codec_preference);
335 })) {
336 return RTCError(
337 RTCErrorType::INVALID_MODIFICATION,
338 std::string(
339 "Invalid codec preferences: invalid codec with name \"") +
340 codec_preference.name + "\".");
341 }
342 }
343 }
344
345 // Check we have a real codec (not just rtx, red or fec)
346 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
347 return codec.name == cricket::kRtxCodecName ||
348 codec.name == cricket::kRedCodecName ||
349 codec.name == cricket::kUlpfecCodecName;
350 })) {
351 return RTCError(RTCErrorType::INVALID_MODIFICATION,
352 "Invalid codec preferences: codec list must have a non "
353 "RTX, RED or FEC entry.");
354 }
355
356 codec_preferences_ = codecs;
357
358 return RTCError::OK();
Steve Anton6e634bf2017-11-13 10:44:53 -0800359}
360
361} // namespace webrtc