blob: 6fa4bae4039985277fa8c33890a513f330cb2ef0 [file] [log] [blame]
Amit Hilbuchaa584152019-02-06 17:09:52 -08001/*
2 * Copyright 2019 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#include <ostream> // no-presubmit-check TODO(webrtc:8982)
12
13#include "absl/algorithm/container.h"
14#include "absl/memory/memory.h"
15#include "api/audio_codecs/builtin_audio_decoder_factory.h"
16#include "api/audio_codecs/builtin_audio_encoder_factory.h"
17#include "api/create_peerconnection_factory.h"
18#include "api/rtp_transceiver_interface.h"
19#include "api/video_codecs/builtin_video_decoder_factory.h"
20#include "api/video_codecs/builtin_video_encoder_factory.h"
21#include "pc/peer_connection.h"
22#include "pc/peer_connection_wrapper.h"
23#include "pc/test/fake_audio_capture_module.h"
24#include "pc/test/mock_peer_connection_observers.h"
25#include "rtc_base/gunit.h"
26#include "test/gmock.h"
27
28using ::testing::Contains;
29using ::testing::Each;
30using ::testing::ElementsAre;
31using ::testing::ElementsAreArray;
32using ::testing::Eq;
33using ::testing::Field;
34using ::testing::IsEmpty;
35using ::testing::Ne;
36using ::testing::Property;
37using ::testing::SizeIs;
38
39using cricket::MediaContentDescription;
40using cricket::RidDescription;
41using cricket::SimulcastDescription;
42using cricket::SimulcastLayer;
43using cricket::StreamParams;
44
45namespace cricket {
46
47std::ostream& operator<<( // no-presubmit-check TODO(webrtc:8982)
48 std::ostream& os, // no-presubmit-check TODO(webrtc:8982)
49 const SimulcastLayer& layer) {
50 if (layer.is_paused) {
51 os << "~";
52 }
53 return os << layer.rid;
54}
55
56} // namespace cricket
57
58namespace {
59
60std::vector<SimulcastLayer> CreateLayers(const std::vector<std::string>& rids,
61 const std::vector<bool>& active) {
62 RTC_DCHECK_EQ(rids.size(), active.size());
63 std::vector<SimulcastLayer> result;
64 absl::c_transform(rids, active, std::back_inserter(result),
65 [](const std::string& rid, bool is_active) {
66 return SimulcastLayer(rid, !is_active);
67 });
68 return result;
69}
70std::vector<SimulcastLayer> CreateLayers(const std::vector<std::string>& rids,
71 bool active) {
72 return CreateLayers(rids, std::vector<bool>(rids.size(), active));
73}
74
75} // namespace
76namespace webrtc {
77
78class PeerConnectionSimulcastTests : public testing::Test {
79 public:
80 PeerConnectionSimulcastTests()
81 : pc_factory_(
82 CreatePeerConnectionFactory(rtc::Thread::Current(),
83 rtc::Thread::Current(),
84 rtc::Thread::Current(),
85 FakeAudioCaptureModule::Create(),
86 CreateBuiltinAudioEncoderFactory(),
87 CreateBuiltinAudioDecoderFactory(),
88 CreateBuiltinVideoEncoderFactory(),
89 CreateBuiltinVideoDecoderFactory(),
90 nullptr,
91 nullptr)) {}
92
93 rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
94 MockPeerConnectionObserver* observer) {
95 PeerConnectionInterface::RTCConfiguration config;
96 config.sdp_semantics = SdpSemantics::kUnifiedPlan;
97 PeerConnectionDependencies pcd(observer);
98 auto pc = pc_factory_->CreatePeerConnection(config, std::move(pcd));
99 EXPECT_TRUE(pc);
100 observer->SetPeerConnectionInterface(pc);
101 return pc;
102 }
103
104 std::unique_ptr<PeerConnectionWrapper> CreatePeerConnectionWrapper() {
105 auto observer = absl::make_unique<MockPeerConnectionObserver>();
106 auto pc = CreatePeerConnection(observer.get());
107 return absl::make_unique<PeerConnectionWrapper>(pc_factory_, pc,
108 std::move(observer));
109 }
110
Amit Hilbuch619b2942019-02-26 15:55:19 -0800111 void ExchangeOfferAnswer(PeerConnectionWrapper* local,
112 PeerConnectionWrapper* remote,
113 const std::vector<SimulcastLayer>& answer_layers) {
114 auto offer = local->CreateOfferAndSetAsLocal();
115 // Remove simulcast as the second peer connection won't support it.
Amit Hilbuchaabd0362019-03-01 13:14:46 -0800116 RemoveSimulcast(offer.get());
Amit Hilbuch619b2942019-02-26 15:55:19 -0800117 std::string err;
118 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &err)) << err;
119 auto answer = remote->CreateAnswerAndSetAsLocal();
120 // Setup the answer to look like a server response.
121 auto mcd_answer = answer->description()->contents()[0].media_description();
122 auto& receive_layers = mcd_answer->simulcast_description().receive_layers();
123 for (const SimulcastLayer& layer : answer_layers) {
124 receive_layers.AddLayer(layer);
125 }
126 EXPECT_TRUE(local->SetRemoteDescription(std::move(answer), &err)) << err;
127 }
128
Amit Hilbuchaa584152019-02-06 17:09:52 -0800129 RtpTransceiverInit CreateTransceiverInit(
130 const std::vector<SimulcastLayer>& layers) {
131 RtpTransceiverInit init;
132 for (const SimulcastLayer& layer : layers) {
133 RtpEncodingParameters encoding;
134 encoding.rid = layer.rid;
135 encoding.active = !layer.is_paused;
136 init.send_encodings.push_back(encoding);
137 }
138 return init;
139 }
140
141 rtc::scoped_refptr<RtpTransceiverInterface> AddTransceiver(
142 PeerConnectionWrapper* pc,
143 const std::vector<SimulcastLayer>& layers) {
144 auto init = CreateTransceiverInit(layers);
145 return pc->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
146 }
147
148 SimulcastDescription RemoveSimulcast(SessionDescriptionInterface* sd) {
149 auto mcd = sd->description()->contents()[0].media_description();
150 auto result = mcd->simulcast_description();
151 mcd->set_simulcast_description(SimulcastDescription());
152 return result;
153 }
154
155 void AddRequestToReceiveSimulcast(const std::vector<SimulcastLayer>& layers,
156 SessionDescriptionInterface* sd) {
157 auto mcd = sd->description()->contents()[0].media_description();
158 SimulcastDescription simulcast;
159 auto& receive_layers = simulcast.receive_layers();
160 for (const SimulcastLayer& layer : layers) {
161 receive_layers.AddLayer(layer);
162 }
163 mcd->set_simulcast_description(simulcast);
164 }
165
166 bool ValidateTransceiverParameters(
167 rtc::scoped_refptr<RtpTransceiverInterface> transceiver,
168 const std::vector<SimulcastLayer>& layers) {
169 bool errors_before = ::testing::Test::HasFailure();
170 auto parameters = transceiver->sender()->GetParameters();
171 std::vector<SimulcastLayer> result_layers;
172 absl::c_transform(parameters.encodings, std::back_inserter(result_layers),
173 [](const RtpEncodingParameters& encoding) {
174 return SimulcastLayer(encoding.rid, !encoding.active);
175 });
176 EXPECT_THAT(result_layers, ElementsAreArray(layers));
177 // If there were errors before this code ran, we cannot tell if this
178 // validation succeeded or not.
179 return errors_before || !::testing::Test::HasFailure();
180 }
181
182 private:
183 rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
184};
185
186// Validates that RIDs are supported arguments when adding a transceiver.
187TEST_F(PeerConnectionSimulcastTests, CanCreateTransceiverWithRid) {
188 auto pc = CreatePeerConnectionWrapper();
189 auto layers = CreateLayers({"f"}, true);
190 auto transceiver = AddTransceiver(pc.get(), layers);
191 ASSERT_TRUE(transceiver);
192 auto parameters = transceiver->sender()->GetParameters();
193 // Single RID should be removed.
194 EXPECT_THAT(parameters.encodings,
Amit Hilbuch2297d332019-02-19 12:49:22 -0800195 ElementsAre(Field("rid", &RtpEncodingParameters::rid, Eq(""))));
Amit Hilbuchaa584152019-02-06 17:09:52 -0800196}
197
198TEST_F(PeerConnectionSimulcastTests, CanCreateTransceiverWithSimulcast) {
199 auto pc = CreatePeerConnectionWrapper();
200 auto layers = CreateLayers({"f", "h", "q"}, true);
201 auto transceiver = AddTransceiver(pc.get(), layers);
202 ASSERT_TRUE(transceiver);
203 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
204}
205
206TEST_F(PeerConnectionSimulcastTests, RidsAreAutogeneratedIfNotProvided) {
207 auto pc = CreatePeerConnectionWrapper();
208 auto init = CreateTransceiverInit(CreateLayers({"f", "h", "q"}, true));
209 for (RtpEncodingParameters& parameters : init.send_encodings) {
210 parameters.rid = "";
211 }
212 auto transceiver = pc->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
213 auto parameters = transceiver->sender()->GetParameters();
214 ASSERT_EQ(3u, parameters.encodings.size());
215 EXPECT_THAT(parameters.encodings,
Amit Hilbuch2297d332019-02-19 12:49:22 -0800216 Each(Field("rid", &RtpEncodingParameters::rid, Ne(""))));
Amit Hilbuchaa584152019-02-06 17:09:52 -0800217}
218
219// Validates that an error is returned when there is a mix of supplied and not
220// supplied RIDs in a call to AddTransceiver.
221TEST_F(PeerConnectionSimulcastTests, MustSupplyAllOrNoRidsInSimulcast) {
222 auto pc_wrapper = CreatePeerConnectionWrapper();
223 auto pc = pc_wrapper->pc();
224 // Cannot create a layer with empty RID. Remove the RID after init is created.
225 auto layers = CreateLayers({"f", "h", "remove"}, true);
226 auto init = CreateTransceiverInit(layers);
227 init.send_encodings[2].rid = "";
228 auto error = pc->AddTransceiver(cricket::MEDIA_TYPE_VIDEO, init);
229 EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, error.error().type());
230}
231
Amit Hilbuch2297d332019-02-19 12:49:22 -0800232// Validates that a single RID is removed from the encoding layer.
Amit Hilbuchaa584152019-02-06 17:09:52 -0800233TEST_F(PeerConnectionSimulcastTests, SingleRidIsRemovedFromSessionDescription) {
234 auto pc = CreatePeerConnectionWrapper();
235 auto transceiver = AddTransceiver(pc.get(), CreateLayers({"1"}, true));
236 auto offer = pc->CreateOfferAndSetAsLocal();
237 ASSERT_TRUE(offer);
238 auto contents = offer->description()->contents();
239 ASSERT_EQ(1u, contents.size());
240 EXPECT_THAT(contents[0].media_description()->streams(),
241 ElementsAre(Property(&StreamParams::has_rids, false)));
242}
243
244TEST_F(PeerConnectionSimulcastTests, SimulcastLayersRemovedFromTail) {
245 static_assert(
246 kMaxSimulcastStreams < 8,
247 "Test assumes that the platform does not allow 8 simulcast layers");
248 auto pc = CreatePeerConnectionWrapper();
249 auto layers = CreateLayers({"1", "2", "3", "4", "5", "6", "7", "8"}, true);
250 std::vector<SimulcastLayer> expected_layers;
251 std::copy_n(layers.begin(), kMaxSimulcastStreams,
252 std::back_inserter(expected_layers));
253 auto transceiver = AddTransceiver(pc.get(), layers);
254 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, expected_layers));
255}
256
257// Checks that an offfer to send simulcast contains a SimulcastDescription.
258TEST_F(PeerConnectionSimulcastTests, SimulcastAppearsInSessionDescription) {
259 auto pc = CreatePeerConnectionWrapper();
260 std::vector<std::string> rids({"f", "h", "q"});
261 auto layers = CreateLayers(rids, true);
262 auto transceiver = AddTransceiver(pc.get(), layers);
263 auto offer = pc->CreateOffer();
264 ASSERT_TRUE(offer);
265 auto contents = offer->description()->contents();
266 ASSERT_EQ(1u, contents.size());
267 auto content = contents[0];
268 auto mcd = content.media_description();
269 ASSERT_TRUE(mcd->HasSimulcast());
270 auto simulcast = mcd->simulcast_description();
271 EXPECT_THAT(simulcast.receive_layers(), IsEmpty());
272 // The size is validated separately because GetAllLayers() flattens the list.
273 EXPECT_THAT(simulcast.send_layers(), SizeIs(3));
274 std::vector<SimulcastLayer> result = simulcast.send_layers().GetAllLayers();
275 EXPECT_THAT(result, ElementsAreArray(layers));
276 auto streams = mcd->streams();
277 ASSERT_EQ(1u, streams.size());
278 auto stream = streams[0];
279 EXPECT_FALSE(stream.has_ssrcs());
280 EXPECT_TRUE(stream.has_rids());
281 std::vector<std::string> result_rids;
282 absl::c_transform(stream.rids(), std::back_inserter(result_rids),
283 [](const RidDescription& rid) { return rid.rid; });
284 EXPECT_THAT(result_rids, ElementsAreArray(rids));
285}
286
287// Checks that Simulcast layers propagate to the sender parameters.
288TEST_F(PeerConnectionSimulcastTests, SimulcastLayersAreSetInSender) {
289 auto local = CreatePeerConnectionWrapper();
290 auto remote = CreatePeerConnectionWrapper();
291 auto layers = CreateLayers({"f", "h", "q"}, true);
292 auto transceiver = AddTransceiver(local.get(), layers);
293 auto offer = local->CreateOfferAndSetAsLocal();
294 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
295
296 // Remove simulcast as the second peer connection won't support it.
297 auto simulcast = RemoveSimulcast(offer.get());
298 std::string error;
299 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &error)) << error;
300 auto answer = remote->CreateAnswerAndSetAsLocal();
301
302 // Setup an answer that mimics a server accepting simulcast.
303 auto mcd_answer = answer->description()->contents()[0].media_description();
304 mcd_answer->mutable_streams().clear();
305 auto simulcast_layers = simulcast.send_layers().GetAllLayers();
306 auto& receive_layers = mcd_answer->simulcast_description().receive_layers();
307 for (const auto& layer : simulcast_layers) {
308 receive_layers.AddLayer(layer);
309 }
310 EXPECT_TRUE(local->SetRemoteDescription(std::move(answer), &error)) << error;
311 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
312}
313
314// Checks that paused Simulcast layers propagate to the sender parameters.
315TEST_F(PeerConnectionSimulcastTests, PausedSimulcastLayersAreDisabledInSender) {
316 auto local = CreatePeerConnectionWrapper();
317 auto remote = CreatePeerConnectionWrapper();
318 auto layers = CreateLayers({"f", "h", "q"}, {true, false, true});
319 auto server_layers = CreateLayers({"f", "h", "q"}, {true, false, false});
320 RTC_DCHECK_EQ(layers.size(), server_layers.size());
321 auto transceiver = AddTransceiver(local.get(), layers);
322 auto offer = local->CreateOfferAndSetAsLocal();
323 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
324
325 // Remove simulcast as the second peer connection won't support it.
326 RemoveSimulcast(offer.get());
327 std::string error;
328 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &error)) << error;
329 auto answer = remote->CreateAnswerAndSetAsLocal();
330
331 // Setup an answer that mimics a server accepting simulcast.
332 auto mcd_answer = answer->description()->contents()[0].media_description();
333 mcd_answer->mutable_streams().clear();
334 auto& receive_layers = mcd_answer->simulcast_description().receive_layers();
335 for (const SimulcastLayer& layer : server_layers) {
336 receive_layers.AddLayer(layer);
337 }
338 EXPECT_TRUE(local->SetRemoteDescription(std::move(answer), &error)) << error;
339 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, server_layers));
340}
341
342// Checks that when Simulcast is not supported by the remote party, then all
Amit Hilbuch2297d332019-02-19 12:49:22 -0800343// the layers (except the first) are removed.
344TEST_F(PeerConnectionSimulcastTests, SimulcastRejectedRemovesExtraLayers) {
Amit Hilbuchaa584152019-02-06 17:09:52 -0800345 auto local = CreatePeerConnectionWrapper();
346 auto remote = CreatePeerConnectionWrapper();
347 auto layers = CreateLayers({"1", "2", "3", "4"}, true);
Amit Hilbuchaa584152019-02-06 17:09:52 -0800348 auto transceiver = AddTransceiver(local.get(), layers);
Amit Hilbuch619b2942019-02-26 15:55:19 -0800349 ExchangeOfferAnswer(local.get(), remote.get(), {});
Amit Hilbuch2297d332019-02-19 12:49:22 -0800350 auto parameters = transceiver->sender()->GetParameters();
351 // Should only have the first layer.
352 EXPECT_THAT(parameters.encodings,
353 ElementsAre(Field("rid", &RtpEncodingParameters::rid, Eq("1"))));
Amit Hilbuchaa584152019-02-06 17:09:52 -0800354}
355
Amit Hilbuch2297d332019-02-19 12:49:22 -0800356// Checks that if Simulcast is supported by remote party, but some layers are
357// rejected, then only rejected layers are removed from the sender.
Amit Hilbuchaa584152019-02-06 17:09:52 -0800358TEST_F(PeerConnectionSimulcastTests, RejectedSimulcastLayersAreDeactivated) {
359 auto local = CreatePeerConnectionWrapper();
360 auto remote = CreatePeerConnectionWrapper();
361 auto layers = CreateLayers({"1", "2", "3", "4"}, true);
Amit Hilbuch2297d332019-02-19 12:49:22 -0800362 auto expected_layers = CreateLayers({"2", "3", "4"}, true);
Amit Hilbuchaa584152019-02-06 17:09:52 -0800363 auto transceiver = AddTransceiver(local.get(), layers);
364 auto offer = local->CreateOfferAndSetAsLocal();
365 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
366 // Remove simulcast as the second peer connection won't support it.
367 auto removed_simulcast = RemoveSimulcast(offer.get());
368 std::string error;
369 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &error)) << error;
370 auto answer = remote->CreateAnswerAndSetAsLocal();
371 auto mcd_answer = answer->description()->contents()[0].media_description();
372 // Setup the answer to look like a server response.
373 // Remove one of the layers to reject it in the answer.
374 auto simulcast_layers = removed_simulcast.send_layers().GetAllLayers();
375 simulcast_layers.erase(simulcast_layers.begin());
376 auto& receive_layers = mcd_answer->simulcast_description().receive_layers();
377 for (const auto& layer : simulcast_layers) {
378 receive_layers.AddLayer(layer);
379 }
380 ASSERT_TRUE(mcd_answer->HasSimulcast());
381 EXPECT_TRUE(local->SetRemoteDescription(std::move(answer), &error)) << error;
Amit Hilbuch2297d332019-02-19 12:49:22 -0800382 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, expected_layers));
Amit Hilbuchaa584152019-02-06 17:09:52 -0800383}
384
385// Checks that simulcast is set up correctly when the server sends an offer
386// requesting to receive simulcast.
387TEST_F(PeerConnectionSimulcastTests, ServerSendsOfferToReceiveSimulcast) {
388 auto local = CreatePeerConnectionWrapper();
389 auto remote = CreatePeerConnectionWrapper();
390 auto layers = CreateLayers({"f", "h", "q"}, true);
391 AddTransceiver(local.get(), layers);
392 auto offer = local->CreateOfferAndSetAsLocal();
393 // Remove simulcast as a sender and set it up as a receiver.
394 RemoveSimulcast(offer.get());
395 AddRequestToReceiveSimulcast(layers, offer.get());
396 std::string error;
397 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &error)) << error;
398 auto transceiver = remote->pc()->GetTransceivers()[0];
399 transceiver->SetDirection(RtpTransceiverDirection::kSendRecv);
400 EXPECT_TRUE(remote->CreateAnswerAndSetAsLocal());
401 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
402}
403
404// Checks that SetRemoteDescription doesn't attempt to associate a transceiver
405// when simulcast is requested by the server.
406TEST_F(PeerConnectionSimulcastTests, TransceiverIsNotRecycledWithSimulcast) {
407 auto local = CreatePeerConnectionWrapper();
408 auto remote = CreatePeerConnectionWrapper();
409 auto layers = CreateLayers({"f", "h", "q"}, true);
410 AddTransceiver(local.get(), layers);
411 auto offer = local->CreateOfferAndSetAsLocal();
412 // Remove simulcast as a sender and set it up as a receiver.
413 RemoveSimulcast(offer.get());
414 AddRequestToReceiveSimulcast(layers, offer.get());
415 // Call AddTrack so that a transceiver is created.
416 remote->AddVideoTrack("fake_track");
417 std::string error;
418 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &error)) << error;
419 auto transceivers = remote->pc()->GetTransceivers();
420 ASSERT_EQ(2u, transceivers.size());
421 auto transceiver = transceivers[1];
422 transceiver->SetDirection(RtpTransceiverDirection::kSendRecv);
423 EXPECT_TRUE(remote->CreateAnswerAndSetAsLocal());
424 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, layers));
425}
426
Amit Hilbuch619b2942019-02-26 15:55:19 -0800427// Checks that if the number of layers changes during negotiation, then any
428// outstanding get/set parameters transaction is invalidated.
429TEST_F(PeerConnectionSimulcastTests, ParametersAreInvalidatedWhenLayersChange) {
430 auto local = CreatePeerConnectionWrapper();
431 auto remote = CreatePeerConnectionWrapper();
432 auto layers = CreateLayers({"1", "2", "3"}, true);
433 auto transceiver = AddTransceiver(local.get(), layers);
434 auto parameters = transceiver->sender()->GetParameters();
435 ASSERT_EQ(3u, parameters.encodings.size());
436 // Response will reject simulcast altogether.
437 ExchangeOfferAnswer(local.get(), remote.get(), {});
438 auto result = transceiver->sender()->SetParameters(parameters);
439 EXPECT_EQ(RTCErrorType::INVALID_STATE, result.type());
440}
441
442// Checks that even though negotiation modifies the sender's parameters, an
443// outstanding get/set parameters transaction is not invalidated.
444// This test negotiates twice because initial parameters before negotiation
445// is missing critical information and cannot be set on the sender.
446TEST_F(PeerConnectionSimulcastTests,
447 NegotiationDoesNotInvalidateParameterTransactions) {
448 auto local = CreatePeerConnectionWrapper();
449 auto remote = CreatePeerConnectionWrapper();
450 auto layers = CreateLayers({"1", "2", "3"}, true);
451 auto expected_layers = CreateLayers({"1", "2", "3"}, false);
452 auto transceiver = AddTransceiver(local.get(), layers);
453 ExchangeOfferAnswer(local.get(), remote.get(), expected_layers);
454
455 // Verify that negotiation does not invalidate the parameters.
456 auto parameters = transceiver->sender()->GetParameters();
457 ExchangeOfferAnswer(local.get(), remote.get(), expected_layers);
458
459 auto result = transceiver->sender()->SetParameters(parameters);
460 EXPECT_TRUE(result.ok());
461 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, expected_layers));
462}
463
Amit Hilbuchaabd0362019-03-01 13:14:46 -0800464TEST_F(PeerConnectionSimulcastTests, NegotiationDoesNotHaveRidExtension) {
465 auto local = CreatePeerConnectionWrapper();
466 auto remote = CreatePeerConnectionWrapper();
467 auto layers = CreateLayers({"1", "2", "3"}, true);
468 auto expected_layers = CreateLayers({"1"}, true);
469 auto transceiver = AddTransceiver(local.get(), layers);
470 auto offer = local->CreateOfferAndSetAsLocal();
471 // Remove simulcast as the second peer connection won't support it.
472 RemoveSimulcast(offer.get());
473 std::string err;
474 EXPECT_TRUE(remote->SetRemoteDescription(std::move(offer), &err)) << err;
475 auto answer = remote->CreateAnswerAndSetAsLocal();
476 // Setup the answer to look like a server response.
477 // Drop the RID header extension.
478 auto mcd_answer = answer->description()->contents()[0].media_description();
479 auto& receive_layers = mcd_answer->simulcast_description().receive_layers();
480 for (const SimulcastLayer& layer : layers) {
481 receive_layers.AddLayer(layer);
482 }
483 cricket::RtpHeaderExtensions extensions;
484 for (auto extension : mcd_answer->rtp_header_extensions()) {
485 if (extension.uri != RtpExtension::kRidUri) {
486 extensions.push_back(extension);
487 }
488 }
489 mcd_answer->set_rtp_header_extensions(extensions);
490 EXPECT_EQ(layers.size(), mcd_answer->simulcast_description()
491 .receive_layers()
492 .GetAllLayers()
493 .size());
494 EXPECT_TRUE(local->SetRemoteDescription(std::move(answer), &err)) << err;
495 EXPECT_TRUE(ValidateTransceiverParameters(transceiver, expected_layers));
496}
497
Amit Hilbuchaa584152019-02-06 17:09:52 -0800498} // namespace webrtc