blob: d8d168191e61723129524e11eba18bbb01cc8f0a [file] [log] [blame]
Steve Anton6e634bf2017-11-13 18:44:531/*
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 17:11:0011#include "pc/rtp_transceiver.h"
Steve Anton6e634bf2017-11-13 18:44:5312
13#include <string>
14
Steve Anton64b626b2019-01-29 01:25:2615#include "absl/algorithm/container.h"
Florent Castelli2d9d82e2019-04-23 17:25:5116#include "pc/channel_manager.h"
Steve Anton10542f22019-01-11 17:11:0017#include "pc/rtp_media_utils.h"
Florent Castelli2d9d82e2019-04-23 17:25:5118#include "pc/rtp_parameters_conversion.h"
Yves Gerey3e707812018-11-28 15:47:4919#include "rtc_base/checks.h"
20#include "rtc_base/logging.h"
Steve Antondcc3c022017-12-23 00:02:5421
Steve Anton6e634bf2017-11-13 18:44:5322namespace 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 18:25:5630RtpTransceiver::RtpTransceiver(
31 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender,
32 rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
Florent Castelli2d9d82e2019-04-23 17:25:5133 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 18:25:5638 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 18:44:5345RtpTransceiver::~RtpTransceiver() {
46 Stop();
47}
48
Amit Hilbuchdd9390c2018-11-14 00:26:0549void 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 18:44:5355 if (channel) {
56 RTC_DCHECK_EQ(media_type(), channel->media_type());
57 }
Steve Anton60776752018-01-10 19:51:3458
59 if (channel_) {
Amit Hilbuchdd9390c2018-11-14 00:26:0560 channel_->SignalFirstPacketReceived().disconnect(this);
Steve Anton60776752018-01-10 19:51:3461 }
62
Steve Anton6e634bf2017-11-13 18:44:5363 channel_ = channel;
Steve Anton60776752018-01-10 19:51:3464
65 if (channel_) {
Amit Hilbuchdd9390c2018-11-14 00:26:0566 channel_->SignalFirstPacketReceived().connect(
Steve Anton60776752018-01-10 19:51:3467 this, &RtpTransceiver::OnFirstPacketReceived);
68 }
69
Mirko Bonadei739baf02019-01-27 16:29:4270 for (const auto& sender : senders_) {
Amit Hilbuchdd9390c2018-11-14 00:26:0571 sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
72 : nullptr);
Steve Anton6e634bf2017-11-13 18:44:5373 }
Steve Anton60776752018-01-10 19:51:3474
Mirko Bonadei739baf02019-01-27 16:29:4275 for (const auto& receiver : receivers_) {
Amit Hilbuchdd9390c2018-11-14 00:26:0576 if (!channel_) {
Steve Anton6e634bf2017-11-13 18:44:5377 receiver->internal()->Stop();
78 }
Amit Hilbuchdd9390c2018-11-14 00:26:0579
80 receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
81 : nullptr);
Steve Anton6e634bf2017-11-13 18:44:5382 }
83}
84
85void RtpTransceiver::AddSender(
86 rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
Amit Hilbuchdd9390c2018-11-14 00:26:0587 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 18:44:5388 RTC_DCHECK(!unified_plan_);
89 RTC_DCHECK(sender);
Steve Anton69470252018-02-09 19:43:0890 RTC_DCHECK_EQ(media_type(), sender->media_type());
Steve Anton64b626b2019-01-29 01:25:2691 RTC_DCHECK(!absl::c_linear_search(senders_, sender));
Steve Anton6e634bf2017-11-13 18:44:5392 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-29 01:25:26100 auto it = absl::c_find(senders_, sender);
Steve Anton6e634bf2017-11-13 18:44:53101 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-14 00:26:05112 RTC_DCHECK(!stopped_);
Steve Anton6e634bf2017-11-13 18:44:53113 RTC_DCHECK(!unified_plan_);
114 RTC_DCHECK(receiver);
Steve Anton69470252018-02-09 19:43:08115 RTC_DCHECK_EQ(media_type(), receiver->media_type());
Steve Anton64b626b2019-01-29 01:25:26116 RTC_DCHECK(!absl::c_linear_search(receivers_, receiver));
Steve Anton6e634bf2017-11-13 18:44:53117 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-29 01:25:26125 auto it = absl::c_find(receivers_, receiver);
Steve Anton6e634bf2017-11-13 18:44:53126 if (it == receivers_.end()) {
127 return false;
128 }
129 (*it)->internal()->Stop();
130 receivers_.erase(it);
131 return true;
132}
133
Steve Antonf9381f02017-12-14 18:23:57134rtc::scoped_refptr<RtpSenderInternal> RtpTransceiver::sender_internal() const {
135 RTC_DCHECK(unified_plan_);
136 RTC_CHECK_EQ(1u, senders_.size());
137 return senders_[0]->internal();
138}
139
140rtc::scoped_refptr<RtpReceiverInternal> RtpTransceiver::receiver_internal()
141 const {
142 RTC_DCHECK(unified_plan_);
143 RTC_CHECK_EQ(1u, receivers_.size());
144 return receivers_[0]->internal();
145}
146
Steve Anton69470252018-02-09 19:43:08147cricket::MediaType RtpTransceiver::media_type() const {
148 return media_type_;
149}
150
Danil Chapovalov66cadcc2018-06-19 14:47:43151absl::optional<std::string> RtpTransceiver::mid() const {
Steve Anton6e634bf2017-11-13 18:44:53152 return mid_;
153}
154
Amit Hilbuchdd9390c2018-11-14 00:26:05155void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
Mirko Bonadei739baf02019-01-27 16:29:42156 for (const auto& receiver : receivers_) {
Steve Anton60776752018-01-10 19:51:34157 receiver->internal()->NotifyFirstPacketReceived();
158 }
159}
160
Steve Anton6e634bf2017-11-13 18:44:53161rtc::scoped_refptr<RtpSenderInterface> RtpTransceiver::sender() const {
162 RTC_DCHECK(unified_plan_);
163 RTC_CHECK_EQ(1u, senders_.size());
164 return senders_[0];
165}
166
167rtc::scoped_refptr<RtpReceiverInterface> RtpTransceiver::receiver() const {
168 RTC_DCHECK(unified_plan_);
169 RTC_CHECK_EQ(1u, receivers_.size());
170 return receivers_[0];
171}
172
Steve Antondcc3c022017-12-23 00:02:54173void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) {
Steve Anton3d954a62018-04-02 18:27:23174 RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("<not set>")
175 << ") current direction from "
176 << (current_direction_ ? RtpTransceiverDirectionToString(
177 *current_direction_)
178 : "<not set>")
179 << " to " << RtpTransceiverDirectionToString(direction)
180 << ".";
Steve Antondcc3c022017-12-23 00:02:54181 current_direction_ = direction;
182 if (RtpTransceiverDirectionHasSend(*current_direction_)) {
183 has_ever_been_used_to_send_ = true;
184 }
185}
186
Steve Anton0f5400a2018-07-17 21:25:36187void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) {
188 fired_direction_ = direction;
189}
190
Steve Anton6e634bf2017-11-13 18:44:53191bool RtpTransceiver::stopped() const {
192 return stopped_;
193}
194
195RtpTransceiverDirection RtpTransceiver::direction() const {
196 return direction_;
197}
198
199void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) {
Steve Anton52d86772018-02-20 23:48:12200 if (stopped()) {
201 return;
202 }
203 if (new_direction == direction_) {
204 return;
205 }
206 direction_ = new_direction;
207 SignalNegotiationNeeded();
Steve Anton6e634bf2017-11-13 18:44:53208}
209
Danil Chapovalov66cadcc2018-06-19 14:47:43210absl::optional<RtpTransceiverDirection> RtpTransceiver::current_direction()
Steve Anton6e634bf2017-11-13 18:44:53211 const {
212 return current_direction_;
213}
214
Steve Anton0f5400a2018-07-17 21:25:36215absl::optional<RtpTransceiverDirection> RtpTransceiver::fired_direction()
216 const {
217 return fired_direction_;
218}
219
Steve Anton6e634bf2017-11-13 18:44:53220void RtpTransceiver::Stop() {
Mirko Bonadei739baf02019-01-27 16:29:42221 for (const auto& sender : senders_) {
Steve Anton6e634bf2017-11-13 18:44:53222 sender->internal()->Stop();
223 }
Mirko Bonadei739baf02019-01-27 16:29:42224 for (const auto& receiver : receivers_) {
Steve Anton6e634bf2017-11-13 18:44:53225 receiver->internal()->Stop();
226 }
227 stopped_ = true;
Danil Chapovalov66cadcc2018-06-19 14:47:43228 current_direction_ = absl::nullopt;
Steve Anton6e634bf2017-11-13 18:44:53229}
230
Florent Castelli2d9d82e2019-04-23 17:25:51231RTCError RtpTransceiver::SetCodecPreferences(
232 rtc::ArrayView<RtpCodecCapability> codec_capabilities) {
233 RTC_DCHECK(unified_plan_);
234
235 // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot
236 // to codecs and abort these steps.
237 if (codec_capabilities.empty()) {
238 codec_preferences_.clear();
239 return RTCError::OK();
240 }
241
242 // 4. Remove any duplicate values in codecs.
243 std::vector<RtpCodecCapability> codecs;
244 absl::c_remove_copy_if(codec_capabilities, std::back_inserter(codecs),
245 [&codecs](const RtpCodecCapability& codec) {
246 return absl::c_linear_search(codecs, codec);
247 });
248
249 if (media_type_ == cricket::MEDIA_TYPE_AUDIO) {
250 std::vector<cricket::AudioCodec> audio_codecs;
251
252 std::vector<cricket::AudioCodec> recv_codecs, send_codecs;
253 channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs);
254 channel_manager_->GetSupportedAudioSendCodecs(&send_codecs);
255
256 // 6. If the intersection between codecs and
257 // RTCRtpSender.getCapabilities(kind).codecs or the intersection between
258 // codecs and RTCRtpReceiver.getCapabilities(kind).codecs only contains RTX,
259 // RED or FEC codecs or is an empty set, throw InvalidModificationError.
260 // This ensures that we always have something to offer, regardless of
261 // transceiver.direction.
262
263 if (!absl::c_any_of(
264 codecs, [&recv_codecs](const RtpCodecCapability& codec) {
265 return codec.name != cricket::kRtxCodecName &&
266 codec.name != cricket::kRedCodecName &&
267 codec.name != cricket::kFlexfecCodecName &&
268 absl::c_any_of(
269 recv_codecs,
270 [&codec](const cricket::AudioCodec& recv_codec) {
271 return recv_codec.MatchesCapability(codec);
272 });
273 })) {
274 return RTCError(RTCErrorType::INVALID_MODIFICATION,
275 "Invalid codec preferences: Missing codec from recv "
276 "codec capabilities.");
277 }
278
279 if (!absl::c_any_of(
280 codecs, [&send_codecs](const RtpCodecCapability& codec) {
281 return codec.name != cricket::kRtxCodecName &&
282 codec.name != cricket::kRedCodecName &&
283 codec.name != cricket::kFlexfecCodecName &&
284 absl::c_any_of(
285 send_codecs,
286 [&codec](const cricket::AudioCodec& send_codec) {
287 return send_codec.MatchesCapability(codec);
288 });
289 })) {
290 return RTCError(RTCErrorType::INVALID_MODIFICATION,
291 "Invalid codec preferences: Missing codec from send "
292 "codec capabilities.");
293 }
294
295 // 7. Let codecCapabilities be the union of
296 // RTCRtpSender.getCapabilities(kind).codecs and
297 // RTCRtpReceiver.getCapabilities(kind).codecs. 8.1 For each codec in
298 // codecs, If codec is not in codecCapabilities, throw
299 // InvalidModificationError.
300 for (const auto& codec_preference : codecs) {
301 bool is_recv_codec = absl::c_any_of(
302 recv_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
303 return codec.MatchesCapability(codec_preference);
304 });
305
306 bool is_send_codec = absl::c_any_of(
307 send_codecs, [&codec_preference](const cricket::AudioCodec& codec) {
308 return codec.MatchesCapability(codec_preference);
309 });
310
311 if (!is_recv_codec && !is_send_codec) {
312 return RTCError(
313 RTCErrorType::INVALID_MODIFICATION,
314 std::string(
315 "Invalid codec preferences: invalid codec with name \"") +
316 codec_preference.name + "\".");
317 }
318 }
319 } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) {
320 std::vector<cricket::VideoCodec> video_codecs;
321 // Video codecs are both for the receive and send side, so the checks are
322 // simpler than the audio ones.
323 channel_manager_->GetSupportedVideoCodecs(&video_codecs);
324
325 // Validate codecs
326 for (const auto& codec_preference : codecs) {
327 if (!absl::c_any_of(video_codecs, [&codec_preference](
328 const cricket::VideoCodec& codec) {
329 return codec.MatchesCapability(codec_preference);
330 })) {
331 return RTCError(
332 RTCErrorType::INVALID_MODIFICATION,
333 std::string(
334 "Invalid codec preferences: invalid codec with name \"") +
335 codec_preference.name + "\".");
336 }
337 }
338 }
339
340 // Check we have a real codec (not just rtx, red or fec)
341 if (absl::c_all_of(codecs, [](const RtpCodecCapability& codec) {
342 return codec.name == cricket::kRtxCodecName ||
343 codec.name == cricket::kRedCodecName ||
344 codec.name == cricket::kUlpfecCodecName;
345 })) {
346 return RTCError(RTCErrorType::INVALID_MODIFICATION,
347 "Invalid codec preferences: codec list must have a non "
348 "RTX, RED or FEC entry.");
349 }
350
351 codec_preferences_ = codecs;
352
353 return RTCError::OK();
Steve Anton6e634bf2017-11-13 18:44:53354}
355
356} // namespace webrtc