blob: 670ace2057fcb60a654ec0b6fa75a5cbd4010109 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg31022942016-03-11 14:18:21 -080011#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012#include <string>
13#include <vector>
14
nissec8ee8822017-01-18 07:20:55 -080015#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000016#include "webrtc/base/fakesslidentity.h"
17#include "webrtc/base/gunit.h"
18#include "webrtc/base/messagedigest.h"
19#include "webrtc/base/ssladapter.h"
kjellandera96e2d72016-02-04 23:52:28 -080020#include "webrtc/media/base/codec.h"
21#include "webrtc/media/base/testutils.h"
kjellanderf4752772016-03-02 05:42:30 -080022#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080023#include "webrtc/p2p/base/transportdescription.h"
24#include "webrtc/p2p/base/transportinfo.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010025#include "webrtc/pc/mediasession.h"
26#include "webrtc/pc/srtpfilter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
henrike@webrtc.org28e20752013-07-10 00:45:36 +000028#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029 ASSERT_EQ(s, cd->cryptos().size()); \
30 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031
32typedef std::vector<cricket::Candidate> Candidates;
33
34using cricket::MediaContentDescription;
35using cricket::MediaSessionDescriptionFactory;
ossu075af922016-06-14 03:29:38 -070036using cricket::MediaContentDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037using cricket::MediaSessionOptions;
38using cricket::MediaType;
39using cricket::SessionDescription;
40using cricket::SsrcGroup;
41using cricket::StreamParams;
42using cricket::StreamParamsVec;
43using cricket::TransportDescription;
44using cricket::TransportDescriptionFactory;
45using cricket::TransportInfo;
46using cricket::ContentInfo;
47using cricket::CryptoParamsVec;
48using cricket::AudioContentDescription;
49using cricket::VideoContentDescription;
50using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080051using cricket::GetFirstAudioContent;
52using cricket::GetFirstVideoContent;
53using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054using cricket::GetFirstAudioContentDescription;
55using cricket::GetFirstVideoContentDescription;
56using cricket::GetFirstDataContentDescription;
57using cricket::kAutoBandwidth;
58using cricket::AudioCodec;
59using cricket::VideoCodec;
60using cricket::DataCodec;
61using cricket::NS_JINGLE_RTP;
62using cricket::MEDIA_TYPE_AUDIO;
63using cricket::MEDIA_TYPE_VIDEO;
64using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065using cricket::SEC_DISABLED;
66using cricket::SEC_ENABLED;
67using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070068using rtc::CS_AES_CM_128_HMAC_SHA1_32;
69using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070070using rtc::CS_AEAD_AES_128_GCM;
71using rtc::CS_AEAD_AES_256_GCM;
isheriff6f8d6862016-05-26 11:24:55 -070072using webrtc::RtpExtension;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000073
74static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070075 AudioCodec(103, "ISAC", 16000, -1, 1),
76 AudioCodec(102, "iLBC", 8000, 13300, 1),
77 AudioCodec(0, "PCMU", 8000, 64000, 1),
78 AudioCodec(8, "PCMA", 8000, 64000, 1),
79 AudioCodec(117, "red", 8000, 0, 1),
80 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000081
82static const AudioCodec kAudioCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070083 AudioCodec(126, "speex", 16000, 22000, 1),
84 AudioCodec(0, "PCMU", 8000, 64000, 1),
85 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086};
87
88static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070089 AudioCodec(102, "iLBC", 8000, 13300, 1),
90 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000091};
92
perkj26752742016-10-24 01:21:16 -070093static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
94 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095
perkj26752742016-10-24 01:21:16 -070096static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
97 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098
perkj26752742016-10-24 01:21:16 -070099static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000100
deadbeef67cf2c12016-04-13 10:07:16 -0700101static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
102 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103
deadbeef67cf2c12016-04-13 10:07:16 -0700104static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
105 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106
deadbeef67cf2c12016-04-13 10:07:16 -0700107static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
108 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109
isheriff6f8d6862016-05-26 11:24:55 -0700110static const RtpExtension kAudioRtpExtension1[] = {
111 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
112 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113};
114
jbauch5869f502017-06-29 12:31:36 -0700115static const RtpExtension kAudioRtpExtensionEncrypted1[] = {
116 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
117 RtpExtension("http://google.com/testing/audio_something", 10),
118 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
119};
120
isheriff6f8d6862016-05-26 11:24:55 -0700121static const RtpExtension kAudioRtpExtension2[] = {
122 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
123 RtpExtension("http://google.com/testing/audio_something_else", 8),
124 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125};
126
isheriff6f8d6862016-05-26 11:24:55 -0700127static const RtpExtension kAudioRtpExtension3[] = {
128 RtpExtension("http://google.com/testing/audio_something", 2),
129 RtpExtension("http://google.com/testing/both_audio_and_video", 3),
deadbeefa5b273a2015-08-20 17:30:13 -0700130};
131
jbauch5869f502017-06-29 12:31:36 -0700132static const RtpExtension kAudioRtpExtension3ForEncryption[] = {
133 RtpExtension("http://google.com/testing/audio_something", 2),
134 // Use RTP extension that supports encryption.
135 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
136};
137
138static const RtpExtension kAudioRtpExtension3ForEncryptionOffer[] = {
139 RtpExtension("http://google.com/testing/audio_something", 2),
140 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 3),
141 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14, true),
142};
143
isheriff6f8d6862016-05-26 11:24:55 -0700144static const RtpExtension kAudioRtpExtensionAnswer[] = {
145 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000146};
147
jbauch5869f502017-06-29 12:31:36 -0700148static const RtpExtension kAudioRtpExtensionEncryptedAnswer[] = {
149 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 12, true),
150};
151
isheriff6f8d6862016-05-26 11:24:55 -0700152static const RtpExtension kVideoRtpExtension1[] = {
153 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
154 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155};
156
jbauch5869f502017-06-29 12:31:36 -0700157static const RtpExtension kVideoRtpExtensionEncrypted1[] = {
158 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
159 RtpExtension("http://google.com/testing/video_something", 13),
160 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
161};
162
isheriff6f8d6862016-05-26 11:24:55 -0700163static const RtpExtension kVideoRtpExtension2[] = {
164 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
165 RtpExtension("http://google.com/testing/video_something_else", 14),
166 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167};
168
isheriff6f8d6862016-05-26 11:24:55 -0700169static const RtpExtension kVideoRtpExtension3[] = {
170 RtpExtension("http://google.com/testing/video_something", 4),
171 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700172};
173
jbauch5869f502017-06-29 12:31:36 -0700174static const RtpExtension kVideoRtpExtension3ForEncryption[] = {
175 RtpExtension("http://google.com/testing/video_something", 4),
176 // Use RTP extension that supports encryption.
177 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 5),
178};
179
isheriff6f8d6862016-05-26 11:24:55 -0700180static const RtpExtension kVideoRtpExtensionAnswer[] = {
181 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000182};
183
jbauch5869f502017-06-29 12:31:36 -0700184static const RtpExtension kVideoRtpExtensionEncryptedAnswer[] = {
185 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 11, true),
186};
187
Peter Boström0c4e06b2015-10-07 12:23:21 +0200188static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
189static const uint32_t kSimSsrc[] = {10, 20, 30};
190static const uint32_t kFec1Ssrc[] = {10, 11};
191static const uint32_t kFec2Ssrc[] = {20, 21};
192static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000193
194static const char kMediaStream1[] = "stream_1";
195static const char kMediaStream2[] = "stream_2";
196static const char kVideoTrack1[] = "video_1";
197static const char kVideoTrack2[] = "video_2";
198static const char kAudioTrack1[] = "audio_1";
199static const char kAudioTrack2[] = "audio_2";
200static const char kAudioTrack3[] = "audio_3";
201static const char kDataTrack1[] = "data_1";
202static const char kDataTrack2[] = "data_2";
203static const char kDataTrack3[] = "data_3";
204
zhihuangcf5b37c2016-05-05 11:44:35 -0700205static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
206 "RTP/SAVPF"};
207static const char* kMediaProtocolsDtls[] = {
208 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
209 "UDP/TLS/RTP/SAVP"};
210
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000211static bool IsMediaContentOfType(const ContentInfo* content,
212 MediaType media_type) {
213 const MediaContentDescription* mdesc =
214 static_cast<const MediaContentDescription*>(content->description);
215 return mdesc && mdesc->type() == media_type;
216}
217
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000218static cricket::MediaContentDirection
219GetMediaDirection(const ContentInfo* content) {
220 cricket::MediaContentDescription* desc =
221 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
222 return desc->direction();
223}
224
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000225static void AddRtxCodec(const VideoCodec& rtx_codec,
226 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800227 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000228 codecs->push_back(rtx_codec);
229}
230
231template <class T>
232static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
233 std::vector<std::string> codec_names;
234 for (const auto& codec : codecs) {
235 codec_names.push_back(codec.name);
236 }
237 return codec_names;
238}
239
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240class MediaSessionDescriptionFactoryTest : public testing::Test {
241 public:
242 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200243 : f1_(&tdf1_),
244 f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700245 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
246 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000247 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
248 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700249 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
250 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
252 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200253 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700254 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200255 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700256 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 }
258
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000259 // Create a video StreamParamsVec object with:
260 // - one video stream with 3 simulcast streams and FEC,
261 StreamParamsVec CreateComplexVideoStreamParamsVec() {
262 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
263 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
264 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
265 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
266
267 std::vector<SsrcGroup> ssrc_groups;
268 ssrc_groups.push_back(sim_group);
269 ssrc_groups.push_back(fec_group1);
270 ssrc_groups.push_back(fec_group2);
271 ssrc_groups.push_back(fec_group3);
272
273 StreamParams simulcast_params;
274 simulcast_params.id = kVideoTrack1;
275 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
276 simulcast_params.ssrc_groups = ssrc_groups;
277 simulcast_params.cname = "Video_SIM_FEC";
278 simulcast_params.sync_label = kMediaStream1;
279
280 StreamParamsVec video_streams;
281 video_streams.push_back(simulcast_params);
282
283 return video_streams;
284 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285
286 bool CompareCryptoParams(const CryptoParamsVec& c1,
287 const CryptoParamsVec& c2) {
288 if (c1.size() != c2.size())
289 return false;
290 for (size_t i = 0; i < c1.size(); ++i)
291 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
292 c1[i].key_params != c2[i].key_params ||
293 c1[i].session_params != c2[i].session_params)
294 return false;
295 return true;
296 }
297
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700298 // Returns true if the transport info contains "renomination" as an
299 // ICE option.
300 bool GetIceRenomination(const TransportInfo* transport_info) {
301 const std::vector<std::string>& ice_options =
302 transport_info->description.transport_options;
deadbeef30952b42017-04-21 02:41:29 -0700303 auto iter =
304 std::find(ice_options.begin(), ice_options.end(), "renomination");
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700305 return iter != ice_options.end();
306 }
307
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000308 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
309 bool has_current_desc) {
310 const std::string current_audio_ufrag = "current_audio_ufrag";
311 const std::string current_audio_pwd = "current_audio_pwd";
312 const std::string current_video_ufrag = "current_video_ufrag";
313 const std::string current_video_pwd = "current_video_pwd";
314 const std::string current_data_ufrag = "current_data_ufrag";
315 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800316 std::unique_ptr<SessionDescription> current_desc;
317 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000318 if (has_current_desc) {
319 current_desc.reset(new SessionDescription());
320 EXPECT_TRUE(current_desc->AddTransportInfo(
321 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700322 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000323 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000324 EXPECT_TRUE(current_desc->AddTransportInfo(
325 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700326 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000327 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 EXPECT_TRUE(current_desc->AddTransportInfo(
329 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700330 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000331 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000332 }
333 if (offer) {
334 desc.reset(f1_.CreateOffer(options, current_desc.get()));
335 } else {
kwiberg31022942016-03-11 14:18:21 -0800336 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000337 offer.reset(f1_.CreateOffer(options, NULL));
338 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
339 }
340 ASSERT_TRUE(desc.get() != NULL);
341 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000342 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000343 EXPECT_TRUE(ti_audio != NULL);
344 if (has_current_desc) {
345 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
346 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
347 } else {
348 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
349 ti_audio->description.ice_ufrag.size());
350 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
351 ti_audio->description.ice_pwd.size());
352 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700353 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000354
355 } else {
356 EXPECT_TRUE(ti_audio == NULL);
357 }
358 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000359 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000360 EXPECT_TRUE(ti_video != NULL);
361 if (options.bundle_enabled) {
362 EXPECT_EQ(ti_audio->description.ice_ufrag,
363 ti_video->description.ice_ufrag);
364 EXPECT_EQ(ti_audio->description.ice_pwd,
365 ti_video->description.ice_pwd);
366 } else {
367 if (has_current_desc) {
368 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
369 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
370 } else {
371 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
372 ti_video->description.ice_ufrag.size());
373 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
374 ti_video->description.ice_pwd.size());
375 }
376 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700377 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 } else {
379 EXPECT_TRUE(ti_video == NULL);
380 }
381 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
382 if (options.has_data()) {
383 EXPECT_TRUE(ti_data != NULL);
384 if (options.bundle_enabled) {
385 EXPECT_EQ(ti_audio->description.ice_ufrag,
386 ti_data->description.ice_ufrag);
387 EXPECT_EQ(ti_audio->description.ice_pwd,
388 ti_data->description.ice_pwd);
389 } else {
390 if (has_current_desc) {
391 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
392 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
393 } else {
394 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
395 ti_data->description.ice_ufrag.size());
396 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
397 ti_data->description.ice_pwd.size());
398 }
399 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700400 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_data));
401
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000402 } else {
403 EXPECT_TRUE(ti_video == NULL);
404 }
405 }
406
407 void TestCryptoWithBundle(bool offer) {
408 f1_.set_secure(SEC_ENABLED);
409 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000410 options.recv_audio = true;
411 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800413 std::unique_ptr<SessionDescription> ref_desc;
414 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000415 if (offer) {
416 options.bundle_enabled = false;
417 ref_desc.reset(f1_.CreateOffer(options, NULL));
418 options.bundle_enabled = true;
419 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
420 } else {
421 options.bundle_enabled = true;
422 ref_desc.reset(f1_.CreateOffer(options, NULL));
423 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
424 }
425 ASSERT_TRUE(desc.get() != NULL);
426 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000427 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428 desc.get()->GetContentDescriptionByName("audio"));
429 ASSERT_TRUE(audio_media_desc != NULL);
430 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000431 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000432 desc.get()->GetContentDescriptionByName("video"));
433 ASSERT_TRUE(video_media_desc != NULL);
434 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
435 video_media_desc->cryptos()));
436 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
437 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
438 audio_media_desc->cryptos()[0].cipher_suite);
439
440 // Verify the selected crypto is one from the reference audio
441 // media content.
442 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000443 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444 ref_desc.get()->GetContentDescriptionByName("audio"));
445 bool found = false;
446 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
447 if (ref_audio_media_desc->cryptos()[i].Matches(
448 audio_media_desc->cryptos()[0])) {
449 found = true;
450 break;
451 }
452 }
453 EXPECT_TRUE(found);
454 }
455
456 // This test that the audio and video media direction is set to
457 // |expected_direction_in_answer| in an answer if the offer direction is set
458 // to |direction_in_offer|.
459 void TestMediaDirectionInAnswer(
460 cricket::MediaContentDirection direction_in_offer,
461 cricket::MediaContentDirection expected_direction_in_answer) {
462 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000463 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800464 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700466 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000467 ASSERT_TRUE(ac_offer != NULL);
468 AudioContentDescription* acd_offer =
469 static_cast<AudioContentDescription*>(ac_offer->description);
470 acd_offer->set_direction(direction_in_offer);
terelius8c011e52016-04-26 05:28:11 -0700471 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000472 ASSERT_TRUE(vc_offer != NULL);
473 VideoContentDescription* vcd_offer =
474 static_cast<VideoContentDescription*>(vc_offer->description);
475 vcd_offer->set_direction(direction_in_offer);
476
kwiberg31022942016-03-11 14:18:21 -0800477 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000478 f2_.CreateAnswer(offer.get(), opts, NULL));
479 const AudioContentDescription* acd_answer =
480 GetFirstAudioContentDescription(answer.get());
481 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
482 const VideoContentDescription* vcd_answer =
483 GetFirstVideoContentDescription(answer.get());
484 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
485 }
486
487 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
488 const cricket::ContentDescription* description = content->description;
nissec8ee8822017-01-18 07:20:55 -0800489 RTC_CHECK(description != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000491 static_cast<const cricket::AudioContentDescription*>(description);
nissec8ee8822017-01-18 07:20:55 -0800492 RTC_CHECK(audio_content_desc != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000493 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
494 if (audio_content_desc->codecs()[i].name == "CN")
495 return false;
496 }
497 return true;
498 }
499
jbauchcb560652016-08-04 05:20:32 -0700500 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
501 MediaSessionOptions offer_opts;
502 offer_opts.recv_video = true;
503 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
504 MediaSessionOptions answer_opts;
505 answer_opts.recv_video = true;
506 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
507 f1_.set_secure(SEC_ENABLED);
508 f2_.set_secure(SEC_ENABLED);
509 std::unique_ptr<SessionDescription> offer(
510 f1_.CreateOffer(offer_opts, NULL));
511 ASSERT_TRUE(offer.get() != NULL);
512 std::unique_ptr<SessionDescription> answer(
513 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
514 const ContentInfo* ac = answer->GetContentByName("audio");
515 const ContentInfo* vc = answer->GetContentByName("video");
516 ASSERT_TRUE(ac != NULL);
517 ASSERT_TRUE(vc != NULL);
518 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
519 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
520 const AudioContentDescription* acd =
521 static_cast<const AudioContentDescription*>(ac->description);
522 const VideoContentDescription* vcd =
523 static_cast<const VideoContentDescription*>(vc->description);
524 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
525 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
526 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
527 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
528 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
529 if (gcm_offer && gcm_answer) {
530 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
531 } else {
532 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
533 }
534 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
535 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
536 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
537 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
538 if (gcm_offer && gcm_answer) {
539 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
540 } else {
541 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
542 }
543 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
544 }
545
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000546 protected:
547 MediaSessionDescriptionFactory f1_;
548 MediaSessionDescriptionFactory f2_;
549 TransportDescriptionFactory tdf1_;
550 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000551};
552
553// Create a typical audio offer, and ensure it matches what we expect.
554TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
555 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800556 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 f1_.CreateOffer(MediaSessionOptions(), NULL));
558 ASSERT_TRUE(offer.get() != NULL);
559 const ContentInfo* ac = offer->GetContentByName("audio");
560 const ContentInfo* vc = offer->GetContentByName("video");
561 ASSERT_TRUE(ac != NULL);
562 ASSERT_TRUE(vc == NULL);
563 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
564 const AudioContentDescription* acd =
565 static_cast<const AudioContentDescription*>(ac->description);
566 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700567 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000568 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
569 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
570 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
571 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
572 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
573}
574
575// Create a typical video offer, and ensure it matches what we expect.
576TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
577 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000578 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800580 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581 ASSERT_TRUE(offer.get() != NULL);
582 const ContentInfo* ac = offer->GetContentByName("audio");
583 const ContentInfo* vc = offer->GetContentByName("video");
584 ASSERT_TRUE(ac != NULL);
585 ASSERT_TRUE(vc != NULL);
586 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
587 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
588 const AudioContentDescription* acd =
589 static_cast<const AudioContentDescription*>(ac->description);
590 const VideoContentDescription* vcd =
591 static_cast<const VideoContentDescription*>(vc->description);
592 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700593 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000594 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
595 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
596 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
597 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
598 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
599 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
600 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
601 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
602 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
603 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
604 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
605 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
606}
607
608// Test creating an offer with bundle where the Codecs have the same dynamic
609// RTP playlod type. The test verifies that the offer don't contain the
610// duplicate RTP payload types.
611TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
612 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700613 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000614 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
615 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
616 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
617
618 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000619 opts.recv_audio = true;
620 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621 opts.data_channel_type = cricket::DCT_RTP;
622 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800623 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000624 const VideoContentDescription* vcd =
625 GetFirstVideoContentDescription(offer.get());
626 const AudioContentDescription* acd =
627 GetFirstAudioContentDescription(offer.get());
628 const DataContentDescription* dcd =
629 GetFirstDataContentDescription(offer.get());
630 ASSERT_TRUE(NULL != vcd);
631 ASSERT_TRUE(NULL != acd);
632 ASSERT_TRUE(NULL != dcd);
633 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
634 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
635 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
636 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
637 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
638 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
639}
640
641// Test creating an updated offer with with bundle, audio, video and data
642// after an audio only session has been negotiated.
643TEST_F(MediaSessionDescriptionFactoryTest,
644 TestCreateUpdatedVideoOfferWithBundle) {
645 f1_.set_secure(SEC_ENABLED);
646 f2_.set_secure(SEC_ENABLED);
647 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000648 opts.recv_audio = true;
649 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650 opts.data_channel_type = cricket::DCT_NONE;
651 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800652 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
653 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 f2_.CreateAnswer(offer.get(), opts, NULL));
655
656 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000657 updated_opts.recv_audio = true;
658 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000659 updated_opts.data_channel_type = cricket::DCT_RTP;
660 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800661 std::unique_ptr<SessionDescription> updated_offer(
662 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663
664 const AudioContentDescription* acd =
665 GetFirstAudioContentDescription(updated_offer.get());
666 const VideoContentDescription* vcd =
667 GetFirstVideoContentDescription(updated_offer.get());
668 const DataContentDescription* dcd =
669 GetFirstDataContentDescription(updated_offer.get());
670 EXPECT_TRUE(NULL != vcd);
671 EXPECT_TRUE(NULL != acd);
672 EXPECT_TRUE(NULL != dcd);
673
674 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
675 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
676 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
677 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
678 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
679 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
680}
deadbeef44f08192015-12-15 16:20:09 -0800681
wu@webrtc.org78187522013-10-07 23:32:02 +0000682// Create a RTP data offer, and ensure it matches what we expect.
683TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684 MediaSessionOptions opts;
685 opts.data_channel_type = cricket::DCT_RTP;
686 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800687 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 ASSERT_TRUE(offer.get() != NULL);
689 const ContentInfo* ac = offer->GetContentByName("audio");
690 const ContentInfo* dc = offer->GetContentByName("data");
691 ASSERT_TRUE(ac != NULL);
692 ASSERT_TRUE(dc != NULL);
693 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
694 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
695 const AudioContentDescription* acd =
696 static_cast<const AudioContentDescription*>(ac->description);
697 const DataContentDescription* dcd =
698 static_cast<const DataContentDescription*>(dc->description);
699 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700700 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000701 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
702 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
703 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
704 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
705 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
706 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
707 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
708 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
709 EXPECT_EQ(cricket::kDataMaxBandwidth,
710 dcd->bandwidth()); // default bandwidth (auto)
711 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
712 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
713 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
714}
715
wu@webrtc.org78187522013-10-07 23:32:02 +0000716// Create an SCTP data offer with bundle without error.
717TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
718 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000719 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000720 opts.bundle_enabled = true;
721 opts.data_channel_type = cricket::DCT_SCTP;
722 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800723 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000724 EXPECT_TRUE(offer.get() != NULL);
725 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
726}
727
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000728// Test creating an sctp data channel from an already generated offer.
729TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
730 MediaSessionOptions opts;
731 opts.recv_audio = false;
732 opts.bundle_enabled = true;
733 opts.data_channel_type = cricket::DCT_SCTP;
734 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800735 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000736 ASSERT_TRUE(offer1.get() != NULL);
737 const ContentInfo* data = offer1->GetContentByName("data");
738 ASSERT_TRUE(data != NULL);
739 const MediaContentDescription* mdesc =
740 static_cast<const MediaContentDescription*>(data->description);
741 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
742
743 // Now set data_channel_type to 'none' (default) and make sure that the
744 // datachannel type that gets generated from the previous offer, is of the
745 // same type.
746 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800747 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000748 f1_.CreateOffer(opts, offer1.get()));
749 data = offer2->GetContentByName("data");
750 ASSERT_TRUE(data != NULL);
751 mdesc = static_cast<const MediaContentDescription*>(data->description);
752 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
753}
754
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000755// Create an audio, video offer without legacy StreamParams.
756TEST_F(MediaSessionDescriptionFactoryTest,
757 TestCreateOfferWithoutLegacyStreams) {
758 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000759 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000760 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800761 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000762 ASSERT_TRUE(offer.get() != NULL);
763 const ContentInfo* ac = offer->GetContentByName("audio");
764 const ContentInfo* vc = offer->GetContentByName("video");
765 ASSERT_TRUE(ac != NULL);
766 ASSERT_TRUE(vc != NULL);
767 const AudioContentDescription* acd =
768 static_cast<const AudioContentDescription*>(ac->description);
769 const VideoContentDescription* vcd =
770 static_cast<const VideoContentDescription*>(vc->description);
771
772 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
773 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
774}
775
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000776// Creates an audio+video sendonly offer.
777TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
778 MediaSessionOptions options;
779 options.recv_audio = false;
780 options.recv_video = false;
781 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
782 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
783
kwiberg31022942016-03-11 14:18:21 -0800784 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000785 ASSERT_TRUE(offer.get() != NULL);
786 EXPECT_EQ(2u, offer->contents().size());
787 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
788 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
789
790 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
791 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
792}
793
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000794// Verifies that the order of the media contents in the current
795// SessionDescription is preserved in the new SessionDescription.
796TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
797 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000798 opts.recv_audio = false;
799 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000800 opts.data_channel_type = cricket::DCT_SCTP;
801
kwiberg31022942016-03-11 14:18:21 -0800802 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000803 ASSERT_TRUE(offer1.get() != NULL);
804 EXPECT_EQ(1u, offer1->contents().size());
805 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
806
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000807 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800808 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000809 f1_.CreateOffer(opts, offer1.get()));
810 ASSERT_TRUE(offer2.get() != NULL);
811 EXPECT_EQ(2u, offer2->contents().size());
812 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
813 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
814
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000815 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800816 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000817 f1_.CreateOffer(opts, offer2.get()));
818 ASSERT_TRUE(offer3.get() != NULL);
819 EXPECT_EQ(3u, offer3->contents().size());
820 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
821 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
822 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
823
824 // Verifies the default order is audio-video-data, so that the previous checks
825 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800826 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000827 ASSERT_TRUE(offer4.get() != NULL);
828 EXPECT_EQ(3u, offer4->contents().size());
829 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
830 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
831 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
832}
833
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000834// Create a typical audio answer, and ensure it matches what we expect.
835TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
836 f1_.set_secure(SEC_ENABLED);
837 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800838 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000839 f1_.CreateOffer(MediaSessionOptions(), NULL));
840 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800841 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000842 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
843 const ContentInfo* ac = answer->GetContentByName("audio");
844 const ContentInfo* vc = answer->GetContentByName("video");
845 ASSERT_TRUE(ac != NULL);
846 ASSERT_TRUE(vc == NULL);
847 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
848 const AudioContentDescription* acd =
849 static_cast<const AudioContentDescription*>(ac->description);
850 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
851 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
852 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
853 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
854 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
855 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
856 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
857}
858
jbauchcb560652016-08-04 05:20:32 -0700859// Create a typical audio answer with GCM ciphers enabled, and ensure it
860// matches what we expect.
861TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
862 f1_.set_secure(SEC_ENABLED);
863 f2_.set_secure(SEC_ENABLED);
864 MediaSessionOptions options;
865 options.crypto_options.enable_gcm_crypto_suites = true;
866 std::unique_ptr<SessionDescription> offer(
867 f1_.CreateOffer(options, NULL));
868 ASSERT_TRUE(offer.get() != NULL);
869 std::unique_ptr<SessionDescription> answer(
870 f2_.CreateAnswer(offer.get(), options, NULL));
871 const ContentInfo* ac = answer->GetContentByName("audio");
872 const ContentInfo* vc = answer->GetContentByName("video");
873 ASSERT_TRUE(ac != NULL);
874 ASSERT_TRUE(vc == NULL);
875 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
876 const AudioContentDescription* acd =
877 static_cast<const AudioContentDescription*>(ac->description);
878 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
879 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
880 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
881 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
882 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
883 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
884 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
885}
886
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000887// Create a typical video answer, and ensure it matches what we expect.
888TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
889 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000890 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000891 f1_.set_secure(SEC_ENABLED);
892 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800893 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000894 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800895 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000896 f2_.CreateAnswer(offer.get(), opts, NULL));
897 const ContentInfo* ac = answer->GetContentByName("audio");
898 const ContentInfo* vc = answer->GetContentByName("video");
899 ASSERT_TRUE(ac != NULL);
900 ASSERT_TRUE(vc != NULL);
901 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
902 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
903 const AudioContentDescription* acd =
904 static_cast<const AudioContentDescription*>(ac->description);
905 const VideoContentDescription* vcd =
906 static_cast<const VideoContentDescription*>(vc->description);
907 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
908 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
909 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
910 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
911 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
912 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
913 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
914 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
915 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
916 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
917 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
918 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
919}
920
jbauchcb560652016-08-04 05:20:32 -0700921// Create a typical video answer with GCM ciphers enabled, and ensure it
922// matches what we expect.
923TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
924 TestVideoGcmCipher(true, true);
925}
926
927// Create a typical video answer with GCM ciphers enabled for the offer only,
928// and ensure it matches what we expect.
929TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
930 TestVideoGcmCipher(true, false);
931}
932
933// Create a typical video answer with GCM ciphers enabled for the answer only,
934// and ensure it matches what we expect.
935TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
936 TestVideoGcmCipher(false, true);
937}
938
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000939TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
940 MediaSessionOptions opts;
941 opts.data_channel_type = cricket::DCT_RTP;
942 f1_.set_secure(SEC_ENABLED);
943 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800944 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000945 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800946 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 f2_.CreateAnswer(offer.get(), opts, NULL));
948 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -0800949 const ContentInfo* dc = answer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -0800951 ASSERT_TRUE(dc != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000952 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
zstein4b2e0822017-02-17 19:48:38 -0800953 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000954 const AudioContentDescription* acd =
955 static_cast<const AudioContentDescription*>(ac->description);
zstein4b2e0822017-02-17 19:48:38 -0800956 const DataContentDescription* dcd =
957 static_cast<const DataContentDescription*>(dc->description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000958 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
959 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
960 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
961 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
962 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
963 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
zstein4b2e0822017-02-17 19:48:38 -0800964 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
965 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
966 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
967 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
968 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
969 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000970}
971
jbauchcb560652016-08-04 05:20:32 -0700972TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
973 MediaSessionOptions opts;
974 opts.data_channel_type = cricket::DCT_RTP;
975 opts.crypto_options.enable_gcm_crypto_suites = true;
976 f1_.set_secure(SEC_ENABLED);
977 f2_.set_secure(SEC_ENABLED);
978 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
979 ASSERT_TRUE(offer.get() != NULL);
980 std::unique_ptr<SessionDescription> answer(
981 f2_.CreateAnswer(offer.get(), opts, NULL));
982 const ContentInfo* ac = answer->GetContentByName("audio");
zstein4b2e0822017-02-17 19:48:38 -0800983 const ContentInfo* dc = answer->GetContentByName("data");
jbauchcb560652016-08-04 05:20:32 -0700984 ASSERT_TRUE(ac != NULL);
zstein4b2e0822017-02-17 19:48:38 -0800985 ASSERT_TRUE(dc != NULL);
jbauchcb560652016-08-04 05:20:32 -0700986 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
zstein4b2e0822017-02-17 19:48:38 -0800987 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
jbauchcb560652016-08-04 05:20:32 -0700988 const AudioContentDescription* acd =
989 static_cast<const AudioContentDescription*>(ac->description);
zstein4b2e0822017-02-17 19:48:38 -0800990 const DataContentDescription* dcd =
991 static_cast<const DataContentDescription*>(dc->description);
jbauchcb560652016-08-04 05:20:32 -0700992 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
993 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
994 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
995 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
996 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
997 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
zstein4b2e0822017-02-17 19:48:38 -0800998 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
999 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1000 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
1001 EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
1002 ASSERT_CRYPTO(dcd, 1U, CS_AEAD_AES_256_GCM);
1003 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
1004}
1005
1006// The use_sctpmap flag should be set in a DataContentDescription by default.
1007// The answer's use_sctpmap flag should match the offer's.
1008TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
1009 MediaSessionOptions opts;
1010 opts.data_channel_type = cricket::DCT_SCTP;
1011 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1012 ASSERT_TRUE(offer.get() != NULL);
1013 ContentInfo* dc_offer = offer->GetContentByName("data");
1014 ASSERT_TRUE(dc_offer != NULL);
1015 DataContentDescription* dcd_offer =
1016 static_cast<DataContentDescription*>(dc_offer->description);
1017 EXPECT_TRUE(dcd_offer->use_sctpmap());
1018
1019 std::unique_ptr<SessionDescription> answer(
1020 f2_.CreateAnswer(offer.get(), opts, NULL));
1021 const ContentInfo* dc_answer = answer->GetContentByName("data");
1022 ASSERT_TRUE(dc_answer != NULL);
1023 const DataContentDescription* dcd_answer =
1024 static_cast<const DataContentDescription*>(dc_answer->description);
1025 EXPECT_TRUE(dcd_answer->use_sctpmap());
1026}
1027
1028// The answer's use_sctpmap flag should match the offer's.
1029TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
1030 MediaSessionOptions opts;
1031 opts.data_channel_type = cricket::DCT_SCTP;
1032 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1033 ASSERT_TRUE(offer.get() != NULL);
1034 ContentInfo* dc_offer = offer->GetContentByName("data");
1035 ASSERT_TRUE(dc_offer != NULL);
1036 DataContentDescription* dcd_offer =
1037 static_cast<DataContentDescription*>(dc_offer->description);
1038 dcd_offer->set_use_sctpmap(false);
1039
1040 std::unique_ptr<SessionDescription> answer(
1041 f2_.CreateAnswer(offer.get(), opts, NULL));
1042 const ContentInfo* dc_answer = answer->GetContentByName("data");
1043 ASSERT_TRUE(dc_answer != NULL);
1044 const DataContentDescription* dcd_answer =
1045 static_cast<const DataContentDescription*>(dc_answer->description);
1046 EXPECT_FALSE(dcd_answer->use_sctpmap());
jbauchcb560652016-08-04 05:20:32 -07001047}
1048
deadbeef8b7e9ad2017-05-25 09:38:55 -07001049// Test that a valid answer will be created for "DTLS/SCTP", "UDP/DTLS/SCTP"
1050// and "TCP/DTLS/SCTP" offers.
1051TEST_F(MediaSessionDescriptionFactoryTest,
1052 TestCreateDataAnswerToDifferentOfferedProtos) {
1053 // Need to enable DTLS offer/answer generation (disabled by default in this
1054 // test).
1055 f1_.set_secure(SEC_ENABLED);
1056 f2_.set_secure(SEC_ENABLED);
1057 tdf1_.set_secure(SEC_ENABLED);
1058 tdf2_.set_secure(SEC_ENABLED);
1059
1060 MediaSessionOptions opts;
1061 opts.data_channel_type = cricket::DCT_SCTP;
1062 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1063 ASSERT_TRUE(offer.get() != nullptr);
1064 ContentInfo* dc_offer = offer->GetContentByName("data");
1065 ASSERT_TRUE(dc_offer != nullptr);
1066 DataContentDescription* dcd_offer =
1067 static_cast<DataContentDescription*>(dc_offer->description);
1068
1069 std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
1070 "TCP/DTLS/SCTP"};
1071 for (const std::string& proto : protos) {
1072 dcd_offer->set_protocol(proto);
1073 std::unique_ptr<SessionDescription> answer(
1074 f2_.CreateAnswer(offer.get(), opts, nullptr));
1075 const ContentInfo* dc_answer = answer->GetContentByName("data");
1076 ASSERT_TRUE(dc_answer != nullptr);
1077 const DataContentDescription* dcd_answer =
1078 static_cast<const DataContentDescription*>(dc_answer->description);
1079 EXPECT_FALSE(dc_answer->rejected);
1080 EXPECT_EQ(proto, dcd_answer->protocol());
1081 }
1082}
1083
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001084// Verifies that the order of the media contents in the offer is preserved in
1085// the answer.
1086TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
1087 MediaSessionOptions opts;
1088
1089 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001090 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001091 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -08001092 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001093 ASSERT_TRUE(offer1.get() != NULL);
1094
1095 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001096 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -08001097 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001098 f1_.CreateOffer(opts, offer1.get()));
1099 ASSERT_TRUE(offer2.get() != NULL);
1100
1101 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001102 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001103 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001104 f1_.CreateOffer(opts, offer2.get()));
1105 ASSERT_TRUE(offer3.get() != NULL);
1106
kwiberg31022942016-03-11 14:18:21 -08001107 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +00001108 f2_.CreateAnswer(offer3.get(), opts, NULL));
1109 ASSERT_TRUE(answer.get() != NULL);
1110 EXPECT_EQ(3u, answer->contents().size());
1111 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1112 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1113 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1114}
1115
ossu075af922016-06-14 03:29:38 -07001116// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1117// answerer settings.
1118
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001119// This test that the media direction is set to send/receive in an answer if
1120// the offer is send receive.
1121TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
1122 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
1123}
1124
1125// This test that the media direction is set to receive only in an answer if
1126// the offer is send only.
1127TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
1128 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
1129}
1130
1131// This test that the media direction is set to send only in an answer if
1132// the offer is recv only.
1133TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
1134 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
1135}
1136
1137// This test that the media direction is set to inactive in an answer if
1138// the offer is inactive.
1139TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
1140 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
1141}
1142
1143// Test that a data content with an unknown protocol is rejected in an answer.
1144TEST_F(MediaSessionDescriptionFactoryTest,
1145 CreateDataAnswerToOfferWithUnknownProtocol) {
1146 MediaSessionOptions opts;
1147 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001148 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149 f1_.set_secure(SEC_ENABLED);
1150 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001151 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001152 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001153 ASSERT_TRUE(dc_offer != NULL);
1154 DataContentDescription* dcd_offer =
1155 static_cast<DataContentDescription*>(dc_offer->description);
1156 ASSERT_TRUE(dcd_offer != NULL);
1157 std::string protocol = "a weird unknown protocol";
1158 dcd_offer->set_protocol(protocol);
1159
kwiberg31022942016-03-11 14:18:21 -08001160 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161 f2_.CreateAnswer(offer.get(), opts, NULL));
1162
1163 const ContentInfo* dc_answer = answer->GetContentByName("data");
1164 ASSERT_TRUE(dc_answer != NULL);
1165 EXPECT_TRUE(dc_answer->rejected);
1166 const DataContentDescription* dcd_answer =
1167 static_cast<const DataContentDescription*>(dc_answer->description);
1168 ASSERT_TRUE(dcd_answer != NULL);
1169 EXPECT_EQ(protocol, dcd_answer->protocol());
1170}
1171
1172// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1173TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
1174 MediaSessionOptions opts;
1175 f1_.set_secure(SEC_DISABLED);
1176 f2_.set_secure(SEC_DISABLED);
1177 tdf1_.set_secure(SEC_DISABLED);
1178 tdf2_.set_secure(SEC_DISABLED);
1179
kwiberg31022942016-03-11 14:18:21 -08001180 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001181 const AudioContentDescription* offer_acd =
1182 GetFirstAudioContentDescription(offer.get());
1183 ASSERT_TRUE(offer_acd != NULL);
1184 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1185
kwiberg31022942016-03-11 14:18:21 -08001186 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187 f2_.CreateAnswer(offer.get(), opts, NULL));
1188
1189 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1190 ASSERT_TRUE(ac_answer != NULL);
1191 EXPECT_FALSE(ac_answer->rejected);
1192
1193 const AudioContentDescription* answer_acd =
1194 GetFirstAudioContentDescription(answer.get());
1195 ASSERT_TRUE(answer_acd != NULL);
1196 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1197}
1198
1199// Create a video offer and answer and ensure the RTP header extensions
1200// matches what we expect.
1201TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1202 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001203 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204
1205 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1206 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1207 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1208 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1209
kwiberg31022942016-03-11 14:18:21 -08001210 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001211 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001212 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213 f2_.CreateAnswer(offer.get(), opts, NULL));
1214
1215 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1216 GetFirstAudioContentDescription(
1217 offer.get())->rtp_header_extensions());
1218 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1219 GetFirstVideoContentDescription(
1220 offer.get())->rtp_header_extensions());
1221 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1222 GetFirstAudioContentDescription(
1223 answer.get())->rtp_header_extensions());
1224 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1225 GetFirstVideoContentDescription(
1226 answer.get())->rtp_header_extensions());
1227}
1228
jbauch5869f502017-06-29 12:31:36 -07001229TEST_F(MediaSessionDescriptionFactoryTest,
1230 TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
1231 MediaSessionOptions opts;
1232 opts.recv_video = true;
1233
1234 f1_.set_enable_encrypted_rtp_header_extensions(true);
1235 f2_.set_enable_encrypted_rtp_header_extensions(true);
1236
1237 f1_.set_audio_rtp_header_extensions(
1238 MAKE_VECTOR(kAudioRtpExtension1));
1239 f1_.set_video_rtp_header_extensions(
1240 MAKE_VECTOR(kVideoRtpExtension1));
1241 f2_.set_audio_rtp_header_extensions(
1242 MAKE_VECTOR(kAudioRtpExtension2));
1243 f2_.set_video_rtp_header_extensions(
1244 MAKE_VECTOR(kVideoRtpExtension2));
1245
1246 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1247 ASSERT_TRUE(offer.get() != NULL);
1248 std::unique_ptr<SessionDescription> answer(
1249 f2_.CreateAnswer(offer.get(), opts, NULL));
1250
1251 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1252 GetFirstAudioContentDescription(
1253 offer.get())->rtp_header_extensions());
1254 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1255 GetFirstVideoContentDescription(
1256 offer.get())->rtp_header_extensions());
1257 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionEncryptedAnswer),
1258 GetFirstAudioContentDescription(
1259 answer.get())->rtp_header_extensions());
1260 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionEncryptedAnswer),
1261 GetFirstVideoContentDescription(
1262 answer.get())->rtp_header_extensions());
1263}
1264
1265TEST_F(MediaSessionDescriptionFactoryTest,
1266 TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
1267 MediaSessionOptions opts;
1268 opts.recv_video = true;
1269
1270 f1_.set_enable_encrypted_rtp_header_extensions(true);
1271
1272 f1_.set_audio_rtp_header_extensions(
1273 MAKE_VECTOR(kAudioRtpExtension1));
1274 f1_.set_video_rtp_header_extensions(
1275 MAKE_VECTOR(kVideoRtpExtension1));
1276 f2_.set_audio_rtp_header_extensions(
1277 MAKE_VECTOR(kAudioRtpExtension2));
1278 f2_.set_video_rtp_header_extensions(
1279 MAKE_VECTOR(kVideoRtpExtension2));
1280
1281 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1282 ASSERT_TRUE(offer.get() != NULL);
1283 std::unique_ptr<SessionDescription> answer(
1284 f2_.CreateAnswer(offer.get(), opts, NULL));
1285
1286 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionEncrypted1),
1287 GetFirstAudioContentDescription(
1288 offer.get())->rtp_header_extensions());
1289 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionEncrypted1),
1290 GetFirstVideoContentDescription(
1291 offer.get())->rtp_header_extensions());
1292 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1293 GetFirstAudioContentDescription(
1294 answer.get())->rtp_header_extensions());
1295 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1296 GetFirstVideoContentDescription(
1297 answer.get())->rtp_header_extensions());
1298}
1299
1300TEST_F(MediaSessionDescriptionFactoryTest,
1301 TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
1302 MediaSessionOptions opts;
1303 opts.recv_video = true;
1304
1305 f2_.set_enable_encrypted_rtp_header_extensions(true);
1306
1307 f1_.set_audio_rtp_header_extensions(
1308 MAKE_VECTOR(kAudioRtpExtension1));
1309 f1_.set_video_rtp_header_extensions(
1310 MAKE_VECTOR(kVideoRtpExtension1));
1311 f2_.set_audio_rtp_header_extensions(
1312 MAKE_VECTOR(kAudioRtpExtension2));
1313 f2_.set_video_rtp_header_extensions(
1314 MAKE_VECTOR(kVideoRtpExtension2));
1315
1316 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1317 ASSERT_TRUE(offer.get() != NULL);
1318 std::unique_ptr<SessionDescription> answer(
1319 f2_.CreateAnswer(offer.get(), opts, NULL));
1320
1321 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1322 GetFirstAudioContentDescription(
1323 offer.get())->rtp_header_extensions());
1324 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1325 GetFirstVideoContentDescription(
1326 offer.get())->rtp_header_extensions());
1327 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1328 GetFirstAudioContentDescription(
1329 answer.get())->rtp_header_extensions());
1330 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1331 GetFirstVideoContentDescription(
1332 answer.get())->rtp_header_extensions());
1333}
1334
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335// Create an audio, video, data answer without legacy StreamParams.
1336TEST_F(MediaSessionDescriptionFactoryTest,
1337 TestCreateAnswerWithoutLegacyStreams) {
1338 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001339 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340 opts.data_channel_type = cricket::DCT_RTP;
1341 f1_.set_add_legacy_streams(false);
1342 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -08001343 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001344 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001345 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001346 f2_.CreateAnswer(offer.get(), opts, NULL));
1347 const ContentInfo* ac = answer->GetContentByName("audio");
1348 const ContentInfo* vc = answer->GetContentByName("video");
1349 const ContentInfo* dc = answer->GetContentByName("data");
1350 ASSERT_TRUE(ac != NULL);
1351 ASSERT_TRUE(vc != NULL);
1352 const AudioContentDescription* acd =
1353 static_cast<const AudioContentDescription*>(ac->description);
1354 const VideoContentDescription* vcd =
1355 static_cast<const VideoContentDescription*>(vc->description);
1356 const DataContentDescription* dcd =
1357 static_cast<const DataContentDescription*>(dc->description);
1358
1359 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1360 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1361 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1362}
1363
1364TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1365 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001366 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367 opts.data_channel_type = cricket::DCT_RTP;
1368 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001369 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001370 ASSERT_TRUE(offer.get() != NULL);
1371 const ContentInfo* ac = offer->GetContentByName("audio");
1372 const ContentInfo* vc = offer->GetContentByName("video");
1373 const ContentInfo* dc = offer->GetContentByName("data");
1374 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1375 static_cast<const AudioContentDescription*>(ac->description));
1376 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1377 static_cast<const VideoContentDescription*>(vc->description));
1378 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1379 static_cast<const DataContentDescription*>(dc->description));
1380
1381 EXPECT_FALSE(acd->partial()); // default is false.
1382 acd->set_partial(true);
1383 EXPECT_TRUE(acd->partial());
1384 acd->set_partial(false);
1385 EXPECT_FALSE(acd->partial());
1386
1387 EXPECT_FALSE(vcd->partial()); // default is false.
1388 vcd->set_partial(true);
1389 EXPECT_TRUE(vcd->partial());
1390 vcd->set_partial(false);
1391 EXPECT_FALSE(vcd->partial());
1392
1393 EXPECT_FALSE(dcd->partial()); // default is false.
1394 dcd->set_partial(true);
1395 EXPECT_TRUE(dcd->partial());
1396 dcd->set_partial(false);
1397 EXPECT_FALSE(dcd->partial());
1398}
1399
1400// Create a typical video answer, and ensure it matches what we expect.
1401TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1402 MediaSessionOptions offer_opts;
1403 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001404 answer_opts.recv_video = true;
1405 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001406 answer_opts.data_channel_type = cricket::DCT_RTP;
1407 offer_opts.data_channel_type = cricket::DCT_RTP;
1408
kwiberg31022942016-03-11 14:18:21 -08001409 std::unique_ptr<SessionDescription> offer;
1410 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001411
1412 offer_opts.rtcp_mux_enabled = true;
1413 answer_opts.rtcp_mux_enabled = true;
1414
1415 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1416 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1417 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1418 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1419 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1420 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1421 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1422 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1423 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1424 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1425 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1426 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1427 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1428 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1429
1430 offer_opts.rtcp_mux_enabled = true;
1431 answer_opts.rtcp_mux_enabled = false;
1432
1433 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1434 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1435 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1436 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1437 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1438 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1439 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1440 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1441 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1442 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1443 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1444 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1445 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1446 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1447
1448 offer_opts.rtcp_mux_enabled = false;
1449 answer_opts.rtcp_mux_enabled = true;
1450
1451 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1452 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1453 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1454 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1455 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1456 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1457 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1458 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1459 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1460 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1461 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1462 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1463 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1464 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1465
1466 offer_opts.rtcp_mux_enabled = false;
1467 answer_opts.rtcp_mux_enabled = false;
1468
1469 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1470 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1471 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1472 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1473 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1474 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1475 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1476 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1477 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1478 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1479 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1480 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1481 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1482 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1483}
1484
1485// Create an audio-only answer to a video offer.
1486TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1487 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001488 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001489 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001490 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001491 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001492 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1493 const ContentInfo* ac = answer->GetContentByName("audio");
1494 const ContentInfo* vc = answer->GetContentByName("video");
1495 ASSERT_TRUE(ac != NULL);
1496 ASSERT_TRUE(vc != NULL);
1497 ASSERT_TRUE(vc->description != NULL);
1498 EXPECT_TRUE(vc->rejected);
1499}
1500
1501// Create an audio-only answer to an offer with data.
1502TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1503 MediaSessionOptions opts;
1504 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001505 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001507 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1509 const ContentInfo* ac = answer->GetContentByName("audio");
1510 const ContentInfo* dc = answer->GetContentByName("data");
1511 ASSERT_TRUE(ac != NULL);
1512 ASSERT_TRUE(dc != NULL);
1513 ASSERT_TRUE(dc->description != NULL);
1514 EXPECT_TRUE(dc->rejected);
1515}
1516
1517// Create an answer that rejects the contents which are rejected in the offer.
1518TEST_F(MediaSessionDescriptionFactoryTest,
1519 CreateAnswerToOfferWithRejectedMedia) {
1520 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001521 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001522 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001523 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 ASSERT_TRUE(offer.get() != NULL);
1525 ContentInfo* ac = offer->GetContentByName("audio");
1526 ContentInfo* vc = offer->GetContentByName("video");
1527 ContentInfo* dc = offer->GetContentByName("data");
1528 ASSERT_TRUE(ac != NULL);
1529 ASSERT_TRUE(vc != NULL);
1530 ASSERT_TRUE(dc != NULL);
1531 ac->rejected = true;
1532 vc->rejected = true;
1533 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001534 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001535 f2_.CreateAnswer(offer.get(), opts, NULL));
1536 ac = answer->GetContentByName("audio");
1537 vc = answer->GetContentByName("video");
1538 dc = answer->GetContentByName("data");
1539 ASSERT_TRUE(ac != NULL);
1540 ASSERT_TRUE(vc != NULL);
1541 ASSERT_TRUE(dc != NULL);
1542 EXPECT_TRUE(ac->rejected);
1543 EXPECT_TRUE(vc->rejected);
1544 EXPECT_TRUE(dc->rejected);
1545}
1546
1547// Create an audio and video offer with:
1548// - one video track
1549// - two audio tracks
1550// - two data tracks
1551// and ensure it matches what we expect. Also updates the initial offer by
1552// adding a new video track and replaces one of the audio tracks.
1553TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1554 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001555 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1556 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1557 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001559 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1560 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561
1562 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001563 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564
1565 ASSERT_TRUE(offer.get() != NULL);
1566 const ContentInfo* ac = offer->GetContentByName("audio");
1567 const ContentInfo* vc = offer->GetContentByName("video");
1568 const ContentInfo* dc = offer->GetContentByName("data");
1569 ASSERT_TRUE(ac != NULL);
1570 ASSERT_TRUE(vc != NULL);
1571 ASSERT_TRUE(dc != NULL);
1572 const AudioContentDescription* acd =
1573 static_cast<const AudioContentDescription*>(ac->description);
1574 const VideoContentDescription* vcd =
1575 static_cast<const VideoContentDescription*>(vc->description);
1576 const DataContentDescription* dcd =
1577 static_cast<const DataContentDescription*>(dc->description);
1578 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001579 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580
1581 const StreamParamsVec& audio_streams = acd->streams();
1582 ASSERT_EQ(2U, audio_streams.size());
1583 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1584 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1585 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1586 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1587 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1588 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1589 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1590
1591 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1592 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1593 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1594
1595 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1596 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1597 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1598
1599 const StreamParamsVec& video_streams = vcd->streams();
1600 ASSERT_EQ(1U, video_streams.size());
1601 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1602 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1603 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1604 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1605
1606 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1607 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1608 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1609
1610 const StreamParamsVec& data_streams = dcd->streams();
1611 ASSERT_EQ(2U, data_streams.size());
1612 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1613 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1614 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1615 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1616 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1617 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1618 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1619
1620 EXPECT_EQ(cricket::kDataMaxBandwidth,
1621 dcd->bandwidth()); // default bandwidth (auto)
1622 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1623 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1624
1625
1626 // Update the offer. Add a new video track that is not synched to the
1627 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001628 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1629 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1630 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1631 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1632 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001633 std::unique_ptr<SessionDescription> updated_offer(
1634 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635
1636 ASSERT_TRUE(updated_offer.get() != NULL);
1637 ac = updated_offer->GetContentByName("audio");
1638 vc = updated_offer->GetContentByName("video");
1639 dc = updated_offer->GetContentByName("data");
1640 ASSERT_TRUE(ac != NULL);
1641 ASSERT_TRUE(vc != NULL);
1642 ASSERT_TRUE(dc != NULL);
1643 const AudioContentDescription* updated_acd =
1644 static_cast<const AudioContentDescription*>(ac->description);
1645 const VideoContentDescription* updated_vcd =
1646 static_cast<const VideoContentDescription*>(vc->description);
1647 const DataContentDescription* updated_dcd =
1648 static_cast<const DataContentDescription*>(dc->description);
1649
1650 EXPECT_EQ(acd->type(), updated_acd->type());
1651 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1652 EXPECT_EQ(vcd->type(), updated_vcd->type());
1653 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1654 EXPECT_EQ(dcd->type(), updated_dcd->type());
1655 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1656 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1657 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1658 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1659 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1660 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1661 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1662
1663 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1664 ASSERT_EQ(2U, updated_audio_streams.size());
1665 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1666 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1667 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1668 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1669 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1670
1671 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1672 ASSERT_EQ(2U, updated_video_streams.size());
1673 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1674 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001675 // All the media streams in one PeerConnection share one RTCP CNAME.
1676 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001677
1678 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1679 ASSERT_EQ(2U, updated_data_streams.size());
1680 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1681 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1682 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1683 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1684 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001685 // The stream correctly got the CNAME from the MediaSessionOptions.
1686 // The Expected RTCP CNAME is the default one as we are using the default
1687 // MediaSessionOptions.
1688 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001689}
1690
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001691// Create an offer with simulcast video stream.
1692TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1693 MediaSessionOptions opts;
1694 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001695 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001696 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001697
1698 ASSERT_TRUE(offer.get() != NULL);
1699 const ContentInfo* vc = offer->GetContentByName("video");
1700 ASSERT_TRUE(vc != NULL);
1701 const VideoContentDescription* vcd =
1702 static_cast<const VideoContentDescription*>(vc->description);
1703
1704 const StreamParamsVec& video_streams = vcd->streams();
1705 ASSERT_EQ(1U, video_streams.size());
1706 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1707 const SsrcGroup* sim_ssrc_group =
1708 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1709 ASSERT_TRUE(sim_ssrc_group != NULL);
1710 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1711}
1712
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001713// Create an audio and video answer to a standard video offer with:
1714// - one video track
1715// - two audio tracks
1716// - two data tracks
1717// and ensure it matches what we expect. Also updates the initial answer by
1718// adding a new video track and removes one of the audio tracks.
1719TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1720 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001721 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722 offer_opts.data_channel_type = cricket::DCT_RTP;
1723 f1_.set_secure(SEC_ENABLED);
1724 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001725 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001726
1727 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001728 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1729 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1730 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001731 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001732 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1733 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001734
kwiberg31022942016-03-11 14:18:21 -08001735 std::unique_ptr<SessionDescription> answer(
1736 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001737
1738 ASSERT_TRUE(answer.get() != NULL);
1739 const ContentInfo* ac = answer->GetContentByName("audio");
1740 const ContentInfo* vc = answer->GetContentByName("video");
1741 const ContentInfo* dc = answer->GetContentByName("data");
1742 ASSERT_TRUE(ac != NULL);
1743 ASSERT_TRUE(vc != NULL);
1744 ASSERT_TRUE(dc != NULL);
1745 const AudioContentDescription* acd =
1746 static_cast<const AudioContentDescription*>(ac->description);
1747 const VideoContentDescription* vcd =
1748 static_cast<const VideoContentDescription*>(vc->description);
1749 const DataContentDescription* dcd =
1750 static_cast<const DataContentDescription*>(dc->description);
1751 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1752 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1753 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1754
1755 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1756 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1757
1758 const StreamParamsVec& audio_streams = acd->streams();
1759 ASSERT_EQ(2U, audio_streams.size());
1760 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1761 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1762 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1763 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1764 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1765 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1766 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1767
1768 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1769 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1770
1771 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1772 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1773
1774 const StreamParamsVec& video_streams = vcd->streams();
1775 ASSERT_EQ(1U, video_streams.size());
1776 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1777 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1778 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1779 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1780
1781 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1782 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1783
1784 const StreamParamsVec& data_streams = dcd->streams();
1785 ASSERT_EQ(2U, data_streams.size());
1786 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1787 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1788 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1789 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1790 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1791 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1792 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1793
1794 EXPECT_EQ(cricket::kDataMaxBandwidth,
1795 dcd->bandwidth()); // default bandwidth (auto)
1796 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1797
1798 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001799 // other tracks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001800 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1801 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1802 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001803 std::unique_ptr<SessionDescription> updated_answer(
1804 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001805
1806 ASSERT_TRUE(updated_answer.get() != NULL);
1807 ac = updated_answer->GetContentByName("audio");
1808 vc = updated_answer->GetContentByName("video");
1809 dc = updated_answer->GetContentByName("data");
1810 ASSERT_TRUE(ac != NULL);
1811 ASSERT_TRUE(vc != NULL);
1812 ASSERT_TRUE(dc != NULL);
1813 const AudioContentDescription* updated_acd =
1814 static_cast<const AudioContentDescription*>(ac->description);
1815 const VideoContentDescription* updated_vcd =
1816 static_cast<const VideoContentDescription*>(vc->description);
1817 const DataContentDescription* updated_dcd =
1818 static_cast<const DataContentDescription*>(dc->description);
1819
1820 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1821 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1822 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1823 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1824 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1825 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1826
1827 EXPECT_EQ(acd->type(), updated_acd->type());
1828 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1829 EXPECT_EQ(vcd->type(), updated_vcd->type());
1830 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1831 EXPECT_EQ(dcd->type(), updated_dcd->type());
1832 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1833
1834 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1835 ASSERT_EQ(1U, updated_audio_streams.size());
1836 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1837
1838 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1839 ASSERT_EQ(2U, updated_video_streams.size());
1840 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1841 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001842 // All media streams in one PeerConnection share one CNAME.
1843 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001844
1845 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1846 ASSERT_EQ(1U, updated_data_streams.size());
1847 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1848}
1849
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001850// Create an updated offer after creating an answer to the original offer and
1851// verify that the codecs that were part of the original answer are not changed
1852// in the updated offer.
1853TEST_F(MediaSessionDescriptionFactoryTest,
1854 RespondentCreatesOfferAfterCreatingAnswer) {
1855 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001856 opts.recv_audio = true;
1857 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001858
kwiberg31022942016-03-11 14:18:21 -08001859 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1860 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001861 f2_.CreateAnswer(offer.get(), opts, NULL));
1862
1863 const AudioContentDescription* acd =
1864 GetFirstAudioContentDescription(answer.get());
1865 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1866
1867 const VideoContentDescription* vcd =
1868 GetFirstVideoContentDescription(answer.get());
1869 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1870
kwiberg31022942016-03-11 14:18:21 -08001871 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001872 f2_.CreateOffer(opts, answer.get()));
1873
1874 // The expected audio codecs are the common audio codecs from the first
1875 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1876 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001877 // TODO(wu): |updated_offer| should not include the codec
1878 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001879 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880 kAudioCodecsAnswer[0],
1881 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001882 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001883 };
1884
1885 // The expected video codecs are the common video codecs from the first
1886 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1887 // preference order.
1888 const VideoCodec kUpdatedVideoCodecOffer[] = {
1889 kVideoCodecsAnswer[0],
1890 kVideoCodecs2[1],
1891 };
1892
1893 const AudioContentDescription* updated_acd =
1894 GetFirstAudioContentDescription(updated_offer.get());
1895 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1896
1897 const VideoContentDescription* updated_vcd =
1898 GetFirstVideoContentDescription(updated_offer.get());
1899 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1900}
1901
1902// Create an updated offer after creating an answer to the original offer and
1903// verify that the codecs that were part of the original answer are not changed
1904// in the updated offer. In this test Rtx is enabled.
1905TEST_F(MediaSessionDescriptionFactoryTest,
1906 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1907 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001908 opts.recv_video = true;
1909 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001910 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001911 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001912 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001913 f1_.set_video_codecs(f1_codecs);
1914
1915 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001916 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001917 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001918 f2_.set_video_codecs(f2_codecs);
1919
kwiberg31022942016-03-11 14:18:21 -08001920 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001921 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001922 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001923 f2_.CreateAnswer(offer.get(), opts, NULL));
1924
1925 const VideoContentDescription* vcd =
1926 GetFirstVideoContentDescription(answer.get());
1927
1928 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001929 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1930 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001931
1932 EXPECT_EQ(expected_codecs, vcd->codecs());
1933
deadbeef67cf2c12016-04-13 10:07:16 -07001934 // Now, make sure we get same result (except for the order) if |f2_| creates
1935 // an updated offer even though the default payload types between |f1_| and
1936 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001937 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001938 f2_.CreateOffer(opts, answer.get()));
1939 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001940 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001941 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1942
1943 const VideoContentDescription* updated_vcd =
1944 GetFirstVideoContentDescription(updated_answer.get());
1945
1946 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1947}
1948
1949// Create an updated offer that adds video after creating an audio only answer
1950// to the original offer. This test verifies that if a video codec and the RTX
1951// codec have the same default payload type as an audio codec that is already in
1952// use, the added codecs payload types are changed.
1953TEST_F(MediaSessionDescriptionFactoryTest,
1954 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1955 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001956 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001957 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001958 f1_.set_video_codecs(f1_codecs);
1959
1960 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001961 opts.recv_audio = true;
1962 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001963
kwiberg31022942016-03-11 14:18:21 -08001964 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1965 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001966 f2_.CreateAnswer(offer.get(), opts, NULL));
1967
1968 const AudioContentDescription* acd =
1969 GetFirstAudioContentDescription(answer.get());
1970 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1971
1972 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1973 // reference be the same as an audio codec that was negotiated in the
1974 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001975 opts.recv_audio = true;
1976 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001977
1978 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1979 int used_pl_type = acd->codecs()[0].id;
1980 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001981 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001982 f2_.set_video_codecs(f2_codecs);
1983
kwiberg31022942016-03-11 14:18:21 -08001984 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001985 f2_.CreateOffer(opts, answer.get()));
1986 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001987 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001988 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1989
1990 const AudioContentDescription* updated_acd =
1991 GetFirstAudioContentDescription(answer.get());
1992 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1993
1994 const VideoContentDescription* updated_vcd =
1995 GetFirstVideoContentDescription(updated_answer.get());
1996
1997 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001998 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001999 int new_h264_pl_type = updated_vcd->codecs()[0].id;
2000 EXPECT_NE(used_pl_type, new_h264_pl_type);
2001 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002002 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002003 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
2004 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
2005}
2006
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002007// Create an updated offer with RTX after creating an answer to an offer
2008// without RTX, and with different default payload types.
2009// Verify that the added RTX codec references the correct payload type.
2010TEST_F(MediaSessionDescriptionFactoryTest,
2011 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
2012 MediaSessionOptions opts;
2013 opts.recv_video = true;
2014 opts.recv_audio = true;
2015
2016 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2017 // This creates rtx for H264 with the payload type |f2_| uses.
2018 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
2019 f2_.set_video_codecs(f2_codecs);
2020
kwiberg31022942016-03-11 14:18:21 -08002021 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002022 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08002023 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002024 f2_.CreateAnswer(offer.get(), opts, nullptr));
2025
2026 const VideoContentDescription* vcd =
2027 GetFirstVideoContentDescription(answer.get());
2028
2029 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2030 EXPECT_EQ(expected_codecs, vcd->codecs());
2031
2032 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
2033 // updated offer, even though the default payload types are different from
2034 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08002035 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002036 f2_.CreateOffer(opts, answer.get()));
2037 ASSERT_TRUE(updated_offer);
2038
2039 const VideoContentDescription* updated_vcd =
2040 GetFirstVideoContentDescription(updated_offer.get());
2041
2042 // New offer should attempt to add H263, and RTX for H264.
2043 expected_codecs.push_back(kVideoCodecs2[1]);
2044 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
2045 &expected_codecs);
2046 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
2047}
2048
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049// Test that RTX is ignored when there is no associated payload type parameter.
2050TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
2051 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002052 opts.recv_video = true;
2053 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002054 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002055 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07002056 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002057 f1_.set_video_codecs(f1_codecs);
2058
2059 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002060 // This creates RTX for H264 with the payload type |f2_| uses.
2061 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002062 f2_.set_video_codecs(f2_codecs);
2063
kwiberg31022942016-03-11 14:18:21 -08002064 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 ASSERT_TRUE(offer.get() != NULL);
2066 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
2067 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
2068 // is possible to test that that RTX is dropped when
2069 // kCodecParamAssociatedPayloadType is missing in the offer.
2070 VideoContentDescription* desc =
2071 static_cast<cricket::VideoContentDescription*>(
2072 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2073 ASSERT_TRUE(desc != NULL);
2074 std::vector<VideoCodec> codecs = desc->codecs();
2075 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
2076 iter != codecs.end(); ++iter) {
2077 if (iter->name.find(cricket::kRtxCodecName) == 0) {
2078 iter->params.clear();
2079 }
2080 }
2081 desc->set_codecs(codecs);
2082
kwiberg31022942016-03-11 14:18:21 -08002083 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002084 f2_.CreateAnswer(offer.get(), opts, NULL));
2085
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002086 std::vector<std::string> codec_names =
2087 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2088 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2089 cricket::kRtxCodecName));
2090}
2091
2092// Test that RTX will be filtered out in the answer if its associated payload
2093// type doesn't match the local value.
2094TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
2095 MediaSessionOptions opts;
2096 opts.recv_video = true;
2097 opts.recv_audio = false;
2098 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2099 // This creates RTX for H264 in sender.
2100 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2101 f1_.set_video_codecs(f1_codecs);
2102
2103 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2104 // This creates RTX for H263 in receiver.
2105 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
2106 f2_.set_video_codecs(f2_codecs);
2107
kwiberg31022942016-03-11 14:18:21 -08002108 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002109 ASSERT_TRUE(offer.get() != NULL);
2110 // Associated payload type doesn't match, therefore, RTX codec is removed in
2111 // the answer.
kwiberg31022942016-03-11 14:18:21 -08002112 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002113 f2_.CreateAnswer(offer.get(), opts, NULL));
2114
2115 std::vector<std::string> codec_names =
2116 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
2117 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
2118 cricket::kRtxCodecName));
2119}
2120
2121// Test that when multiple RTX codecs are offered, only the matched RTX codec
2122// is added in the answer, and the unsupported RTX codec is filtered out.
2123TEST_F(MediaSessionDescriptionFactoryTest,
2124 FilterOutUnsupportedRtxWhenCreatingAnswer) {
2125 MediaSessionOptions opts;
2126 opts.recv_video = true;
2127 opts.recv_audio = false;
2128 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2129 // This creates RTX for H264-SVC in sender.
2130 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2131 f1_.set_video_codecs(f1_codecs);
2132
2133 // This creates RTX for H264 in sender.
2134 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2135 f1_.set_video_codecs(f1_codecs);
2136
2137 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
2138 // This creates RTX for H264 in receiver.
2139 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
2140 f2_.set_video_codecs(f2_codecs);
2141
2142 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
2143 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08002144 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002145 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002146 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002147 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002148 const VideoContentDescription* vcd =
2149 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002150 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
2151 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2152 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002153
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00002154 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002155}
2156
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002157// Test that after one RTX codec has been negotiated, a new offer can attempt
2158// to add another.
2159TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
2160 MediaSessionOptions opts;
2161 opts.recv_video = true;
2162 opts.recv_audio = false;
2163 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
2164 // This creates RTX for H264 for the offerer.
2165 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
2166 f1_.set_video_codecs(f1_codecs);
2167
kwiberg31022942016-03-11 14:18:21 -08002168 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002169 ASSERT_TRUE(offer);
2170 const VideoContentDescription* vcd =
2171 GetFirstVideoContentDescription(offer.get());
2172
2173 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
2174 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
2175 &expected_codecs);
2176 EXPECT_EQ(expected_codecs, vcd->codecs());
2177
2178 // Now, attempt to add RTX for H264-SVC.
2179 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
2180 f1_.set_video_codecs(f1_codecs);
2181
kwiberg31022942016-03-11 14:18:21 -08002182 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08002183 f1_.CreateOffer(opts, offer.get()));
2184 ASSERT_TRUE(updated_offer);
2185 vcd = GetFirstVideoContentDescription(updated_offer.get());
2186
2187 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
2188 &expected_codecs);
2189 EXPECT_EQ(expected_codecs, vcd->codecs());
2190}
2191
Noah Richards2e7a0982015-05-18 14:02:54 -07002192// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
2193// generated for each simulcast ssrc and correctly grouped.
2194TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
2195 MediaSessionOptions opts;
2196 opts.recv_video = true;
2197 opts.recv_audio = false;
2198
2199 // Add simulcast streams.
2200 opts.AddSendVideoStream("stream1", "stream1label", 3);
2201
2202 // Use a single real codec, and then add RTX for it.
2203 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07002204 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07002205 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
2206 f1_.set_video_codecs(f1_codecs);
2207
2208 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
2209 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08002210 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07002211 ASSERT_TRUE(offer.get() != NULL);
2212 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2213 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2214 ASSERT_TRUE(desc != NULL);
2215 EXPECT_TRUE(desc->multistream());
2216 const StreamParamsVec& streams = desc->streams();
2217 // Single stream.
2218 ASSERT_EQ(1u, streams.size());
2219 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2220 EXPECT_EQ(6u, streams[0].ssrcs.size());
2221 // And should have a SIM group for the simulcast.
2222 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2223 // And a FID group for RTX.
2224 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002225 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002226 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2227 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002228 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002229 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2230 EXPECT_EQ(3u, fid_ssrcs.size());
2231}
2232
brandtr03d5fb12016-11-22 03:37:59 -08002233// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2234// together with a FEC-FR grouping.
2235TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2236 MediaSessionOptions opts;
2237 opts.recv_video = true;
2238 opts.recv_audio = false;
2239
2240 // Add single stream.
2241 opts.AddSendVideoStream("stream1", "stream1label", 1);
2242
2243 // Use a single real codec, and then add FlexFEC for it.
2244 std::vector<VideoCodec> f1_codecs;
2245 f1_codecs.push_back(VideoCodec(97, "H264"));
2246 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2247 f1_.set_video_codecs(f1_codecs);
2248
2249 // Ensure that the offer has a single FlexFEC ssrc and that
2250 // there is no FEC-FR ssrc + grouping for each.
2251 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2252 ASSERT_TRUE(offer.get() != nullptr);
2253 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2254 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2255 ASSERT_TRUE(desc != nullptr);
2256 EXPECT_TRUE(desc->multistream());
2257 const StreamParamsVec& streams = desc->streams();
2258 // Single stream.
2259 ASSERT_EQ(1u, streams.size());
2260 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2261 EXPECT_EQ(2u, streams[0].ssrcs.size());
2262 // And should have a FEC-FR group for FlexFEC.
2263 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2264 std::vector<uint32_t> primary_ssrcs;
2265 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2266 ASSERT_EQ(1u, primary_ssrcs.size());
2267 uint32_t flexfec_ssrc;
2268 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2269 EXPECT_NE(flexfec_ssrc, 0u);
2270}
2271
2272// Test that FlexFEC is disabled for simulcast.
2273// TODO(brandtr): Remove this test when we support simulcast, either through
2274// multiple FlexfecSenders, or through multistream protection.
2275TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2276 MediaSessionOptions opts;
2277 opts.recv_video = true;
2278 opts.recv_audio = false;
2279
2280 // Add simulcast streams.
2281 opts.AddSendVideoStream("stream1", "stream1label", 3);
2282
2283 // Use a single real codec, and then add FlexFEC for it.
2284 std::vector<VideoCodec> f1_codecs;
2285 f1_codecs.push_back(VideoCodec(97, "H264"));
2286 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2287 f1_.set_video_codecs(f1_codecs);
2288
2289 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2290 // there is no FEC-FR ssrc + grouping for each.
2291 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2292 ASSERT_TRUE(offer.get() != nullptr);
2293 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2294 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2295 ASSERT_TRUE(desc != nullptr);
2296 EXPECT_FALSE(desc->multistream());
2297 const StreamParamsVec& streams = desc->streams();
2298 // Single stream.
2299 ASSERT_EQ(1u, streams.size());
2300 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2301 EXPECT_EQ(3u, streams[0].ssrcs.size());
2302 // And should have a SIM group for the simulcast.
2303 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2304 // And not a FEC-FR group for FlexFEC.
2305 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2306 std::vector<uint32_t> primary_ssrcs;
2307 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2308 EXPECT_EQ(3u, primary_ssrcs.size());
2309 for (uint32_t primary_ssrc : primary_ssrcs) {
2310 uint32_t flexfec_ssrc;
2311 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2312 }
2313}
2314
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002315// Create an updated offer after creating an answer to the original offer and
2316// verify that the RTP header extensions that were part of the original answer
2317// are not changed in the updated offer.
2318TEST_F(MediaSessionDescriptionFactoryTest,
2319 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2320 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002321 opts.recv_audio = true;
2322 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002323
2324 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2325 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2326 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2327 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2328
kwiberg31022942016-03-11 14:18:21 -08002329 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2330 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002331 f2_.CreateAnswer(offer.get(), opts, NULL));
2332
2333 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
2334 GetFirstAudioContentDescription(
2335 answer.get())->rtp_header_extensions());
2336 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
2337 GetFirstVideoContentDescription(
2338 answer.get())->rtp_header_extensions());
2339
kwiberg31022942016-03-11 14:18:21 -08002340 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002341 f2_.CreateOffer(opts, answer.get()));
2342
2343 // The expected RTP header extensions in the new offer are the resulting
2344 // extensions from the first offer/answer exchange plus the extensions only
2345 // |f2_| offer.
2346 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002347 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002348 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2349 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2350 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002351 };
2352
2353 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002354 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002355 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2356 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2357 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002358 };
2359
2360 const AudioContentDescription* updated_acd =
2361 GetFirstAudioContentDescription(updated_offer.get());
2362 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2363 updated_acd->rtp_header_extensions());
2364
2365 const VideoContentDescription* updated_vcd =
2366 GetFirstVideoContentDescription(updated_offer.get());
2367 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2368 updated_vcd->rtp_header_extensions());
2369}
2370
deadbeefa5b273a2015-08-20 17:30:13 -07002371// Verify that if the same RTP extension URI is used for audio and video, the
2372// same ID is used. Also verify that the ID isn't changed when creating an
2373// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002374TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002375 MediaSessionOptions opts;
2376 opts.recv_audio = true;
2377 opts.recv_video = true;
2378
2379 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2380 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2381
kwiberg31022942016-03-11 14:18:21 -08002382 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002383
2384 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2385 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002386 const RtpExtension kExpectedVideoRtpExtension[] = {
2387 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002388 };
2389
2390 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2391 GetFirstAudioContentDescription(
2392 offer.get())->rtp_header_extensions());
2393 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2394 GetFirstVideoContentDescription(
2395 offer.get())->rtp_header_extensions());
2396
2397 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002398 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002399 f1_.CreateOffer(opts, offer.get()));
2400
2401 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2402 GetFirstAudioContentDescription(
2403 updated_offer.get())->rtp_header_extensions());
2404 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2405 GetFirstVideoContentDescription(
2406 updated_offer.get())->rtp_header_extensions());
2407}
2408
jbauch5869f502017-06-29 12:31:36 -07002409// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
2410TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
2411 MediaSessionOptions opts;
2412 opts.recv_audio = true;
2413 opts.recv_video = true;
2414
2415 f1_.set_enable_encrypted_rtp_header_extensions(true);
2416 f2_.set_enable_encrypted_rtp_header_extensions(true);
2417
2418 f1_.set_audio_rtp_header_extensions(
2419 MAKE_VECTOR(kAudioRtpExtension3ForEncryption));
2420 f1_.set_video_rtp_header_extensions(
2421 MAKE_VECTOR(kVideoRtpExtension3ForEncryption));
2422
2423 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2424
2425 // The extensions that are shared between audio and video should use the same
2426 // id.
2427 const RtpExtension kExpectedVideoRtpExtension[] = {
2428 kVideoRtpExtension3ForEncryption[0],
2429 kAudioRtpExtension3ForEncryptionOffer[1],
2430 kAudioRtpExtension3ForEncryptionOffer[2],
2431 };
2432
2433 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2434 GetFirstAudioContentDescription(
2435 offer.get())->rtp_header_extensions());
2436 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2437 GetFirstVideoContentDescription(
2438 offer.get())->rtp_header_extensions());
2439
2440 // Nothing should change when creating a new offer
2441 std::unique_ptr<SessionDescription> updated_offer(
2442 f1_.CreateOffer(opts, offer.get()));
2443
2444 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3ForEncryptionOffer),
2445 GetFirstAudioContentDescription(
2446 updated_offer.get())->rtp_header_extensions());
2447 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2448 GetFirstVideoContentDescription(
2449 updated_offer.get())->rtp_header_extensions());
2450}
2451
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002452TEST(MediaSessionDescription, CopySessionDescription) {
2453 SessionDescription source;
2454 cricket::ContentGroup group(cricket::CN_AUDIO);
2455 source.AddGroup(group);
2456 AudioContentDescription* acd(new AudioContentDescription());
2457 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2458 acd->AddLegacyStream(1);
2459 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
2460 VideoContentDescription* vcd(new VideoContentDescription());
2461 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2462 vcd->AddLegacyStream(2);
2463 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
2464
kwiberg31022942016-03-11 14:18:21 -08002465 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002466 ASSERT_TRUE(copy.get() != NULL);
2467 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2468 const ContentInfo* ac = copy->GetContentByName("audio");
2469 const ContentInfo* vc = copy->GetContentByName("video");
2470 ASSERT_TRUE(ac != NULL);
2471 ASSERT_TRUE(vc != NULL);
2472 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
2473 const AudioContentDescription* acd_copy =
2474 static_cast<const AudioContentDescription*>(ac->description);
2475 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2476 EXPECT_EQ(1u, acd->first_ssrc());
2477
2478 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
2479 const VideoContentDescription* vcd_copy =
2480 static_cast<const VideoContentDescription*>(vc->description);
2481 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2482 EXPECT_EQ(2u, vcd->first_ssrc());
2483}
2484
2485// The below TestTransportInfoXXX tests create different offers/answers, and
2486// ensure the TransportInfo in the SessionDescription matches what we expect.
2487TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2488 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002489 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002490 TestTransportInfo(true, options, false);
2491}
2492
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002493TEST_F(MediaSessionDescriptionFactoryTest,
2494 TestTransportInfoOfferIceRenomination) {
2495 MediaSessionOptions options;
2496 options.enable_ice_renomination = true;
2497 TestTransportInfo(true, options, false);
2498}
2499
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002500TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2501 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002502 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002503 TestTransportInfo(true, options, true);
2504}
2505
2506TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2507 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002508 options.recv_audio = true;
2509 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002510 options.data_channel_type = cricket::DCT_RTP;
2511 TestTransportInfo(true, options, false);
2512}
2513
2514TEST_F(MediaSessionDescriptionFactoryTest,
2515 TestTransportInfoOfferMultimediaCurrent) {
2516 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002517 options.recv_audio = true;
2518 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002519 options.data_channel_type = cricket::DCT_RTP;
2520 TestTransportInfo(true, options, true);
2521}
2522
2523TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2524 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002525 options.recv_audio = true;
2526 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002527 options.data_channel_type = cricket::DCT_RTP;
2528 options.bundle_enabled = true;
2529 TestTransportInfo(true, options, false);
2530}
2531
2532TEST_F(MediaSessionDescriptionFactoryTest,
2533 TestTransportInfoOfferBundleCurrent) {
2534 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002535 options.recv_audio = true;
2536 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002537 options.data_channel_type = cricket::DCT_RTP;
2538 options.bundle_enabled = true;
2539 TestTransportInfo(true, options, true);
2540}
2541
2542TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2543 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002544 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002545 TestTransportInfo(false, options, false);
2546}
2547
2548TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002549 TestTransportInfoAnswerIceRenomination) {
2550 MediaSessionOptions options;
2551 options.enable_ice_renomination = true;
2552 TestTransportInfo(false, options, false);
2553}
2554
2555TEST_F(MediaSessionDescriptionFactoryTest,
2556 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002557 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002558 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002559 TestTransportInfo(false, options, true);
2560}
2561
2562TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2563 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002564 options.recv_audio = true;
2565 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002566 options.data_channel_type = cricket::DCT_RTP;
2567 TestTransportInfo(false, options, false);
2568}
2569
2570TEST_F(MediaSessionDescriptionFactoryTest,
2571 TestTransportInfoAnswerMultimediaCurrent) {
2572 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002573 options.recv_audio = true;
2574 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002575 options.data_channel_type = cricket::DCT_RTP;
2576 TestTransportInfo(false, options, true);
2577}
2578
2579TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2580 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002581 options.recv_audio = true;
2582 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002583 options.data_channel_type = cricket::DCT_RTP;
2584 options.bundle_enabled = true;
2585 TestTransportInfo(false, options, false);
2586}
2587
2588TEST_F(MediaSessionDescriptionFactoryTest,
2589 TestTransportInfoAnswerBundleCurrent) {
2590 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002591 options.recv_audio = true;
2592 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002593 options.data_channel_type = cricket::DCT_RTP;
2594 options.bundle_enabled = true;
2595 TestTransportInfo(false, options, true);
2596}
2597
2598// Create an offer with bundle enabled and verify the crypto parameters are
2599// the common set of the available cryptos.
2600TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2601 TestCryptoWithBundle(true);
2602}
2603
2604// Create an answer with bundle enabled and verify the crypto parameters are
2605// the common set of the available cryptos.
2606TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2607 TestCryptoWithBundle(false);
2608}
2609
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002610// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2611// DTLS is not enabled locally.
2612TEST_F(MediaSessionDescriptionFactoryTest,
2613 TestOfferDtlsSavpfWithoutDtlsFailed) {
2614 f1_.set_secure(SEC_ENABLED);
2615 f2_.set_secure(SEC_ENABLED);
2616 tdf1_.set_secure(SEC_DISABLED);
2617 tdf2_.set_secure(SEC_DISABLED);
2618
kwiberg31022942016-03-11 14:18:21 -08002619 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002620 f1_.CreateOffer(MediaSessionOptions(), NULL));
2621 ASSERT_TRUE(offer.get() != NULL);
2622 ContentInfo* offer_content = offer->GetContentByName("audio");
2623 ASSERT_TRUE(offer_content != NULL);
2624 AudioContentDescription* offer_audio_desc =
2625 static_cast<AudioContentDescription*>(offer_content->description);
2626 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2627
kwiberg31022942016-03-11 14:18:21 -08002628 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002629 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2630 ASSERT_TRUE(answer != NULL);
2631 ContentInfo* answer_content = answer->GetContentByName("audio");
2632 ASSERT_TRUE(answer_content != NULL);
2633
2634 ASSERT_TRUE(answer_content->rejected);
2635}
2636
2637// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2638// UDP/TLS/RTP/SAVPF.
2639TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2640 f1_.set_secure(SEC_ENABLED);
2641 f2_.set_secure(SEC_ENABLED);
2642 tdf1_.set_secure(SEC_ENABLED);
2643 tdf2_.set_secure(SEC_ENABLED);
2644
kwiberg31022942016-03-11 14:18:21 -08002645 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002646 f1_.CreateOffer(MediaSessionOptions(), NULL));
2647 ASSERT_TRUE(offer.get() != NULL);
2648 ContentInfo* offer_content = offer->GetContentByName("audio");
2649 ASSERT_TRUE(offer_content != NULL);
2650 AudioContentDescription* offer_audio_desc =
2651 static_cast<AudioContentDescription*>(offer_content->description);
2652 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2653
kwiberg31022942016-03-11 14:18:21 -08002654 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002655 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2656 ASSERT_TRUE(answer != NULL);
2657
2658 const ContentInfo* answer_content = answer->GetContentByName("audio");
2659 ASSERT_TRUE(answer_content != NULL);
2660 ASSERT_FALSE(answer_content->rejected);
2661
2662 const AudioContentDescription* answer_audio_desc =
2663 static_cast<const AudioContentDescription*>(answer_content->description);
2664 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2665 answer_audio_desc->protocol());
2666}
2667
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002668// Test that we include both SDES and DTLS in the offer, but only include SDES
2669// in the answer if DTLS isn't negotiated.
2670TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2671 f1_.set_secure(SEC_ENABLED);
2672 f2_.set_secure(SEC_ENABLED);
2673 tdf1_.set_secure(SEC_ENABLED);
2674 tdf2_.set_secure(SEC_DISABLED);
2675 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002676 options.recv_audio = true;
2677 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002678 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002679 const cricket::MediaContentDescription* audio_media_desc;
2680 const cricket::MediaContentDescription* video_media_desc;
2681 const cricket::TransportDescription* audio_trans_desc;
2682 const cricket::TransportDescription* video_trans_desc;
2683
2684 // Generate an offer with SDES and DTLS support.
2685 offer.reset(f1_.CreateOffer(options, NULL));
2686 ASSERT_TRUE(offer.get() != NULL);
2687
2688 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2689 offer->GetContentDescriptionByName("audio"));
2690 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002691 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002692 offer->GetContentDescriptionByName("video"));
2693 ASSERT_TRUE(video_media_desc != NULL);
2694 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2695 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2696
2697 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2698 ASSERT_TRUE(audio_trans_desc != NULL);
2699 video_trans_desc = offer->GetTransportDescriptionByName("video");
2700 ASSERT_TRUE(video_trans_desc != NULL);
2701 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2702 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2703
2704 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2705 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2706 ASSERT_TRUE(answer.get() != NULL);
2707
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002708 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002709 answer->GetContentDescriptionByName("audio"));
2710 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002711 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002712 answer->GetContentDescriptionByName("video"));
2713 ASSERT_TRUE(video_media_desc != NULL);
2714 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2715 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2716
2717 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2718 ASSERT_TRUE(audio_trans_desc != NULL);
2719 video_trans_desc = answer->GetTransportDescriptionByName("video");
2720 ASSERT_TRUE(video_trans_desc != NULL);
2721 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2722 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2723
2724 // Enable DTLS; the answer should now only have DTLS support.
2725 tdf2_.set_secure(SEC_ENABLED);
2726 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2727 ASSERT_TRUE(answer.get() != NULL);
2728
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002729 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002730 answer->GetContentDescriptionByName("audio"));
2731 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002732 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002733 answer->GetContentDescriptionByName("video"));
2734 ASSERT_TRUE(video_media_desc != NULL);
2735 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2736 EXPECT_TRUE(video_media_desc->cryptos().empty());
2737 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2738 audio_media_desc->protocol());
2739 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2740 video_media_desc->protocol());
2741
2742 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2743 ASSERT_TRUE(audio_trans_desc != NULL);
2744 video_trans_desc = answer->GetTransportDescriptionByName("video");
2745 ASSERT_TRUE(video_trans_desc != NULL);
2746 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2747 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002748
2749 // Try creating offer again. DTLS enabled now, crypto's should be empty
2750 // in new offer.
2751 offer.reset(f1_.CreateOffer(options, offer.get()));
2752 ASSERT_TRUE(offer.get() != NULL);
2753 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2754 offer->GetContentDescriptionByName("audio"));
2755 ASSERT_TRUE(audio_media_desc != NULL);
2756 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2757 offer->GetContentDescriptionByName("video"));
2758 ASSERT_TRUE(video_media_desc != NULL);
2759 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2760 EXPECT_TRUE(video_media_desc->cryptos().empty());
2761
2762 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2763 ASSERT_TRUE(audio_trans_desc != NULL);
2764 video_trans_desc = offer->GetTransportDescriptionByName("video");
2765 ASSERT_TRUE(video_trans_desc != NULL);
2766 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2767 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002768}
2769
2770// Test that an answer can't be created if cryptos are required but the offer is
2771// unsecure.
2772TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2773 MediaSessionOptions options;
2774 f1_.set_secure(SEC_DISABLED);
2775 tdf1_.set_secure(SEC_DISABLED);
2776 f2_.set_secure(SEC_REQUIRED);
2777 tdf1_.set_secure(SEC_ENABLED);
2778
kwiberg31022942016-03-11 14:18:21 -08002779 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002780 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002781 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002782 f2_.CreateAnswer(offer.get(), options, NULL));
2783 EXPECT_TRUE(answer.get() == NULL);
2784}
2785
2786// Test that we accept a DTLS offer without SDES and create an appropriate
2787// answer.
2788TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2789 f1_.set_secure(SEC_DISABLED);
2790 f2_.set_secure(SEC_ENABLED);
2791 tdf1_.set_secure(SEC_ENABLED);
2792 tdf2_.set_secure(SEC_ENABLED);
2793 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002794 options.recv_audio = true;
2795 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002796 options.data_channel_type = cricket::DCT_RTP;
2797
kwiberg31022942016-03-11 14:18:21 -08002798 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002799
2800 // Generate an offer with DTLS but without SDES.
2801 offer.reset(f1_.CreateOffer(options, NULL));
2802 ASSERT_TRUE(offer.get() != NULL);
2803
2804 const AudioContentDescription* audio_offer =
2805 GetFirstAudioContentDescription(offer.get());
2806 ASSERT_TRUE(audio_offer->cryptos().empty());
2807 const VideoContentDescription* video_offer =
2808 GetFirstVideoContentDescription(offer.get());
2809 ASSERT_TRUE(video_offer->cryptos().empty());
2810 const DataContentDescription* data_offer =
2811 GetFirstDataContentDescription(offer.get());
2812 ASSERT_TRUE(data_offer->cryptos().empty());
2813
2814 const cricket::TransportDescription* audio_offer_trans_desc =
2815 offer->GetTransportDescriptionByName("audio");
2816 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2817 const cricket::TransportDescription* video_offer_trans_desc =
2818 offer->GetTransportDescriptionByName("video");
2819 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2820 const cricket::TransportDescription* data_offer_trans_desc =
2821 offer->GetTransportDescriptionByName("data");
2822 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2823
2824 // Generate an answer with DTLS.
2825 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2826 ASSERT_TRUE(answer.get() != NULL);
2827
2828 const cricket::TransportDescription* audio_answer_trans_desc =
2829 answer->GetTransportDescriptionByName("audio");
2830 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2831 const cricket::TransportDescription* video_answer_trans_desc =
2832 answer->GetTransportDescriptionByName("video");
2833 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2834 const cricket::TransportDescription* data_answer_trans_desc =
2835 answer->GetTransportDescriptionByName("data");
2836 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2837}
2838
2839// Verifies if vad_enabled option is set to false, CN codecs are not present in
2840// offer or answer.
2841TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2842 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002843 options.recv_audio = true;
2844 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002845 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002846 ASSERT_TRUE(offer.get() != NULL);
2847 const ContentInfo* audio_content = offer->GetContentByName("audio");
2848 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2849
2850 options.vad_enabled = false;
2851 offer.reset(f1_.CreateOffer(options, NULL));
2852 ASSERT_TRUE(offer.get() != NULL);
2853 audio_content = offer->GetContentByName("audio");
2854 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002855 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002856 f1_.CreateAnswer(offer.get(), options, NULL));
2857 ASSERT_TRUE(answer.get() != NULL);
2858 audio_content = answer->GetContentByName("audio");
2859 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2860}
deadbeef44f08192015-12-15 16:20:09 -08002861
2862// Test that the content name ("mid" in SDP) is unchanged when creating a
2863// new offer.
2864TEST_F(MediaSessionDescriptionFactoryTest,
2865 TestContentNameNotChangedInSubsequentOffers) {
2866 MediaSessionOptions opts;
2867 opts.recv_audio = true;
2868 opts.recv_video = true;
2869 opts.data_channel_type = cricket::DCT_SCTP;
2870 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002871 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002872 for (ContentInfo& content : offer->contents()) {
2873 content.name.append("_modified");
2874 }
2875
kwiberg31022942016-03-11 14:18:21 -08002876 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002877 f1_.CreateOffer(opts, offer.get()));
2878 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2879 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2880 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2881 ASSERT_TRUE(audio_content != nullptr);
2882 ASSERT_TRUE(video_content != nullptr);
2883 ASSERT_TRUE(data_content != nullptr);
2884 EXPECT_EQ("audio_modified", audio_content->name);
2885 EXPECT_EQ("video_modified", video_content->name);
2886 EXPECT_EQ("data_modified", data_content->name);
2887}
zhihuangcf5b37c2016-05-05 11:44:35 -07002888
2889class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2890 public:
2891 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07002892 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
2893 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07002894 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2895 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07002896 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
2897 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07002898 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2899 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2900 f1_.set_secure(SEC_ENABLED);
2901 f2_.set_secure(SEC_ENABLED);
2902 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002903 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002904 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002905 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002906 tdf1_.set_secure(SEC_ENABLED);
2907 tdf2_.set_secure(SEC_ENABLED);
2908 }
2909
2910 protected:
2911 MediaSessionDescriptionFactory f1_;
2912 MediaSessionDescriptionFactory f2_;
2913 TransportDescriptionFactory tdf1_;
2914 TransportDescriptionFactory tdf2_;
2915};
2916
2917TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2918 MediaSessionOptions opts;
2919 opts.recv_video = true;
2920 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2921 ASSERT_TRUE(offer.get() != nullptr);
2922 // Set the protocol for all the contents.
2923 for (auto content : offer.get()->contents()) {
2924 static_cast<MediaContentDescription*>(content.description)
2925 ->set_protocol(GetParam());
2926 }
2927 std::unique_ptr<SessionDescription> answer(
2928 f2_.CreateAnswer(offer.get(), opts, nullptr));
2929 const ContentInfo* ac = answer->GetContentByName("audio");
2930 const ContentInfo* vc = answer->GetContentByName("video");
2931 ASSERT_TRUE(ac != nullptr);
2932 ASSERT_TRUE(vc != nullptr);
2933 EXPECT_FALSE(ac->rejected); // the offer is accepted
2934 EXPECT_FALSE(vc->rejected);
2935 const AudioContentDescription* acd =
2936 static_cast<const AudioContentDescription*>(ac->description);
2937 const VideoContentDescription* vcd =
2938 static_cast<const VideoContentDescription*>(vc->description);
2939 EXPECT_EQ(GetParam(), acd->protocol());
2940 EXPECT_EQ(GetParam(), vcd->protocol());
2941}
2942
2943INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2944 MediaProtocolTest,
2945 ::testing::ValuesIn(kMediaProtocols));
2946INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2947 MediaProtocolTest,
2948 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07002949
2950TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
2951 TransportDescriptionFactory tdf;
2952 MediaSessionDescriptionFactory sf(&tdf);
2953 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2954 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2955
2956 // The merged list of codecs should contain any send codecs that are also
2957 // nominally in the recieve codecs list. Payload types should be picked from
2958 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
2959 // (set to 1). This equals what happens when the send codecs are used in an
2960 // offer and the receive codecs are used in the following answer.
2961 const std::vector<AudioCodec> sendrecv_codecs =
2962 MAKE_VECTOR(kAudioCodecsAnswer);
2963 const std::vector<AudioCodec> no_codecs;
2964
2965 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
2966 << "Please don't change shared test data!";
2967 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
2968 << "Please don't change shared test data!";
2969 // Alter iLBC send codec to have zero channels, to test that that is handled
2970 // properly.
2971 send_codecs[1].channels = 0;
2972
2973 // Alther iLBC receive codec to be lowercase, to test that case conversions
2974 // are handled properly.
2975 recv_codecs[2].name = "ilbc";
2976
2977 // Test proper merge
2978 sf.set_audio_codecs(send_codecs, recv_codecs);
2979 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2980 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002981 EXPECT_TRUE(sf.audio_sendrecv_codecs() == sendrecv_codecs);
ossu075af922016-06-14 03:29:38 -07002982
2983 // Test empty send codecs list
2984 sf.set_audio_codecs(no_codecs, recv_codecs);
2985 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2986 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002987 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002988
2989 // Test empty recv codecs list
2990 sf.set_audio_codecs(send_codecs, no_codecs);
2991 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2992 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002993 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002994
2995 // Test all empty codec lists
2996 sf.set_audio_codecs(no_codecs, no_codecs);
2997 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2998 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002999 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07003000}
3001
3002namespace {
3003void TestAudioCodecsOffer(MediaContentDirection direction,
3004 bool add_legacy_stream) {
3005 TransportDescriptionFactory tdf;
3006 MediaSessionDescriptionFactory sf(&tdf);
3007 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
3008 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
3009 const std::vector<AudioCodec> sendrecv_codecs =
3010 MAKE_VECTOR(kAudioCodecsAnswer);
3011 sf.set_audio_codecs(send_codecs, recv_codecs);
3012 sf.set_add_legacy_streams(add_legacy_stream);
3013
3014 MediaSessionOptions opts;
3015 opts.recv_audio = (direction == cricket::MD_RECVONLY ||
3016 direction == cricket::MD_SENDRECV);
3017 opts.recv_video = false;
3018 if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV)
3019 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
3020
3021 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
3022 ASSERT_TRUE(offer.get() != NULL);
3023 const ContentInfo* ac = offer->GetContentByName("audio");
3024
3025 // If the factory didn't add any audio content to the offer, we cannot check
3026 // that the codecs put in are right. This happens when we neither want to send
3027 // nor receive audio. The checks are still in place if at some point we'd
3028 // instead create an inactive stream.
3029 if (ac) {
3030 AudioContentDescription* acd =
3031 static_cast<AudioContentDescription*>(ac->description);
3032 // sendrecv and inactive should both present lists as if the channel was to
3033 // be used for sending and receiving. Inactive essentially means it might
3034 // eventually be used anything, but we don't know more at this moment.
3035 if (acd->direction() == cricket::MD_SENDONLY) {
3036 EXPECT_TRUE(acd->codecs() == send_codecs);
3037 } else if (acd->direction() == cricket::MD_RECVONLY) {
3038 EXPECT_TRUE(acd->codecs() == recv_codecs);
3039 } else {
3040 EXPECT_TRUE(acd->codecs() == sendrecv_codecs);
3041 }
3042 }
3043}
3044
3045static const AudioCodec kOfferAnswerCodecs[] = {
3046 AudioCodec(0, "codec0", 16000, -1, 1),
3047 AudioCodec(1, "codec1", 8000, 13300, 1),
3048 AudioCodec(2, "codec2", 8000, 64000, 1),
3049 AudioCodec(3, "codec3", 8000, 64000, 1),
3050 AudioCodec(4, "codec4", 8000, 0, 2),
3051 AudioCodec(5, "codec5", 32000, 0, 1),
3052 AudioCodec(6, "codec6", 48000, 0, 1)
3053};
3054
3055
3056/* The codecs groups below are chosen as per the matrix below. The objective is
3057 * to have different sets of codecs in the inputs, to get unique sets of codecs
3058 * after negotiation, depending on offer and answer communication directions.
3059 * One-way directions in the offer should either result in the opposite
3060 * direction in the answer, or an inactive answer. Regardless, the choice of
3061 * codecs should be as if the answer contained the opposite direction.
3062 * Inactive offers should be treated as sendrecv/sendrecv.
3063 *
3064 * | Offer | Answer | Result
3065 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
3066 * 0 | x - - | - x - | x - - - -
3067 * 1 | x x x | - x - | x - - x -
3068 * 2 | - x - | x - - | - x - - -
3069 * 3 | x x x | x - - | - x x - -
3070 * 4 | - x - | x x x | - x - - -
3071 * 5 | x - - | x x x | x - - - -
3072 * 6 | x x x | x x x | x x x x x
3073 */
3074// Codecs used by offerer in the AudioCodecsAnswerTest
3075static const int kOfferSendCodecs[] = { 0, 1, 3, 5, 6 };
3076static const int kOfferRecvCodecs[] = { 1, 2, 3, 4, 6 };
3077// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
3078// jumbled to catch the answer not following the order in the offer.
3079static const int kAnswerSendCodecs[] = { 6, 5, 2, 3, 4 };
3080static const int kAnswerRecvCodecs[] = { 6, 5, 4, 1, 0 };
3081// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
3082static const int kResultSend_RecvCodecs[] = { 0, 1, 5, 6 };
3083static const int kResultRecv_SendCodecs[] = { 2, 3, 4, 6 };
3084static const int kResultSendrecv_SendCodecs[] = { 3, 6 };
3085static const int kResultSendrecv_RecvCodecs[] = { 1, 6 };
3086static const int kResultSendrecv_SendrecvCodecs[] = { 6 };
3087
3088template <typename T, int IDXS>
3089std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
3090 std::vector<T> out;
3091 out.reserve(IDXS);
3092 for (int idx : indices)
3093 out.push_back(array[idx]);
3094
3095 return out;
3096}
3097
3098void TestAudioCodecsAnswer(MediaContentDirection offer_direction,
3099 MediaContentDirection answer_direction,
3100 bool add_legacy_stream) {
3101 TransportDescriptionFactory offer_tdf;
3102 TransportDescriptionFactory answer_tdf;
3103 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
3104 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
3105 offer_factory.set_audio_codecs(
3106 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
3107 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
3108 answer_factory.set_audio_codecs(
3109 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
3110 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
3111
3112 // Never add a legacy stream to offer - we want to control the offer
3113 // parameters exactly.
3114 offer_factory.set_add_legacy_streams(false);
3115 answer_factory.set_add_legacy_streams(add_legacy_stream);
3116 MediaSessionOptions offer_opts;
3117 offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY ||
3118 offer_direction == cricket::MD_SENDRECV);
3119 offer_opts.recv_video = false;
3120 if (offer_direction == cricket::MD_SENDONLY ||
3121 offer_direction == cricket::MD_SENDRECV) {
3122 offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
3123 }
3124
3125 std::unique_ptr<SessionDescription> offer(
3126 offer_factory.CreateOffer(offer_opts, NULL));
3127 ASSERT_TRUE(offer.get() != NULL);
3128
3129 MediaSessionOptions answer_opts;
3130 answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY ||
3131 answer_direction == cricket::MD_SENDRECV);
3132 answer_opts.recv_video = false;
3133 if (answer_direction == cricket::MD_SENDONLY ||
3134 answer_direction == cricket::MD_SENDRECV) {
3135 answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
3136 }
3137 std::unique_ptr<SessionDescription> answer(
3138 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
3139 const ContentInfo* ac = answer->GetContentByName("audio");
3140
3141 // If the factory didn't add any audio content to the answer, we cannot check
3142 // that the codecs put in are right. This happens when we neither want to send
3143 // nor receive audio. The checks are still in place if at some point we'd
3144 // instead create an inactive stream.
3145 if (ac) {
3146 const AudioContentDescription* acd =
3147 static_cast<const AudioContentDescription*>(ac->description);
3148 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
3149
3150
3151 std::vector<AudioCodec> target_codecs;
3152 // For offers with sendrecv or inactive, we should never reply with more
3153 // codecs than offered, with these codec sets.
3154 switch (offer_direction) {
3155 case cricket::MD_INACTIVE:
3156 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3157 kResultSendrecv_SendrecvCodecs);
3158 break;
3159 case cricket::MD_SENDONLY:
3160 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3161 kResultSend_RecvCodecs);
3162 break;
3163 case cricket::MD_RECVONLY:
3164 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3165 kResultRecv_SendCodecs);
3166 break;
3167 case cricket::MD_SENDRECV:
3168 if (acd->direction() == cricket::MD_SENDONLY) {
3169 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3170 kResultSendrecv_SendCodecs);
3171 } else if (acd->direction() == cricket::MD_RECVONLY) {
3172 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3173 kResultSendrecv_RecvCodecs);
3174 } else {
3175 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
3176 kResultSendrecv_SendrecvCodecs);
3177 }
3178 break;
3179 }
3180
3181 auto format_codecs = [] (const std::vector<AudioCodec>& codecs) {
3182 std::stringstream os;
3183 bool first = true;
3184 os << "{";
3185 for (const auto& c : codecs) {
3186 os << (first ? " " : ", ") << c.id;
3187 first = false;
3188 }
3189 os << " }";
3190 return os.str();
3191 };
3192
3193 EXPECT_TRUE(acd->codecs() == target_codecs)
3194 << "Expected: " << format_codecs(target_codecs)
3195 << ", got: " << format_codecs(acd->codecs())
3196 << "; Offered: " << MediaContentDirectionToString(offer_direction)
3197 << ", answerer wants: "
3198 << MediaContentDirectionToString(answer_direction)
3199 << "; got: " << MediaContentDirectionToString(acd->direction());
3200 } else {
3201 EXPECT_EQ(offer_direction, cricket::MD_INACTIVE)
3202 << "Only inactive offers are allowed to not generate any audio content";
3203 }
3204}
brandtr03d5fb12016-11-22 03:37:59 -08003205
3206} // namespace
ossu075af922016-06-14 03:29:38 -07003207
3208class AudioCodecsOfferTest
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003209 : public ::testing::TestWithParam<::testing::tuple<MediaContentDirection,
3210 bool>> {
ossu075af922016-06-14 03:29:38 -07003211};
3212
3213TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003214 TestAudioCodecsOffer(::testing::get<0>(GetParam()),
3215 ::testing::get<1>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003216}
3217
3218INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3219 AudioCodecsOfferTest,
3220 ::testing::Combine(
3221 ::testing::Values(cricket::MD_SENDONLY,
3222 cricket::MD_RECVONLY,
3223 cricket::MD_SENDRECV,
3224 cricket::MD_INACTIVE),
3225 ::testing::Bool()));
3226
3227class AudioCodecsAnswerTest
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003228 : public ::testing::TestWithParam<::testing::tuple<MediaContentDirection,
3229 MediaContentDirection,
3230 bool>> {
ossu075af922016-06-14 03:29:38 -07003231};
3232
3233TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08003234 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
3235 ::testing::get<1>(GetParam()),
3236 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07003237}
3238
3239INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
3240 AudioCodecsAnswerTest,
3241 ::testing::Combine(
3242 ::testing::Values(cricket::MD_SENDONLY,
3243 cricket::MD_RECVONLY,
3244 cricket::MD_SENDRECV,
3245 cricket::MD_INACTIVE),
3246 ::testing::Values(cricket::MD_SENDONLY,
3247 cricket::MD_RECVONLY,
3248 cricket::MD_SENDRECV,
3249 cricket::MD_INACTIVE),
3250 ::testing::Bool()));