blob: ca1e4b39394c4af9bb75a2fb03842662cbd32c75 [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
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000015#include "webrtc/base/fakesslidentity.h"
16#include "webrtc/base/gunit.h"
17#include "webrtc/base/messagedigest.h"
18#include "webrtc/base/ssladapter.h"
kjellandera96e2d72016-02-04 23:52:28 -080019#include "webrtc/media/base/codec.h"
20#include "webrtc/media/base/testutils.h"
kjellanderf4752772016-03-02 05:42:30 -080021#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/p2p/base/transportdescription.h"
23#include "webrtc/p2p/base/transportinfo.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010024#include "webrtc/pc/mediasession.h"
25#include "webrtc/pc/srtpfilter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000026
27#ifdef HAVE_SRTP
28#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000029 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030 ASSERT_EQ(s, cd->cryptos().size()); \
31 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
32#else
33#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000034 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035 ASSERT_EQ(0U, cd->cryptos().size());
36#endif
37
38typedef std::vector<cricket::Candidate> Candidates;
39
40using cricket::MediaContentDescription;
41using cricket::MediaSessionDescriptionFactory;
ossu075af922016-06-14 03:29:38 -070042using cricket::MediaContentDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043using cricket::MediaSessionOptions;
44using cricket::MediaType;
45using cricket::SessionDescription;
46using cricket::SsrcGroup;
47using cricket::StreamParams;
48using cricket::StreamParamsVec;
49using cricket::TransportDescription;
50using cricket::TransportDescriptionFactory;
51using cricket::TransportInfo;
52using cricket::ContentInfo;
53using cricket::CryptoParamsVec;
54using cricket::AudioContentDescription;
55using cricket::VideoContentDescription;
56using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080057using cricket::GetFirstAudioContent;
58using cricket::GetFirstVideoContent;
59using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060using cricket::GetFirstAudioContentDescription;
61using cricket::GetFirstVideoContentDescription;
62using cricket::GetFirstDataContentDescription;
63using cricket::kAutoBandwidth;
64using cricket::AudioCodec;
65using cricket::VideoCodec;
66using cricket::DataCodec;
67using cricket::NS_JINGLE_RTP;
68using cricket::MEDIA_TYPE_AUDIO;
69using cricket::MEDIA_TYPE_VIDEO;
70using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071using cricket::SEC_DISABLED;
72using cricket::SEC_ENABLED;
73using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070074using rtc::CS_AES_CM_128_HMAC_SHA1_32;
75using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070076using rtc::CS_AEAD_AES_128_GCM;
77using rtc::CS_AEAD_AES_256_GCM;
isheriff6f8d6862016-05-26 11:24:55 -070078using webrtc::RtpExtension;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079
80static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070081 AudioCodec(103, "ISAC", 16000, -1, 1),
82 AudioCodec(102, "iLBC", 8000, 13300, 1),
83 AudioCodec(0, "PCMU", 8000, 64000, 1),
84 AudioCodec(8, "PCMA", 8000, 64000, 1),
85 AudioCodec(117, "red", 8000, 0, 1),
86 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087
88static const AudioCodec kAudioCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070089 AudioCodec(126, "speex", 16000, 22000, 1),
90 AudioCodec(0, "PCMU", 8000, 64000, 1),
91 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092};
93
94static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070095 AudioCodec(102, "iLBC", 8000, 13300, 1),
96 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097};
98
perkj26752742016-10-24 01:21:16 -070099static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
100 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101
perkj26752742016-10-24 01:21:16 -0700102static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
103 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104
perkj26752742016-10-24 01:21:16 -0700105static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106
deadbeef67cf2c12016-04-13 10:07:16 -0700107static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
108 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109
deadbeef67cf2c12016-04-13 10:07:16 -0700110static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
111 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112
deadbeef67cf2c12016-04-13 10:07:16 -0700113static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
114 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115
isheriff6f8d6862016-05-26 11:24:55 -0700116static const RtpExtension kAudioRtpExtension1[] = {
117 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
118 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119};
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
isheriff6f8d6862016-05-26 11:24:55 -0700132static const RtpExtension kAudioRtpExtensionAnswer[] = {
133 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000134};
135
isheriff6f8d6862016-05-26 11:24:55 -0700136static const RtpExtension kVideoRtpExtension1[] = {
137 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
138 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000139};
140
isheriff6f8d6862016-05-26 11:24:55 -0700141static const RtpExtension kVideoRtpExtension2[] = {
142 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
143 RtpExtension("http://google.com/testing/video_something_else", 14),
144 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145};
146
isheriff6f8d6862016-05-26 11:24:55 -0700147static const RtpExtension kVideoRtpExtension3[] = {
148 RtpExtension("http://google.com/testing/video_something", 4),
149 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700150};
151
isheriff6f8d6862016-05-26 11:24:55 -0700152static const RtpExtension kVideoRtpExtensionAnswer[] = {
153 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000154};
155
Peter Boström0c4e06b2015-10-07 12:23:21 +0200156static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
157static const uint32_t kSimSsrc[] = {10, 20, 30};
158static const uint32_t kFec1Ssrc[] = {10, 11};
159static const uint32_t kFec2Ssrc[] = {20, 21};
160static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161
162static const char kMediaStream1[] = "stream_1";
163static const char kMediaStream2[] = "stream_2";
164static const char kVideoTrack1[] = "video_1";
165static const char kVideoTrack2[] = "video_2";
166static const char kAudioTrack1[] = "audio_1";
167static const char kAudioTrack2[] = "audio_2";
168static const char kAudioTrack3[] = "audio_3";
169static const char kDataTrack1[] = "data_1";
170static const char kDataTrack2[] = "data_2";
171static const char kDataTrack3[] = "data_3";
172
zhihuangcf5b37c2016-05-05 11:44:35 -0700173static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
174 "RTP/SAVPF"};
175static const char* kMediaProtocolsDtls[] = {
176 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
177 "UDP/TLS/RTP/SAVP"};
178
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000179static bool IsMediaContentOfType(const ContentInfo* content,
180 MediaType media_type) {
181 const MediaContentDescription* mdesc =
182 static_cast<const MediaContentDescription*>(content->description);
183 return mdesc && mdesc->type() == media_type;
184}
185
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000186static cricket::MediaContentDirection
187GetMediaDirection(const ContentInfo* content) {
188 cricket::MediaContentDescription* desc =
189 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
190 return desc->direction();
191}
192
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000193static void AddRtxCodec(const VideoCodec& rtx_codec,
194 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800195 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000196 codecs->push_back(rtx_codec);
197}
198
199template <class T>
200static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
201 std::vector<std::string> codec_names;
202 for (const auto& codec : codecs) {
203 codec_names.push_back(codec.name);
204 }
205 return codec_names;
206}
207
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208class MediaSessionDescriptionFactoryTest : public testing::Test {
209 public:
210 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200211 : f1_(&tdf1_),
212 f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700213 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
214 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
216 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700217 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
218 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000219 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
220 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200221 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700222 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200223 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700224 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000225 }
226
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000227 // Create a video StreamParamsVec object with:
228 // - one video stream with 3 simulcast streams and FEC,
229 StreamParamsVec CreateComplexVideoStreamParamsVec() {
230 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
231 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
232 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
233 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
234
235 std::vector<SsrcGroup> ssrc_groups;
236 ssrc_groups.push_back(sim_group);
237 ssrc_groups.push_back(fec_group1);
238 ssrc_groups.push_back(fec_group2);
239 ssrc_groups.push_back(fec_group3);
240
241 StreamParams simulcast_params;
242 simulcast_params.id = kVideoTrack1;
243 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
244 simulcast_params.ssrc_groups = ssrc_groups;
245 simulcast_params.cname = "Video_SIM_FEC";
246 simulcast_params.sync_label = kMediaStream1;
247
248 StreamParamsVec video_streams;
249 video_streams.push_back(simulcast_params);
250
251 return video_streams;
252 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000253
254 bool CompareCryptoParams(const CryptoParamsVec& c1,
255 const CryptoParamsVec& c2) {
256 if (c1.size() != c2.size())
257 return false;
258 for (size_t i = 0; i < c1.size(); ++i)
259 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
260 c1[i].key_params != c2[i].key_params ||
261 c1[i].session_params != c2[i].session_params)
262 return false;
263 return true;
264 }
265
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700266 // Returns true if the transport info contains "renomination" as an
267 // ICE option.
268 bool GetIceRenomination(const TransportInfo* transport_info) {
269 const std::vector<std::string>& ice_options =
270 transport_info->description.transport_options;
271 auto iter = std::find(ice_options.begin(), ice_options.end(),
272 cricket::ICE_RENOMINATION_STR);
273 return iter != ice_options.end();
274 }
275
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
277 bool has_current_desc) {
278 const std::string current_audio_ufrag = "current_audio_ufrag";
279 const std::string current_audio_pwd = "current_audio_pwd";
280 const std::string current_video_ufrag = "current_video_ufrag";
281 const std::string current_video_pwd = "current_video_pwd";
282 const std::string current_data_ufrag = "current_data_ufrag";
283 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800284 std::unique_ptr<SessionDescription> current_desc;
285 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 if (has_current_desc) {
287 current_desc.reset(new SessionDescription());
288 EXPECT_TRUE(current_desc->AddTransportInfo(
289 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700290 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000291 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 EXPECT_TRUE(current_desc->AddTransportInfo(
293 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700294 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000295 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 EXPECT_TRUE(current_desc->AddTransportInfo(
297 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700298 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000299 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000300 }
301 if (offer) {
302 desc.reset(f1_.CreateOffer(options, current_desc.get()));
303 } else {
kwiberg31022942016-03-11 14:18:21 -0800304 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000305 offer.reset(f1_.CreateOffer(options, NULL));
306 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
307 }
308 ASSERT_TRUE(desc.get() != NULL);
309 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000310 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 EXPECT_TRUE(ti_audio != NULL);
312 if (has_current_desc) {
313 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
314 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
315 } else {
316 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
317 ti_audio->description.ice_ufrag.size());
318 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
319 ti_audio->description.ice_pwd.size());
320 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700321 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322
323 } else {
324 EXPECT_TRUE(ti_audio == NULL);
325 }
326 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000327 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 EXPECT_TRUE(ti_video != NULL);
329 if (options.bundle_enabled) {
330 EXPECT_EQ(ti_audio->description.ice_ufrag,
331 ti_video->description.ice_ufrag);
332 EXPECT_EQ(ti_audio->description.ice_pwd,
333 ti_video->description.ice_pwd);
334 } else {
335 if (has_current_desc) {
336 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
337 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
338 } else {
339 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
340 ti_video->description.ice_ufrag.size());
341 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
342 ti_video->description.ice_pwd.size());
343 }
344 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700345 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 } else {
347 EXPECT_TRUE(ti_video == NULL);
348 }
349 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
350 if (options.has_data()) {
351 EXPECT_TRUE(ti_data != NULL);
352 if (options.bundle_enabled) {
353 EXPECT_EQ(ti_audio->description.ice_ufrag,
354 ti_data->description.ice_ufrag);
355 EXPECT_EQ(ti_audio->description.ice_pwd,
356 ti_data->description.ice_pwd);
357 } else {
358 if (has_current_desc) {
359 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
360 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
361 } else {
362 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
363 ti_data->description.ice_ufrag.size());
364 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
365 ti_data->description.ice_pwd.size());
366 }
367 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700368 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_data));
369
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000370 } else {
371 EXPECT_TRUE(ti_video == NULL);
372 }
373 }
374
375 void TestCryptoWithBundle(bool offer) {
376 f1_.set_secure(SEC_ENABLED);
377 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000378 options.recv_audio = true;
379 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800381 std::unique_ptr<SessionDescription> ref_desc;
382 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383 if (offer) {
384 options.bundle_enabled = false;
385 ref_desc.reset(f1_.CreateOffer(options, NULL));
386 options.bundle_enabled = true;
387 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
388 } else {
389 options.bundle_enabled = true;
390 ref_desc.reset(f1_.CreateOffer(options, NULL));
391 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
392 }
393 ASSERT_TRUE(desc.get() != NULL);
394 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000395 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000396 desc.get()->GetContentDescriptionByName("audio"));
397 ASSERT_TRUE(audio_media_desc != NULL);
398 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000399 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000400 desc.get()->GetContentDescriptionByName("video"));
401 ASSERT_TRUE(video_media_desc != NULL);
402 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
403 video_media_desc->cryptos()));
404 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
405 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
406 audio_media_desc->cryptos()[0].cipher_suite);
407
408 // Verify the selected crypto is one from the reference audio
409 // media content.
410 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000411 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 ref_desc.get()->GetContentDescriptionByName("audio"));
413 bool found = false;
414 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
415 if (ref_audio_media_desc->cryptos()[i].Matches(
416 audio_media_desc->cryptos()[0])) {
417 found = true;
418 break;
419 }
420 }
421 EXPECT_TRUE(found);
422 }
423
424 // This test that the audio and video media direction is set to
425 // |expected_direction_in_answer| in an answer if the offer direction is set
426 // to |direction_in_offer|.
427 void TestMediaDirectionInAnswer(
428 cricket::MediaContentDirection direction_in_offer,
429 cricket::MediaContentDirection expected_direction_in_answer) {
430 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000431 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800432 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700434 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 ASSERT_TRUE(ac_offer != NULL);
436 AudioContentDescription* acd_offer =
437 static_cast<AudioContentDescription*>(ac_offer->description);
438 acd_offer->set_direction(direction_in_offer);
terelius8c011e52016-04-26 05:28:11 -0700439 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 ASSERT_TRUE(vc_offer != NULL);
441 VideoContentDescription* vcd_offer =
442 static_cast<VideoContentDescription*>(vc_offer->description);
443 vcd_offer->set_direction(direction_in_offer);
444
kwiberg31022942016-03-11 14:18:21 -0800445 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 f2_.CreateAnswer(offer.get(), opts, NULL));
447 const AudioContentDescription* acd_answer =
448 GetFirstAudioContentDescription(answer.get());
449 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
450 const VideoContentDescription* vcd_answer =
451 GetFirstVideoContentDescription(answer.get());
452 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
453 }
454
455 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
456 const cricket::ContentDescription* description = content->description;
457 ASSERT(description != NULL);
458 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000459 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000460 ASSERT(audio_content_desc != NULL);
461 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
462 if (audio_content_desc->codecs()[i].name == "CN")
463 return false;
464 }
465 return true;
466 }
467
jbauchcb560652016-08-04 05:20:32 -0700468 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
469 MediaSessionOptions offer_opts;
470 offer_opts.recv_video = true;
471 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
472 MediaSessionOptions answer_opts;
473 answer_opts.recv_video = true;
474 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
475 f1_.set_secure(SEC_ENABLED);
476 f2_.set_secure(SEC_ENABLED);
477 std::unique_ptr<SessionDescription> offer(
478 f1_.CreateOffer(offer_opts, NULL));
479 ASSERT_TRUE(offer.get() != NULL);
480 std::unique_ptr<SessionDescription> answer(
481 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
482 const ContentInfo* ac = answer->GetContentByName("audio");
483 const ContentInfo* vc = answer->GetContentByName("video");
484 ASSERT_TRUE(ac != NULL);
485 ASSERT_TRUE(vc != NULL);
486 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
487 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
488 const AudioContentDescription* acd =
489 static_cast<const AudioContentDescription*>(ac->description);
490 const VideoContentDescription* vcd =
491 static_cast<const VideoContentDescription*>(vc->description);
492 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
493 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
494 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
495 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
496 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
497 if (gcm_offer && gcm_answer) {
498 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
499 } else {
500 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
501 }
502 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
503 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
504 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
505 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
506 if (gcm_offer && gcm_answer) {
507 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
508 } else {
509 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
510 }
511 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
512 }
513
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000514 protected:
515 MediaSessionDescriptionFactory f1_;
516 MediaSessionDescriptionFactory f2_;
517 TransportDescriptionFactory tdf1_;
518 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519};
520
521// Create a typical audio offer, and ensure it matches what we expect.
522TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
523 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800524 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525 f1_.CreateOffer(MediaSessionOptions(), NULL));
526 ASSERT_TRUE(offer.get() != NULL);
527 const ContentInfo* ac = offer->GetContentByName("audio");
528 const ContentInfo* vc = offer->GetContentByName("video");
529 ASSERT_TRUE(ac != NULL);
530 ASSERT_TRUE(vc == NULL);
531 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
532 const AudioContentDescription* acd =
533 static_cast<const AudioContentDescription*>(ac->description);
534 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700535 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
537 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
538 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
539 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
540 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
541}
542
543// Create a typical video offer, and ensure it matches what we expect.
544TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
545 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000546 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800548 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 ASSERT_TRUE(offer.get() != NULL);
550 const ContentInfo* ac = offer->GetContentByName("audio");
551 const ContentInfo* vc = offer->GetContentByName("video");
552 ASSERT_TRUE(ac != NULL);
553 ASSERT_TRUE(vc != NULL);
554 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
555 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
556 const AudioContentDescription* acd =
557 static_cast<const AudioContentDescription*>(ac->description);
558 const VideoContentDescription* vcd =
559 static_cast<const VideoContentDescription*>(vc->description);
560 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700561 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
563 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
564 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
565 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
566 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
567 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
568 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
569 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
570 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
571 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
572 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
573 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
574}
575
576// Test creating an offer with bundle where the Codecs have the same dynamic
577// RTP playlod type. The test verifies that the offer don't contain the
578// duplicate RTP payload types.
579TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
580 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700581 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
583 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
584 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
585
586 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000587 opts.recv_audio = true;
588 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 opts.data_channel_type = cricket::DCT_RTP;
590 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800591 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000592 const VideoContentDescription* vcd =
593 GetFirstVideoContentDescription(offer.get());
594 const AudioContentDescription* acd =
595 GetFirstAudioContentDescription(offer.get());
596 const DataContentDescription* dcd =
597 GetFirstDataContentDescription(offer.get());
598 ASSERT_TRUE(NULL != vcd);
599 ASSERT_TRUE(NULL != acd);
600 ASSERT_TRUE(NULL != dcd);
601 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
602 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
603 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
604 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
605 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
606 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
607}
608
609// Test creating an updated offer with with bundle, audio, video and data
610// after an audio only session has been negotiated.
611TEST_F(MediaSessionDescriptionFactoryTest,
612 TestCreateUpdatedVideoOfferWithBundle) {
613 f1_.set_secure(SEC_ENABLED);
614 f2_.set_secure(SEC_ENABLED);
615 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000616 opts.recv_audio = true;
617 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000618 opts.data_channel_type = cricket::DCT_NONE;
619 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800620 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
621 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000622 f2_.CreateAnswer(offer.get(), opts, NULL));
623
624 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000625 updated_opts.recv_audio = true;
626 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627 updated_opts.data_channel_type = cricket::DCT_RTP;
628 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800629 std::unique_ptr<SessionDescription> updated_offer(
630 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631
632 const AudioContentDescription* acd =
633 GetFirstAudioContentDescription(updated_offer.get());
634 const VideoContentDescription* vcd =
635 GetFirstVideoContentDescription(updated_offer.get());
636 const DataContentDescription* dcd =
637 GetFirstDataContentDescription(updated_offer.get());
638 EXPECT_TRUE(NULL != vcd);
639 EXPECT_TRUE(NULL != acd);
640 EXPECT_TRUE(NULL != dcd);
641
642 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
643 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
644 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
645 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
646 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
647 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
648}
deadbeef44f08192015-12-15 16:20:09 -0800649
wu@webrtc.org78187522013-10-07 23:32:02 +0000650// Create a RTP data offer, and ensure it matches what we expect.
651TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 MediaSessionOptions opts;
653 opts.data_channel_type = cricket::DCT_RTP;
654 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800655 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 ASSERT_TRUE(offer.get() != NULL);
657 const ContentInfo* ac = offer->GetContentByName("audio");
658 const ContentInfo* dc = offer->GetContentByName("data");
659 ASSERT_TRUE(ac != NULL);
660 ASSERT_TRUE(dc != NULL);
661 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
662 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
663 const AudioContentDescription* acd =
664 static_cast<const AudioContentDescription*>(ac->description);
665 const DataContentDescription* dcd =
666 static_cast<const DataContentDescription*>(dc->description);
667 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700668 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
670 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
671 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
672 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
673 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
674 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
675 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
676 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
677 EXPECT_EQ(cricket::kDataMaxBandwidth,
678 dcd->bandwidth()); // default bandwidth (auto)
679 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
680 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
681 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
682}
683
wu@webrtc.org78187522013-10-07 23:32:02 +0000684// Create an SCTP data offer with bundle without error.
685TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
686 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000687 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000688 opts.bundle_enabled = true;
689 opts.data_channel_type = cricket::DCT_SCTP;
690 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800691 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000692 EXPECT_TRUE(offer.get() != NULL);
693 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
694}
695
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000696// Test creating an sctp data channel from an already generated offer.
697TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
698 MediaSessionOptions opts;
699 opts.recv_audio = false;
700 opts.bundle_enabled = true;
701 opts.data_channel_type = cricket::DCT_SCTP;
702 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800703 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000704 ASSERT_TRUE(offer1.get() != NULL);
705 const ContentInfo* data = offer1->GetContentByName("data");
706 ASSERT_TRUE(data != NULL);
707 const MediaContentDescription* mdesc =
708 static_cast<const MediaContentDescription*>(data->description);
709 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
710
711 // Now set data_channel_type to 'none' (default) and make sure that the
712 // datachannel type that gets generated from the previous offer, is of the
713 // same type.
714 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800715 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000716 f1_.CreateOffer(opts, offer1.get()));
717 data = offer2->GetContentByName("data");
718 ASSERT_TRUE(data != NULL);
719 mdesc = static_cast<const MediaContentDescription*>(data->description);
720 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
721}
722
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723// Create an audio, video offer without legacy StreamParams.
724TEST_F(MediaSessionDescriptionFactoryTest,
725 TestCreateOfferWithoutLegacyStreams) {
726 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000727 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800729 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 ASSERT_TRUE(offer.get() != NULL);
731 const ContentInfo* ac = offer->GetContentByName("audio");
732 const ContentInfo* vc = offer->GetContentByName("video");
733 ASSERT_TRUE(ac != NULL);
734 ASSERT_TRUE(vc != NULL);
735 const AudioContentDescription* acd =
736 static_cast<const AudioContentDescription*>(ac->description);
737 const VideoContentDescription* vcd =
738 static_cast<const VideoContentDescription*>(vc->description);
739
740 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
741 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
742}
743
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000744// Creates an audio+video sendonly offer.
745TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
746 MediaSessionOptions options;
747 options.recv_audio = false;
748 options.recv_video = false;
749 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
750 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
751
kwiberg31022942016-03-11 14:18:21 -0800752 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000753 ASSERT_TRUE(offer.get() != NULL);
754 EXPECT_EQ(2u, offer->contents().size());
755 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
756 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
757
758 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
759 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
760}
761
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000762// Verifies that the order of the media contents in the current
763// SessionDescription is preserved in the new SessionDescription.
764TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
765 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000766 opts.recv_audio = false;
767 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000768 opts.data_channel_type = cricket::DCT_SCTP;
769
kwiberg31022942016-03-11 14:18:21 -0800770 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000771 ASSERT_TRUE(offer1.get() != NULL);
772 EXPECT_EQ(1u, offer1->contents().size());
773 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
774
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000775 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800776 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000777 f1_.CreateOffer(opts, offer1.get()));
778 ASSERT_TRUE(offer2.get() != NULL);
779 EXPECT_EQ(2u, offer2->contents().size());
780 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
781 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
782
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000783 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800784 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000785 f1_.CreateOffer(opts, offer2.get()));
786 ASSERT_TRUE(offer3.get() != NULL);
787 EXPECT_EQ(3u, offer3->contents().size());
788 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
789 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
790 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
791
792 // Verifies the default order is audio-video-data, so that the previous checks
793 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800794 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000795 ASSERT_TRUE(offer4.get() != NULL);
796 EXPECT_EQ(3u, offer4->contents().size());
797 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
798 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
799 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
800}
801
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802// Create a typical audio answer, and ensure it matches what we expect.
803TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
804 f1_.set_secure(SEC_ENABLED);
805 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800806 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 f1_.CreateOffer(MediaSessionOptions(), NULL));
808 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800809 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
811 const ContentInfo* ac = answer->GetContentByName("audio");
812 const ContentInfo* vc = answer->GetContentByName("video");
813 ASSERT_TRUE(ac != NULL);
814 ASSERT_TRUE(vc == NULL);
815 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
816 const AudioContentDescription* acd =
817 static_cast<const AudioContentDescription*>(ac->description);
818 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
819 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
820 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
821 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
822 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
823 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
824 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
825}
826
jbauchcb560652016-08-04 05:20:32 -0700827// Create a typical audio answer with GCM ciphers enabled, and ensure it
828// matches what we expect.
829TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
830 f1_.set_secure(SEC_ENABLED);
831 f2_.set_secure(SEC_ENABLED);
832 MediaSessionOptions options;
833 options.crypto_options.enable_gcm_crypto_suites = true;
834 std::unique_ptr<SessionDescription> offer(
835 f1_.CreateOffer(options, NULL));
836 ASSERT_TRUE(offer.get() != NULL);
837 std::unique_ptr<SessionDescription> answer(
838 f2_.CreateAnswer(offer.get(), options, NULL));
839 const ContentInfo* ac = answer->GetContentByName("audio");
840 const ContentInfo* vc = answer->GetContentByName("video");
841 ASSERT_TRUE(ac != NULL);
842 ASSERT_TRUE(vc == NULL);
843 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
844 const AudioContentDescription* acd =
845 static_cast<const AudioContentDescription*>(ac->description);
846 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
847 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
848 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
849 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
850 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
851 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
852 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
853}
854
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000855// Create a typical video answer, and ensure it matches what we expect.
856TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
857 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000858 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 f1_.set_secure(SEC_ENABLED);
860 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800861 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800863 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 f2_.CreateAnswer(offer.get(), opts, NULL));
865 const ContentInfo* ac = answer->GetContentByName("audio");
866 const ContentInfo* vc = answer->GetContentByName("video");
867 ASSERT_TRUE(ac != NULL);
868 ASSERT_TRUE(vc != NULL);
869 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
870 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
871 const AudioContentDescription* acd =
872 static_cast<const AudioContentDescription*>(ac->description);
873 const VideoContentDescription* vcd =
874 static_cast<const VideoContentDescription*>(vc->description);
875 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
876 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
877 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
878 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
879 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
880 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
881 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
882 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
883 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
884 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
885 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
886 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
887}
888
jbauchcb560652016-08-04 05:20:32 -0700889// Create a typical video answer with GCM ciphers enabled, and ensure it
890// matches what we expect.
891TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
892 TestVideoGcmCipher(true, true);
893}
894
895// Create a typical video answer with GCM ciphers enabled for the offer only,
896// and ensure it matches what we expect.
897TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
898 TestVideoGcmCipher(true, false);
899}
900
901// Create a typical video answer with GCM ciphers enabled for the answer only,
902// and ensure it matches what we expect.
903TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
904 TestVideoGcmCipher(false, true);
905}
906
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
908 MediaSessionOptions opts;
909 opts.data_channel_type = cricket::DCT_RTP;
910 f1_.set_secure(SEC_ENABLED);
911 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800912 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000913 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800914 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915 f2_.CreateAnswer(offer.get(), opts, NULL));
916 const ContentInfo* ac = answer->GetContentByName("audio");
917 const ContentInfo* vc = answer->GetContentByName("data");
918 ASSERT_TRUE(ac != NULL);
919 ASSERT_TRUE(vc != NULL);
920 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
921 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
922 const AudioContentDescription* acd =
923 static_cast<const AudioContentDescription*>(ac->description);
924 const DataContentDescription* vcd =
925 static_cast<const DataContentDescription*>(vc->description);
926 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
927 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
928 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
929 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
930 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
931 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
932 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
933 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
934 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
935 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
936 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
937 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
938}
939
jbauchcb560652016-08-04 05:20:32 -0700940TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
941 MediaSessionOptions opts;
942 opts.data_channel_type = cricket::DCT_RTP;
943 opts.crypto_options.enable_gcm_crypto_suites = true;
944 f1_.set_secure(SEC_ENABLED);
945 f2_.set_secure(SEC_ENABLED);
946 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
947 ASSERT_TRUE(offer.get() != NULL);
948 std::unique_ptr<SessionDescription> answer(
949 f2_.CreateAnswer(offer.get(), opts, NULL));
950 const ContentInfo* ac = answer->GetContentByName("audio");
951 const ContentInfo* vc = answer->GetContentByName("data");
952 ASSERT_TRUE(ac != NULL);
953 ASSERT_TRUE(vc != NULL);
954 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
955 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
956 const AudioContentDescription* acd =
957 static_cast<const AudioContentDescription*>(ac->description);
958 const DataContentDescription* vcd =
959 static_cast<const DataContentDescription*>(vc->description);
960 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
961 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
962 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
963 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
964 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
965 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
966 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
967 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
968 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
969 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
970 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
971 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
972}
973
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000974// Verifies that the order of the media contents in the offer is preserved in
975// the answer.
976TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
977 MediaSessionOptions opts;
978
979 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000980 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000981 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -0800982 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000983 ASSERT_TRUE(offer1.get() != NULL);
984
985 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000986 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800987 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000988 f1_.CreateOffer(opts, offer1.get()));
989 ASSERT_TRUE(offer2.get() != NULL);
990
991 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000992 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800993 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000994 f1_.CreateOffer(opts, offer2.get()));
995 ASSERT_TRUE(offer3.get() != NULL);
996
kwiberg31022942016-03-11 14:18:21 -0800997 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000998 f2_.CreateAnswer(offer3.get(), opts, NULL));
999 ASSERT_TRUE(answer.get() != NULL);
1000 EXPECT_EQ(3u, answer->contents().size());
1001 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1002 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1003 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1004}
1005
ossu075af922016-06-14 03:29:38 -07001006// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1007// answerer settings.
1008
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001009// This test that the media direction is set to send/receive in an answer if
1010// the offer is send receive.
1011TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
1012 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
1013}
1014
1015// This test that the media direction is set to receive only in an answer if
1016// the offer is send only.
1017TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
1018 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
1019}
1020
1021// This test that the media direction is set to send only in an answer if
1022// the offer is recv only.
1023TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
1024 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
1025}
1026
1027// This test that the media direction is set to inactive in an answer if
1028// the offer is inactive.
1029TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
1030 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
1031}
1032
1033// Test that a data content with an unknown protocol is rejected in an answer.
1034TEST_F(MediaSessionDescriptionFactoryTest,
1035 CreateDataAnswerToOfferWithUnknownProtocol) {
1036 MediaSessionOptions opts;
1037 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001038 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001039 f1_.set_secure(SEC_ENABLED);
1040 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001041 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001042 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043 ASSERT_TRUE(dc_offer != NULL);
1044 DataContentDescription* dcd_offer =
1045 static_cast<DataContentDescription*>(dc_offer->description);
1046 ASSERT_TRUE(dcd_offer != NULL);
1047 std::string protocol = "a weird unknown protocol";
1048 dcd_offer->set_protocol(protocol);
1049
kwiberg31022942016-03-11 14:18:21 -08001050 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051 f2_.CreateAnswer(offer.get(), opts, NULL));
1052
1053 const ContentInfo* dc_answer = answer->GetContentByName("data");
1054 ASSERT_TRUE(dc_answer != NULL);
1055 EXPECT_TRUE(dc_answer->rejected);
1056 const DataContentDescription* dcd_answer =
1057 static_cast<const DataContentDescription*>(dc_answer->description);
1058 ASSERT_TRUE(dcd_answer != NULL);
1059 EXPECT_EQ(protocol, dcd_answer->protocol());
1060}
1061
1062// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1063TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
1064 MediaSessionOptions opts;
1065 f1_.set_secure(SEC_DISABLED);
1066 f2_.set_secure(SEC_DISABLED);
1067 tdf1_.set_secure(SEC_DISABLED);
1068 tdf2_.set_secure(SEC_DISABLED);
1069
kwiberg31022942016-03-11 14:18:21 -08001070 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001071 const AudioContentDescription* offer_acd =
1072 GetFirstAudioContentDescription(offer.get());
1073 ASSERT_TRUE(offer_acd != NULL);
1074 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1075
kwiberg31022942016-03-11 14:18:21 -08001076 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001077 f2_.CreateAnswer(offer.get(), opts, NULL));
1078
1079 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1080 ASSERT_TRUE(ac_answer != NULL);
1081 EXPECT_FALSE(ac_answer->rejected);
1082
1083 const AudioContentDescription* answer_acd =
1084 GetFirstAudioContentDescription(answer.get());
1085 ASSERT_TRUE(answer_acd != NULL);
1086 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1087}
1088
1089// Create a video offer and answer and ensure the RTP header extensions
1090// matches what we expect.
1091TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1092 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001093 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094
1095 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1096 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1097 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1098 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1099
kwiberg31022942016-03-11 14:18:21 -08001100 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001102 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001103 f2_.CreateAnswer(offer.get(), opts, NULL));
1104
1105 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1106 GetFirstAudioContentDescription(
1107 offer.get())->rtp_header_extensions());
1108 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1109 GetFirstVideoContentDescription(
1110 offer.get())->rtp_header_extensions());
1111 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1112 GetFirstAudioContentDescription(
1113 answer.get())->rtp_header_extensions());
1114 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1115 GetFirstVideoContentDescription(
1116 answer.get())->rtp_header_extensions());
1117}
1118
1119// Create an audio, video, data answer without legacy StreamParams.
1120TEST_F(MediaSessionDescriptionFactoryTest,
1121 TestCreateAnswerWithoutLegacyStreams) {
1122 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001123 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001124 opts.data_channel_type = cricket::DCT_RTP;
1125 f1_.set_add_legacy_streams(false);
1126 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -08001127 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001128 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001129 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001130 f2_.CreateAnswer(offer.get(), opts, NULL));
1131 const ContentInfo* ac = answer->GetContentByName("audio");
1132 const ContentInfo* vc = answer->GetContentByName("video");
1133 const ContentInfo* dc = answer->GetContentByName("data");
1134 ASSERT_TRUE(ac != NULL);
1135 ASSERT_TRUE(vc != NULL);
1136 const AudioContentDescription* acd =
1137 static_cast<const AudioContentDescription*>(ac->description);
1138 const VideoContentDescription* vcd =
1139 static_cast<const VideoContentDescription*>(vc->description);
1140 const DataContentDescription* dcd =
1141 static_cast<const DataContentDescription*>(dc->description);
1142
1143 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1144 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1145 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1146}
1147
1148TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1149 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001150 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 opts.data_channel_type = cricket::DCT_RTP;
1152 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001153 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 ASSERT_TRUE(offer.get() != NULL);
1155 const ContentInfo* ac = offer->GetContentByName("audio");
1156 const ContentInfo* vc = offer->GetContentByName("video");
1157 const ContentInfo* dc = offer->GetContentByName("data");
1158 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1159 static_cast<const AudioContentDescription*>(ac->description));
1160 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1161 static_cast<const VideoContentDescription*>(vc->description));
1162 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1163 static_cast<const DataContentDescription*>(dc->description));
1164
1165 EXPECT_FALSE(acd->partial()); // default is false.
1166 acd->set_partial(true);
1167 EXPECT_TRUE(acd->partial());
1168 acd->set_partial(false);
1169 EXPECT_FALSE(acd->partial());
1170
1171 EXPECT_FALSE(vcd->partial()); // default is false.
1172 vcd->set_partial(true);
1173 EXPECT_TRUE(vcd->partial());
1174 vcd->set_partial(false);
1175 EXPECT_FALSE(vcd->partial());
1176
1177 EXPECT_FALSE(dcd->partial()); // default is false.
1178 dcd->set_partial(true);
1179 EXPECT_TRUE(dcd->partial());
1180 dcd->set_partial(false);
1181 EXPECT_FALSE(dcd->partial());
1182}
1183
1184// Create a typical video answer, and ensure it matches what we expect.
1185TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1186 MediaSessionOptions offer_opts;
1187 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001188 answer_opts.recv_video = true;
1189 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001190 answer_opts.data_channel_type = cricket::DCT_RTP;
1191 offer_opts.data_channel_type = cricket::DCT_RTP;
1192
kwiberg31022942016-03-11 14:18:21 -08001193 std::unique_ptr<SessionDescription> offer;
1194 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001195
1196 offer_opts.rtcp_mux_enabled = true;
1197 answer_opts.rtcp_mux_enabled = true;
1198
1199 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1200 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1201 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1202 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1203 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1204 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1205 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1206 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1207 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1208 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1209 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1210 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1211 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1212 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1213
1214 offer_opts.rtcp_mux_enabled = true;
1215 answer_opts.rtcp_mux_enabled = false;
1216
1217 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1218 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1219 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1220 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1221 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1222 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1223 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1224 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1225 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1226 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1227 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1228 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1229 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1230 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1231
1232 offer_opts.rtcp_mux_enabled = false;
1233 answer_opts.rtcp_mux_enabled = true;
1234
1235 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1236 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1237 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1238 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1239 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1240 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1241 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1242 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1243 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1244 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1245 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1246 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1247 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1248 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1249
1250 offer_opts.rtcp_mux_enabled = false;
1251 answer_opts.rtcp_mux_enabled = false;
1252
1253 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1254 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1255 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1256 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1257 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1258 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1259 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1260 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1261 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1262 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1263 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1264 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1265 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1266 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1267}
1268
1269// Create an audio-only answer to a video offer.
1270TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1271 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001272 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001273 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001274 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001275 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001276 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1277 const ContentInfo* ac = answer->GetContentByName("audio");
1278 const ContentInfo* vc = answer->GetContentByName("video");
1279 ASSERT_TRUE(ac != NULL);
1280 ASSERT_TRUE(vc != NULL);
1281 ASSERT_TRUE(vc->description != NULL);
1282 EXPECT_TRUE(vc->rejected);
1283}
1284
1285// Create an audio-only answer to an offer with data.
1286TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1287 MediaSessionOptions opts;
1288 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001289 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001291 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1293 const ContentInfo* ac = answer->GetContentByName("audio");
1294 const ContentInfo* dc = answer->GetContentByName("data");
1295 ASSERT_TRUE(ac != NULL);
1296 ASSERT_TRUE(dc != NULL);
1297 ASSERT_TRUE(dc->description != NULL);
1298 EXPECT_TRUE(dc->rejected);
1299}
1300
1301// Create an answer that rejects the contents which are rejected in the offer.
1302TEST_F(MediaSessionDescriptionFactoryTest,
1303 CreateAnswerToOfferWithRejectedMedia) {
1304 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001305 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001307 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001308 ASSERT_TRUE(offer.get() != NULL);
1309 ContentInfo* ac = offer->GetContentByName("audio");
1310 ContentInfo* vc = offer->GetContentByName("video");
1311 ContentInfo* dc = offer->GetContentByName("data");
1312 ASSERT_TRUE(ac != NULL);
1313 ASSERT_TRUE(vc != NULL);
1314 ASSERT_TRUE(dc != NULL);
1315 ac->rejected = true;
1316 vc->rejected = true;
1317 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001318 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001319 f2_.CreateAnswer(offer.get(), opts, NULL));
1320 ac = answer->GetContentByName("audio");
1321 vc = answer->GetContentByName("video");
1322 dc = answer->GetContentByName("data");
1323 ASSERT_TRUE(ac != NULL);
1324 ASSERT_TRUE(vc != NULL);
1325 ASSERT_TRUE(dc != NULL);
1326 EXPECT_TRUE(ac->rejected);
1327 EXPECT_TRUE(vc->rejected);
1328 EXPECT_TRUE(dc->rejected);
1329}
1330
1331// Create an audio and video offer with:
1332// - one video track
1333// - two audio tracks
1334// - two data tracks
1335// and ensure it matches what we expect. Also updates the initial offer by
1336// adding a new video track and replaces one of the audio tracks.
1337TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1338 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001339 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1340 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1341 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001343 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1344 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001345
1346 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001347 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348
1349 ASSERT_TRUE(offer.get() != NULL);
1350 const ContentInfo* ac = offer->GetContentByName("audio");
1351 const ContentInfo* vc = offer->GetContentByName("video");
1352 const ContentInfo* dc = offer->GetContentByName("data");
1353 ASSERT_TRUE(ac != NULL);
1354 ASSERT_TRUE(vc != NULL);
1355 ASSERT_TRUE(dc != NULL);
1356 const AudioContentDescription* acd =
1357 static_cast<const AudioContentDescription*>(ac->description);
1358 const VideoContentDescription* vcd =
1359 static_cast<const VideoContentDescription*>(vc->description);
1360 const DataContentDescription* dcd =
1361 static_cast<const DataContentDescription*>(dc->description);
1362 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001363 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001364
1365 const StreamParamsVec& audio_streams = acd->streams();
1366 ASSERT_EQ(2U, audio_streams.size());
1367 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1368 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1369 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1370 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1371 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1372 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1373 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1374
1375 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1376 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1377 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1378
1379 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1380 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1381 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1382
1383 const StreamParamsVec& video_streams = vcd->streams();
1384 ASSERT_EQ(1U, video_streams.size());
1385 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1386 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1387 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1388 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1389
1390 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1391 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1392 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1393
1394 const StreamParamsVec& data_streams = dcd->streams();
1395 ASSERT_EQ(2U, data_streams.size());
1396 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1397 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1398 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1399 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1400 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1401 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1402 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1403
1404 EXPECT_EQ(cricket::kDataMaxBandwidth,
1405 dcd->bandwidth()); // default bandwidth (auto)
1406 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1407 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1408
1409
1410 // Update the offer. Add a new video track that is not synched to the
1411 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001412 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1413 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1414 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1415 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1416 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001417 std::unique_ptr<SessionDescription> updated_offer(
1418 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001419
1420 ASSERT_TRUE(updated_offer.get() != NULL);
1421 ac = updated_offer->GetContentByName("audio");
1422 vc = updated_offer->GetContentByName("video");
1423 dc = updated_offer->GetContentByName("data");
1424 ASSERT_TRUE(ac != NULL);
1425 ASSERT_TRUE(vc != NULL);
1426 ASSERT_TRUE(dc != NULL);
1427 const AudioContentDescription* updated_acd =
1428 static_cast<const AudioContentDescription*>(ac->description);
1429 const VideoContentDescription* updated_vcd =
1430 static_cast<const VideoContentDescription*>(vc->description);
1431 const DataContentDescription* updated_dcd =
1432 static_cast<const DataContentDescription*>(dc->description);
1433
1434 EXPECT_EQ(acd->type(), updated_acd->type());
1435 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1436 EXPECT_EQ(vcd->type(), updated_vcd->type());
1437 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1438 EXPECT_EQ(dcd->type(), updated_dcd->type());
1439 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1440 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1441 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1442 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1443 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1444 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1445 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1446
1447 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1448 ASSERT_EQ(2U, updated_audio_streams.size());
1449 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1450 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1451 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1452 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1453 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1454
1455 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1456 ASSERT_EQ(2U, updated_video_streams.size());
1457 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1458 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001459 // All the media streams in one PeerConnection share one RTCP CNAME.
1460 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001461
1462 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1463 ASSERT_EQ(2U, updated_data_streams.size());
1464 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1465 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1466 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1467 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1468 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001469 // The stream correctly got the CNAME from the MediaSessionOptions.
1470 // The Expected RTCP CNAME is the default one as we are using the default
1471 // MediaSessionOptions.
1472 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001473}
1474
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001475// Create an offer with simulcast video stream.
1476TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1477 MediaSessionOptions opts;
1478 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001479 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001480 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001481
1482 ASSERT_TRUE(offer.get() != NULL);
1483 const ContentInfo* vc = offer->GetContentByName("video");
1484 ASSERT_TRUE(vc != NULL);
1485 const VideoContentDescription* vcd =
1486 static_cast<const VideoContentDescription*>(vc->description);
1487
1488 const StreamParamsVec& video_streams = vcd->streams();
1489 ASSERT_EQ(1U, video_streams.size());
1490 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1491 const SsrcGroup* sim_ssrc_group =
1492 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1493 ASSERT_TRUE(sim_ssrc_group != NULL);
1494 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1495}
1496
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497// Create an audio and video answer to a standard video offer with:
1498// - one video track
1499// - two audio tracks
1500// - two data tracks
1501// and ensure it matches what we expect. Also updates the initial answer by
1502// adding a new video track and removes one of the audio tracks.
1503TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1504 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001505 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 offer_opts.data_channel_type = cricket::DCT_RTP;
1507 f1_.set_secure(SEC_ENABLED);
1508 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001509 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001510
1511 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001512 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1513 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1514 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001515 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001516 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1517 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518
kwiberg31022942016-03-11 14:18:21 -08001519 std::unique_ptr<SessionDescription> answer(
1520 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521
1522 ASSERT_TRUE(answer.get() != NULL);
1523 const ContentInfo* ac = answer->GetContentByName("audio");
1524 const ContentInfo* vc = answer->GetContentByName("video");
1525 const ContentInfo* dc = answer->GetContentByName("data");
1526 ASSERT_TRUE(ac != NULL);
1527 ASSERT_TRUE(vc != NULL);
1528 ASSERT_TRUE(dc != NULL);
1529 const AudioContentDescription* acd =
1530 static_cast<const AudioContentDescription*>(ac->description);
1531 const VideoContentDescription* vcd =
1532 static_cast<const VideoContentDescription*>(vc->description);
1533 const DataContentDescription* dcd =
1534 static_cast<const DataContentDescription*>(dc->description);
1535 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1536 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1537 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1538
1539 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1540 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1541
1542 const StreamParamsVec& audio_streams = acd->streams();
1543 ASSERT_EQ(2U, audio_streams.size());
1544 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1545 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1546 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1547 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1548 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1549 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1550 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1551
1552 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1553 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1554
1555 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1556 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1557
1558 const StreamParamsVec& video_streams = vcd->streams();
1559 ASSERT_EQ(1U, video_streams.size());
1560 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1561 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1562 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1563 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1564
1565 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1566 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1567
1568 const StreamParamsVec& data_streams = dcd->streams();
1569 ASSERT_EQ(2U, data_streams.size());
1570 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1571 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1572 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1573 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1574 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1575 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1576 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1577
1578 EXPECT_EQ(cricket::kDataMaxBandwidth,
1579 dcd->bandwidth()); // default bandwidth (auto)
1580 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1581
1582 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001583 // other tracks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001584 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1585 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1586 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001587 std::unique_ptr<SessionDescription> updated_answer(
1588 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001589
1590 ASSERT_TRUE(updated_answer.get() != NULL);
1591 ac = updated_answer->GetContentByName("audio");
1592 vc = updated_answer->GetContentByName("video");
1593 dc = updated_answer->GetContentByName("data");
1594 ASSERT_TRUE(ac != NULL);
1595 ASSERT_TRUE(vc != NULL);
1596 ASSERT_TRUE(dc != NULL);
1597 const AudioContentDescription* updated_acd =
1598 static_cast<const AudioContentDescription*>(ac->description);
1599 const VideoContentDescription* updated_vcd =
1600 static_cast<const VideoContentDescription*>(vc->description);
1601 const DataContentDescription* updated_dcd =
1602 static_cast<const DataContentDescription*>(dc->description);
1603
1604 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1605 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1606 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1607 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1608 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1609 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1610
1611 EXPECT_EQ(acd->type(), updated_acd->type());
1612 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1613 EXPECT_EQ(vcd->type(), updated_vcd->type());
1614 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1615 EXPECT_EQ(dcd->type(), updated_dcd->type());
1616 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1617
1618 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1619 ASSERT_EQ(1U, updated_audio_streams.size());
1620 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1621
1622 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1623 ASSERT_EQ(2U, updated_video_streams.size());
1624 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1625 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001626 // All media streams in one PeerConnection share one CNAME.
1627 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628
1629 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1630 ASSERT_EQ(1U, updated_data_streams.size());
1631 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1632}
1633
1634
1635// Create an updated offer after creating an answer to the original offer and
1636// verify that the codecs that were part of the original answer are not changed
1637// in the updated offer.
1638TEST_F(MediaSessionDescriptionFactoryTest,
1639 RespondentCreatesOfferAfterCreatingAnswer) {
1640 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001641 opts.recv_audio = true;
1642 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001643
kwiberg31022942016-03-11 14:18:21 -08001644 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1645 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646 f2_.CreateAnswer(offer.get(), opts, NULL));
1647
1648 const AudioContentDescription* acd =
1649 GetFirstAudioContentDescription(answer.get());
1650 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1651
1652 const VideoContentDescription* vcd =
1653 GetFirstVideoContentDescription(answer.get());
1654 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1655
kwiberg31022942016-03-11 14:18:21 -08001656 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657 f2_.CreateOffer(opts, answer.get()));
1658
1659 // The expected audio codecs are the common audio codecs from the first
1660 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1661 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001662 // TODO(wu): |updated_offer| should not include the codec
1663 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665 kAudioCodecsAnswer[0],
1666 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001667 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 };
1669
1670 // The expected video codecs are the common video codecs from the first
1671 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1672 // preference order.
1673 const VideoCodec kUpdatedVideoCodecOffer[] = {
1674 kVideoCodecsAnswer[0],
1675 kVideoCodecs2[1],
1676 };
1677
1678 const AudioContentDescription* updated_acd =
1679 GetFirstAudioContentDescription(updated_offer.get());
1680 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1681
1682 const VideoContentDescription* updated_vcd =
1683 GetFirstVideoContentDescription(updated_offer.get());
1684 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1685}
1686
1687// Create an updated offer after creating an answer to the original offer and
1688// verify that the codecs that were part of the original answer are not changed
1689// in the updated offer. In this test Rtx is enabled.
1690TEST_F(MediaSessionDescriptionFactoryTest,
1691 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1692 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001693 opts.recv_video = true;
1694 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001696 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001697 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001698 f1_.set_video_codecs(f1_codecs);
1699
1700 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001701 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001702 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703 f2_.set_video_codecs(f2_codecs);
1704
kwiberg31022942016-03-11 14:18:21 -08001705 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001707 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001708 f2_.CreateAnswer(offer.get(), opts, NULL));
1709
1710 const VideoContentDescription* vcd =
1711 GetFirstVideoContentDescription(answer.get());
1712
1713 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001714 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1715 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001716
1717 EXPECT_EQ(expected_codecs, vcd->codecs());
1718
deadbeef67cf2c12016-04-13 10:07:16 -07001719 // Now, make sure we get same result (except for the order) if |f2_| creates
1720 // an updated offer even though the default payload types between |f1_| and
1721 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001722 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001723 f2_.CreateOffer(opts, answer.get()));
1724 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001725 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001726 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1727
1728 const VideoContentDescription* updated_vcd =
1729 GetFirstVideoContentDescription(updated_answer.get());
1730
1731 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1732}
1733
1734// Create an updated offer that adds video after creating an audio only answer
1735// to the original offer. This test verifies that if a video codec and the RTX
1736// codec have the same default payload type as an audio codec that is already in
1737// use, the added codecs payload types are changed.
1738TEST_F(MediaSessionDescriptionFactoryTest,
1739 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1740 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001742 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001743 f1_.set_video_codecs(f1_codecs);
1744
1745 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001746 opts.recv_audio = true;
1747 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001748
kwiberg31022942016-03-11 14:18:21 -08001749 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1750 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 f2_.CreateAnswer(offer.get(), opts, NULL));
1752
1753 const AudioContentDescription* acd =
1754 GetFirstAudioContentDescription(answer.get());
1755 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1756
1757 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1758 // reference be the same as an audio codec that was negotiated in the
1759 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001760 opts.recv_audio = true;
1761 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001762
1763 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1764 int used_pl_type = acd->codecs()[0].id;
1765 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001766 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001767 f2_.set_video_codecs(f2_codecs);
1768
kwiberg31022942016-03-11 14:18:21 -08001769 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001770 f2_.CreateOffer(opts, answer.get()));
1771 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001772 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1774
1775 const AudioContentDescription* updated_acd =
1776 GetFirstAudioContentDescription(answer.get());
1777 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1778
1779 const VideoContentDescription* updated_vcd =
1780 GetFirstVideoContentDescription(updated_answer.get());
1781
1782 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001783 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1785 EXPECT_NE(used_pl_type, new_h264_pl_type);
1786 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001787 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001788 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1789 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1790}
1791
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001792// Create an updated offer with RTX after creating an answer to an offer
1793// without RTX, and with different default payload types.
1794// Verify that the added RTX codec references the correct payload type.
1795TEST_F(MediaSessionDescriptionFactoryTest,
1796 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1797 MediaSessionOptions opts;
1798 opts.recv_video = true;
1799 opts.recv_audio = true;
1800
1801 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1802 // This creates rtx for H264 with the payload type |f2_| uses.
1803 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1804 f2_.set_video_codecs(f2_codecs);
1805
kwiberg31022942016-03-11 14:18:21 -08001806 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001807 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001808 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001809 f2_.CreateAnswer(offer.get(), opts, nullptr));
1810
1811 const VideoContentDescription* vcd =
1812 GetFirstVideoContentDescription(answer.get());
1813
1814 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1815 EXPECT_EQ(expected_codecs, vcd->codecs());
1816
1817 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1818 // updated offer, even though the default payload types are different from
1819 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001820 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001821 f2_.CreateOffer(opts, answer.get()));
1822 ASSERT_TRUE(updated_offer);
1823
1824 const VideoContentDescription* updated_vcd =
1825 GetFirstVideoContentDescription(updated_offer.get());
1826
1827 // New offer should attempt to add H263, and RTX for H264.
1828 expected_codecs.push_back(kVideoCodecs2[1]);
1829 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1830 &expected_codecs);
1831 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1832}
1833
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001834// Test that RTX is ignored when there is no associated payload type parameter.
1835TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1836 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001837 opts.recv_video = true;
1838 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001839 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001840 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07001841 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001842 f1_.set_video_codecs(f1_codecs);
1843
1844 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001845 // This creates RTX for H264 with the payload type |f2_| uses.
1846 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 f2_.set_video_codecs(f2_codecs);
1848
kwiberg31022942016-03-11 14:18:21 -08001849 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001850 ASSERT_TRUE(offer.get() != NULL);
1851 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1852 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1853 // is possible to test that that RTX is dropped when
1854 // kCodecParamAssociatedPayloadType is missing in the offer.
1855 VideoContentDescription* desc =
1856 static_cast<cricket::VideoContentDescription*>(
1857 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1858 ASSERT_TRUE(desc != NULL);
1859 std::vector<VideoCodec> codecs = desc->codecs();
1860 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1861 iter != codecs.end(); ++iter) {
1862 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1863 iter->params.clear();
1864 }
1865 }
1866 desc->set_codecs(codecs);
1867
kwiberg31022942016-03-11 14:18:21 -08001868 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001869 f2_.CreateAnswer(offer.get(), opts, NULL));
1870
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001871 std::vector<std::string> codec_names =
1872 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1873 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1874 cricket::kRtxCodecName));
1875}
1876
1877// Test that RTX will be filtered out in the answer if its associated payload
1878// type doesn't match the local value.
1879TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1880 MediaSessionOptions opts;
1881 opts.recv_video = true;
1882 opts.recv_audio = false;
1883 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1884 // This creates RTX for H264 in sender.
1885 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1886 f1_.set_video_codecs(f1_codecs);
1887
1888 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1889 // This creates RTX for H263 in receiver.
1890 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1891 f2_.set_video_codecs(f2_codecs);
1892
kwiberg31022942016-03-11 14:18:21 -08001893 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001894 ASSERT_TRUE(offer.get() != NULL);
1895 // Associated payload type doesn't match, therefore, RTX codec is removed in
1896 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001897 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001898 f2_.CreateAnswer(offer.get(), opts, NULL));
1899
1900 std::vector<std::string> codec_names =
1901 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1902 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1903 cricket::kRtxCodecName));
1904}
1905
1906// Test that when multiple RTX codecs are offered, only the matched RTX codec
1907// is added in the answer, and the unsupported RTX codec is filtered out.
1908TEST_F(MediaSessionDescriptionFactoryTest,
1909 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1910 MediaSessionOptions opts;
1911 opts.recv_video = true;
1912 opts.recv_audio = false;
1913 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1914 // This creates RTX for H264-SVC in sender.
1915 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1916 f1_.set_video_codecs(f1_codecs);
1917
1918 // This creates RTX for H264 in sender.
1919 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1920 f1_.set_video_codecs(f1_codecs);
1921
1922 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1923 // This creates RTX for H264 in receiver.
1924 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1925 f2_.set_video_codecs(f2_codecs);
1926
1927 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1928 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001929 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001930 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001931 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001932 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001933 const VideoContentDescription* vcd =
1934 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001935 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1936 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1937 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001938
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001939 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001940}
1941
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001942// Test that after one RTX codec has been negotiated, a new offer can attempt
1943// to add another.
1944TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1945 MediaSessionOptions opts;
1946 opts.recv_video = true;
1947 opts.recv_audio = false;
1948 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1949 // This creates RTX for H264 for the offerer.
1950 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1951 f1_.set_video_codecs(f1_codecs);
1952
kwiberg31022942016-03-11 14:18:21 -08001953 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001954 ASSERT_TRUE(offer);
1955 const VideoContentDescription* vcd =
1956 GetFirstVideoContentDescription(offer.get());
1957
1958 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1959 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1960 &expected_codecs);
1961 EXPECT_EQ(expected_codecs, vcd->codecs());
1962
1963 // Now, attempt to add RTX for H264-SVC.
1964 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1965 f1_.set_video_codecs(f1_codecs);
1966
kwiberg31022942016-03-11 14:18:21 -08001967 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001968 f1_.CreateOffer(opts, offer.get()));
1969 ASSERT_TRUE(updated_offer);
1970 vcd = GetFirstVideoContentDescription(updated_offer.get());
1971
1972 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1973 &expected_codecs);
1974 EXPECT_EQ(expected_codecs, vcd->codecs());
1975}
1976
Noah Richards2e7a0982015-05-18 14:02:54 -07001977// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1978// generated for each simulcast ssrc and correctly grouped.
1979TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1980 MediaSessionOptions opts;
1981 opts.recv_video = true;
1982 opts.recv_audio = false;
1983
1984 // Add simulcast streams.
1985 opts.AddSendVideoStream("stream1", "stream1label", 3);
1986
1987 // Use a single real codec, and then add RTX for it.
1988 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07001989 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07001990 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1991 f1_.set_video_codecs(f1_codecs);
1992
1993 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1994 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001995 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001996 ASSERT_TRUE(offer.get() != NULL);
1997 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1998 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1999 ASSERT_TRUE(desc != NULL);
2000 EXPECT_TRUE(desc->multistream());
2001 const StreamParamsVec& streams = desc->streams();
2002 // Single stream.
2003 ASSERT_EQ(1u, streams.size());
2004 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2005 EXPECT_EQ(6u, streams[0].ssrcs.size());
2006 // And should have a SIM group for the simulcast.
2007 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2008 // And a FID group for RTX.
2009 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002010 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002011 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2012 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002013 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002014 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2015 EXPECT_EQ(3u, fid_ssrcs.size());
2016}
2017
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018// Create an updated offer after creating an answer to the original offer and
2019// verify that the RTP header extensions that were part of the original answer
2020// are not changed in the updated offer.
2021TEST_F(MediaSessionDescriptionFactoryTest,
2022 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2023 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002024 opts.recv_audio = true;
2025 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026
2027 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2028 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2029 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2030 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2031
kwiberg31022942016-03-11 14:18:21 -08002032 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2033 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034 f2_.CreateAnswer(offer.get(), opts, NULL));
2035
2036 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
2037 GetFirstAudioContentDescription(
2038 answer.get())->rtp_header_extensions());
2039 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
2040 GetFirstVideoContentDescription(
2041 answer.get())->rtp_header_extensions());
2042
kwiberg31022942016-03-11 14:18:21 -08002043 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002044 f2_.CreateOffer(opts, answer.get()));
2045
2046 // The expected RTP header extensions in the new offer are the resulting
2047 // extensions from the first offer/answer exchange plus the extensions only
2048 // |f2_| offer.
2049 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002050 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002051 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2052 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2053 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002054 };
2055
2056 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002057 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002058 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2059 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2060 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002061 };
2062
2063 const AudioContentDescription* updated_acd =
2064 GetFirstAudioContentDescription(updated_offer.get());
2065 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2066 updated_acd->rtp_header_extensions());
2067
2068 const VideoContentDescription* updated_vcd =
2069 GetFirstVideoContentDescription(updated_offer.get());
2070 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2071 updated_vcd->rtp_header_extensions());
2072}
2073
deadbeefa5b273a2015-08-20 17:30:13 -07002074// Verify that if the same RTP extension URI is used for audio and video, the
2075// same ID is used. Also verify that the ID isn't changed when creating an
2076// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002077TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002078 MediaSessionOptions opts;
2079 opts.recv_audio = true;
2080 opts.recv_video = true;
2081
2082 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2083 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2084
kwiberg31022942016-03-11 14:18:21 -08002085 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002086
2087 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2088 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002089 const RtpExtension kExpectedVideoRtpExtension[] = {
2090 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002091 };
2092
2093 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2094 GetFirstAudioContentDescription(
2095 offer.get())->rtp_header_extensions());
2096 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2097 GetFirstVideoContentDescription(
2098 offer.get())->rtp_header_extensions());
2099
2100 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002101 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002102 f1_.CreateOffer(opts, offer.get()));
2103
2104 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2105 GetFirstAudioContentDescription(
2106 updated_offer.get())->rtp_header_extensions());
2107 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2108 GetFirstVideoContentDescription(
2109 updated_offer.get())->rtp_header_extensions());
2110}
2111
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002112TEST(MediaSessionDescription, CopySessionDescription) {
2113 SessionDescription source;
2114 cricket::ContentGroup group(cricket::CN_AUDIO);
2115 source.AddGroup(group);
2116 AudioContentDescription* acd(new AudioContentDescription());
2117 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2118 acd->AddLegacyStream(1);
2119 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
2120 VideoContentDescription* vcd(new VideoContentDescription());
2121 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2122 vcd->AddLegacyStream(2);
2123 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
2124
kwiberg31022942016-03-11 14:18:21 -08002125 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002126 ASSERT_TRUE(copy.get() != NULL);
2127 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2128 const ContentInfo* ac = copy->GetContentByName("audio");
2129 const ContentInfo* vc = copy->GetContentByName("video");
2130 ASSERT_TRUE(ac != NULL);
2131 ASSERT_TRUE(vc != NULL);
2132 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
2133 const AudioContentDescription* acd_copy =
2134 static_cast<const AudioContentDescription*>(ac->description);
2135 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2136 EXPECT_EQ(1u, acd->first_ssrc());
2137
2138 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
2139 const VideoContentDescription* vcd_copy =
2140 static_cast<const VideoContentDescription*>(vc->description);
2141 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2142 EXPECT_EQ(2u, vcd->first_ssrc());
2143}
2144
2145// The below TestTransportInfoXXX tests create different offers/answers, and
2146// ensure the TransportInfo in the SessionDescription matches what we expect.
2147TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2148 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002149 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002150 TestTransportInfo(true, options, false);
2151}
2152
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002153TEST_F(MediaSessionDescriptionFactoryTest,
2154 TestTransportInfoOfferIceRenomination) {
2155 MediaSessionOptions options;
2156 options.enable_ice_renomination = true;
2157 TestTransportInfo(true, options, false);
2158}
2159
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002160TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2161 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002162 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002163 TestTransportInfo(true, options, true);
2164}
2165
2166TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2167 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002168 options.recv_audio = true;
2169 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002170 options.data_channel_type = cricket::DCT_RTP;
2171 TestTransportInfo(true, options, false);
2172}
2173
2174TEST_F(MediaSessionDescriptionFactoryTest,
2175 TestTransportInfoOfferMultimediaCurrent) {
2176 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002177 options.recv_audio = true;
2178 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002179 options.data_channel_type = cricket::DCT_RTP;
2180 TestTransportInfo(true, options, true);
2181}
2182
2183TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2184 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002185 options.recv_audio = true;
2186 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002187 options.data_channel_type = cricket::DCT_RTP;
2188 options.bundle_enabled = true;
2189 TestTransportInfo(true, options, false);
2190}
2191
2192TEST_F(MediaSessionDescriptionFactoryTest,
2193 TestTransportInfoOfferBundleCurrent) {
2194 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002195 options.recv_audio = true;
2196 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002197 options.data_channel_type = cricket::DCT_RTP;
2198 options.bundle_enabled = true;
2199 TestTransportInfo(true, options, true);
2200}
2201
2202TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2203 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002204 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002205 TestTransportInfo(false, options, false);
2206}
2207
2208TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002209 TestTransportInfoAnswerIceRenomination) {
2210 MediaSessionOptions options;
2211 options.enable_ice_renomination = true;
2212 TestTransportInfo(false, options, false);
2213}
2214
2215TEST_F(MediaSessionDescriptionFactoryTest,
2216 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002217 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002218 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002219 TestTransportInfo(false, options, true);
2220}
2221
2222TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2223 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002224 options.recv_audio = true;
2225 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002226 options.data_channel_type = cricket::DCT_RTP;
2227 TestTransportInfo(false, options, false);
2228}
2229
2230TEST_F(MediaSessionDescriptionFactoryTest,
2231 TestTransportInfoAnswerMultimediaCurrent) {
2232 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002233 options.recv_audio = true;
2234 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002235 options.data_channel_type = cricket::DCT_RTP;
2236 TestTransportInfo(false, options, true);
2237}
2238
2239TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2240 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002241 options.recv_audio = true;
2242 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002243 options.data_channel_type = cricket::DCT_RTP;
2244 options.bundle_enabled = true;
2245 TestTransportInfo(false, options, false);
2246}
2247
2248TEST_F(MediaSessionDescriptionFactoryTest,
2249 TestTransportInfoAnswerBundleCurrent) {
2250 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002251 options.recv_audio = true;
2252 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002253 options.data_channel_type = cricket::DCT_RTP;
2254 options.bundle_enabled = true;
2255 TestTransportInfo(false, options, true);
2256}
2257
2258// Create an offer with bundle enabled and verify the crypto parameters are
2259// the common set of the available cryptos.
2260TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2261 TestCryptoWithBundle(true);
2262}
2263
2264// Create an answer with bundle enabled and verify the crypto parameters are
2265// the common set of the available cryptos.
2266TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2267 TestCryptoWithBundle(false);
2268}
2269
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002270// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2271// DTLS is not enabled locally.
2272TEST_F(MediaSessionDescriptionFactoryTest,
2273 TestOfferDtlsSavpfWithoutDtlsFailed) {
2274 f1_.set_secure(SEC_ENABLED);
2275 f2_.set_secure(SEC_ENABLED);
2276 tdf1_.set_secure(SEC_DISABLED);
2277 tdf2_.set_secure(SEC_DISABLED);
2278
kwiberg31022942016-03-11 14:18:21 -08002279 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002280 f1_.CreateOffer(MediaSessionOptions(), NULL));
2281 ASSERT_TRUE(offer.get() != NULL);
2282 ContentInfo* offer_content = offer->GetContentByName("audio");
2283 ASSERT_TRUE(offer_content != NULL);
2284 AudioContentDescription* offer_audio_desc =
2285 static_cast<AudioContentDescription*>(offer_content->description);
2286 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2287
kwiberg31022942016-03-11 14:18:21 -08002288 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002289 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2290 ASSERT_TRUE(answer != NULL);
2291 ContentInfo* answer_content = answer->GetContentByName("audio");
2292 ASSERT_TRUE(answer_content != NULL);
2293
2294 ASSERT_TRUE(answer_content->rejected);
2295}
2296
2297// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2298// UDP/TLS/RTP/SAVPF.
2299TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2300 f1_.set_secure(SEC_ENABLED);
2301 f2_.set_secure(SEC_ENABLED);
2302 tdf1_.set_secure(SEC_ENABLED);
2303 tdf2_.set_secure(SEC_ENABLED);
2304
kwiberg31022942016-03-11 14:18:21 -08002305 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002306 f1_.CreateOffer(MediaSessionOptions(), NULL));
2307 ASSERT_TRUE(offer.get() != NULL);
2308 ContentInfo* offer_content = offer->GetContentByName("audio");
2309 ASSERT_TRUE(offer_content != NULL);
2310 AudioContentDescription* offer_audio_desc =
2311 static_cast<AudioContentDescription*>(offer_content->description);
2312 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2313
kwiberg31022942016-03-11 14:18:21 -08002314 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002315 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2316 ASSERT_TRUE(answer != NULL);
2317
2318 const ContentInfo* answer_content = answer->GetContentByName("audio");
2319 ASSERT_TRUE(answer_content != NULL);
2320 ASSERT_FALSE(answer_content->rejected);
2321
2322 const AudioContentDescription* answer_audio_desc =
2323 static_cast<const AudioContentDescription*>(answer_content->description);
2324 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2325 answer_audio_desc->protocol());
2326}
2327
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002328// Test that we include both SDES and DTLS in the offer, but only include SDES
2329// in the answer if DTLS isn't negotiated.
2330TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2331 f1_.set_secure(SEC_ENABLED);
2332 f2_.set_secure(SEC_ENABLED);
2333 tdf1_.set_secure(SEC_ENABLED);
2334 tdf2_.set_secure(SEC_DISABLED);
2335 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002336 options.recv_audio = true;
2337 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002338 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002339 const cricket::MediaContentDescription* audio_media_desc;
2340 const cricket::MediaContentDescription* video_media_desc;
2341 const cricket::TransportDescription* audio_trans_desc;
2342 const cricket::TransportDescription* video_trans_desc;
2343
2344 // Generate an offer with SDES and DTLS support.
2345 offer.reset(f1_.CreateOffer(options, NULL));
2346 ASSERT_TRUE(offer.get() != NULL);
2347
2348 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2349 offer->GetContentDescriptionByName("audio"));
2350 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002351 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352 offer->GetContentDescriptionByName("video"));
2353 ASSERT_TRUE(video_media_desc != NULL);
2354 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2355 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2356
2357 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2358 ASSERT_TRUE(audio_trans_desc != NULL);
2359 video_trans_desc = offer->GetTransportDescriptionByName("video");
2360 ASSERT_TRUE(video_trans_desc != NULL);
2361 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2362 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2363
2364 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2365 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2366 ASSERT_TRUE(answer.get() != NULL);
2367
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002368 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002369 answer->GetContentDescriptionByName("audio"));
2370 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002371 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002372 answer->GetContentDescriptionByName("video"));
2373 ASSERT_TRUE(video_media_desc != NULL);
2374 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2375 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2376
2377 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2378 ASSERT_TRUE(audio_trans_desc != NULL);
2379 video_trans_desc = answer->GetTransportDescriptionByName("video");
2380 ASSERT_TRUE(video_trans_desc != NULL);
2381 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2382 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2383
2384 // Enable DTLS; the answer should now only have DTLS support.
2385 tdf2_.set_secure(SEC_ENABLED);
2386 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2387 ASSERT_TRUE(answer.get() != NULL);
2388
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002389 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002390 answer->GetContentDescriptionByName("audio"));
2391 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002392 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002393 answer->GetContentDescriptionByName("video"));
2394 ASSERT_TRUE(video_media_desc != NULL);
2395 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2396 EXPECT_TRUE(video_media_desc->cryptos().empty());
2397 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2398 audio_media_desc->protocol());
2399 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2400 video_media_desc->protocol());
2401
2402 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2403 ASSERT_TRUE(audio_trans_desc != NULL);
2404 video_trans_desc = answer->GetTransportDescriptionByName("video");
2405 ASSERT_TRUE(video_trans_desc != NULL);
2406 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2407 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002408
2409 // Try creating offer again. DTLS enabled now, crypto's should be empty
2410 // in new offer.
2411 offer.reset(f1_.CreateOffer(options, offer.get()));
2412 ASSERT_TRUE(offer.get() != NULL);
2413 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2414 offer->GetContentDescriptionByName("audio"));
2415 ASSERT_TRUE(audio_media_desc != NULL);
2416 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2417 offer->GetContentDescriptionByName("video"));
2418 ASSERT_TRUE(video_media_desc != NULL);
2419 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2420 EXPECT_TRUE(video_media_desc->cryptos().empty());
2421
2422 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2423 ASSERT_TRUE(audio_trans_desc != NULL);
2424 video_trans_desc = offer->GetTransportDescriptionByName("video");
2425 ASSERT_TRUE(video_trans_desc != NULL);
2426 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2427 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002428}
2429
2430// Test that an answer can't be created if cryptos are required but the offer is
2431// unsecure.
2432TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2433 MediaSessionOptions options;
2434 f1_.set_secure(SEC_DISABLED);
2435 tdf1_.set_secure(SEC_DISABLED);
2436 f2_.set_secure(SEC_REQUIRED);
2437 tdf1_.set_secure(SEC_ENABLED);
2438
kwiberg31022942016-03-11 14:18:21 -08002439 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002440 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002441 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002442 f2_.CreateAnswer(offer.get(), options, NULL));
2443 EXPECT_TRUE(answer.get() == NULL);
2444}
2445
2446// Test that we accept a DTLS offer without SDES and create an appropriate
2447// answer.
2448TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2449 f1_.set_secure(SEC_DISABLED);
2450 f2_.set_secure(SEC_ENABLED);
2451 tdf1_.set_secure(SEC_ENABLED);
2452 tdf2_.set_secure(SEC_ENABLED);
2453 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002454 options.recv_audio = true;
2455 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002456 options.data_channel_type = cricket::DCT_RTP;
2457
kwiberg31022942016-03-11 14:18:21 -08002458 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002459
2460 // Generate an offer with DTLS but without SDES.
2461 offer.reset(f1_.CreateOffer(options, NULL));
2462 ASSERT_TRUE(offer.get() != NULL);
2463
2464 const AudioContentDescription* audio_offer =
2465 GetFirstAudioContentDescription(offer.get());
2466 ASSERT_TRUE(audio_offer->cryptos().empty());
2467 const VideoContentDescription* video_offer =
2468 GetFirstVideoContentDescription(offer.get());
2469 ASSERT_TRUE(video_offer->cryptos().empty());
2470 const DataContentDescription* data_offer =
2471 GetFirstDataContentDescription(offer.get());
2472 ASSERT_TRUE(data_offer->cryptos().empty());
2473
2474 const cricket::TransportDescription* audio_offer_trans_desc =
2475 offer->GetTransportDescriptionByName("audio");
2476 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2477 const cricket::TransportDescription* video_offer_trans_desc =
2478 offer->GetTransportDescriptionByName("video");
2479 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2480 const cricket::TransportDescription* data_offer_trans_desc =
2481 offer->GetTransportDescriptionByName("data");
2482 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2483
2484 // Generate an answer with DTLS.
2485 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2486 ASSERT_TRUE(answer.get() != NULL);
2487
2488 const cricket::TransportDescription* audio_answer_trans_desc =
2489 answer->GetTransportDescriptionByName("audio");
2490 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2491 const cricket::TransportDescription* video_answer_trans_desc =
2492 answer->GetTransportDescriptionByName("video");
2493 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2494 const cricket::TransportDescription* data_answer_trans_desc =
2495 answer->GetTransportDescriptionByName("data");
2496 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2497}
2498
2499// Verifies if vad_enabled option is set to false, CN codecs are not present in
2500// offer or answer.
2501TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2502 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002503 options.recv_audio = true;
2504 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002505 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002506 ASSERT_TRUE(offer.get() != NULL);
2507 const ContentInfo* audio_content = offer->GetContentByName("audio");
2508 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2509
2510 options.vad_enabled = false;
2511 offer.reset(f1_.CreateOffer(options, NULL));
2512 ASSERT_TRUE(offer.get() != NULL);
2513 audio_content = offer->GetContentByName("audio");
2514 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002515 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002516 f1_.CreateAnswer(offer.get(), options, NULL));
2517 ASSERT_TRUE(answer.get() != NULL);
2518 audio_content = answer->GetContentByName("audio");
2519 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2520}
deadbeef44f08192015-12-15 16:20:09 -08002521
2522// Test that the content name ("mid" in SDP) is unchanged when creating a
2523// new offer.
2524TEST_F(MediaSessionDescriptionFactoryTest,
2525 TestContentNameNotChangedInSubsequentOffers) {
2526 MediaSessionOptions opts;
2527 opts.recv_audio = true;
2528 opts.recv_video = true;
2529 opts.data_channel_type = cricket::DCT_SCTP;
2530 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002531 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002532 for (ContentInfo& content : offer->contents()) {
2533 content.name.append("_modified");
2534 }
2535
kwiberg31022942016-03-11 14:18:21 -08002536 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002537 f1_.CreateOffer(opts, offer.get()));
2538 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2539 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2540 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2541 ASSERT_TRUE(audio_content != nullptr);
2542 ASSERT_TRUE(video_content != nullptr);
2543 ASSERT_TRUE(data_content != nullptr);
2544 EXPECT_EQ("audio_modified", audio_content->name);
2545 EXPECT_EQ("video_modified", video_content->name);
2546 EXPECT_EQ("data_modified", data_content->name);
2547}
zhihuangcf5b37c2016-05-05 11:44:35 -07002548
2549class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2550 public:
2551 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07002552 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
2553 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07002554 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2555 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07002556 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
2557 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07002558 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2559 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2560 f1_.set_secure(SEC_ENABLED);
2561 f2_.set_secure(SEC_ENABLED);
2562 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002563 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002564 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002565 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002566 tdf1_.set_secure(SEC_ENABLED);
2567 tdf2_.set_secure(SEC_ENABLED);
2568 }
2569
2570 protected:
2571 MediaSessionDescriptionFactory f1_;
2572 MediaSessionDescriptionFactory f2_;
2573 TransportDescriptionFactory tdf1_;
2574 TransportDescriptionFactory tdf2_;
2575};
2576
2577TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2578 MediaSessionOptions opts;
2579 opts.recv_video = true;
2580 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2581 ASSERT_TRUE(offer.get() != nullptr);
2582 // Set the protocol for all the contents.
2583 for (auto content : offer.get()->contents()) {
2584 static_cast<MediaContentDescription*>(content.description)
2585 ->set_protocol(GetParam());
2586 }
2587 std::unique_ptr<SessionDescription> answer(
2588 f2_.CreateAnswer(offer.get(), opts, nullptr));
2589 const ContentInfo* ac = answer->GetContentByName("audio");
2590 const ContentInfo* vc = answer->GetContentByName("video");
2591 ASSERT_TRUE(ac != nullptr);
2592 ASSERT_TRUE(vc != nullptr);
2593 EXPECT_FALSE(ac->rejected); // the offer is accepted
2594 EXPECT_FALSE(vc->rejected);
2595 const AudioContentDescription* acd =
2596 static_cast<const AudioContentDescription*>(ac->description);
2597 const VideoContentDescription* vcd =
2598 static_cast<const VideoContentDescription*>(vc->description);
2599 EXPECT_EQ(GetParam(), acd->protocol());
2600 EXPECT_EQ(GetParam(), vcd->protocol());
2601}
2602
2603INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2604 MediaProtocolTest,
2605 ::testing::ValuesIn(kMediaProtocols));
2606INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2607 MediaProtocolTest,
2608 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07002609
2610TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
2611 TransportDescriptionFactory tdf;
2612 MediaSessionDescriptionFactory sf(&tdf);
2613 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2614 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2615
2616 // The merged list of codecs should contain any send codecs that are also
2617 // nominally in the recieve codecs list. Payload types should be picked from
2618 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
2619 // (set to 1). This equals what happens when the send codecs are used in an
2620 // offer and the receive codecs are used in the following answer.
2621 const std::vector<AudioCodec> sendrecv_codecs =
2622 MAKE_VECTOR(kAudioCodecsAnswer);
2623 const std::vector<AudioCodec> no_codecs;
2624
2625 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
2626 << "Please don't change shared test data!";
2627 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
2628 << "Please don't change shared test data!";
2629 // Alter iLBC send codec to have zero channels, to test that that is handled
2630 // properly.
2631 send_codecs[1].channels = 0;
2632
2633 // Alther iLBC receive codec to be lowercase, to test that case conversions
2634 // are handled properly.
2635 recv_codecs[2].name = "ilbc";
2636
2637 // Test proper merge
2638 sf.set_audio_codecs(send_codecs, recv_codecs);
2639 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2640 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002641 EXPECT_TRUE(sf.audio_sendrecv_codecs() == sendrecv_codecs);
ossu075af922016-06-14 03:29:38 -07002642
2643 // Test empty send codecs list
2644 sf.set_audio_codecs(no_codecs, recv_codecs);
2645 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2646 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002647 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002648
2649 // Test empty recv codecs list
2650 sf.set_audio_codecs(send_codecs, no_codecs);
2651 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2652 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002653 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002654
2655 // Test all empty codec lists
2656 sf.set_audio_codecs(no_codecs, no_codecs);
2657 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2658 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002659 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002660}
2661
2662namespace {
2663void TestAudioCodecsOffer(MediaContentDirection direction,
2664 bool add_legacy_stream) {
2665 TransportDescriptionFactory tdf;
2666 MediaSessionDescriptionFactory sf(&tdf);
2667 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2668 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2669 const std::vector<AudioCodec> sendrecv_codecs =
2670 MAKE_VECTOR(kAudioCodecsAnswer);
2671 sf.set_audio_codecs(send_codecs, recv_codecs);
2672 sf.set_add_legacy_streams(add_legacy_stream);
2673
2674 MediaSessionOptions opts;
2675 opts.recv_audio = (direction == cricket::MD_RECVONLY ||
2676 direction == cricket::MD_SENDRECV);
2677 opts.recv_video = false;
2678 if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV)
2679 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2680
2681 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
2682 ASSERT_TRUE(offer.get() != NULL);
2683 const ContentInfo* ac = offer->GetContentByName("audio");
2684
2685 // If the factory didn't add any audio content to the offer, we cannot check
2686 // that the codecs put in are right. This happens when we neither want to send
2687 // nor receive audio. The checks are still in place if at some point we'd
2688 // instead create an inactive stream.
2689 if (ac) {
2690 AudioContentDescription* acd =
2691 static_cast<AudioContentDescription*>(ac->description);
2692 // sendrecv and inactive should both present lists as if the channel was to
2693 // be used for sending and receiving. Inactive essentially means it might
2694 // eventually be used anything, but we don't know more at this moment.
2695 if (acd->direction() == cricket::MD_SENDONLY) {
2696 EXPECT_TRUE(acd->codecs() == send_codecs);
2697 } else if (acd->direction() == cricket::MD_RECVONLY) {
2698 EXPECT_TRUE(acd->codecs() == recv_codecs);
2699 } else {
2700 EXPECT_TRUE(acd->codecs() == sendrecv_codecs);
2701 }
2702 }
2703}
2704
2705static const AudioCodec kOfferAnswerCodecs[] = {
2706 AudioCodec(0, "codec0", 16000, -1, 1),
2707 AudioCodec(1, "codec1", 8000, 13300, 1),
2708 AudioCodec(2, "codec2", 8000, 64000, 1),
2709 AudioCodec(3, "codec3", 8000, 64000, 1),
2710 AudioCodec(4, "codec4", 8000, 0, 2),
2711 AudioCodec(5, "codec5", 32000, 0, 1),
2712 AudioCodec(6, "codec6", 48000, 0, 1)
2713};
2714
2715
2716/* The codecs groups below are chosen as per the matrix below. The objective is
2717 * to have different sets of codecs in the inputs, to get unique sets of codecs
2718 * after negotiation, depending on offer and answer communication directions.
2719 * One-way directions in the offer should either result in the opposite
2720 * direction in the answer, or an inactive answer. Regardless, the choice of
2721 * codecs should be as if the answer contained the opposite direction.
2722 * Inactive offers should be treated as sendrecv/sendrecv.
2723 *
2724 * | Offer | Answer | Result
2725 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
2726 * 0 | x - - | - x - | x - - - -
2727 * 1 | x x x | - x - | x - - x -
2728 * 2 | - x - | x - - | - x - - -
2729 * 3 | x x x | x - - | - x x - -
2730 * 4 | - x - | x x x | - x - - -
2731 * 5 | x - - | x x x | x - - - -
2732 * 6 | x x x | x x x | x x x x x
2733 */
2734// Codecs used by offerer in the AudioCodecsAnswerTest
2735static const int kOfferSendCodecs[] = { 0, 1, 3, 5, 6 };
2736static const int kOfferRecvCodecs[] = { 1, 2, 3, 4, 6 };
2737// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
2738// jumbled to catch the answer not following the order in the offer.
2739static const int kAnswerSendCodecs[] = { 6, 5, 2, 3, 4 };
2740static const int kAnswerRecvCodecs[] = { 6, 5, 4, 1, 0 };
2741// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
2742static const int kResultSend_RecvCodecs[] = { 0, 1, 5, 6 };
2743static const int kResultRecv_SendCodecs[] = { 2, 3, 4, 6 };
2744static const int kResultSendrecv_SendCodecs[] = { 3, 6 };
2745static const int kResultSendrecv_RecvCodecs[] = { 1, 6 };
2746static const int kResultSendrecv_SendrecvCodecs[] = { 6 };
2747
2748template <typename T, int IDXS>
2749std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
2750 std::vector<T> out;
2751 out.reserve(IDXS);
2752 for (int idx : indices)
2753 out.push_back(array[idx]);
2754
2755 return out;
2756}
2757
2758void TestAudioCodecsAnswer(MediaContentDirection offer_direction,
2759 MediaContentDirection answer_direction,
2760 bool add_legacy_stream) {
2761 TransportDescriptionFactory offer_tdf;
2762 TransportDescriptionFactory answer_tdf;
2763 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
2764 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
2765 offer_factory.set_audio_codecs(
2766 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
2767 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
2768 answer_factory.set_audio_codecs(
2769 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
2770 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
2771
2772 // Never add a legacy stream to offer - we want to control the offer
2773 // parameters exactly.
2774 offer_factory.set_add_legacy_streams(false);
2775 answer_factory.set_add_legacy_streams(add_legacy_stream);
2776 MediaSessionOptions offer_opts;
2777 offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY ||
2778 offer_direction == cricket::MD_SENDRECV);
2779 offer_opts.recv_video = false;
2780 if (offer_direction == cricket::MD_SENDONLY ||
2781 offer_direction == cricket::MD_SENDRECV) {
2782 offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2783 }
2784
2785 std::unique_ptr<SessionDescription> offer(
2786 offer_factory.CreateOffer(offer_opts, NULL));
2787 ASSERT_TRUE(offer.get() != NULL);
2788
2789 MediaSessionOptions answer_opts;
2790 answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY ||
2791 answer_direction == cricket::MD_SENDRECV);
2792 answer_opts.recv_video = false;
2793 if (answer_direction == cricket::MD_SENDONLY ||
2794 answer_direction == cricket::MD_SENDRECV) {
2795 answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2796 }
2797 std::unique_ptr<SessionDescription> answer(
2798 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
2799 const ContentInfo* ac = answer->GetContentByName("audio");
2800
2801 // If the factory didn't add any audio content to the answer, we cannot check
2802 // that the codecs put in are right. This happens when we neither want to send
2803 // nor receive audio. The checks are still in place if at some point we'd
2804 // instead create an inactive stream.
2805 if (ac) {
2806 const AudioContentDescription* acd =
2807 static_cast<const AudioContentDescription*>(ac->description);
2808 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
2809
2810
2811 std::vector<AudioCodec> target_codecs;
2812 // For offers with sendrecv or inactive, we should never reply with more
2813 // codecs than offered, with these codec sets.
2814 switch (offer_direction) {
2815 case cricket::MD_INACTIVE:
2816 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2817 kResultSendrecv_SendrecvCodecs);
2818 break;
2819 case cricket::MD_SENDONLY:
2820 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2821 kResultSend_RecvCodecs);
2822 break;
2823 case cricket::MD_RECVONLY:
2824 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2825 kResultRecv_SendCodecs);
2826 break;
2827 case cricket::MD_SENDRECV:
2828 if (acd->direction() == cricket::MD_SENDONLY) {
2829 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2830 kResultSendrecv_SendCodecs);
2831 } else if (acd->direction() == cricket::MD_RECVONLY) {
2832 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2833 kResultSendrecv_RecvCodecs);
2834 } else {
2835 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2836 kResultSendrecv_SendrecvCodecs);
2837 }
2838 break;
2839 }
2840
2841 auto format_codecs = [] (const std::vector<AudioCodec>& codecs) {
2842 std::stringstream os;
2843 bool first = true;
2844 os << "{";
2845 for (const auto& c : codecs) {
2846 os << (first ? " " : ", ") << c.id;
2847 first = false;
2848 }
2849 os << " }";
2850 return os.str();
2851 };
2852
2853 EXPECT_TRUE(acd->codecs() == target_codecs)
2854 << "Expected: " << format_codecs(target_codecs)
2855 << ", got: " << format_codecs(acd->codecs())
2856 << "; Offered: " << MediaContentDirectionToString(offer_direction)
2857 << ", answerer wants: "
2858 << MediaContentDirectionToString(answer_direction)
2859 << "; got: " << MediaContentDirectionToString(acd->direction());
2860 } else {
2861 EXPECT_EQ(offer_direction, cricket::MD_INACTIVE)
2862 << "Only inactive offers are allowed to not generate any audio content";
2863 }
2864}
2865}
2866
2867class AudioCodecsOfferTest
2868 : public ::testing::TestWithParam<std::tr1::tuple<MediaContentDirection,
2869 bool>> {
2870};
2871
2872TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
2873 TestAudioCodecsOffer(std::tr1::get<0>(GetParam()),
2874 std::tr1::get<1>(GetParam()));
2875}
2876
2877INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
2878 AudioCodecsOfferTest,
2879 ::testing::Combine(
2880 ::testing::Values(cricket::MD_SENDONLY,
2881 cricket::MD_RECVONLY,
2882 cricket::MD_SENDRECV,
2883 cricket::MD_INACTIVE),
2884 ::testing::Bool()));
2885
2886class AudioCodecsAnswerTest
2887 : public ::testing::TestWithParam<std::tr1::tuple<MediaContentDirection,
2888 MediaContentDirection,
2889 bool>> {
2890};
2891
2892TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
2893 TestAudioCodecsAnswer(std::tr1::get<0>(GetParam()),
2894 std::tr1::get<1>(GetParam()),
2895 std::tr1::get<2>(GetParam()));
2896}
2897
2898INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
2899 AudioCodecsAnswerTest,
2900 ::testing::Combine(
2901 ::testing::Values(cricket::MD_SENDONLY,
2902 cricket::MD_RECVONLY,
2903 cricket::MD_SENDRECV,
2904 cricket::MD_INACTIVE),
2905 ::testing::Values(cricket::MD_SENDONLY,
2906 cricket::MD_RECVONLY,
2907 cricket::MD_SENDRECV,
2908 cricket::MD_INACTIVE),
2909 ::testing::Bool()));