1 /*
2 * Copyright 2018 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
11 // This file contains tests for `RtpTransceiver`.
12
13 #include "pc/rtp_transceiver.h"
14
15 #include <memory>
16 #include <utility>
17
18 #include "absl/strings/string_view.h"
19 #include "absl/types/optional.h"
20 #include "api/peer_connection_interface.h"
21 #include "api/rtp_parameters.h"
22 #include "media/base/fake_media_engine.h"
23 #include "media/base/media_engine.h"
24 #include "pc/test/mock_channel_interface.h"
25 #include "pc/test/mock_rtp_receiver_internal.h"
26 #include "pc/test/mock_rtp_sender_internal.h"
27 #include "rtc_base/thread.h"
28 #include "test/gmock.h"
29 #include "test/gtest.h"
30
31 using ::testing::_;
32 using ::testing::ElementsAre;
33 using ::testing::Optional;
34 using ::testing::Property;
35 using ::testing::Return;
36 using ::testing::ReturnRef;
37
38 namespace webrtc {
39
40 namespace {
41
42 class RtpTransceiverTest : public testing::Test {
43 public:
RtpTransceiverTest()44 RtpTransceiverTest()
45 : dependencies_(MakeDependencies()),
46 context_(ConnectionContext::Create(&dependencies_)) {}
47
48 protected:
media_engine()49 cricket::MediaEngineInterface* media_engine() {
50 return context_->media_engine();
51 }
context()52 ConnectionContext* context() { return context_.get(); }
53
54 private:
55 rtc::AutoThread main_thread_;
56
MakeDependencies()57 static PeerConnectionFactoryDependencies MakeDependencies() {
58 PeerConnectionFactoryDependencies d;
59 d.network_thread = rtc::Thread::Current();
60 d.worker_thread = rtc::Thread::Current();
61 d.signaling_thread = rtc::Thread::Current();
62 d.media_engine = std::make_unique<cricket::FakeMediaEngine>();
63 return d;
64 }
65
66 PeerConnectionFactoryDependencies dependencies_;
67 rtc::scoped_refptr<ConnectionContext> context_;
68 };
69
70 // Checks that a channel cannot be set on a stopped `RtpTransceiver`.
TEST_F(RtpTransceiverTest,CannotSetChannelOnStoppedTransceiver)71 TEST_F(RtpTransceiverTest, CannotSetChannelOnStoppedTransceiver) {
72 const std::string content_name("my_mid");
73 auto transceiver = rtc::make_ref_counted<RtpTransceiver>(
74 cricket::MediaType::MEDIA_TYPE_AUDIO, context());
75 auto channel1 = std::make_unique<cricket::MockChannelInterface>();
76 EXPECT_CALL(*channel1, media_type())
77 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
78 EXPECT_CALL(*channel1, mid()).WillRepeatedly(ReturnRef(content_name));
79 EXPECT_CALL(*channel1, SetFirstPacketReceivedCallback(_));
80 EXPECT_CALL(*channel1, SetRtpTransport(_)).WillRepeatedly(Return(true));
81 auto channel1_ptr = channel1.get();
82 transceiver->SetChannel(std::move(channel1), [&](const std::string& mid) {
83 EXPECT_EQ(mid, content_name);
84 return nullptr;
85 });
86 EXPECT_EQ(channel1_ptr, transceiver->channel());
87
88 // Stop the transceiver.
89 transceiver->StopInternal();
90 EXPECT_EQ(channel1_ptr, transceiver->channel());
91
92 auto channel2 = std::make_unique<cricket::MockChannelInterface>();
93 EXPECT_CALL(*channel2, media_type())
94 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
95
96 // Clear the current channel - required to allow SetChannel()
97 EXPECT_CALL(*channel1_ptr, SetFirstPacketReceivedCallback(_));
98 transceiver->ClearChannel();
99 // Channel can no longer be set, so this call should be a no-op.
100 transceiver->SetChannel(std::move(channel2),
101 [](const std::string&) { return nullptr; });
102 EXPECT_EQ(nullptr, transceiver->channel());
103 }
104
105 // Checks that a channel can be unset on a stopped `RtpTransceiver`
TEST_F(RtpTransceiverTest,CanUnsetChannelOnStoppedTransceiver)106 TEST_F(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) {
107 const std::string content_name("my_mid");
108 auto transceiver = rtc::make_ref_counted<RtpTransceiver>(
109 cricket::MediaType::MEDIA_TYPE_VIDEO, context());
110 auto channel = std::make_unique<cricket::MockChannelInterface>();
111 EXPECT_CALL(*channel, media_type())
112 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_VIDEO));
113 EXPECT_CALL(*channel, mid()).WillRepeatedly(ReturnRef(content_name));
114 EXPECT_CALL(*channel, SetFirstPacketReceivedCallback(_))
115 .WillRepeatedly(testing::Return());
116 EXPECT_CALL(*channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
117
118 auto channel_ptr = channel.get();
119 transceiver->SetChannel(std::move(channel), [&](const std::string& mid) {
120 EXPECT_EQ(mid, content_name);
121 return nullptr;
122 });
123 EXPECT_EQ(channel_ptr, transceiver->channel());
124
125 // Stop the transceiver.
126 transceiver->StopInternal();
127 EXPECT_EQ(channel_ptr, transceiver->channel());
128
129 // Set the channel to `nullptr`.
130 transceiver->ClearChannel();
131 EXPECT_EQ(nullptr, transceiver->channel());
132 }
133
134 class RtpTransceiverUnifiedPlanTest : public RtpTransceiverTest {
135 public:
RtpTransceiverUnifiedPlanTest()136 RtpTransceiverUnifiedPlanTest()
137 : transceiver_(rtc::make_ref_counted<RtpTransceiver>(
138 RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
139 rtc::Thread::Current(),
140 sender_),
141 RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
142 rtc::Thread::Current(),
143 rtc::Thread::Current(),
144 receiver_),
145 context(),
146 media_engine()->voice().GetRtpHeaderExtensions(),
147 /* on_negotiation_needed= */ [] {})) {}
148
MockReceiver()149 static rtc::scoped_refptr<MockRtpReceiverInternal> MockReceiver() {
150 auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
151 EXPECT_CALL(*receiver.get(), media_type())
152 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
153 return receiver;
154 }
155
MockSender()156 static rtc::scoped_refptr<MockRtpSenderInternal> MockSender() {
157 auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
158 EXPECT_CALL(*sender.get(), media_type())
159 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
160 return sender;
161 }
162
163 rtc::AutoThread main_thread_;
164 rtc::scoped_refptr<MockRtpReceiverInternal> receiver_ = MockReceiver();
165 rtc::scoped_refptr<MockRtpSenderInternal> sender_ = MockSender();
166 rtc::scoped_refptr<RtpTransceiver> transceiver_;
167 };
168
169 // Basic tests for Stop()
TEST_F(RtpTransceiverUnifiedPlanTest,StopSetsDirection)170 TEST_F(RtpTransceiverUnifiedPlanTest, StopSetsDirection) {
171 EXPECT_CALL(*receiver_.get(), Stop());
172 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
173 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
174 EXPECT_CALL(*sender_.get(), Stop());
175
176 EXPECT_EQ(RtpTransceiverDirection::kInactive, transceiver_->direction());
177 EXPECT_FALSE(transceiver_->current_direction());
178 transceiver_->StopStandard();
179 EXPECT_EQ(RtpTransceiverDirection::kStopped, transceiver_->direction());
180 EXPECT_FALSE(transceiver_->current_direction());
181 transceiver_->StopTransceiverProcedure();
182 EXPECT_TRUE(transceiver_->current_direction());
183 EXPECT_EQ(RtpTransceiverDirection::kStopped, transceiver_->direction());
184 EXPECT_EQ(RtpTransceiverDirection::kStopped,
185 *transceiver_->current_direction());
186 }
187
188 class RtpTransceiverTestForHeaderExtensions : public RtpTransceiverTest {
189 public:
RtpTransceiverTestForHeaderExtensions()190 RtpTransceiverTestForHeaderExtensions()
191 : extensions_(
192 {RtpHeaderExtensionCapability("uri1",
193 1,
194 RtpTransceiverDirection::kSendOnly),
195 RtpHeaderExtensionCapability("uri2",
196 2,
197 RtpTransceiverDirection::kRecvOnly),
198 RtpHeaderExtensionCapability(RtpExtension::kMidUri,
199 3,
200 RtpTransceiverDirection::kSendRecv),
201 RtpHeaderExtensionCapability(RtpExtension::kVideoRotationUri,
202 4,
203 RtpTransceiverDirection::kSendRecv)}),
204 transceiver_(rtc::make_ref_counted<RtpTransceiver>(
205 RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
206 rtc::Thread::Current(),
207 sender_),
208 RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
209 rtc::Thread::Current(),
210 rtc::Thread::Current(),
211 receiver_),
212 context(),
213 extensions_,
__anon9397170d0602null214 /* on_negotiation_needed= */ [] {})) {}
215
MockReceiver()216 static rtc::scoped_refptr<MockRtpReceiverInternal> MockReceiver() {
217 auto receiver = rtc::make_ref_counted<MockRtpReceiverInternal>();
218 EXPECT_CALL(*receiver.get(), media_type())
219 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
220 return receiver;
221 }
222
MockSender()223 static rtc::scoped_refptr<MockRtpSenderInternal> MockSender() {
224 auto sender = rtc::make_ref_counted<MockRtpSenderInternal>();
225 EXPECT_CALL(*sender.get(), media_type())
226 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
227 return sender;
228 }
229
ClearChannel()230 void ClearChannel() {
231 EXPECT_CALL(*sender_.get(), SetMediaChannel(_));
232 transceiver_->ClearChannel();
233 }
234
235 rtc::AutoThread main_thread_;
236 rtc::scoped_refptr<MockRtpReceiverInternal> receiver_ = MockReceiver();
237 rtc::scoped_refptr<MockRtpSenderInternal> sender_ = MockSender();
238
239 std::vector<RtpHeaderExtensionCapability> extensions_;
240 rtc::scoped_refptr<RtpTransceiver> transceiver_;
241 };
242
TEST_F(RtpTransceiverTestForHeaderExtensions,OffersChannelManagerList)243 TEST_F(RtpTransceiverTestForHeaderExtensions, OffersChannelManagerList) {
244 EXPECT_CALL(*receiver_.get(), Stop());
245 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
246 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
247 EXPECT_CALL(*sender_.get(), Stop());
248
249 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
250 }
251
TEST_F(RtpTransceiverTestForHeaderExtensions,ModifiesDirection)252 TEST_F(RtpTransceiverTestForHeaderExtensions, ModifiesDirection) {
253 EXPECT_CALL(*receiver_.get(), Stop());
254 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
255 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
256 EXPECT_CALL(*sender_.get(), Stop());
257
258 auto modified_extensions = extensions_;
259 modified_extensions[0].direction = RtpTransceiverDirection::kSendOnly;
260 EXPECT_TRUE(
261 transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
262 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
263 modified_extensions[0].direction = RtpTransceiverDirection::kRecvOnly;
264 EXPECT_TRUE(
265 transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
266 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
267 modified_extensions[0].direction = RtpTransceiverDirection::kSendRecv;
268 EXPECT_TRUE(
269 transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
270 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
271 modified_extensions[0].direction = RtpTransceiverDirection::kInactive;
272 EXPECT_TRUE(
273 transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
274 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
275 }
276
TEST_F(RtpTransceiverTestForHeaderExtensions,AcceptsStoppedExtension)277 TEST_F(RtpTransceiverTestForHeaderExtensions, AcceptsStoppedExtension) {
278 EXPECT_CALL(*receiver_.get(), Stop());
279 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
280 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
281 EXPECT_CALL(*sender_.get(), Stop());
282
283 auto modified_extensions = extensions_;
284 modified_extensions[0].direction = RtpTransceiverDirection::kStopped;
285 EXPECT_TRUE(
286 transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions).ok());
287 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), modified_extensions);
288 }
289
TEST_F(RtpTransceiverTestForHeaderExtensions,RejectsUnsupportedExtension)290 TEST_F(RtpTransceiverTestForHeaderExtensions, RejectsUnsupportedExtension) {
291 EXPECT_CALL(*receiver_.get(), Stop());
292 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
293 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
294 EXPECT_CALL(*sender_.get(), Stop());
295
296 std::vector<RtpHeaderExtensionCapability> modified_extensions(
297 {RtpHeaderExtensionCapability("uri3", 1,
298 RtpTransceiverDirection::kSendRecv)});
299 EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
300 Property(&RTCError::type, RTCErrorType::UNSUPPORTED_PARAMETER));
301 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
302 }
303
TEST_F(RtpTransceiverTestForHeaderExtensions,RejectsStoppedMandatoryExtensions)304 TEST_F(RtpTransceiverTestForHeaderExtensions,
305 RejectsStoppedMandatoryExtensions) {
306 EXPECT_CALL(*receiver_.get(), Stop());
307 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
308 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
309 EXPECT_CALL(*sender_.get(), Stop());
310
311 std::vector<RtpHeaderExtensionCapability> modified_extensions = extensions_;
312 // Attempting to stop the mandatory MID extension.
313 modified_extensions[2].direction = RtpTransceiverDirection::kStopped;
314 EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
315 Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
316 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
317 modified_extensions = extensions_;
318 // Attempting to stop the mandatory video orientation extension.
319 modified_extensions[3].direction = RtpTransceiverDirection::kStopped;
320 EXPECT_THAT(transceiver_->SetOfferedRtpHeaderExtensions(modified_extensions),
321 Property(&RTCError::type, RTCErrorType::INVALID_MODIFICATION));
322 EXPECT_EQ(transceiver_->HeaderExtensionsToOffer(), extensions_);
323 }
324
TEST_F(RtpTransceiverTestForHeaderExtensions,NoNegotiatedHdrExtsWithoutChannel)325 TEST_F(RtpTransceiverTestForHeaderExtensions,
326 NoNegotiatedHdrExtsWithoutChannel) {
327 EXPECT_CALL(*receiver_.get(), Stop());
328 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
329 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
330 EXPECT_CALL(*sender_.get(), Stop());
331 EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(), ElementsAre());
332 }
333
TEST_F(RtpTransceiverTestForHeaderExtensions,NoNegotiatedHdrExtsWithChannelWithoutNegotiation)334 TEST_F(RtpTransceiverTestForHeaderExtensions,
335 NoNegotiatedHdrExtsWithChannelWithoutNegotiation) {
336 const std::string content_name("my_mid");
337 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)).WillRepeatedly(Return());
338 EXPECT_CALL(*receiver_.get(), Stop()).WillRepeatedly(Return());
339 EXPECT_CALL(*sender_.get(), SetMediaChannel(_));
340 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
341 EXPECT_CALL(*sender_.get(), Stop());
342 auto mock_channel = std::make_unique<cricket::MockChannelInterface>();
343 auto mock_channel_ptr = mock_channel.get();
344 EXPECT_CALL(*mock_channel, SetFirstPacketReceivedCallback(_));
345 EXPECT_CALL(*mock_channel, media_type())
346 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
347 EXPECT_CALL(*mock_channel, media_channel()).WillRepeatedly(Return(nullptr));
348 EXPECT_CALL(*mock_channel, mid()).WillRepeatedly(ReturnRef(content_name));
349 EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
350 transceiver_->SetChannel(std::move(mock_channel),
351 [](const std::string&) { return nullptr; });
352 EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(), ElementsAre());
353
354 EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_));
355 ClearChannel();
356 }
357
TEST_F(RtpTransceiverTestForHeaderExtensions,ReturnsNegotiatedHdrExts)358 TEST_F(RtpTransceiverTestForHeaderExtensions, ReturnsNegotiatedHdrExts) {
359 const std::string content_name("my_mid");
360 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_)).WillRepeatedly(Return());
361 EXPECT_CALL(*receiver_.get(), Stop()).WillRepeatedly(Return());
362 EXPECT_CALL(*sender_.get(), SetMediaChannel(_));
363 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
364 EXPECT_CALL(*sender_.get(), Stop());
365
366 auto mock_channel = std::make_unique<cricket::MockChannelInterface>();
367 auto mock_channel_ptr = mock_channel.get();
368 EXPECT_CALL(*mock_channel, SetFirstPacketReceivedCallback(_));
369 EXPECT_CALL(*mock_channel, media_type())
370 .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
371 EXPECT_CALL(*mock_channel, media_channel()).WillRepeatedly(Return(nullptr));
372 EXPECT_CALL(*mock_channel, mid()).WillRepeatedly(ReturnRef(content_name));
373 EXPECT_CALL(*mock_channel, SetRtpTransport(_)).WillRepeatedly(Return(true));
374
375 cricket::RtpHeaderExtensions extensions = {webrtc::RtpExtension("uri1", 1),
376 webrtc::RtpExtension("uri2", 2)};
377 cricket::AudioContentDescription description;
378 description.set_rtp_header_extensions(extensions);
379 transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
380
381 transceiver_->SetChannel(std::move(mock_channel),
382 [](const std::string&) { return nullptr; });
383 EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
384 ElementsAre(RtpHeaderExtensionCapability(
385 "uri1", 1, RtpTransceiverDirection::kSendRecv),
386 RtpHeaderExtensionCapability(
387 "uri2", 2, RtpTransceiverDirection::kSendRecv)));
388
389 EXPECT_CALL(*mock_channel_ptr, SetFirstPacketReceivedCallback(_));
390 ClearChannel();
391 }
392
TEST_F(RtpTransceiverTestForHeaderExtensions,ReturnsNegotiatedHdrExtsSecondTime)393 TEST_F(RtpTransceiverTestForHeaderExtensions,
394 ReturnsNegotiatedHdrExtsSecondTime) {
395 EXPECT_CALL(*receiver_.get(), Stop());
396 EXPECT_CALL(*receiver_.get(), SetMediaChannel(_));
397 EXPECT_CALL(*sender_.get(), SetTransceiverAsStopped());
398 EXPECT_CALL(*sender_.get(), Stop());
399
400 cricket::RtpHeaderExtensions extensions = {webrtc::RtpExtension("uri1", 1),
401 webrtc::RtpExtension("uri2", 2)};
402 cricket::AudioContentDescription description;
403 description.set_rtp_header_extensions(extensions);
404 transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
405
406 EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
407 ElementsAre(RtpHeaderExtensionCapability(
408 "uri1", 1, RtpTransceiverDirection::kSendRecv),
409 RtpHeaderExtensionCapability(
410 "uri2", 2, RtpTransceiverDirection::kSendRecv)));
411
412 extensions = {webrtc::RtpExtension("uri3", 4),
413 webrtc::RtpExtension("uri5", 6)};
414 description.set_rtp_header_extensions(extensions);
415 transceiver_->OnNegotiationUpdate(SdpType::kAnswer, &description);
416
417 EXPECT_THAT(transceiver_->HeaderExtensionsNegotiated(),
418 ElementsAre(RtpHeaderExtensionCapability(
419 "uri3", 4, RtpTransceiverDirection::kSendRecv),
420 RtpHeaderExtensionCapability(
421 "uri5", 6, RtpTransceiverDirection::kSendRecv)));
422 }
423
424 } // namespace
425
426 } // namespace webrtc
427