blob: a9803347e695e94c338cfcd0b468d0e7767ff3bb [file] [log] [blame]
Steve Anton8d3444d2017-10-20 15:30:51 -07001/*
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
11// This file contains tests that check the interaction between the
12// PeerConnection and the underlying media engine, as well as tests that check
13// the media-related aspects of SDP.
14
15#include <tuple>
16
Steve Anton64b626b2019-01-28 17:25:26 -080017#include "absl/algorithm/container.h"
Mirta Dvornicic479a3c02019-06-04 15:38:50 +020018#include "absl/types/optional.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "api/call/call_factory_interface.h"
Danil Chapovalov9da25bd2019-06-20 10:19:42 +020020#include "api/rtc_event_log/rtc_event_log_factory.h"
21#include "api/task_queue/default_task_queue_factory.h"
Anton Sukhanov98a462c2018-10-17 13:15:42 -070022#include "api/test/fake_media_transport.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "media/base/fake_media_engine.h"
24#include "p2p/base/fake_port_allocator.h"
25#include "pc/media_session.h"
26#include "pc/peer_connection_wrapper.h"
27#include "pc/rtp_media_utils.h"
28#include "pc/sdp_utils.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070029#ifdef WEBRTC_ANDROID
Steve Anton10542f22019-01-11 09:11:00 -080030#include "pc/test/android_test_initializer.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070031#endif
Karl Wiberg918f50c2018-07-05 11:40:33 +020032#include "absl/memory/memory.h"
Steve Anton10542f22019-01-11 09:11:00 -080033#include "pc/test/fake_rtc_certificate_generator.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070034#include "rtc_base/gunit.h"
Steve Anton10542f22019-01-11 09:11:00 -080035#include "rtc_base/virtual_socket_server.h"
Steve Anton8d3444d2017-10-20 15:30:51 -070036#include "test/gmock.h"
37
38namespace webrtc {
39
40using cricket::FakeMediaEngine;
41using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
42using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
43using ::testing::Bool;
44using ::testing::Combine;
Steve Anton8d3444d2017-10-20 15:30:51 -070045using ::testing::ElementsAre;
Jonas Olssona4d87372019-07-05 19:08:33 +020046using ::testing::Values;
Steve Anton8d3444d2017-10-20 15:30:51 -070047
48class PeerConnectionWrapperForMediaTest : public PeerConnectionWrapper {
49 public:
50 using PeerConnectionWrapper::PeerConnectionWrapper;
51
52 FakeMediaEngine* media_engine() { return media_engine_; }
53 void set_media_engine(FakeMediaEngine* media_engine) {
54 media_engine_ = media_engine;
55 }
56
57 private:
58 FakeMediaEngine* media_engine_;
59};
60
Steve Antonad7bffc2018-01-22 10:21:56 -080061class PeerConnectionMediaBaseTest : public ::testing::Test {
Steve Anton8d3444d2017-10-20 15:30:51 -070062 protected:
63 typedef std::unique_ptr<PeerConnectionWrapperForMediaTest> WrapperPtr;
64
Steve Antonad7bffc2018-01-22 10:21:56 -080065 explicit PeerConnectionMediaBaseTest(SdpSemantics sdp_semantics)
66 : vss_(new rtc::VirtualSocketServer()),
67 main_(vss_.get()),
68 sdp_semantics_(sdp_semantics) {
Steve Anton8d3444d2017-10-20 15:30:51 -070069#ifdef WEBRTC_ANDROID
70 InitializeAndroidObjects();
71#endif
72 }
73
74 WrapperPtr CreatePeerConnection() {
75 return CreatePeerConnection(RTCConfiguration());
76 }
77
Florent Castelli2d9d82e2019-04-23 19:25:51 +020078 WrapperPtr CreatePeerConnection(const RTCConfiguration& config) {
79 return CreatePeerConnection(config, absl::make_unique<FakeMediaEngine>());
80 }
81
82 WrapperPtr CreatePeerConnection(
83 std::unique_ptr<FakeMediaEngine> media_engine) {
84 return CreatePeerConnection(RTCConfiguration(), std::move(media_engine));
85 }
86
Anton Sukhanov98a462c2018-10-17 13:15:42 -070087 // Creates PeerConnectionFactory and PeerConnection for given configuration.
88 // Note that PeerConnectionFactory is created with MediaTransportFactory,
89 // because some tests pass config.use_media_transport = true.
Florent Castelli2d9d82e2019-04-23 19:25:51 +020090 WrapperPtr CreatePeerConnection(
91 const RTCConfiguration& config,
92 std::unique_ptr<FakeMediaEngine> media_engine) {
Steve Anton8d3444d2017-10-20 15:30:51 -070093 auto* media_engine_ptr = media_engine.get();
Anton Sukhanov98a462c2018-10-17 13:15:42 -070094
95 PeerConnectionFactoryDependencies factory_dependencies;
96
97 factory_dependencies.network_thread = rtc::Thread::Current();
98 factory_dependencies.worker_thread = rtc::Thread::Current();
99 factory_dependencies.signaling_thread = rtc::Thread::Current();
Danil Chapovalov9da25bd2019-06-20 10:19:42 +0200100 factory_dependencies.task_queue_factory = CreateDefaultTaskQueueFactory();
Anton Sukhanov98a462c2018-10-17 13:15:42 -0700101 factory_dependencies.media_engine = std::move(media_engine);
102 factory_dependencies.call_factory = CreateCallFactory();
Danil Chapovalov9da25bd2019-06-20 10:19:42 +0200103 factory_dependencies.event_log_factory =
104 absl::make_unique<RtcEventLogFactory>(
105 factory_dependencies.task_queue_factory.get());
Anton Sukhanov98a462c2018-10-17 13:15:42 -0700106 factory_dependencies.media_transport_factory =
107 absl::make_unique<FakeMediaTransportFactory>();
108
109 auto pc_factory =
110 CreateModularPeerConnectionFactory(std::move(factory_dependencies));
Steve Anton8d3444d2017-10-20 15:30:51 -0700111
Karl Wiberg918f50c2018-07-05 11:40:33 +0200112 auto fake_port_allocator = absl::make_unique<cricket::FakePortAllocator>(
Steve Anton8d3444d2017-10-20 15:30:51 -0700113 rtc::Thread::Current(), nullptr);
Karl Wiberg918f50c2018-07-05 11:40:33 +0200114 auto observer = absl::make_unique<MockPeerConnectionObserver>();
Steve Antonad7bffc2018-01-22 10:21:56 -0800115 auto modified_config = config;
116 modified_config.sdp_semantics = sdp_semantics_;
117 auto pc = pc_factory->CreatePeerConnection(modified_config,
118 std::move(fake_port_allocator),
119 nullptr, observer.get());
Steve Anton8d3444d2017-10-20 15:30:51 -0700120 if (!pc) {
121 return nullptr;
122 }
123
Yves Gerey4e933292018-10-31 15:36:05 +0100124 observer->SetPeerConnectionInterface(pc.get());
Karl Wiberg918f50c2018-07-05 11:40:33 +0200125 auto wrapper = absl::make_unique<PeerConnectionWrapperForMediaTest>(
Steve Anton8d3444d2017-10-20 15:30:51 -0700126 pc_factory, pc, std::move(observer));
127 wrapper->set_media_engine(media_engine_ptr);
128 return wrapper;
129 }
130
131 // Accepts the same arguments as CreatePeerConnection and adds default audio
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -0800132 // track (but no video).
133 template <typename... Args>
134 WrapperPtr CreatePeerConnectionWithAudio(Args&&... args) {
135 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
136 if (!wrapper) {
137 return nullptr;
138 }
139 wrapper->AddAudioTrack("a");
140 return wrapper;
141 }
142
Florent Castelli2d9d82e2019-04-23 19:25:51 +0200143 // Accepts the same arguments as CreatePeerConnection and adds default video
144 // track (but no audio).
145 template <typename... Args>
146 WrapperPtr CreatePeerConnectionWithVideo(Args&&... args) {
147 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
148 if (!wrapper) {
149 return nullptr;
150 }
151 wrapper->AddVideoTrack("v");
152 return wrapper;
153 }
154
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -0800155 // Accepts the same arguments as CreatePeerConnection and adds default audio
Steve Anton8d3444d2017-10-20 15:30:51 -0700156 // and video tracks.
157 template <typename... Args>
158 WrapperPtr CreatePeerConnectionWithAudioVideo(Args&&... args) {
159 auto wrapper = CreatePeerConnection(std::forward<Args>(args)...);
160 if (!wrapper) {
161 return nullptr;
162 }
163 wrapper->AddAudioTrack("a");
164 wrapper->AddVideoTrack("v");
165 return wrapper;
166 }
167
Steve Anton4e70a722017-11-28 14:57:10 -0800168 RtpTransceiverDirection GetMediaContentDirection(
Steve Anton8d3444d2017-10-20 15:30:51 -0700169 const SessionDescriptionInterface* sdesc,
Steve Antonad7bffc2018-01-22 10:21:56 -0800170 cricket::MediaType media_type) {
171 auto* content =
172 cricket::GetFirstMediaContent(sdesc->description(), media_type);
173 RTC_DCHECK(content);
174 return content->media_description()->direction();
175 }
176
177 bool IsUnifiedPlan() const {
178 return sdp_semantics_ == SdpSemantics::kUnifiedPlan;
Steve Anton8d3444d2017-10-20 15:30:51 -0700179 }
180
181 std::unique_ptr<rtc::VirtualSocketServer> vss_;
182 rtc::AutoSocketServerThread main_;
Steve Antonad7bffc2018-01-22 10:21:56 -0800183 const SdpSemantics sdp_semantics_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700184};
185
Steve Antonad7bffc2018-01-22 10:21:56 -0800186class PeerConnectionMediaTest
187 : public PeerConnectionMediaBaseTest,
188 public ::testing::WithParamInterface<SdpSemantics> {
189 protected:
190 PeerConnectionMediaTest() : PeerConnectionMediaBaseTest(GetParam()) {}
191};
192
193class PeerConnectionMediaTestUnifiedPlan : public PeerConnectionMediaBaseTest {
194 protected:
195 PeerConnectionMediaTestUnifiedPlan()
196 : PeerConnectionMediaBaseTest(SdpSemantics::kUnifiedPlan) {}
197};
198
199class PeerConnectionMediaTestPlanB : public PeerConnectionMediaBaseTest {
200 protected:
201 PeerConnectionMediaTestPlanB()
202 : PeerConnectionMediaBaseTest(SdpSemantics::kPlanB) {}
203};
204
205TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700206 FailToSetRemoteDescriptionIfCreateMediaChannelFails) {
207 auto caller = CreatePeerConnectionWithAudioVideo();
208 auto callee = CreatePeerConnectionWithAudioVideo();
209 callee->media_engine()->set_fail_create_channel(true);
210
211 std::string error;
212 ASSERT_FALSE(callee->SetRemoteDescription(caller->CreateOffer(), &error));
Steve Antonad7bffc2018-01-22 10:21:56 -0800213 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
214 "Failed to set remote offer sdp: Failed to create");
Steve Anton8d3444d2017-10-20 15:30:51 -0700215}
216
Steve Antonad7bffc2018-01-22 10:21:56 -0800217TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700218 FailToSetLocalDescriptionIfCreateMediaChannelFails) {
219 auto caller = CreatePeerConnectionWithAudioVideo();
220 caller->media_engine()->set_fail_create_channel(true);
221
222 std::string error;
223 ASSERT_FALSE(caller->SetLocalDescription(caller->CreateOffer(), &error));
Steve Antonad7bffc2018-01-22 10:21:56 -0800224 EXPECT_PRED_FORMAT2(AssertStartsWith, error,
225 "Failed to set local offer sdp: Failed to create");
Steve Anton8d3444d2017-10-20 15:30:51 -0700226}
227
228std::vector<std::string> GetIds(
229 const std::vector<cricket::StreamParams>& streams) {
230 std::vector<std::string> ids;
Mirko Bonadei649a4c22019-01-29 10:11:53 +0100231 ids.reserve(streams.size());
Steve Anton8d3444d2017-10-20 15:30:51 -0700232 for (const auto& stream : streams) {
233 ids.push_back(stream.id);
234 }
235 return ids;
236}
237
238// Test that exchanging an offer and answer with each side having an audio and
239// video stream creates the appropriate send/recv streams in the underlying
240// media engine on both sides.
Steve Antonad7bffc2018-01-22 10:21:56 -0800241TEST_P(PeerConnectionMediaTest, AudioVideoOfferAnswerCreateSendRecvStreams) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700242 const std::string kCallerAudioId = "caller_a";
243 const std::string kCallerVideoId = "caller_v";
244 const std::string kCalleeAudioId = "callee_a";
245 const std::string kCalleeVideoId = "callee_v";
246
247 auto caller = CreatePeerConnection();
248 caller->AddAudioTrack(kCallerAudioId);
249 caller->AddVideoTrack(kCallerVideoId);
250
251 auto callee = CreatePeerConnection();
252 callee->AddAudioTrack(kCalleeAudioId);
253 callee->AddVideoTrack(kCalleeVideoId);
254
255 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
256 ASSERT_TRUE(
257 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
258
259 auto* caller_voice = caller->media_engine()->GetVoiceChannel(0);
260 EXPECT_THAT(GetIds(caller_voice->recv_streams()),
261 ElementsAre(kCalleeAudioId));
262 EXPECT_THAT(GetIds(caller_voice->send_streams()),
263 ElementsAre(kCallerAudioId));
264
265 auto* caller_video = caller->media_engine()->GetVideoChannel(0);
266 EXPECT_THAT(GetIds(caller_video->recv_streams()),
267 ElementsAre(kCalleeVideoId));
268 EXPECT_THAT(GetIds(caller_video->send_streams()),
269 ElementsAre(kCallerVideoId));
270
271 auto* callee_voice = callee->media_engine()->GetVoiceChannel(0);
272 EXPECT_THAT(GetIds(callee_voice->recv_streams()),
273 ElementsAre(kCallerAudioId));
274 EXPECT_THAT(GetIds(callee_voice->send_streams()),
275 ElementsAre(kCalleeAudioId));
276
277 auto* callee_video = callee->media_engine()->GetVideoChannel(0);
278 EXPECT_THAT(GetIds(callee_video->recv_streams()),
279 ElementsAre(kCallerVideoId));
280 EXPECT_THAT(GetIds(callee_video->send_streams()),
281 ElementsAre(kCalleeVideoId));
282}
283
Steve Antonad7bffc2018-01-22 10:21:56 -0800284// Test that stopping the caller transceivers causes the media channels on the
285// callee to be destroyed after calling SetRemoteDescription on the generated
286// offer.
287// See next test for equivalent behavior with Plan B semantics.
288TEST_F(PeerConnectionMediaTestUnifiedPlan,
289 StoppedRemoteTransceiversRemovesMediaChannels) {
290 auto caller = CreatePeerConnectionWithAudioVideo();
291 auto callee = CreatePeerConnection();
292
293 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
294
295 // Stop both audio and video transceivers on the caller.
296 auto transceivers = caller->pc()->GetTransceivers();
297 ASSERT_EQ(2u, transceivers.size());
298 transceivers[0]->Stop();
299 transceivers[1]->Stop();
300
301 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
302
303 ASSERT_FALSE(callee->media_engine()->GetVoiceChannel(0));
304 ASSERT_FALSE(callee->media_engine()->GetVideoChannel(0));
305}
306
Steve Anton8d3444d2017-10-20 15:30:51 -0700307// Test that removing streams from a subsequent offer causes the receive streams
308// on the callee to be removed.
Steve Antonad7bffc2018-01-22 10:21:56 -0800309// See previous test for equivalent behavior with Unified Plan semantics.
310TEST_F(PeerConnectionMediaTestPlanB, EmptyRemoteOfferRemovesRecvStreams) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700311 auto caller = CreatePeerConnection();
312 auto caller_audio_track = caller->AddAudioTrack("a");
313 auto caller_video_track = caller->AddVideoTrack("v");
314 auto callee = CreatePeerConnectionWithAudioVideo();
315
Steve Antonad7bffc2018-01-22 10:21:56 -0800316 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700317
318 // Remove both tracks from caller.
319 caller->pc()->RemoveTrack(caller_audio_track);
320 caller->pc()->RemoveTrack(caller_video_track);
321
Steve Antonad7bffc2018-01-22 10:21:56 -0800322 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700323
324 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
Steve Antonad7bffc2018-01-22 10:21:56 -0800325 auto callee_video = callee->media_engine()->GetVideoChannel(0);
Steve Anton8d3444d2017-10-20 15:30:51 -0700326 EXPECT_EQ(1u, callee_voice->send_streams().size());
327 EXPECT_EQ(0u, callee_voice->recv_streams().size());
Steve Anton8d3444d2017-10-20 15:30:51 -0700328 EXPECT_EQ(1u, callee_video->send_streams().size());
329 EXPECT_EQ(0u, callee_video->recv_streams().size());
330}
331
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200332// Test enabling of simulcast with Plan B semantics.
333// This test creating an offer.
334TEST_F(PeerConnectionMediaTestPlanB, SimulcastOffer) {
335 auto caller = CreatePeerConnection();
336 auto caller_video_track = caller->AddVideoTrack("v");
337 RTCOfferAnswerOptions options;
338 options.num_simulcast_layers = 3;
339 auto offer = caller->CreateOffer(options);
Jonas Olssona4d87372019-07-05 19:08:33 +0200340 auto* description = cricket::GetFirstMediaContent(offer->description(),
341 cricket::MEDIA_TYPE_VIDEO)
342 ->media_description();
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200343 ASSERT_EQ(1u, description->streams().size());
344 ASSERT_TRUE(description->streams()[0].get_ssrc_group("SIM"));
345 EXPECT_EQ(3u, description->streams()[0].get_ssrc_group("SIM")->ssrcs.size());
346
347 // Check that it actually creates simulcast aswell.
348 caller->SetLocalDescription(std::move(offer));
349 auto senders = caller->pc()->GetSenders();
350 ASSERT_EQ(1u, senders.size());
351 EXPECT_EQ(cricket::MediaType::MEDIA_TYPE_VIDEO, senders[0]->media_type());
352 EXPECT_EQ(3u, senders[0]->GetParameters().encodings.size());
353}
354
355// Test enabling of simulcast with Plan B semantics.
356// This test creating an answer.
357TEST_F(PeerConnectionMediaTestPlanB, SimulcastAnswer) {
358 auto caller = CreatePeerConnection();
359 caller->AddVideoTrack("v0");
360 auto offer = caller->CreateOffer();
361 auto callee = CreatePeerConnection();
362 auto callee_video_track = callee->AddVideoTrack("v1");
363 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
364 RTCOfferAnswerOptions options;
365 options.num_simulcast_layers = 3;
366 auto answer = callee->CreateAnswer(options);
Jonas Olssona4d87372019-07-05 19:08:33 +0200367 auto* description = cricket::GetFirstMediaContent(answer->description(),
368 cricket::MEDIA_TYPE_VIDEO)
369 ->media_description();
Jonas Orelandfc1acd22018-08-24 10:58:37 +0200370 ASSERT_EQ(1u, description->streams().size());
371 ASSERT_TRUE(description->streams()[0].get_ssrc_group("SIM"));
372 EXPECT_EQ(3u, description->streams()[0].get_ssrc_group("SIM")->ssrcs.size());
373
374 // Check that it actually creates simulcast aswell.
375 callee->SetLocalDescription(std::move(answer));
376 auto senders = callee->pc()->GetSenders();
377 ASSERT_EQ(1u, senders.size());
378 EXPECT_EQ(cricket::MediaType::MEDIA_TYPE_VIDEO, senders[0]->media_type());
379 EXPECT_EQ(3u, senders[0]->GetParameters().encodings.size());
380}
381
Steve Antonad7bffc2018-01-22 10:21:56 -0800382// Test that stopping the callee transceivers causes the media channels to be
383// destroyed on the callee after calling SetLocalDescription on the local
384// answer.
385// See next test for equivalent behavior with Plan B semantics.
386TEST_F(PeerConnectionMediaTestUnifiedPlan,
387 StoppedLocalTransceiversRemovesMediaChannels) {
388 auto caller = CreatePeerConnectionWithAudioVideo();
389 auto callee = CreatePeerConnectionWithAudioVideo();
390
391 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
392
393 // Stop both audio and video transceivers on the callee.
394 auto transceivers = callee->pc()->GetTransceivers();
395 ASSERT_EQ(2u, transceivers.size());
396 transceivers[0]->Stop();
397 transceivers[1]->Stop();
398
399 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
400
401 EXPECT_FALSE(callee->media_engine()->GetVoiceChannel(0));
402 EXPECT_FALSE(callee->media_engine()->GetVideoChannel(0));
403}
404
Steve Anton8d3444d2017-10-20 15:30:51 -0700405// Test that removing streams from a subsequent answer causes the send streams
406// on the callee to be removed when applied locally.
Steve Antonad7bffc2018-01-22 10:21:56 -0800407// See previous test for equivalent behavior with Unified Plan semantics.
408TEST_F(PeerConnectionMediaTestPlanB, EmptyLocalAnswerRemovesSendStreams) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700409 auto caller = CreatePeerConnectionWithAudioVideo();
410 auto callee = CreatePeerConnection();
411 auto callee_audio_track = callee->AddAudioTrack("a");
412 auto callee_video_track = callee->AddVideoTrack("v");
413
Steve Antonad7bffc2018-01-22 10:21:56 -0800414 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700415
416 // Remove both tracks from callee.
417 callee->pc()->RemoveTrack(callee_audio_track);
418 callee->pc()->RemoveTrack(callee_video_track);
419
Steve Antonad7bffc2018-01-22 10:21:56 -0800420 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700421
422 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
Steve Antonad7bffc2018-01-22 10:21:56 -0800423 auto callee_video = callee->media_engine()->GetVideoChannel(0);
Steve Anton8d3444d2017-10-20 15:30:51 -0700424 EXPECT_EQ(0u, callee_voice->send_streams().size());
425 EXPECT_EQ(1u, callee_voice->recv_streams().size());
Steve Anton8d3444d2017-10-20 15:30:51 -0700426 EXPECT_EQ(0u, callee_video->send_streams().size());
427 EXPECT_EQ(1u, callee_video->recv_streams().size());
428}
429
430// Test that a new stream in a subsequent offer causes a new receive stream to
431// be created on the callee.
Steve Antonad7bffc2018-01-22 10:21:56 -0800432TEST_P(PeerConnectionMediaTest, NewStreamInRemoteOfferAddsRecvStreams) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700433 auto caller = CreatePeerConnectionWithAudioVideo();
434 auto callee = CreatePeerConnection();
435
Steve Antonad7bffc2018-01-22 10:21:56 -0800436 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700437
438 // Add second set of tracks to the caller.
439 caller->AddAudioTrack("a2");
440 caller->AddVideoTrack("v2");
441
Steve Antonad7bffc2018-01-22 10:21:56 -0800442 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get()));
Steve Anton8d3444d2017-10-20 15:30:51 -0700443
Steve Antonad7bffc2018-01-22 10:21:56 -0800444 auto a1 = callee->media_engine()->GetVoiceChannel(0);
445 auto a2 = callee->media_engine()->GetVoiceChannel(1);
446 auto v1 = callee->media_engine()->GetVideoChannel(0);
447 auto v2 = callee->media_engine()->GetVideoChannel(1);
448 if (IsUnifiedPlan()) {
449 ASSERT_TRUE(a1);
450 EXPECT_EQ(1u, a1->recv_streams().size());
451 ASSERT_TRUE(a2);
452 EXPECT_EQ(1u, a2->recv_streams().size());
453 ASSERT_TRUE(v1);
454 EXPECT_EQ(1u, v1->recv_streams().size());
455 ASSERT_TRUE(v2);
456 EXPECT_EQ(1u, v2->recv_streams().size());
457 } else {
458 ASSERT_TRUE(a1);
459 EXPECT_EQ(2u, a1->recv_streams().size());
460 ASSERT_FALSE(a2);
461 ASSERT_TRUE(v1);
462 EXPECT_EQ(2u, v1->recv_streams().size());
463 ASSERT_FALSE(v2);
464 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700465}
466
467// Test that a new stream in a subsequent answer causes a new send stream to be
468// created on the callee when added locally.
Steve Antonad7bffc2018-01-22 10:21:56 -0800469TEST_P(PeerConnectionMediaTest, NewStreamInLocalAnswerAddsSendStreams) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700470 auto caller = CreatePeerConnection();
471 auto callee = CreatePeerConnectionWithAudioVideo();
472
Steve Anton22da89f2018-01-25 13:58:07 -0800473 RTCOfferAnswerOptions offer_options;
474 offer_options.offer_to_receive_audio =
Steve Anton8d3444d2017-10-20 15:30:51 -0700475 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
Steve Anton22da89f2018-01-25 13:58:07 -0800476 offer_options.offer_to_receive_video =
Steve Anton8d3444d2017-10-20 15:30:51 -0700477 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
Steve Anton22da89f2018-01-25 13:58:07 -0800478 RTCOfferAnswerOptions answer_options;
Steve Anton8d3444d2017-10-20 15:30:51 -0700479
Steve Anton22da89f2018-01-25 13:58:07 -0800480 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get(), offer_options,
481 answer_options));
Steve Anton8d3444d2017-10-20 15:30:51 -0700482
483 // Add second set of tracks to the callee.
484 callee->AddAudioTrack("a2");
485 callee->AddVideoTrack("v2");
486
Steve Anton22da89f2018-01-25 13:58:07 -0800487 ASSERT_TRUE(caller->ExchangeOfferAnswerWith(callee.get(), offer_options,
488 answer_options));
Steve Anton8d3444d2017-10-20 15:30:51 -0700489
490 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
Steve Anton22da89f2018-01-25 13:58:07 -0800491 ASSERT_TRUE(callee_voice);
Steve Anton8d3444d2017-10-20 15:30:51 -0700492 auto callee_video = callee->media_engine()->GetVideoChannel(0);
Steve Anton22da89f2018-01-25 13:58:07 -0800493 ASSERT_TRUE(callee_video);
494
495 if (IsUnifiedPlan()) {
496 EXPECT_EQ(1u, callee_voice->send_streams().size());
497 EXPECT_EQ(1u, callee_video->send_streams().size());
498 } else {
499 EXPECT_EQ(2u, callee_voice->send_streams().size());
500 EXPECT_EQ(2u, callee_video->send_streams().size());
501 }
Steve Anton8d3444d2017-10-20 15:30:51 -0700502}
503
504// A PeerConnection with no local streams and no explicit answer constraints
505// should not reject any offered media sections.
Steve Antonad7bffc2018-01-22 10:21:56 -0800506TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700507 CreateAnswerWithNoStreamsAndDefaultOptionsDoesNotReject) {
508 auto caller = CreatePeerConnectionWithAudioVideo();
509 auto callee = CreatePeerConnection();
510 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
511 auto answer = callee->CreateAnswer();
512
513 const auto* audio_content =
514 cricket::GetFirstAudioContent(answer->description());
515 ASSERT_TRUE(audio_content);
516 EXPECT_FALSE(audio_content->rejected);
517
518 const auto* video_content =
519 cricket::GetFirstVideoContent(answer->description());
520 ASSERT_TRUE(video_content);
521 EXPECT_FALSE(video_content->rejected);
522}
523
Mirta Dvornicic479a3c02019-06-04 15:38:50 +0200524// Test that raw packetization is not set in the offer by default.
525TEST_P(PeerConnectionMediaTest, RawPacketizationNotSetInOffer) {
526 std::vector<cricket::VideoCodec> fake_codecs;
527 fake_codecs.push_back(cricket::VideoCodec(111, cricket::kVp8CodecName));
528 fake_codecs.push_back(cricket::VideoCodec(112, cricket::kRtxCodecName));
529 fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
530 fake_codecs.push_back(cricket::VideoCodec(113, cricket::kVp9CodecName));
531 fake_codecs.push_back(cricket::VideoCodec(114, cricket::kH264CodecName));
532 fake_codecs.push_back(cricket::VideoCodec(115, "HEVC"));
533 auto caller_fake_engine = absl::make_unique<FakeMediaEngine>();
534 caller_fake_engine->SetVideoCodecs(fake_codecs);
535
536 auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
537 auto offer = caller->CreateOfferAndSetAsLocal();
538 auto* offer_description =
539 cricket::GetFirstVideoContentDescription(offer->description());
540 for (const auto& codec : offer_description->codecs()) {
541 EXPECT_EQ(codec.packetization, absl::nullopt);
542 }
543}
544
545// Test that raw packetization is set in the offer and answer for all
546// video payload when raw_packetization_for_video is true.
547TEST_P(PeerConnectionMediaTest, RawPacketizationSetInOfferAndAnswer) {
548 std::vector<cricket::VideoCodec> fake_codecs;
549 fake_codecs.push_back(cricket::VideoCodec(111, cricket::kVp8CodecName));
550 fake_codecs.push_back(cricket::VideoCodec(112, cricket::kRtxCodecName));
551 fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
552 fake_codecs.push_back(cricket::VideoCodec(113, cricket::kVp9CodecName));
553 fake_codecs.push_back(cricket::VideoCodec(114, cricket::kH264CodecName));
554 fake_codecs.push_back(cricket::VideoCodec(115, "HEVC"));
555 auto caller_fake_engine = absl::make_unique<FakeMediaEngine>();
556 caller_fake_engine->SetVideoCodecs(fake_codecs);
557 auto callee_fake_engine = absl::make_unique<FakeMediaEngine>();
558 callee_fake_engine->SetVideoCodecs(fake_codecs);
559
560 RTCOfferAnswerOptions options;
561 options.raw_packetization_for_video = true;
562
563 auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
564 auto offer = caller->CreateOfferAndSetAsLocal(options);
565 auto* offer_description =
566 cricket::GetFirstVideoContentDescription(offer->description());
567 for (const auto& codec : offer_description->codecs()) {
568 if (codec.GetCodecType() == cricket::VideoCodec::CODEC_VIDEO) {
569 EXPECT_EQ(codec.packetization, cricket::kPacketizationParamRaw);
570 }
571 }
572
573 auto callee = CreatePeerConnectionWithVideo(std::move(callee_fake_engine));
574 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
575 auto answer = callee->CreateAnswerAndSetAsLocal(options);
576 auto* answer_description =
577 cricket::GetFirstVideoContentDescription(answer->description());
578 for (const auto& codec : answer_description->codecs()) {
579 if (codec.GetCodecType() == cricket::VideoCodec::CODEC_VIDEO) {
580 EXPECT_EQ(codec.packetization, cricket::kPacketizationParamRaw);
581 }
582 }
583
584 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
585}
586
587// Test that raw packetization is not set in the answer when
588// raw_packetization_for_video is true if it was not set in the offer.
589TEST_P(PeerConnectionMediaTest,
590 RawPacketizationNotSetInAnswerWhenNotSetInOffer) {
591 std::vector<cricket::VideoCodec> fake_codecs;
592 fake_codecs.push_back(cricket::VideoCodec(111, cricket::kVp8CodecName));
593 fake_codecs.push_back(cricket::VideoCodec(112, cricket::kRtxCodecName));
594 fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
595 fake_codecs.push_back(cricket::VideoCodec(113, cricket::kVp9CodecName));
596 fake_codecs.push_back(cricket::VideoCodec(114, cricket::kH264CodecName));
597 fake_codecs.push_back(cricket::VideoCodec(115, "HEVC"));
598 auto caller_fake_engine = absl::make_unique<FakeMediaEngine>();
599 caller_fake_engine->SetVideoCodecs(fake_codecs);
600 auto callee_fake_engine = absl::make_unique<FakeMediaEngine>();
601 callee_fake_engine->SetVideoCodecs(fake_codecs);
602
603 RTCOfferAnswerOptions caller_options;
604 caller_options.raw_packetization_for_video = false;
605 RTCOfferAnswerOptions callee_options;
606 callee_options.raw_packetization_for_video = true;
607
608 auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
609 auto offer = caller->CreateOfferAndSetAsLocal(caller_options);
610
611 auto callee = CreatePeerConnectionWithVideo(std::move(callee_fake_engine));
612 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
613 auto answer = callee->CreateAnswerAndSetAsLocal(callee_options);
614
615 auto* answer_description =
616 cricket::GetFirstVideoContentDescription(answer->description());
617 for (const auto& codec : answer_description->codecs()) {
618 EXPECT_EQ(codec.packetization, absl::nullopt);
619 }
620
621 ASSERT_TRUE(caller->SetRemoteDescription(std::move(answer)));
622}
623
Steve Anton8d3444d2017-10-20 15:30:51 -0700624class PeerConnectionMediaOfferDirectionTest
Steve Antonad7bffc2018-01-22 10:21:56 -0800625 : public PeerConnectionMediaBaseTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700626 public ::testing::WithParamInterface<
Steve Antonad7bffc2018-01-22 10:21:56 -0800627 std::tuple<SdpSemantics,
628 std::tuple<bool, int, RtpTransceiverDirection>>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700629 protected:
Steve Antonad7bffc2018-01-22 10:21:56 -0800630 PeerConnectionMediaOfferDirectionTest()
631 : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) {
632 auto param = std::get<1>(GetParam());
633 send_media_ = std::get<0>(param);
634 offer_to_receive_ = std::get<1>(param);
635 expected_direction_ = std::get<2>(param);
Steve Anton8d3444d2017-10-20 15:30:51 -0700636 }
637
638 bool send_media_;
639 int offer_to_receive_;
Steve Anton4e70a722017-11-28 14:57:10 -0800640 RtpTransceiverDirection expected_direction_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700641};
642
643// Tests that the correct direction is set on the media description according
644// to the presence of a local media track and the offer_to_receive setting.
645TEST_P(PeerConnectionMediaOfferDirectionTest, VerifyDirection) {
646 auto caller = CreatePeerConnection();
647 if (send_media_) {
648 caller->AddAudioTrack("a");
649 }
650
651 RTCOfferAnswerOptions options;
652 options.offer_to_receive_audio = offer_to_receive_;
653 auto offer = caller->CreateOffer(options);
654
Steve Antonad7bffc2018-01-22 10:21:56 -0800655 auto* content = cricket::GetFirstMediaContent(offer->description(),
656 cricket::MEDIA_TYPE_AUDIO);
Steve Anton4e70a722017-11-28 14:57:10 -0800657 if (expected_direction_ == RtpTransceiverDirection::kInactive) {
Steve Antonad7bffc2018-01-22 10:21:56 -0800658 EXPECT_FALSE(content);
Steve Anton8d3444d2017-10-20 15:30:51 -0700659 } else {
Steve Antonad7bffc2018-01-22 10:21:56 -0800660 EXPECT_EQ(expected_direction_, content->media_description()->direction());
Steve Anton8d3444d2017-10-20 15:30:51 -0700661 }
662}
663
664// Note that in these tests, MD_INACTIVE indicates that no media section is
665// included in the offer, not that the media direction is inactive.
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100666INSTANTIATE_TEST_SUITE_P(
Steve Anton4e70a722017-11-28 14:57:10 -0800667 PeerConnectionMediaTest,
668 PeerConnectionMediaOfferDirectionTest,
Steve Antonad7bffc2018-01-22 10:21:56 -0800669 Combine(
670 Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
671 Values(std::make_tuple(false, -1, RtpTransceiverDirection::kInactive),
672 std::make_tuple(false, 0, RtpTransceiverDirection::kInactive),
673 std::make_tuple(false, 1, RtpTransceiverDirection::kRecvOnly),
674 std::make_tuple(true, -1, RtpTransceiverDirection::kSendRecv),
675 std::make_tuple(true, 0, RtpTransceiverDirection::kSendOnly),
676 std::make_tuple(true, 1, RtpTransceiverDirection::kSendRecv))));
Steve Anton8d3444d2017-10-20 15:30:51 -0700677
678class PeerConnectionMediaAnswerDirectionTest
Steve Antonad7bffc2018-01-22 10:21:56 -0800679 : public PeerConnectionMediaBaseTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700680 public ::testing::WithParamInterface<
Steve Antonad7bffc2018-01-22 10:21:56 -0800681 std::tuple<SdpSemantics, RtpTransceiverDirection, bool, int>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700682 protected:
Steve Antonad7bffc2018-01-22 10:21:56 -0800683 PeerConnectionMediaAnswerDirectionTest()
684 : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) {
685 offer_direction_ = std::get<1>(GetParam());
686 send_media_ = std::get<2>(GetParam());
687 offer_to_receive_ = std::get<3>(GetParam());
Steve Anton8d3444d2017-10-20 15:30:51 -0700688 }
689
Steve Anton4e70a722017-11-28 14:57:10 -0800690 RtpTransceiverDirection offer_direction_;
Steve Anton8d3444d2017-10-20 15:30:51 -0700691 bool send_media_;
692 int offer_to_receive_;
693};
694
695// Tests that the direction in an answer is correct according to direction sent
696// in the offer, the presence of a local media track on the receive side and the
697// offer_to_receive setting.
698TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyDirection) {
Steve Anton22da89f2018-01-25 13:58:07 -0800699 if (IsUnifiedPlan() &&
700 offer_to_receive_ != RTCOfferAnswerOptions::kUndefined) {
701 // offer_to_receive_ is not implemented when creating answers with Unified
702 // Plan semantics specified.
Steve Antonad7bffc2018-01-22 10:21:56 -0800703 return;
704 }
Steve Anton22da89f2018-01-25 13:58:07 -0800705
Steve Anton8d3444d2017-10-20 15:30:51 -0700706 auto caller = CreatePeerConnection();
707 caller->AddAudioTrack("a");
708
709 // Create the offer with an audio section and set its direction.
710 auto offer = caller->CreateOffer();
711 cricket::GetFirstAudioContentDescription(offer->description())
712 ->set_direction(offer_direction_);
713
714 auto callee = CreatePeerConnection();
715 if (send_media_) {
716 callee->AddAudioTrack("a");
717 }
718 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
719
720 // Create the answer according to the test parameters.
721 RTCOfferAnswerOptions options;
722 options.offer_to_receive_audio = offer_to_receive_;
723 auto answer = callee->CreateAnswer(options);
724
725 // The expected direction in the answer is the intersection of each side's
726 // capability to send/recv media.
727 // For the offerer, the direction is given in the offer (offer_direction_).
728 // For the answerer, the direction has two components:
729 // 1. Send if the answerer has a local track to send.
730 // 2. Receive if the answerer has explicitly set the offer_to_receive to 1 or
731 // if it has been left as default.
Steve Anton4e70a722017-11-28 14:57:10 -0800732 bool offer_send = RtpTransceiverDirectionHasSend(offer_direction_);
733 bool offer_recv = RtpTransceiverDirectionHasRecv(offer_direction_);
Steve Anton8d3444d2017-10-20 15:30:51 -0700734
735 // The negotiated components determine the direction set in the answer.
Steve Anton1d03a752017-11-27 14:30:09 -0800736 bool negotiate_send = (send_media_ && offer_recv);
737 bool negotiate_recv = ((offer_to_receive_ != 0) && offer_send);
Steve Anton8d3444d2017-10-20 15:30:51 -0700738
739 auto expected_direction =
Steve Anton4e70a722017-11-28 14:57:10 -0800740 RtpTransceiverDirectionFromSendRecv(negotiate_send, negotiate_recv);
Steve Anton8d3444d2017-10-20 15:30:51 -0700741 EXPECT_EQ(expected_direction,
Steve Antonad7bffc2018-01-22 10:21:56 -0800742 GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_AUDIO));
Steve Anton8d3444d2017-10-20 15:30:51 -0700743}
744
745// Tests that the media section is rejected if and only if the callee has no
746// local media track and has set offer_to_receive to 0, no matter which
747// direction the caller indicated in the offer.
748TEST_P(PeerConnectionMediaAnswerDirectionTest, VerifyRejected) {
Steve Anton22da89f2018-01-25 13:58:07 -0800749 if (IsUnifiedPlan() &&
750 offer_to_receive_ != RTCOfferAnswerOptions::kUndefined) {
751 // offer_to_receive_ is not implemented when creating answers with Unified
752 // Plan semantics specified.
Steve Antonad7bffc2018-01-22 10:21:56 -0800753 return;
754 }
Steve Anton22da89f2018-01-25 13:58:07 -0800755
Steve Anton8d3444d2017-10-20 15:30:51 -0700756 auto caller = CreatePeerConnection();
757 caller->AddAudioTrack("a");
758
759 // Create the offer with an audio section and set its direction.
760 auto offer = caller->CreateOffer();
761 cricket::GetFirstAudioContentDescription(offer->description())
762 ->set_direction(offer_direction_);
763
764 auto callee = CreatePeerConnection();
765 if (send_media_) {
766 callee->AddAudioTrack("a");
767 }
768 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
769
770 // Create the answer according to the test parameters.
771 RTCOfferAnswerOptions options;
772 options.offer_to_receive_audio = offer_to_receive_;
773 auto answer = callee->CreateAnswer(options);
774
775 // The media section is rejected if and only if offer_to_receive is explicitly
776 // set to 0 and there is no media to send.
777 auto* audio_content = cricket::GetFirstAudioContent(answer->description());
778 ASSERT_TRUE(audio_content);
779 EXPECT_EQ((offer_to_receive_ == 0 && !send_media_), audio_content->rejected);
780}
781
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100782INSTANTIATE_TEST_SUITE_P(PeerConnectionMediaTest,
783 PeerConnectionMediaAnswerDirectionTest,
784 Combine(Values(SdpSemantics::kPlanB,
785 SdpSemantics::kUnifiedPlan),
786 Values(RtpTransceiverDirection::kInactive,
787 RtpTransceiverDirection::kSendOnly,
788 RtpTransceiverDirection::kRecvOnly,
789 RtpTransceiverDirection::kSendRecv),
790 Bool(),
791 Values(-1, 0, 1)));
Steve Anton8d3444d2017-10-20 15:30:51 -0700792
Steve Antonad7bffc2018-01-22 10:21:56 -0800793TEST_P(PeerConnectionMediaTest, OfferHasDifferentDirectionForAudioVideo) {
Steve Anton8d3444d2017-10-20 15:30:51 -0700794 auto caller = CreatePeerConnection();
795 caller->AddVideoTrack("v");
796
797 RTCOfferAnswerOptions options;
798 options.offer_to_receive_audio = 1;
799 options.offer_to_receive_video = 0;
800 auto offer = caller->CreateOffer(options);
801
Steve Anton4e70a722017-11-28 14:57:10 -0800802 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
Steve Antonad7bffc2018-01-22 10:21:56 -0800803 GetMediaContentDirection(offer.get(), cricket::MEDIA_TYPE_AUDIO));
Steve Anton4e70a722017-11-28 14:57:10 -0800804 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
Steve Antonad7bffc2018-01-22 10:21:56 -0800805 GetMediaContentDirection(offer.get(), cricket::MEDIA_TYPE_VIDEO));
Steve Anton8d3444d2017-10-20 15:30:51 -0700806}
807
Steve Antonad7bffc2018-01-22 10:21:56 -0800808TEST_P(PeerConnectionMediaTest, AnswerHasDifferentDirectionsForAudioVideo) {
Steve Antonad7bffc2018-01-22 10:21:56 -0800809 if (IsUnifiedPlan()) {
Steve Anton22da89f2018-01-25 13:58:07 -0800810 // offer_to_receive_ is not implemented when creating answers with Unified
811 // Plan semantics specified.
Steve Antonad7bffc2018-01-22 10:21:56 -0800812 return;
813 }
814
Steve Anton8d3444d2017-10-20 15:30:51 -0700815 auto caller = CreatePeerConnectionWithAudioVideo();
816 auto callee = CreatePeerConnection();
817 callee->AddVideoTrack("v");
818
819 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
820
821 RTCOfferAnswerOptions options;
822 options.offer_to_receive_audio = 1;
823 options.offer_to_receive_video = 0;
824 auto answer = callee->CreateAnswer(options);
825
Steve Anton4e70a722017-11-28 14:57:10 -0800826 EXPECT_EQ(RtpTransceiverDirection::kRecvOnly,
Steve Antonad7bffc2018-01-22 10:21:56 -0800827 GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_AUDIO));
Steve Anton4e70a722017-11-28 14:57:10 -0800828 EXPECT_EQ(RtpTransceiverDirection::kSendOnly,
Steve Antonad7bffc2018-01-22 10:21:56 -0800829 GetMediaContentDirection(answer.get(), cricket::MEDIA_TYPE_VIDEO));
Steve Anton8d3444d2017-10-20 15:30:51 -0700830}
831
832void AddComfortNoiseCodecsToSend(cricket::FakeMediaEngine* media_engine) {
833 const cricket::AudioCodec kComfortNoiseCodec8k(102, "CN", 8000, 0, 1);
834 const cricket::AudioCodec kComfortNoiseCodec16k(103, "CN", 16000, 0, 1);
835
Sebastian Jansson6eb8a162018-11-16 11:29:55 +0100836 auto codecs = media_engine->voice().send_codecs();
Steve Anton8d3444d2017-10-20 15:30:51 -0700837 codecs.push_back(kComfortNoiseCodec8k);
838 codecs.push_back(kComfortNoiseCodec16k);
839 media_engine->SetAudioCodecs(codecs);
840}
841
842bool HasAnyComfortNoiseCodecs(const cricket::SessionDescription* desc) {
843 const auto* audio_desc = cricket::GetFirstAudioContentDescription(desc);
844 for (const auto& codec : audio_desc->codecs()) {
845 if (codec.name == "CN") {
846 return true;
847 }
848 }
849 return false;
850}
851
Steve Antonad7bffc2018-01-22 10:21:56 -0800852TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700853 CreateOfferWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs) {
854 auto caller = CreatePeerConnectionWithAudioVideo();
855 AddComfortNoiseCodecsToSend(caller->media_engine());
856
857 RTCOfferAnswerOptions options;
858 options.voice_activity_detection = false;
859 auto offer = caller->CreateOffer(options);
860
861 EXPECT_FALSE(HasAnyComfortNoiseCodecs(offer->description()));
862}
863
Steve Antonad7bffc2018-01-22 10:21:56 -0800864TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -0700865 CreateAnswerWithNoVoiceActivityDetectionIncludesNoComfortNoiseCodecs) {
866 auto caller = CreatePeerConnectionWithAudioVideo();
867 AddComfortNoiseCodecsToSend(caller->media_engine());
868 auto callee = CreatePeerConnectionWithAudioVideo();
869 AddComfortNoiseCodecsToSend(callee->media_engine());
870
871 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
872
873 RTCOfferAnswerOptions options;
874 options.voice_activity_detection = false;
875 auto answer = callee->CreateAnswer(options);
876
877 EXPECT_FALSE(HasAnyComfortNoiseCodecs(answer->description()));
878}
879
880// The following test group verifies that we reject answers with invalid media
881// sections as per RFC 3264.
882
883class PeerConnectionMediaInvalidMediaTest
Steve Antonad7bffc2018-01-22 10:21:56 -0800884 : public PeerConnectionMediaBaseTest,
885 public ::testing::WithParamInterface<std::tuple<
886 SdpSemantics,
Steve Anton8d3444d2017-10-20 15:30:51 -0700887 std::tuple<std::string,
888 std::function<void(cricket::SessionDescription*)>,
Steve Antonad7bffc2018-01-22 10:21:56 -0800889 std::string>>> {
Steve Anton8d3444d2017-10-20 15:30:51 -0700890 protected:
Steve Antonad7bffc2018-01-22 10:21:56 -0800891 PeerConnectionMediaInvalidMediaTest()
892 : PeerConnectionMediaBaseTest(std::get<0>(GetParam())) {
893 auto param = std::get<1>(GetParam());
894 mutator_ = std::get<1>(param);
895 expected_error_ = std::get<2>(param);
Steve Anton8d3444d2017-10-20 15:30:51 -0700896 }
897
898 std::function<void(cricket::SessionDescription*)> mutator_;
899 std::string expected_error_;
900};
901
902TEST_P(PeerConnectionMediaInvalidMediaTest, FailToSetRemoteAnswer) {
903 auto caller = CreatePeerConnectionWithAudioVideo();
904 auto callee = CreatePeerConnectionWithAudioVideo();
905
906 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
907
908 auto answer = callee->CreateAnswer();
909 mutator_(answer->description());
910
911 std::string error;
912 ASSERT_FALSE(caller->SetRemoteDescription(std::move(answer), &error));
913 EXPECT_EQ("Failed to set remote answer sdp: " + expected_error_, error);
914}
915
916TEST_P(PeerConnectionMediaInvalidMediaTest, FailToSetLocalAnswer) {
917 auto caller = CreatePeerConnectionWithAudioVideo();
918 auto callee = CreatePeerConnectionWithAudioVideo();
919
920 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
921
922 auto answer = callee->CreateAnswer();
923 mutator_(answer->description());
924
925 std::string error;
926 ASSERT_FALSE(callee->SetLocalDescription(std::move(answer), &error));
927 EXPECT_EQ("Failed to set local answer sdp: " + expected_error_, error);
928}
929
930void RemoveVideoContent(cricket::SessionDescription* desc) {
931 auto content_name = cricket::GetFirstVideoContent(desc)->name;
932 desc->RemoveContentByName(content_name);
933 desc->RemoveTransportInfoByName(content_name);
934}
935
936void RenameVideoContent(cricket::SessionDescription* desc) {
937 auto* video_content = cricket::GetFirstVideoContent(desc);
938 auto* transport_info = desc->GetTransportInfoByName(video_content->name);
939 video_content->name = "video_renamed";
940 transport_info->content_name = video_content->name;
941}
942
943void ReverseMediaContent(cricket::SessionDescription* desc) {
Steve Anton64b626b2019-01-28 17:25:26 -0800944 absl::c_reverse(desc->contents());
945 absl::c_reverse(desc->transport_infos());
Steve Anton8d3444d2017-10-20 15:30:51 -0700946}
947
948void ChangeMediaTypeAudioToVideo(cricket::SessionDescription* desc) {
Steve Antonad7bffc2018-01-22 10:21:56 -0800949 std::string audio_mid = cricket::GetFirstAudioContent(desc)->name;
950 desc->RemoveContentByName(audio_mid);
951 auto* video_content = cricket::GetFirstVideoContent(desc);
952 desc->AddContent(audio_mid, video_content->type,
Harald Alvestrand1716d392019-06-03 20:35:45 +0200953 video_content->media_description()->Clone());
Steve Anton8d3444d2017-10-20 15:30:51 -0700954}
955
956constexpr char kMLinesOutOfOrder[] =
957 "The order of m-lines in answer doesn't match order in offer. Rejecting "
958 "answer.";
959
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100960INSTANTIATE_TEST_SUITE_P(
Steve Anton8d3444d2017-10-20 15:30:51 -0700961 PeerConnectionMediaTest,
962 PeerConnectionMediaInvalidMediaTest,
Steve Antonad7bffc2018-01-22 10:21:56 -0800963 Combine(Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan),
964 Values(std::make_tuple("remove video",
965 RemoveVideoContent,
966 kMLinesOutOfOrder),
967 std::make_tuple("rename video",
968 RenameVideoContent,
969 kMLinesOutOfOrder),
970 std::make_tuple("reverse media sections",
971 ReverseMediaContent,
972 kMLinesOutOfOrder),
973 std::make_tuple("change audio type to video type",
974 ChangeMediaTypeAudioToVideo,
975 kMLinesOutOfOrder))));
Steve Anton8d3444d2017-10-20 15:30:51 -0700976
977// Test that the correct media engine send/recv streams are created when doing
978// a series of offer/answers where audio/video are both sent, then audio is
979// rejected, then both audio/video sent again.
Steve Antonad7bffc2018-01-22 10:21:56 -0800980TEST_P(PeerConnectionMediaTest, TestAVOfferWithAudioOnlyAnswer) {
Steve Antonad7bffc2018-01-22 10:21:56 -0800981 if (IsUnifiedPlan()) {
Steve Anton22da89f2018-01-25 13:58:07 -0800982 // offer_to_receive_ is not implemented when creating answers with Unified
983 // Plan semantics specified.
Steve Antonad7bffc2018-01-22 10:21:56 -0800984 return;
985 }
986
Steve Anton8d3444d2017-10-20 15:30:51 -0700987 RTCOfferAnswerOptions options_reject_video;
988 options_reject_video.offer_to_receive_audio =
989 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
990 options_reject_video.offer_to_receive_video = 0;
991
992 auto caller = CreatePeerConnection();
993 caller->AddAudioTrack("a");
994 caller->AddVideoTrack("v");
995 auto callee = CreatePeerConnection();
996
997 // Caller initially offers to send/recv audio and video.
998 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
999 // Callee accepts the audio as recv only but rejects the video.
1000 ASSERT_TRUE(caller->SetRemoteDescription(
1001 callee->CreateAnswerAndSetAsLocal(options_reject_video)));
1002
1003 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1004 ASSERT_TRUE(caller_voice);
1005 EXPECT_EQ(0u, caller_voice->recv_streams().size());
1006 EXPECT_EQ(1u, caller_voice->send_streams().size());
1007 auto caller_video = caller->media_engine()->GetVideoChannel(0);
1008 EXPECT_FALSE(caller_video);
1009
1010 // Callee adds its own audio/video stream and offers to receive audio/video
1011 // too.
1012 callee->AddAudioTrack("a");
1013 auto callee_video_track = callee->AddVideoTrack("v");
1014 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1015 ASSERT_TRUE(
1016 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1017
1018 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1019 ASSERT_TRUE(callee_voice);
1020 EXPECT_EQ(1u, callee_voice->recv_streams().size());
1021 EXPECT_EQ(1u, callee_voice->send_streams().size());
1022 auto callee_video = callee->media_engine()->GetVideoChannel(0);
1023 ASSERT_TRUE(callee_video);
1024 EXPECT_EQ(1u, callee_video->recv_streams().size());
1025 EXPECT_EQ(1u, callee_video->send_streams().size());
1026
1027 // Callee removes video but keeps audio and rejects the video once again.
1028 callee->pc()->RemoveTrack(callee_video_track);
1029 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1030 ASSERT_TRUE(
1031 callee->SetLocalDescription(callee->CreateAnswer(options_reject_video)));
1032
1033 callee_voice = callee->media_engine()->GetVoiceChannel(0);
1034 ASSERT_TRUE(callee_voice);
1035 EXPECT_EQ(1u, callee_voice->recv_streams().size());
1036 EXPECT_EQ(1u, callee_voice->send_streams().size());
1037 callee_video = callee->media_engine()->GetVideoChannel(0);
1038 EXPECT_FALSE(callee_video);
1039}
1040
1041// Test that the correct media engine send/recv streams are created when doing
1042// a series of offer/answers where audio/video are both sent, then video is
1043// rejected, then both audio/video sent again.
Steve Antonad7bffc2018-01-22 10:21:56 -08001044TEST_P(PeerConnectionMediaTest, TestAVOfferWithVideoOnlyAnswer) {
Steve Antonad7bffc2018-01-22 10:21:56 -08001045 if (IsUnifiedPlan()) {
Steve Anton22da89f2018-01-25 13:58:07 -08001046 // offer_to_receive_ is not implemented when creating answers with Unified
1047 // Plan semantics specified.
Steve Antonad7bffc2018-01-22 10:21:56 -08001048 return;
1049 }
1050
Steve Anton8d3444d2017-10-20 15:30:51 -07001051 // Disable the bundling here. If the media is bundled on audio
1052 // transport, then we can't reject the audio because switching the bundled
1053 // transport is not currently supported.
1054 // (https://bugs.chromium.org/p/webrtc/issues/detail?id=6704)
1055 RTCOfferAnswerOptions options_no_bundle;
1056 options_no_bundle.use_rtp_mux = false;
1057 RTCOfferAnswerOptions options_reject_audio = options_no_bundle;
1058 options_reject_audio.offer_to_receive_audio = 0;
1059 options_reject_audio.offer_to_receive_video =
1060 RTCOfferAnswerOptions::kMaxOfferToReceiveMedia;
1061
1062 auto caller = CreatePeerConnection();
1063 caller->AddAudioTrack("a");
1064 caller->AddVideoTrack("v");
1065 auto callee = CreatePeerConnection();
1066
1067 // Caller initially offers to send/recv audio and video.
1068 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1069 // Callee accepts the video as recv only but rejects the audio.
1070 ASSERT_TRUE(caller->SetRemoteDescription(
1071 callee->CreateAnswerAndSetAsLocal(options_reject_audio)));
1072
1073 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1074 EXPECT_FALSE(caller_voice);
1075 auto caller_video = caller->media_engine()->GetVideoChannel(0);
1076 ASSERT_TRUE(caller_video);
1077 EXPECT_EQ(0u, caller_video->recv_streams().size());
1078 EXPECT_EQ(1u, caller_video->send_streams().size());
1079
1080 // Callee adds its own audio/video stream and offers to receive audio/video
1081 // too.
1082 auto callee_audio_track = callee->AddAudioTrack("a");
1083 callee->AddVideoTrack("v");
1084 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1085 ASSERT_TRUE(caller->SetRemoteDescription(
1086 callee->CreateAnswerAndSetAsLocal(options_no_bundle)));
1087
1088 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1089 ASSERT_TRUE(callee_voice);
1090 EXPECT_EQ(1u, callee_voice->recv_streams().size());
1091 EXPECT_EQ(1u, callee_voice->send_streams().size());
1092 auto callee_video = callee->media_engine()->GetVideoChannel(0);
1093 ASSERT_TRUE(callee_video);
1094 EXPECT_EQ(1u, callee_video->recv_streams().size());
1095 EXPECT_EQ(1u, callee_video->send_streams().size());
1096
1097 // Callee removes audio but keeps video and rejects the audio once again.
1098 callee->pc()->RemoveTrack(callee_audio_track);
1099 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1100 ASSERT_TRUE(
1101 callee->SetLocalDescription(callee->CreateAnswer(options_reject_audio)));
1102
1103 callee_voice = callee->media_engine()->GetVoiceChannel(0);
1104 EXPECT_FALSE(callee_voice);
1105 callee_video = callee->media_engine()->GetVideoChannel(0);
1106 ASSERT_TRUE(callee_video);
1107 EXPECT_EQ(1u, callee_video->recv_streams().size());
1108 EXPECT_EQ(1u, callee_video->send_streams().size());
1109}
1110
1111// Tests that if the underlying video encoder fails to be initialized (signaled
1112// by failing to set send codecs), the PeerConnection signals the error to the
1113// client.
Steve Antonad7bffc2018-01-22 10:21:56 -08001114TEST_P(PeerConnectionMediaTest, MediaEngineErrorPropagatedToClients) {
Steve Anton8d3444d2017-10-20 15:30:51 -07001115 auto caller = CreatePeerConnectionWithAudioVideo();
1116 auto callee = CreatePeerConnectionWithAudioVideo();
1117
1118 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1119
1120 auto video_channel = caller->media_engine()->GetVideoChannel(0);
1121 video_channel->set_fail_set_send_codecs(true);
1122
1123 std::string error;
1124 ASSERT_FALSE(caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal(),
1125 &error));
1126 EXPECT_EQ(
Steve Anton80dd7b52018-02-16 17:08:42 -08001127 "Failed to set remote answer sdp: Failed to set remote video description "
1128 "send parameters.",
Steve Anton8d3444d2017-10-20 15:30:51 -07001129 error);
1130}
1131
1132// Tests that if the underlying video encoder fails once then subsequent
1133// attempts at setting the local/remote description will also fail, even if
1134// SetSendCodecs no longer fails.
Steve Antonad7bffc2018-01-22 10:21:56 -08001135TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -07001136 FailToApplyDescriptionIfVideoEncoderHasEverFailed) {
1137 auto caller = CreatePeerConnectionWithAudioVideo();
1138 auto callee = CreatePeerConnectionWithAudioVideo();
1139
1140 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1141
1142 auto video_channel = caller->media_engine()->GetVideoChannel(0);
1143 video_channel->set_fail_set_send_codecs(true);
1144
1145 EXPECT_FALSE(
1146 caller->SetRemoteDescription(callee->CreateAnswerAndSetAsLocal()));
1147
1148 video_channel->set_fail_set_send_codecs(false);
1149
1150 EXPECT_FALSE(caller->SetRemoteDescription(callee->CreateAnswer()));
1151 EXPECT_FALSE(caller->SetLocalDescription(caller->CreateOffer()));
1152}
1153
1154void RenameContent(cricket::SessionDescription* desc,
Steve Antonad7bffc2018-01-22 10:21:56 -08001155 cricket::MediaType media_type,
Steve Anton8d3444d2017-10-20 15:30:51 -07001156 const std::string& new_name) {
Steve Antonad7bffc2018-01-22 10:21:56 -08001157 auto* content = cricket::GetFirstMediaContent(desc, media_type);
Steve Anton8d3444d2017-10-20 15:30:51 -07001158 RTC_DCHECK(content);
Steve Antonad7bffc2018-01-22 10:21:56 -08001159 std::string old_name = content->name;
Steve Anton8d3444d2017-10-20 15:30:51 -07001160 content->name = new_name;
1161 auto* transport = desc->GetTransportInfoByName(old_name);
1162 RTC_DCHECK(transport);
1163 transport->content_name = new_name;
Zhi Huangd2248f82018-04-10 14:41:03 -07001164
1165 // Rename the content name in the BUNDLE group.
1166 cricket::ContentGroup new_bundle_group =
1167 *desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
1168 new_bundle_group.RemoveContentName(old_name);
1169 new_bundle_group.AddContentName(new_name);
1170 desc->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE);
1171 desc->AddGroup(new_bundle_group);
Steve Anton8d3444d2017-10-20 15:30:51 -07001172}
1173
1174// Tests that an answer responds with the same MIDs as the offer.
Steve Antonad7bffc2018-01-22 10:21:56 -08001175TEST_P(PeerConnectionMediaTest, AnswerHasSameMidsAsOffer) {
Zhi Huang365381f2018-04-13 16:44:34 -07001176 const std::string kAudioMid = "notdefault1";
1177 const std::string kVideoMid = "notdefault2";
Steve Anton8d3444d2017-10-20 15:30:51 -07001178
1179 auto caller = CreatePeerConnectionWithAudioVideo();
1180 auto callee = CreatePeerConnectionWithAudioVideo();
1181
1182 auto offer = caller->CreateOffer();
Steve Antonad7bffc2018-01-22 10:21:56 -08001183 RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, kAudioMid);
1184 RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, kVideoMid);
Steve Anton8d3444d2017-10-20 15:30:51 -07001185 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1186
1187 auto answer = callee->CreateAnswer();
1188 EXPECT_EQ(kAudioMid,
1189 cricket::GetFirstAudioContent(answer->description())->name);
1190 EXPECT_EQ(kVideoMid,
1191 cricket::GetFirstVideoContent(answer->description())->name);
1192}
1193
1194// Test that if the callee creates a re-offer, the MIDs are the same as the
1195// original offer.
Steve Antonad7bffc2018-01-22 10:21:56 -08001196TEST_P(PeerConnectionMediaTest, ReOfferHasSameMidsAsFirstOffer) {
Zhi Huang365381f2018-04-13 16:44:34 -07001197 const std::string kAudioMid = "notdefault1";
1198 const std::string kVideoMid = "notdefault2";
Steve Anton8d3444d2017-10-20 15:30:51 -07001199
1200 auto caller = CreatePeerConnectionWithAudioVideo();
1201 auto callee = CreatePeerConnectionWithAudioVideo();
1202
1203 auto offer = caller->CreateOffer();
Steve Antonad7bffc2018-01-22 10:21:56 -08001204 RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, kAudioMid);
1205 RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, kVideoMid);
Steve Anton8d3444d2017-10-20 15:30:51 -07001206 ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer)));
1207 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1208
1209 auto reoffer = callee->CreateOffer();
1210 EXPECT_EQ(kAudioMid,
1211 cricket::GetFirstAudioContent(reoffer->description())->name);
1212 EXPECT_EQ(kVideoMid,
1213 cricket::GetFirstVideoContent(reoffer->description())->name);
1214}
1215
Steve Anton06817cd2018-12-18 15:55:30 -08001216// Test that SetRemoteDescription returns an error if there are two m= sections
1217// with the same MID value.
1218TEST_P(PeerConnectionMediaTest, SetRemoteDescriptionFailsWithDuplicateMids) {
1219 auto caller = CreatePeerConnectionWithAudioVideo();
1220 auto callee = CreatePeerConnectionWithAudioVideo();
1221
1222 auto offer = caller->CreateOffer();
1223 RenameContent(offer->description(), cricket::MEDIA_TYPE_AUDIO, "same");
1224 RenameContent(offer->description(), cricket::MEDIA_TYPE_VIDEO, "same");
1225
1226 std::string error;
1227 EXPECT_FALSE(callee->SetRemoteDescription(std::move(offer), &error));
1228 EXPECT_EQ(error,
1229 "Failed to set remote offer sdp: Duplicate a=mid value 'same'.");
1230}
1231
Steve Antonad7bffc2018-01-22 10:21:56 -08001232TEST_P(PeerConnectionMediaTest,
Steve Anton8d3444d2017-10-20 15:30:51 -07001233 CombinedAudioVideoBweConfigPropagatedToMediaEngine) {
1234 RTCConfiguration config;
1235 config.combined_audio_video_bwe.emplace(true);
1236 auto caller = CreatePeerConnectionWithAudioVideo(config);
1237
1238 ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer()));
1239
1240 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1241 ASSERT_TRUE(caller_voice);
1242 const cricket::AudioOptions& audio_options = caller_voice->options();
1243 EXPECT_EQ(config.combined_audio_video_bwe,
1244 audio_options.combined_audio_video_bwe);
1245}
1246
Anton Sukhanov98a462c2018-10-17 13:15:42 -07001247TEST_P(PeerConnectionMediaTest, MediaTransportPropagatedToVoiceEngine) {
1248 RTCConfiguration config;
1249
1250 // Setup PeerConnection to use media transport.
1251 config.use_media_transport = true;
1252
Piotr (Peter) Slatala9f956252018-10-31 08:25:26 -07001253 // Force SDES.
1254 config.enable_dtls_srtp = false;
1255
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -08001256 auto caller = CreatePeerConnectionWithAudio(config);
1257 auto callee = CreatePeerConnectionWithAudio(config);
Anton Sukhanov98a462c2018-10-17 13:15:42 -07001258
1259 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1260 auto answer = callee->CreateAnswer();
1261 ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
1262
1263 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1264 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1265 ASSERT_TRUE(caller_voice);
1266 ASSERT_TRUE(callee_voice);
1267
1268 // Make sure media transport is propagated to voice channel.
1269 FakeMediaTransport* caller_voice_media_transport =
1270 static_cast<FakeMediaTransport*>(caller_voice->media_transport());
1271 FakeMediaTransport* callee_voice_media_transport =
1272 static_cast<FakeMediaTransport*>(callee_voice->media_transport());
1273 ASSERT_NE(nullptr, caller_voice_media_transport);
1274 ASSERT_NE(nullptr, callee_voice_media_transport);
1275
1276 // Make sure media transport is created with correct is_caller.
1277 EXPECT_TRUE(caller_voice_media_transport->is_caller());
1278 EXPECT_FALSE(callee_voice_media_transport->is_caller());
1279
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -08001280 // TODO(sukhanov): Propagate media transport to video channel.
1281 // This test does NOT set up video channels, because currently it causes
1282 // us to create two media transports.
Anton Sukhanov98a462c2018-10-17 13:15:42 -07001283}
1284
Bjorn Mellema9bbd862018-11-02 09:07:48 -07001285TEST_P(PeerConnectionMediaTest, MediaTransportOnlyForDataChannels) {
1286 RTCConfiguration config;
1287
1288 // Setup PeerConnection to use media transport for data channels.
1289 config.use_media_transport_for_data_channels = true;
1290
1291 // Force SDES.
1292 config.enable_dtls_srtp = false;
1293
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -08001294 auto caller = CreatePeerConnectionWithAudio(config);
1295 auto callee = CreatePeerConnectionWithAudio(config);
Bjorn Mellema9bbd862018-11-02 09:07:48 -07001296
1297 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1298 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1299
1300 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1301 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1302 ASSERT_TRUE(caller_voice);
1303 ASSERT_TRUE(callee_voice);
1304
1305 // Make sure media transport is not propagated to voice channel.
1306 EXPECT_EQ(nullptr, caller_voice->media_transport());
1307 EXPECT_EQ(nullptr, callee_voice->media_transport());
1308}
1309
1310TEST_P(PeerConnectionMediaTest, MediaTransportForMediaAndDataChannels) {
1311 RTCConfiguration config;
1312
1313 // Setup PeerConnection to use media transport for both media and data
1314 // channels.
1315 config.use_media_transport = true;
1316 config.use_media_transport_for_data_channels = true;
1317
1318 // Force SDES.
1319 config.enable_dtls_srtp = false;
1320
Piotr (Peter) Slatala10aeb2a2018-11-14 10:57:24 -08001321 auto caller = CreatePeerConnectionWithAudio(config);
1322 auto callee = CreatePeerConnectionWithAudio(config);
Bjorn Mellema9bbd862018-11-02 09:07:48 -07001323
1324 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1325 ASSERT_TRUE(callee->SetLocalDescription(callee->CreateAnswer()));
1326
1327 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1328 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1329 ASSERT_TRUE(caller_voice);
1330 ASSERT_TRUE(callee_voice);
1331
1332 // Make sure media transport is propagated to voice channel.
1333 FakeMediaTransport* caller_voice_media_transport =
1334 static_cast<FakeMediaTransport*>(caller_voice->media_transport());
1335 FakeMediaTransport* callee_voice_media_transport =
1336 static_cast<FakeMediaTransport*>(callee_voice->media_transport());
1337 ASSERT_NE(nullptr, caller_voice_media_transport);
1338 ASSERT_NE(nullptr, callee_voice_media_transport);
1339
1340 // Make sure media transport is created with correct is_caller.
1341 EXPECT_TRUE(caller_voice_media_transport->is_caller());
1342 EXPECT_FALSE(callee_voice_media_transport->is_caller());
Bjorn Mellema9bbd862018-11-02 09:07:48 -07001343}
1344
Anton Sukhanov98a462c2018-10-17 13:15:42 -07001345TEST_P(PeerConnectionMediaTest, MediaTransportNotPropagatedToVoiceEngine) {
1346 auto caller = CreatePeerConnectionWithAudioVideo();
1347 auto callee = CreatePeerConnectionWithAudioVideo();
1348
1349 ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
1350 auto answer = callee->CreateAnswer();
1351 ASSERT_TRUE(callee->SetLocalDescription(std::move(answer)));
1352
1353 auto caller_voice = caller->media_engine()->GetVoiceChannel(0);
1354 auto callee_voice = callee->media_engine()->GetVoiceChannel(0);
1355 ASSERT_TRUE(caller_voice);
1356 ASSERT_TRUE(callee_voice);
1357
1358 // Since we did not setup PeerConnection to use media transport, media
1359 // transport should not be created / propagated to the voice engine.
1360 ASSERT_EQ(nullptr, caller_voice->media_transport());
1361 ASSERT_EQ(nullptr, callee_voice->media_transport());
1362
1363 auto caller_video = caller->media_engine()->GetVideoChannel(0);
1364 auto callee_video = callee->media_engine()->GetVideoChannel(0);
1365 ASSERT_EQ(nullptr, caller_video->media_transport());
1366 ASSERT_EQ(nullptr, callee_video->media_transport());
1367}
1368
Florent Castelli2d9d82e2019-04-23 19:25:51 +02001369template <typename C>
1370bool CompareCodecs(const std::vector<webrtc::RtpCodecCapability>& capabilities,
1371 const std::vector<C>& codecs) {
1372 bool capability_has_rtx =
1373 absl::c_any_of(capabilities, [](const webrtc::RtpCodecCapability& codec) {
1374 return codec.name == cricket::kRtxCodecName;
1375 });
1376 bool codecs_has_rtx = absl::c_any_of(codecs, [](const C& codec) {
1377 return codec.name == cricket::kRtxCodecName;
1378 });
1379
1380 std::vector<C> codecs_no_rtx;
1381 absl::c_copy_if(
1382 codecs, std::back_inserter(codecs_no_rtx),
1383 [](const C& codec) { return codec.name != cricket::kRtxCodecName; });
1384
1385 std::vector<webrtc::RtpCodecCapability> capabilities_no_rtx;
1386 absl::c_copy_if(capabilities, std::back_inserter(capabilities_no_rtx),
1387 [](const webrtc::RtpCodecCapability& codec) {
1388 return codec.name != cricket::kRtxCodecName;
1389 });
1390
1391 return capability_has_rtx == codecs_has_rtx &&
1392 absl::c_equal(
1393 capabilities_no_rtx, codecs_no_rtx,
1394 [](const webrtc::RtpCodecCapability& capability, const C& codec) {
1395 return codec.MatchesCapability(capability);
1396 });
1397}
1398
1399TEST_F(PeerConnectionMediaTestUnifiedPlan,
1400 SetCodecPreferencesAudioMissingRecvCodec) {
1401 auto fake_engine = absl::make_unique<FakeMediaEngine>();
1402 auto send_codecs = fake_engine->voice().send_codecs();
1403 send_codecs.push_back(cricket::AudioCodec(send_codecs.back().id + 1,
1404 "send_only_codec", 0, 0, 1));
1405 fake_engine->SetAudioSendCodecs(send_codecs);
1406
1407 auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
1408
1409 auto transceiver = caller->pc()->GetTransceivers().front();
1410 auto capabilities = caller->pc_factory()->GetRtpSenderCapabilities(
1411 cricket::MediaType::MEDIA_TYPE_AUDIO);
1412
1413 std::vector<webrtc::RtpCodecCapability> codecs;
1414 absl::c_copy_if(capabilities.codecs, std::back_inserter(codecs),
1415 [](const webrtc::RtpCodecCapability& codec) {
1416 return codec.name.find("_only_") != std::string::npos;
1417 });
1418
1419 auto result = transceiver->SetCodecPreferences(codecs);
1420 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1421}
1422
1423TEST_F(PeerConnectionMediaTestUnifiedPlan,
1424 SetCodecPreferencesAudioMissingSendCodec) {
1425 auto fake_engine = absl::make_unique<FakeMediaEngine>();
1426 auto recv_codecs = fake_engine->voice().recv_codecs();
1427 recv_codecs.push_back(cricket::AudioCodec(recv_codecs.back().id + 1,
1428 "recv_only_codec", 0, 0, 1));
1429 fake_engine->SetAudioRecvCodecs(recv_codecs);
1430 auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
1431
1432 auto transceiver = caller->pc()->GetTransceivers().front();
1433 auto capabilities = caller->pc_factory()->GetRtpReceiverCapabilities(
1434 cricket::MediaType::MEDIA_TYPE_AUDIO);
1435
1436 std::vector<webrtc::RtpCodecCapability> codecs;
1437 absl::c_copy_if(capabilities.codecs, std::back_inserter(codecs),
1438 [](const webrtc::RtpCodecCapability& codec) {
1439 return codec.name.find("_only_") != std::string::npos;
1440 });
1441
1442 auto result = transceiver->SetCodecPreferences(codecs);
1443 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1444}
1445
1446TEST_F(PeerConnectionMediaTestUnifiedPlan,
1447 SetCodecPreferencesAudioRejectsVideoCodec) {
1448 auto caller = CreatePeerConnectionWithAudio();
1449
1450 auto transceiver = caller->pc()->GetTransceivers().front();
1451 auto video_codecs =
1452 caller->pc_factory()
1453 ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
1454 .codecs;
1455 auto codecs =
1456 caller->pc_factory()
1457 ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
1458 .codecs;
1459 codecs.insert(codecs.end(), video_codecs.begin(), video_codecs.end());
1460 auto result = transceiver->SetCodecPreferences(codecs);
1461 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1462}
1463
1464TEST_F(PeerConnectionMediaTestUnifiedPlan,
1465 SetCodecPreferencesAudioRejectsOnlyRtxRedFec) {
1466 auto fake_engine = absl::make_unique<FakeMediaEngine>();
1467 auto audio_codecs = fake_engine->voice().send_codecs();
1468 audio_codecs.push_back(cricket::AudioCodec(audio_codecs.back().id + 1,
1469 cricket::kRtxCodecName, 0, 0, 1));
1470 audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1471 std::to_string(audio_codecs.back().id - 1);
1472 audio_codecs.push_back(cricket::AudioCodec(audio_codecs.back().id + 1,
1473 cricket::kRedCodecName, 0, 0, 1));
1474 audio_codecs.push_back(cricket::AudioCodec(
1475 audio_codecs.back().id + 1, cricket::kUlpfecCodecName, 0, 0, 1));
1476 fake_engine->SetAudioCodecs(audio_codecs);
1477
1478 auto caller = CreatePeerConnectionWithAudio(std::move(fake_engine));
1479
1480 auto transceiver = caller->pc()->GetTransceivers().front();
1481 auto codecs =
1482 caller->pc_factory()
1483 ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
1484 .codecs;
1485 auto codecs_only_rtx_red_fec = codecs;
1486 auto it = std::remove_if(codecs_only_rtx_red_fec.begin(),
1487 codecs_only_rtx_red_fec.end(),
1488 [](const webrtc::RtpCodecCapability& codec) {
1489 return !(codec.name == cricket::kRtxCodecName ||
1490 codec.name == cricket::kRedCodecName ||
1491 codec.name == cricket::kUlpfecCodecName);
1492 });
1493 codecs_only_rtx_red_fec.erase(it, codecs_only_rtx_red_fec.end());
1494
1495 auto result = transceiver->SetCodecPreferences(codecs_only_rtx_red_fec);
1496 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1497}
1498
1499TEST_F(PeerConnectionMediaTestUnifiedPlan, SetCodecPreferencesAllAudioCodecs) {
1500 auto caller = CreatePeerConnectionWithAudio();
1501
1502 auto sender_audio_codecs =
1503 caller->pc_factory()
1504 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO)
1505 .codecs;
1506
1507 auto audio_transceiver = caller->pc()->GetTransceivers().front();
1508
1509 // Normal case, set all capabilities as preferences
1510 EXPECT_TRUE(audio_transceiver->SetCodecPreferences(sender_audio_codecs).ok());
1511 auto offer = caller->CreateOffer();
1512 auto codecs = offer->description()
1513 ->contents()[0]
1514 .media_description()
1515 ->as_audio()
1516 ->codecs();
1517 EXPECT_TRUE(CompareCodecs(sender_audio_codecs, codecs));
1518}
1519
1520TEST_F(PeerConnectionMediaTestUnifiedPlan,
1521 SetCodecPreferencesResetAudioCodecs) {
1522 auto caller = CreatePeerConnectionWithAudio();
1523
1524 auto sender_audio_codecs =
1525 caller->pc_factory()
1526 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO)
1527 .codecs;
1528 std::vector<webrtc::RtpCodecCapability> empty_codecs = {};
1529
1530 auto audio_transceiver = caller->pc()->GetTransceivers().front();
1531
1532 // Normal case, reset codec preferences
1533 EXPECT_TRUE(audio_transceiver->SetCodecPreferences(empty_codecs).ok());
1534 auto offer = caller->CreateOffer();
1535 auto codecs = offer->description()
1536 ->contents()[0]
1537 .media_description()
1538 ->as_audio()
1539 ->codecs();
1540 EXPECT_TRUE(CompareCodecs(sender_audio_codecs, codecs));
1541}
1542
1543TEST_F(PeerConnectionMediaTestUnifiedPlan,
1544 SetCodecPreferencesVideoRejectsAudioCodec) {
1545 auto caller = CreatePeerConnectionWithVideo();
1546
1547 auto transceiver = caller->pc()->GetTransceivers().front();
1548 auto audio_codecs =
1549 caller->pc_factory()
1550 ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_AUDIO)
1551 .codecs;
1552 auto codecs =
1553 caller->pc_factory()
1554 ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
1555 .codecs;
1556 codecs.insert(codecs.end(), audio_codecs.begin(), audio_codecs.end());
1557 auto result = transceiver->SetCodecPreferences(codecs);
1558 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1559}
1560
1561TEST_F(PeerConnectionMediaTestUnifiedPlan,
1562 SetCodecPreferencesVideoRejectsOnlyRtxRedFec) {
1563 auto fake_engine = absl::make_unique<FakeMediaEngine>();
1564 auto video_codecs = fake_engine->video().codecs();
1565 video_codecs.push_back(
1566 cricket::VideoCodec(video_codecs.back().id + 1, cricket::kRtxCodecName));
1567 video_codecs.push_back(
1568 cricket::VideoCodec(video_codecs.back().id + 1, cricket::kRedCodecName));
1569 video_codecs.push_back(cricket::VideoCodec(video_codecs.back().id + 1,
1570 cricket::kUlpfecCodecName));
1571 fake_engine->SetVideoCodecs(video_codecs);
1572
1573 auto caller = CreatePeerConnectionWithVideo(std::move(fake_engine));
1574
1575 auto transceiver = caller->pc()->GetTransceivers().front();
1576 auto codecs =
1577 caller->pc_factory()
1578 ->GetRtpSenderCapabilities(cricket::MediaType::MEDIA_TYPE_VIDEO)
1579 .codecs;
1580 auto codecs_only_rtx_red_fec = codecs;
1581 auto it = std::remove_if(codecs_only_rtx_red_fec.begin(),
1582 codecs_only_rtx_red_fec.end(),
1583 [](const webrtc::RtpCodecCapability& codec) {
1584 return !(codec.name == cricket::kRtxCodecName ||
1585 codec.name == cricket::kRedCodecName ||
1586 codec.name == cricket::kUlpfecCodecName);
1587 });
1588 codecs_only_rtx_red_fec.erase(it, codecs_only_rtx_red_fec.end());
1589
1590 auto result = transceiver->SetCodecPreferences(codecs_only_rtx_red_fec);
1591 EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION, result.type());
1592}
1593
1594TEST_F(PeerConnectionMediaTestUnifiedPlan, SetCodecPreferencesAllVideoCodecs) {
1595 auto caller = CreatePeerConnectionWithVideo();
1596
1597 auto sender_video_codecs =
1598 caller->pc_factory()
1599 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1600 .codecs;
1601
1602 auto video_transceiver = caller->pc()->GetTransceivers().front();
1603
1604 // Normal case, setting preferences to normal capabilities
1605 EXPECT_TRUE(video_transceiver->SetCodecPreferences(sender_video_codecs).ok());
1606 auto offer = caller->CreateOffer();
1607 auto codecs = offer->description()
1608 ->contents()[0]
1609 .media_description()
1610 ->as_video()
1611 ->codecs();
1612 EXPECT_TRUE(CompareCodecs(sender_video_codecs, codecs));
1613}
1614
1615TEST_F(PeerConnectionMediaTestUnifiedPlan,
1616 SetCodecPreferencesResetVideoCodecs) {
1617 auto caller = CreatePeerConnectionWithVideo();
1618
1619 auto sender_video_codecs =
1620 caller->pc_factory()
1621 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1622 .codecs;
1623
1624 std::vector<webrtc::RtpCodecCapability> empty_codecs = {};
1625
1626 auto video_transceiver = caller->pc()->GetTransceivers().front();
1627
1628 // Normal case, resetting preferences with empty list of codecs
1629 EXPECT_TRUE(video_transceiver->SetCodecPreferences(empty_codecs).ok());
1630 auto offer = caller->CreateOffer();
1631 auto codecs = offer->description()
1632 ->contents()[0]
1633 .media_description()
1634 ->as_video()
1635 ->codecs();
1636 EXPECT_TRUE(CompareCodecs(sender_video_codecs, codecs));
1637}
1638
1639TEST_F(PeerConnectionMediaTestUnifiedPlan,
1640 SetCodecPreferencesVideoCodecDuplicatesRemoved) {
1641 auto caller = CreatePeerConnectionWithVideo();
1642
1643 auto sender_video_codecs =
1644 caller->pc_factory()
1645 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1646 .codecs;
1647
1648 auto video_transceiver = caller->pc()->GetTransceivers().front();
1649
1650 // Check duplicates are removed
1651 auto single_codec = sender_video_codecs;
1652 single_codec.resize(1);
1653 auto duplicate_codec = single_codec;
1654 duplicate_codec.push_back(duplicate_codec.front());
1655 duplicate_codec.push_back(duplicate_codec.front());
1656 duplicate_codec.push_back(duplicate_codec.front());
1657
1658 EXPECT_TRUE(video_transceiver->SetCodecPreferences(duplicate_codec).ok());
1659 auto offer = caller->CreateOffer();
1660 auto codecs = offer->description()
1661 ->contents()[0]
1662 .media_description()
1663 ->as_video()
1664 ->codecs();
1665 EXPECT_TRUE(CompareCodecs(single_codec, codecs));
1666}
1667
1668TEST_F(PeerConnectionMediaTestUnifiedPlan, SetCodecPreferencesVideoWithRtx) {
1669 auto caller_fake_engine = absl::make_unique<FakeMediaEngine>();
1670 auto caller_video_codecs = caller_fake_engine->video().codecs();
1671 caller_video_codecs.push_back(cricket::VideoCodec(
1672 caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
1673 caller_video_codecs.push_back(cricket::VideoCodec(
1674 caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1675 caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1676 std::to_string(caller_video_codecs.back().id - 1);
1677 caller_video_codecs.push_back(cricket::VideoCodec(
1678 caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
1679 caller_video_codecs.push_back(cricket::VideoCodec(
1680 caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1681 caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1682 std::to_string(caller_video_codecs.back().id - 1);
1683 caller_fake_engine->SetVideoCodecs(caller_video_codecs);
1684
1685 auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
1686
1687 auto sender_video_codecs =
1688 caller->pc_factory()
1689 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1690 .codecs;
1691
1692 auto video_transceiver = caller->pc()->GetTransceivers().front();
1693
1694 // Check that RTX codec is properly added
1695 auto video_codecs_vpx_rtx = sender_video_codecs;
1696 auto it =
1697 std::remove_if(video_codecs_vpx_rtx.begin(), video_codecs_vpx_rtx.end(),
1698 [](const webrtc::RtpCodecCapability& codec) {
1699 return codec.name != cricket::kRtxCodecName &&
1700 codec.name != cricket::kVp8CodecName &&
1701 codec.name != cricket::kVp9CodecName;
1702 });
1703 video_codecs_vpx_rtx.erase(it, video_codecs_vpx_rtx.end());
1704 absl::c_reverse(video_codecs_vpx_rtx);
1705 EXPECT_EQ(video_codecs_vpx_rtx.size(), 3u); // VP8, VP9, RTX
1706 EXPECT_TRUE(
1707 video_transceiver->SetCodecPreferences(video_codecs_vpx_rtx).ok());
1708 auto offer = caller->CreateOffer();
1709 auto codecs = offer->description()
1710 ->contents()[0]
1711 .media_description()
1712 ->as_video()
1713 ->codecs();
1714
1715 EXPECT_TRUE(CompareCodecs(video_codecs_vpx_rtx, codecs));
1716 EXPECT_EQ(codecs.size(), 4u);
1717}
1718
1719TEST_F(PeerConnectionMediaTestUnifiedPlan,
1720 SetCodecPreferencesVideoCodecsNegotiation) {
1721 auto caller_fake_engine = absl::make_unique<FakeMediaEngine>();
1722 auto caller_video_codecs = caller_fake_engine->video().codecs();
1723 caller_video_codecs.push_back(cricket::VideoCodec(
1724 caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
1725 caller_video_codecs.push_back(cricket::VideoCodec(
1726 caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1727 caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1728 std::to_string(caller_video_codecs.back().id - 1);
1729 caller_video_codecs.push_back(cricket::VideoCodec(
1730 caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
1731 caller_video_codecs.push_back(cricket::VideoCodec(
1732 caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1733 caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1734 std::to_string(caller_video_codecs.back().id - 1);
1735 caller_fake_engine->SetVideoCodecs(caller_video_codecs);
1736
1737 auto callee_fake_engine = absl::make_unique<FakeMediaEngine>();
1738 callee_fake_engine->SetVideoCodecs(caller_video_codecs);
1739
1740 auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
1741 auto callee = CreatePeerConnection(std::move(callee_fake_engine));
1742
1743 auto video_codecs = caller->pc_factory()
1744 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1745 .codecs;
1746
1747 auto send_transceiver = caller->pc()->GetTransceivers().front();
1748
1749 auto video_codecs_vpx = video_codecs;
1750 auto it = std::remove_if(video_codecs_vpx.begin(), video_codecs_vpx.end(),
1751 [](const webrtc::RtpCodecCapability& codec) {
1752 return codec.name != cricket::kVp8CodecName &&
1753 codec.name != cricket::kVp9CodecName;
1754 });
1755 video_codecs_vpx.erase(it, video_codecs_vpx.end());
1756 EXPECT_EQ(video_codecs_vpx.size(), 2u); // VP8, VP9
1757 EXPECT_TRUE(send_transceiver->SetCodecPreferences(video_codecs_vpx).ok());
1758
1759 auto offer = caller->CreateOfferAndSetAsLocal();
1760 auto codecs = offer->description()
1761 ->contents()[0]
1762 .media_description()
1763 ->as_video()
1764 ->codecs();
1765
1766 EXPECT_EQ(codecs.size(), 2u); // VP8, VP9
1767 EXPECT_TRUE(CompareCodecs(video_codecs_vpx, codecs));
1768
1769 callee->SetRemoteDescription(std::move(offer));
1770
1771 auto recv_transceiver = callee->pc()->GetTransceivers().front();
1772 auto video_codecs_vp8_rtx = video_codecs;
1773 it = std::remove_if(video_codecs_vp8_rtx.begin(), video_codecs_vp8_rtx.end(),
1774 [](const webrtc::RtpCodecCapability& codec) {
1775 bool r = codec.name != cricket::kVp8CodecName &&
1776 codec.name != cricket::kRtxCodecName;
1777 return r;
1778 });
1779 video_codecs_vp8_rtx.erase(it, video_codecs_vp8_rtx.end());
1780 EXPECT_EQ(video_codecs_vp8_rtx.size(), 2u); // VP8, RTX
1781 recv_transceiver->SetCodecPreferences(video_codecs_vp8_rtx);
1782
1783 auto answer = callee->CreateAnswerAndSetAsLocal();
1784
1785 auto recv_codecs = answer->description()
1786 ->contents()[0]
1787 .media_description()
1788 ->as_video()
1789 ->codecs();
1790 EXPECT_EQ(recv_codecs.size(), 1u); // VP8
1791}
1792
1793TEST_F(PeerConnectionMediaTestUnifiedPlan,
1794 SetCodecPreferencesVideoCodecsNegotiationReverseOrder) {
1795 auto caller_fake_engine = absl::make_unique<FakeMediaEngine>();
1796 auto caller_video_codecs = caller_fake_engine->video().codecs();
1797 caller_video_codecs.push_back(cricket::VideoCodec(
1798 caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
1799 caller_video_codecs.push_back(cricket::VideoCodec(
1800 caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1801 caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1802 std::to_string(caller_video_codecs.back().id - 1);
1803 caller_video_codecs.push_back(cricket::VideoCodec(
1804 caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
1805 caller_video_codecs.push_back(cricket::VideoCodec(
1806 caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
1807 caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
1808 std::to_string(caller_video_codecs.back().id - 1);
1809 caller_fake_engine->SetVideoCodecs(caller_video_codecs);
1810
1811 auto callee_fake_engine = absl::make_unique<FakeMediaEngine>();
1812 callee_fake_engine->SetVideoCodecs(caller_video_codecs);
1813
1814 auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
1815 auto callee = CreatePeerConnection(std::move(callee_fake_engine));
1816
1817 auto video_codecs = caller->pc_factory()
1818 ->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)
1819 .codecs;
1820
1821 auto send_transceiver = caller->pc()->GetTransceivers().front();
1822
1823 auto video_codecs_vpx = video_codecs;
1824 auto it = std::remove_if(video_codecs_vpx.begin(), video_codecs_vpx.end(),
1825 [](const webrtc::RtpCodecCapability& codec) {
1826 return codec.name != cricket::kVp8CodecName &&
1827 codec.name != cricket::kVp9CodecName;
1828 });
1829 video_codecs_vpx.erase(it, video_codecs_vpx.end());
1830 EXPECT_EQ(video_codecs_vpx.size(), 2u); // VP8, VP9
1831 EXPECT_TRUE(send_transceiver->SetCodecPreferences(video_codecs_vpx).ok());
1832
1833 auto video_codecs_vpx_reverse = video_codecs_vpx;
1834 absl::c_reverse(video_codecs_vpx_reverse);
1835
1836 auto offer = caller->CreateOfferAndSetAsLocal();
1837 auto codecs = offer->description()
1838 ->contents()[0]
1839 .media_description()
1840 ->as_video()
1841 ->codecs();
1842 EXPECT_EQ(codecs.size(), 2u); // VP9, VP8
1843 EXPECT_TRUE(CompareCodecs(video_codecs_vpx, codecs));
1844
1845 callee->SetRemoteDescription(std::move(offer));
1846
1847 auto recv_transceiver = callee->pc()->GetTransceivers().front();
1848 recv_transceiver->SetCodecPreferences(video_codecs_vpx_reverse);
1849
1850 auto answer = callee->CreateAnswerAndSetAsLocal();
1851
1852 auto recv_codecs = answer->description()
1853 ->contents()[0]
1854 .media_description()
1855 ->as_video()
1856 ->codecs();
1857
1858 EXPECT_TRUE(CompareCodecs(video_codecs_vpx_reverse, recv_codecs));
1859}
1860
Mirko Bonadeic84f6612019-01-31 12:20:57 +01001861INSTANTIATE_TEST_SUITE_P(PeerConnectionMediaTest,
1862 PeerConnectionMediaTest,
1863 Values(SdpSemantics::kPlanB,
1864 SdpSemantics::kUnifiedPlan));
Steve Antonad7bffc2018-01-22 10:21:56 -08001865
Steve Anton8d3444d2017-10-20 15:30:51 -07001866} // namespace webrtc