blob: a6f6658d81fd39d191aa1297440c31146e19cf86 [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;
42using cricket::MediaSessionOptions;
43using cricket::MediaType;
44using cricket::SessionDescription;
45using cricket::SsrcGroup;
46using cricket::StreamParams;
47using cricket::StreamParamsVec;
48using cricket::TransportDescription;
49using cricket::TransportDescriptionFactory;
50using cricket::TransportInfo;
51using cricket::ContentInfo;
52using cricket::CryptoParamsVec;
53using cricket::AudioContentDescription;
54using cricket::VideoContentDescription;
55using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080056using cricket::GetFirstAudioContent;
57using cricket::GetFirstVideoContent;
58using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059using cricket::GetFirstAudioContentDescription;
60using cricket::GetFirstVideoContentDescription;
61using cricket::GetFirstDataContentDescription;
62using cricket::kAutoBandwidth;
63using cricket::AudioCodec;
64using cricket::VideoCodec;
65using cricket::DataCodec;
66using cricket::NS_JINGLE_RTP;
67using cricket::MEDIA_TYPE_AUDIO;
68using cricket::MEDIA_TYPE_VIDEO;
69using cricket::MEDIA_TYPE_DATA;
70using cricket::RtpHeaderExtension;
71using 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;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076
77static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070078 AudioCodec(103, "ISAC", 16000, -1, 1),
79 AudioCodec(102, "iLBC", 8000, 13300, 1),
80 AudioCodec(0, "PCMU", 8000, 64000, 1),
81 AudioCodec(8, "PCMA", 8000, 64000, 1),
82 AudioCodec(117, "red", 8000, 0, 1),
83 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
85static const AudioCodec kAudioCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070086 AudioCodec(126, "speex", 16000, 22000, 1),
87 AudioCodec(0, "PCMU", 8000, 64000, 1),
88 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089};
90
91static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070092 AudioCodec(102, "iLBC", 8000, 13300, 1),
93 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094};
95
96static const VideoCodec kVideoCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070097 VideoCodec(96, "H264-SVC", 320, 200, 30),
98 VideoCodec(97, "H264", 320, 200, 30)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099
100static const VideoCodec kVideoCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -0700101 VideoCodec(126, "H264", 320, 200, 30),
102 VideoCodec(127, "H263", 320, 200, 30)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103
104static const VideoCodec kVideoCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -0700105 VideoCodec(97, "H264", 320, 200, 30)};
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
116static const RtpHeaderExtension kAudioRtpExtension1[] = {
117 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
118 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
119};
120
121static const RtpHeaderExtension kAudioRtpExtension2[] = {
122 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
123 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000124 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125};
126
deadbeefa5b273a2015-08-20 17:30:13 -0700127static const RtpHeaderExtension kAudioRtpExtension3[] = {
128 RtpHeaderExtension("http://google.com/testing/audio_something", 2),
129 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 3),
130};
131
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000132static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
133 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
134};
135
136static const RtpHeaderExtension kVideoRtpExtension1[] = {
137 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000138 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000139};
140
141static const RtpHeaderExtension kVideoRtpExtension2[] = {
142 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
143 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000144 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145};
146
deadbeefa5b273a2015-08-20 17:30:13 -0700147static const RtpHeaderExtension kVideoRtpExtension3[] = {
148 RtpHeaderExtension("http://google.com/testing/video_something", 4),
149 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 5),
150};
151
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
153 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
154};
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
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000173static bool IsMediaContentOfType(const ContentInfo* content,
174 MediaType media_type) {
175 const MediaContentDescription* mdesc =
176 static_cast<const MediaContentDescription*>(content->description);
177 return mdesc && mdesc->type() == media_type;
178}
179
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000180static cricket::MediaContentDirection
181GetMediaDirection(const ContentInfo* content) {
182 cricket::MediaContentDescription* desc =
183 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
184 return desc->direction();
185}
186
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000187static void AddRtxCodec(const VideoCodec& rtx_codec,
188 std::vector<VideoCodec>* codecs) {
189 VideoCodec rtx;
190 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
191 codecs->push_back(rtx_codec);
192}
193
194template <class T>
195static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
196 std::vector<std::string> codec_names;
197 for (const auto& codec : codecs) {
198 codec_names.push_back(codec.name);
199 }
200 return codec_names;
201}
202
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000203class MediaSessionDescriptionFactoryTest : public testing::Test {
204 public:
205 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200206 : f1_(&tdf1_),
207 f2_(&tdf2_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
209 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
210 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
211 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
212 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
213 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200214 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700215 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200216 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700217 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000218 }
219
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000220 // Create a video StreamParamsVec object with:
221 // - one video stream with 3 simulcast streams and FEC,
222 StreamParamsVec CreateComplexVideoStreamParamsVec() {
223 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
224 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
225 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
226 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
227
228 std::vector<SsrcGroup> ssrc_groups;
229 ssrc_groups.push_back(sim_group);
230 ssrc_groups.push_back(fec_group1);
231 ssrc_groups.push_back(fec_group2);
232 ssrc_groups.push_back(fec_group3);
233
234 StreamParams simulcast_params;
235 simulcast_params.id = kVideoTrack1;
236 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
237 simulcast_params.ssrc_groups = ssrc_groups;
238 simulcast_params.cname = "Video_SIM_FEC";
239 simulcast_params.sync_label = kMediaStream1;
240
241 StreamParamsVec video_streams;
242 video_streams.push_back(simulcast_params);
243
244 return video_streams;
245 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000246
247 bool CompareCryptoParams(const CryptoParamsVec& c1,
248 const CryptoParamsVec& c2) {
249 if (c1.size() != c2.size())
250 return false;
251 for (size_t i = 0; i < c1.size(); ++i)
252 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
253 c1[i].key_params != c2[i].key_params ||
254 c1[i].session_params != c2[i].session_params)
255 return false;
256 return true;
257 }
258
259 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
260 bool has_current_desc) {
261 const std::string current_audio_ufrag = "current_audio_ufrag";
262 const std::string current_audio_pwd = "current_audio_pwd";
263 const std::string current_video_ufrag = "current_video_ufrag";
264 const std::string current_video_pwd = "current_video_pwd";
265 const std::string current_data_ufrag = "current_data_ufrag";
266 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800267 std::unique_ptr<SessionDescription> current_desc;
268 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000269 if (has_current_desc) {
270 current_desc.reset(new SessionDescription());
271 EXPECT_TRUE(current_desc->AddTransportInfo(
272 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700273 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000274 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275 EXPECT_TRUE(current_desc->AddTransportInfo(
276 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700277 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000278 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279 EXPECT_TRUE(current_desc->AddTransportInfo(
280 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700281 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000282 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283 }
284 if (offer) {
285 desc.reset(f1_.CreateOffer(options, current_desc.get()));
286 } else {
kwiberg31022942016-03-11 14:18:21 -0800287 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000288 offer.reset(f1_.CreateOffer(options, NULL));
289 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
290 }
291 ASSERT_TRUE(desc.get() != NULL);
292 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000293 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 EXPECT_TRUE(ti_audio != NULL);
295 if (has_current_desc) {
296 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
297 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
298 } else {
299 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
300 ti_audio->description.ice_ufrag.size());
301 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
302 ti_audio->description.ice_pwd.size());
303 }
304
305 } else {
306 EXPECT_TRUE(ti_audio == NULL);
307 }
308 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000309 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000310 EXPECT_TRUE(ti_video != NULL);
311 if (options.bundle_enabled) {
312 EXPECT_EQ(ti_audio->description.ice_ufrag,
313 ti_video->description.ice_ufrag);
314 EXPECT_EQ(ti_audio->description.ice_pwd,
315 ti_video->description.ice_pwd);
316 } else {
317 if (has_current_desc) {
318 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
319 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
320 } else {
321 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
322 ti_video->description.ice_ufrag.size());
323 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
324 ti_video->description.ice_pwd.size());
325 }
326 }
327 } else {
328 EXPECT_TRUE(ti_video == NULL);
329 }
330 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
331 if (options.has_data()) {
332 EXPECT_TRUE(ti_data != NULL);
333 if (options.bundle_enabled) {
334 EXPECT_EQ(ti_audio->description.ice_ufrag,
335 ti_data->description.ice_ufrag);
336 EXPECT_EQ(ti_audio->description.ice_pwd,
337 ti_data->description.ice_pwd);
338 } else {
339 if (has_current_desc) {
340 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
341 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
342 } else {
343 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
344 ti_data->description.ice_ufrag.size());
345 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
346 ti_data->description.ice_pwd.size());
347 }
348 }
349 } else {
350 EXPECT_TRUE(ti_video == NULL);
351 }
352 }
353
354 void TestCryptoWithBundle(bool offer) {
355 f1_.set_secure(SEC_ENABLED);
356 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000357 options.recv_audio = true;
358 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800360 std::unique_ptr<SessionDescription> ref_desc;
361 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362 if (offer) {
363 options.bundle_enabled = false;
364 ref_desc.reset(f1_.CreateOffer(options, NULL));
365 options.bundle_enabled = true;
366 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
367 } else {
368 options.bundle_enabled = true;
369 ref_desc.reset(f1_.CreateOffer(options, NULL));
370 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
371 }
372 ASSERT_TRUE(desc.get() != NULL);
373 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000374 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000375 desc.get()->GetContentDescriptionByName("audio"));
376 ASSERT_TRUE(audio_media_desc != NULL);
377 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000378 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000379 desc.get()->GetContentDescriptionByName("video"));
380 ASSERT_TRUE(video_media_desc != NULL);
381 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
382 video_media_desc->cryptos()));
383 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
384 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
385 audio_media_desc->cryptos()[0].cipher_suite);
386
387 // Verify the selected crypto is one from the reference audio
388 // media content.
389 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000390 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000391 ref_desc.get()->GetContentDescriptionByName("audio"));
392 bool found = false;
393 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
394 if (ref_audio_media_desc->cryptos()[i].Matches(
395 audio_media_desc->cryptos()[0])) {
396 found = true;
397 break;
398 }
399 }
400 EXPECT_TRUE(found);
401 }
402
403 // This test that the audio and video media direction is set to
404 // |expected_direction_in_answer| in an answer if the offer direction is set
405 // to |direction_in_offer|.
406 void TestMediaDirectionInAnswer(
407 cricket::MediaContentDirection direction_in_offer,
408 cricket::MediaContentDirection expected_direction_in_answer) {
409 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000410 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800411 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700413 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000414 ASSERT_TRUE(ac_offer != NULL);
415 AudioContentDescription* acd_offer =
416 static_cast<AudioContentDescription*>(ac_offer->description);
417 acd_offer->set_direction(direction_in_offer);
terelius8c011e52016-04-26 05:28:11 -0700418 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000419 ASSERT_TRUE(vc_offer != NULL);
420 VideoContentDescription* vcd_offer =
421 static_cast<VideoContentDescription*>(vc_offer->description);
422 vcd_offer->set_direction(direction_in_offer);
423
kwiberg31022942016-03-11 14:18:21 -0800424 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 f2_.CreateAnswer(offer.get(), opts, NULL));
426 const AudioContentDescription* acd_answer =
427 GetFirstAudioContentDescription(answer.get());
428 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
429 const VideoContentDescription* vcd_answer =
430 GetFirstVideoContentDescription(answer.get());
431 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
432 }
433
434 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
435 const cricket::ContentDescription* description = content->description;
436 ASSERT(description != NULL);
437 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000438 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000439 ASSERT(audio_content_desc != NULL);
440 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
441 if (audio_content_desc->codecs()[i].name == "CN")
442 return false;
443 }
444 return true;
445 }
446
447 protected:
448 MediaSessionDescriptionFactory f1_;
449 MediaSessionDescriptionFactory f2_;
450 TransportDescriptionFactory tdf1_;
451 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000452};
453
454// Create a typical audio offer, and ensure it matches what we expect.
455TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
456 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800457 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458 f1_.CreateOffer(MediaSessionOptions(), NULL));
459 ASSERT_TRUE(offer.get() != NULL);
460 const ContentInfo* ac = offer->GetContentByName("audio");
461 const ContentInfo* vc = offer->GetContentByName("video");
462 ASSERT_TRUE(ac != NULL);
463 ASSERT_TRUE(vc == NULL);
464 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
465 const AudioContentDescription* acd =
466 static_cast<const AudioContentDescription*>(ac->description);
467 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
468 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
469 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
470 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
471 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
472 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
473 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
474}
475
476// Create a typical video offer, and ensure it matches what we expect.
477TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
478 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000479 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000480 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800481 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000482 ASSERT_TRUE(offer.get() != NULL);
483 const ContentInfo* ac = offer->GetContentByName("audio");
484 const ContentInfo* vc = offer->GetContentByName("video");
485 ASSERT_TRUE(ac != NULL);
486 ASSERT_TRUE(vc != NULL);
487 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
488 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
489 const AudioContentDescription* acd =
490 static_cast<const AudioContentDescription*>(ac->description);
491 const VideoContentDescription* vcd =
492 static_cast<const VideoContentDescription*>(vc->description);
493 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
494 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
495 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
496 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
497 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
498 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
499 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
500 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
501 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
502 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
503 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
504 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
505 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
506 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
507}
508
509// Test creating an offer with bundle where the Codecs have the same dynamic
510// RTP playlod type. The test verifies that the offer don't contain the
511// duplicate RTP payload types.
512TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
513 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
514 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
515 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
516 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
517 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
518
519 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000520 opts.recv_audio = true;
521 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522 opts.data_channel_type = cricket::DCT_RTP;
523 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800524 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525 const VideoContentDescription* vcd =
526 GetFirstVideoContentDescription(offer.get());
527 const AudioContentDescription* acd =
528 GetFirstAudioContentDescription(offer.get());
529 const DataContentDescription* dcd =
530 GetFirstDataContentDescription(offer.get());
531 ASSERT_TRUE(NULL != vcd);
532 ASSERT_TRUE(NULL != acd);
533 ASSERT_TRUE(NULL != dcd);
534 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
535 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
536 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
537 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
538 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
539 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
540}
541
542// Test creating an updated offer with with bundle, audio, video and data
543// after an audio only session has been negotiated.
544TEST_F(MediaSessionDescriptionFactoryTest,
545 TestCreateUpdatedVideoOfferWithBundle) {
546 f1_.set_secure(SEC_ENABLED);
547 f2_.set_secure(SEC_ENABLED);
548 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000549 opts.recv_audio = true;
550 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000551 opts.data_channel_type = cricket::DCT_NONE;
552 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800553 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
554 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000555 f2_.CreateAnswer(offer.get(), opts, NULL));
556
557 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000558 updated_opts.recv_audio = true;
559 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000560 updated_opts.data_channel_type = cricket::DCT_RTP;
561 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800562 std::unique_ptr<SessionDescription> updated_offer(
563 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000564
565 const AudioContentDescription* acd =
566 GetFirstAudioContentDescription(updated_offer.get());
567 const VideoContentDescription* vcd =
568 GetFirstVideoContentDescription(updated_offer.get());
569 const DataContentDescription* dcd =
570 GetFirstDataContentDescription(updated_offer.get());
571 EXPECT_TRUE(NULL != vcd);
572 EXPECT_TRUE(NULL != acd);
573 EXPECT_TRUE(NULL != dcd);
574
575 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
576 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
577 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
578 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
579 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
580 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
581}
deadbeef44f08192015-12-15 16:20:09 -0800582
wu@webrtc.org78187522013-10-07 23:32:02 +0000583// Create a RTP data offer, and ensure it matches what we expect.
584TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585 MediaSessionOptions opts;
586 opts.data_channel_type = cricket::DCT_RTP;
587 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800588 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 ASSERT_TRUE(offer.get() != NULL);
590 const ContentInfo* ac = offer->GetContentByName("audio");
591 const ContentInfo* dc = offer->GetContentByName("data");
592 ASSERT_TRUE(ac != NULL);
593 ASSERT_TRUE(dc != NULL);
594 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
595 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
596 const AudioContentDescription* acd =
597 static_cast<const AudioContentDescription*>(ac->description);
598 const DataContentDescription* dcd =
599 static_cast<const DataContentDescription*>(dc->description);
600 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
601 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
602 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
603 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
604 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
605 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
606 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
607 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
608 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
609 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
610 EXPECT_EQ(cricket::kDataMaxBandwidth,
611 dcd->bandwidth()); // default bandwidth (auto)
612 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
613 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
614 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
615}
616
wu@webrtc.org78187522013-10-07 23:32:02 +0000617// Create an SCTP data offer with bundle without error.
618TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
619 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000620 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000621 opts.bundle_enabled = true;
622 opts.data_channel_type = cricket::DCT_SCTP;
623 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800624 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000625 EXPECT_TRUE(offer.get() != NULL);
626 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
627}
628
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000629// Test creating an sctp data channel from an already generated offer.
630TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
631 MediaSessionOptions opts;
632 opts.recv_audio = false;
633 opts.bundle_enabled = true;
634 opts.data_channel_type = cricket::DCT_SCTP;
635 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800636 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000637 ASSERT_TRUE(offer1.get() != NULL);
638 const ContentInfo* data = offer1->GetContentByName("data");
639 ASSERT_TRUE(data != NULL);
640 const MediaContentDescription* mdesc =
641 static_cast<const MediaContentDescription*>(data->description);
642 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
643
644 // Now set data_channel_type to 'none' (default) and make sure that the
645 // datachannel type that gets generated from the previous offer, is of the
646 // same type.
647 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800648 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000649 f1_.CreateOffer(opts, offer1.get()));
650 data = offer2->GetContentByName("data");
651 ASSERT_TRUE(data != NULL);
652 mdesc = static_cast<const MediaContentDescription*>(data->description);
653 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
654}
655
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656// Create an audio, video offer without legacy StreamParams.
657TEST_F(MediaSessionDescriptionFactoryTest,
658 TestCreateOfferWithoutLegacyStreams) {
659 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000660 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000661 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800662 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000663 ASSERT_TRUE(offer.get() != NULL);
664 const ContentInfo* ac = offer->GetContentByName("audio");
665 const ContentInfo* vc = offer->GetContentByName("video");
666 ASSERT_TRUE(ac != NULL);
667 ASSERT_TRUE(vc != NULL);
668 const AudioContentDescription* acd =
669 static_cast<const AudioContentDescription*>(ac->description);
670 const VideoContentDescription* vcd =
671 static_cast<const VideoContentDescription*>(vc->description);
672
673 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
674 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
675}
676
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000677// Creates an audio+video sendonly offer.
678TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
679 MediaSessionOptions options;
680 options.recv_audio = false;
681 options.recv_video = false;
682 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
683 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
684
kwiberg31022942016-03-11 14:18:21 -0800685 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000686 ASSERT_TRUE(offer.get() != NULL);
687 EXPECT_EQ(2u, offer->contents().size());
688 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
689 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
690
691 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
692 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
693}
694
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000695// Verifies that the order of the media contents in the current
696// SessionDescription is preserved in the new SessionDescription.
697TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
698 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000699 opts.recv_audio = false;
700 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000701 opts.data_channel_type = cricket::DCT_SCTP;
702
kwiberg31022942016-03-11 14:18:21 -0800703 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000704 ASSERT_TRUE(offer1.get() != NULL);
705 EXPECT_EQ(1u, offer1->contents().size());
706 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
707
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000708 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800709 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000710 f1_.CreateOffer(opts, offer1.get()));
711 ASSERT_TRUE(offer2.get() != NULL);
712 EXPECT_EQ(2u, offer2->contents().size());
713 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
714 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
715
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000716 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800717 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000718 f1_.CreateOffer(opts, offer2.get()));
719 ASSERT_TRUE(offer3.get() != NULL);
720 EXPECT_EQ(3u, offer3->contents().size());
721 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
722 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
723 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
724
725 // Verifies the default order is audio-video-data, so that the previous checks
726 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800727 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000728 ASSERT_TRUE(offer4.get() != NULL);
729 EXPECT_EQ(3u, offer4->contents().size());
730 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
731 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
732 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
733}
734
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000735// Create a typical audio answer, and ensure it matches what we expect.
736TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
737 f1_.set_secure(SEC_ENABLED);
738 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800739 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000740 f1_.CreateOffer(MediaSessionOptions(), NULL));
741 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800742 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
744 const ContentInfo* ac = answer->GetContentByName("audio");
745 const ContentInfo* vc = answer->GetContentByName("video");
746 ASSERT_TRUE(ac != NULL);
747 ASSERT_TRUE(vc == NULL);
748 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
749 const AudioContentDescription* acd =
750 static_cast<const AudioContentDescription*>(ac->description);
751 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
752 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
753 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
754 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
755 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
756 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
757 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
758}
759
760// Create a typical video answer, and ensure it matches what we expect.
761TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
762 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000763 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764 f1_.set_secure(SEC_ENABLED);
765 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800766 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000767 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800768 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 f2_.CreateAnswer(offer.get(), opts, NULL));
770 const ContentInfo* ac = answer->GetContentByName("audio");
771 const ContentInfo* vc = answer->GetContentByName("video");
772 ASSERT_TRUE(ac != NULL);
773 ASSERT_TRUE(vc != NULL);
774 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
775 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
776 const AudioContentDescription* acd =
777 static_cast<const AudioContentDescription*>(ac->description);
778 const VideoContentDescription* vcd =
779 static_cast<const VideoContentDescription*>(vc->description);
780 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
781 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
782 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
783 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
784 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
785 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
786 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
787 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
788 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
789 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
790 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
791 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
792}
793
794TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
795 MediaSessionOptions opts;
796 opts.data_channel_type = cricket::DCT_RTP;
797 f1_.set_secure(SEC_ENABLED);
798 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800799 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000800 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800801 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802 f2_.CreateAnswer(offer.get(), opts, NULL));
803 const ContentInfo* ac = answer->GetContentByName("audio");
804 const ContentInfo* vc = answer->GetContentByName("data");
805 ASSERT_TRUE(ac != NULL);
806 ASSERT_TRUE(vc != NULL);
807 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
808 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
809 const AudioContentDescription* acd =
810 static_cast<const AudioContentDescription*>(ac->description);
811 const DataContentDescription* vcd =
812 static_cast<const DataContentDescription*>(vc->description);
813 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
814 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
815 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
816 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
817 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
818 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
819 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
820 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
821 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
822 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
823 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
824 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
825}
826
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000827// Verifies that the order of the media contents in the offer is preserved in
828// the answer.
829TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
830 MediaSessionOptions opts;
831
832 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000833 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000834 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -0800835 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000836 ASSERT_TRUE(offer1.get() != NULL);
837
838 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000839 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800840 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000841 f1_.CreateOffer(opts, offer1.get()));
842 ASSERT_TRUE(offer2.get() != NULL);
843
844 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000845 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800846 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000847 f1_.CreateOffer(opts, offer2.get()));
848 ASSERT_TRUE(offer3.get() != NULL);
849
kwiberg31022942016-03-11 14:18:21 -0800850 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000851 f2_.CreateAnswer(offer3.get(), opts, NULL));
852 ASSERT_TRUE(answer.get() != NULL);
853 EXPECT_EQ(3u, answer->contents().size());
854 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
855 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
856 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
857}
858
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859// This test that the media direction is set to send/receive in an answer if
860// the offer is send receive.
861TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
862 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
863}
864
865// This test that the media direction is set to receive only in an answer if
866// the offer is send only.
867TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
868 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
869}
870
871// This test that the media direction is set to send only in an answer if
872// the offer is recv only.
873TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
874 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
875}
876
877// This test that the media direction is set to inactive in an answer if
878// the offer is inactive.
879TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
880 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
881}
882
883// Test that a data content with an unknown protocol is rejected in an answer.
884TEST_F(MediaSessionDescriptionFactoryTest,
885 CreateDataAnswerToOfferWithUnknownProtocol) {
886 MediaSessionOptions opts;
887 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000888 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000889 f1_.set_secure(SEC_ENABLED);
890 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800891 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -0700892 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000893 ASSERT_TRUE(dc_offer != NULL);
894 DataContentDescription* dcd_offer =
895 static_cast<DataContentDescription*>(dc_offer->description);
896 ASSERT_TRUE(dcd_offer != NULL);
897 std::string protocol = "a weird unknown protocol";
898 dcd_offer->set_protocol(protocol);
899
kwiberg31022942016-03-11 14:18:21 -0800900 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000901 f2_.CreateAnswer(offer.get(), opts, NULL));
902
903 const ContentInfo* dc_answer = answer->GetContentByName("data");
904 ASSERT_TRUE(dc_answer != NULL);
905 EXPECT_TRUE(dc_answer->rejected);
906 const DataContentDescription* dcd_answer =
907 static_cast<const DataContentDescription*>(dc_answer->description);
908 ASSERT_TRUE(dcd_answer != NULL);
909 EXPECT_EQ(protocol, dcd_answer->protocol());
910}
911
912// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
913TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
914 MediaSessionOptions opts;
915 f1_.set_secure(SEC_DISABLED);
916 f2_.set_secure(SEC_DISABLED);
917 tdf1_.set_secure(SEC_DISABLED);
918 tdf2_.set_secure(SEC_DISABLED);
919
kwiberg31022942016-03-11 14:18:21 -0800920 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000921 const AudioContentDescription* offer_acd =
922 GetFirstAudioContentDescription(offer.get());
923 ASSERT_TRUE(offer_acd != NULL);
924 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
925
kwiberg31022942016-03-11 14:18:21 -0800926 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000927 f2_.CreateAnswer(offer.get(), opts, NULL));
928
929 const ContentInfo* ac_answer = answer->GetContentByName("audio");
930 ASSERT_TRUE(ac_answer != NULL);
931 EXPECT_FALSE(ac_answer->rejected);
932
933 const AudioContentDescription* answer_acd =
934 GetFirstAudioContentDescription(answer.get());
935 ASSERT_TRUE(answer_acd != NULL);
936 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
937}
938
939// Create a video offer and answer and ensure the RTP header extensions
940// matches what we expect.
941TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
942 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000943 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000944
945 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
946 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
947 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
948 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
949
kwiberg31022942016-03-11 14:18:21 -0800950 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000951 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800952 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953 f2_.CreateAnswer(offer.get(), opts, NULL));
954
955 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
956 GetFirstAudioContentDescription(
957 offer.get())->rtp_header_extensions());
958 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
959 GetFirstVideoContentDescription(
960 offer.get())->rtp_header_extensions());
961 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
962 GetFirstAudioContentDescription(
963 answer.get())->rtp_header_extensions());
964 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
965 GetFirstVideoContentDescription(
966 answer.get())->rtp_header_extensions());
967}
968
969// Create an audio, video, data answer without legacy StreamParams.
970TEST_F(MediaSessionDescriptionFactoryTest,
971 TestCreateAnswerWithoutLegacyStreams) {
972 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000973 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000974 opts.data_channel_type = cricket::DCT_RTP;
975 f1_.set_add_legacy_streams(false);
976 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800977 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000978 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800979 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 f2_.CreateAnswer(offer.get(), opts, NULL));
981 const ContentInfo* ac = answer->GetContentByName("audio");
982 const ContentInfo* vc = answer->GetContentByName("video");
983 const ContentInfo* dc = answer->GetContentByName("data");
984 ASSERT_TRUE(ac != NULL);
985 ASSERT_TRUE(vc != NULL);
986 const AudioContentDescription* acd =
987 static_cast<const AudioContentDescription*>(ac->description);
988 const VideoContentDescription* vcd =
989 static_cast<const VideoContentDescription*>(vc->description);
990 const DataContentDescription* dcd =
991 static_cast<const DataContentDescription*>(dc->description);
992
993 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
994 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
995 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
996}
997
998TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
999 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001000 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001001 opts.data_channel_type = cricket::DCT_RTP;
1002 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001003 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001004 ASSERT_TRUE(offer.get() != NULL);
1005 const ContentInfo* ac = offer->GetContentByName("audio");
1006 const ContentInfo* vc = offer->GetContentByName("video");
1007 const ContentInfo* dc = offer->GetContentByName("data");
1008 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1009 static_cast<const AudioContentDescription*>(ac->description));
1010 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1011 static_cast<const VideoContentDescription*>(vc->description));
1012 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1013 static_cast<const DataContentDescription*>(dc->description));
1014
1015 EXPECT_FALSE(acd->partial()); // default is false.
1016 acd->set_partial(true);
1017 EXPECT_TRUE(acd->partial());
1018 acd->set_partial(false);
1019 EXPECT_FALSE(acd->partial());
1020
1021 EXPECT_FALSE(vcd->partial()); // default is false.
1022 vcd->set_partial(true);
1023 EXPECT_TRUE(vcd->partial());
1024 vcd->set_partial(false);
1025 EXPECT_FALSE(vcd->partial());
1026
1027 EXPECT_FALSE(dcd->partial()); // default is false.
1028 dcd->set_partial(true);
1029 EXPECT_TRUE(dcd->partial());
1030 dcd->set_partial(false);
1031 EXPECT_FALSE(dcd->partial());
1032}
1033
1034// Create a typical video answer, and ensure it matches what we expect.
1035TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1036 MediaSessionOptions offer_opts;
1037 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001038 answer_opts.recv_video = true;
1039 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001040 answer_opts.data_channel_type = cricket::DCT_RTP;
1041 offer_opts.data_channel_type = cricket::DCT_RTP;
1042
kwiberg31022942016-03-11 14:18:21 -08001043 std::unique_ptr<SessionDescription> offer;
1044 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001045
1046 offer_opts.rtcp_mux_enabled = true;
1047 answer_opts.rtcp_mux_enabled = true;
1048
1049 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1050 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1051 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1052 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1053 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1054 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1055 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1056 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1057 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1058 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1059 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1060 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1061 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1062 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1063
1064 offer_opts.rtcp_mux_enabled = true;
1065 answer_opts.rtcp_mux_enabled = false;
1066
1067 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1068 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1069 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1070 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1071 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1072 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1073 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1074 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1075 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1076 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1077 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1078 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1079 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1080 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1081
1082 offer_opts.rtcp_mux_enabled = false;
1083 answer_opts.rtcp_mux_enabled = true;
1084
1085 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1086 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1087 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1088 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1089 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1090 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1091 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1092 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1093 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1094 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1095 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1096 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1097 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1098 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1099
1100 offer_opts.rtcp_mux_enabled = false;
1101 answer_opts.rtcp_mux_enabled = false;
1102
1103 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1104 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1105 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1106 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1107 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1108 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1109 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1110 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1111 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1112 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1113 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1114 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1115 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1116 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1117}
1118
1119// Create an audio-only answer to a video offer.
1120TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1121 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001122 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001123 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001124 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001125 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001126 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1127 const ContentInfo* ac = answer->GetContentByName("audio");
1128 const ContentInfo* vc = answer->GetContentByName("video");
1129 ASSERT_TRUE(ac != NULL);
1130 ASSERT_TRUE(vc != NULL);
1131 ASSERT_TRUE(vc->description != NULL);
1132 EXPECT_TRUE(vc->rejected);
1133}
1134
1135// Create an audio-only answer to an offer with data.
1136TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1137 MediaSessionOptions opts;
1138 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001139 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001141 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001142 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1143 const ContentInfo* ac = answer->GetContentByName("audio");
1144 const ContentInfo* dc = answer->GetContentByName("data");
1145 ASSERT_TRUE(ac != NULL);
1146 ASSERT_TRUE(dc != NULL);
1147 ASSERT_TRUE(dc->description != NULL);
1148 EXPECT_TRUE(dc->rejected);
1149}
1150
1151// Create an answer that rejects the contents which are rejected in the offer.
1152TEST_F(MediaSessionDescriptionFactoryTest,
1153 CreateAnswerToOfferWithRejectedMedia) {
1154 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001155 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001157 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158 ASSERT_TRUE(offer.get() != NULL);
1159 ContentInfo* ac = offer->GetContentByName("audio");
1160 ContentInfo* vc = offer->GetContentByName("video");
1161 ContentInfo* dc = offer->GetContentByName("data");
1162 ASSERT_TRUE(ac != NULL);
1163 ASSERT_TRUE(vc != NULL);
1164 ASSERT_TRUE(dc != NULL);
1165 ac->rejected = true;
1166 vc->rejected = true;
1167 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001168 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001169 f2_.CreateAnswer(offer.get(), opts, NULL));
1170 ac = answer->GetContentByName("audio");
1171 vc = answer->GetContentByName("video");
1172 dc = answer->GetContentByName("data");
1173 ASSERT_TRUE(ac != NULL);
1174 ASSERT_TRUE(vc != NULL);
1175 ASSERT_TRUE(dc != NULL);
1176 EXPECT_TRUE(ac->rejected);
1177 EXPECT_TRUE(vc->rejected);
1178 EXPECT_TRUE(dc->rejected);
1179}
1180
1181// Create an audio and video offer with:
1182// - one video track
1183// - two audio tracks
1184// - two data tracks
1185// and ensure it matches what we expect. Also updates the initial offer by
1186// adding a new video track and replaces one of the audio tracks.
1187TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1188 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001189 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1190 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1191 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001192 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001193 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1194 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001195
1196 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001197 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001198
1199 ASSERT_TRUE(offer.get() != NULL);
1200 const ContentInfo* ac = offer->GetContentByName("audio");
1201 const ContentInfo* vc = offer->GetContentByName("video");
1202 const ContentInfo* dc = offer->GetContentByName("data");
1203 ASSERT_TRUE(ac != NULL);
1204 ASSERT_TRUE(vc != NULL);
1205 ASSERT_TRUE(dc != NULL);
1206 const AudioContentDescription* acd =
1207 static_cast<const AudioContentDescription*>(ac->description);
1208 const VideoContentDescription* vcd =
1209 static_cast<const VideoContentDescription*>(vc->description);
1210 const DataContentDescription* dcd =
1211 static_cast<const DataContentDescription*>(dc->description);
1212 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1213 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1214
1215 const StreamParamsVec& audio_streams = acd->streams();
1216 ASSERT_EQ(2U, audio_streams.size());
1217 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1218 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1219 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1220 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1221 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1222 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1223 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1224
1225 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1226 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1227 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1228
1229 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1230 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1231 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1232
1233 const StreamParamsVec& video_streams = vcd->streams();
1234 ASSERT_EQ(1U, video_streams.size());
1235 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1236 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1237 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1238 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1239
1240 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1241 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1242 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1243
1244 const StreamParamsVec& data_streams = dcd->streams();
1245 ASSERT_EQ(2U, data_streams.size());
1246 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1247 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1248 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1249 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1250 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1251 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1252 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1253
1254 EXPECT_EQ(cricket::kDataMaxBandwidth,
1255 dcd->bandwidth()); // default bandwidth (auto)
1256 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1257 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1258
1259
1260 // Update the offer. Add a new video track that is not synched to the
1261 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001262 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1263 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1264 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1265 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1266 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001267 std::unique_ptr<SessionDescription> updated_offer(
1268 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001269
1270 ASSERT_TRUE(updated_offer.get() != NULL);
1271 ac = updated_offer->GetContentByName("audio");
1272 vc = updated_offer->GetContentByName("video");
1273 dc = updated_offer->GetContentByName("data");
1274 ASSERT_TRUE(ac != NULL);
1275 ASSERT_TRUE(vc != NULL);
1276 ASSERT_TRUE(dc != NULL);
1277 const AudioContentDescription* updated_acd =
1278 static_cast<const AudioContentDescription*>(ac->description);
1279 const VideoContentDescription* updated_vcd =
1280 static_cast<const VideoContentDescription*>(vc->description);
1281 const DataContentDescription* updated_dcd =
1282 static_cast<const DataContentDescription*>(dc->description);
1283
1284 EXPECT_EQ(acd->type(), updated_acd->type());
1285 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1286 EXPECT_EQ(vcd->type(), updated_vcd->type());
1287 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1288 EXPECT_EQ(dcd->type(), updated_dcd->type());
1289 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1290 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1291 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1292 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1293 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1294 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1295 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1296
1297 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1298 ASSERT_EQ(2U, updated_audio_streams.size());
1299 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1300 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1301 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1302 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1303 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1304
1305 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1306 ASSERT_EQ(2U, updated_video_streams.size());
1307 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1308 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1309 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1310
1311 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1312 ASSERT_EQ(2U, updated_data_streams.size());
1313 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1314 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1315 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1316 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1317 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1318}
1319
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001320// Create an offer with simulcast video stream.
1321TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1322 MediaSessionOptions opts;
1323 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001324 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001325 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001326
1327 ASSERT_TRUE(offer.get() != NULL);
1328 const ContentInfo* vc = offer->GetContentByName("video");
1329 ASSERT_TRUE(vc != NULL);
1330 const VideoContentDescription* vcd =
1331 static_cast<const VideoContentDescription*>(vc->description);
1332
1333 const StreamParamsVec& video_streams = vcd->streams();
1334 ASSERT_EQ(1U, video_streams.size());
1335 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1336 const SsrcGroup* sim_ssrc_group =
1337 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1338 ASSERT_TRUE(sim_ssrc_group != NULL);
1339 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1340}
1341
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342// Create an audio and video answer to a standard video offer with:
1343// - one video track
1344// - two audio tracks
1345// - two data tracks
1346// and ensure it matches what we expect. Also updates the initial answer by
1347// adding a new video track and removes one of the audio tracks.
1348TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1349 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001350 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001351 offer_opts.data_channel_type = cricket::DCT_RTP;
1352 f1_.set_secure(SEC_ENABLED);
1353 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001354 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001355
1356 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001357 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1358 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1359 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001361 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1362 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001363
kwiberg31022942016-03-11 14:18:21 -08001364 std::unique_ptr<SessionDescription> answer(
1365 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366
1367 ASSERT_TRUE(answer.get() != NULL);
1368 const ContentInfo* ac = answer->GetContentByName("audio");
1369 const ContentInfo* vc = answer->GetContentByName("video");
1370 const ContentInfo* dc = answer->GetContentByName("data");
1371 ASSERT_TRUE(ac != NULL);
1372 ASSERT_TRUE(vc != NULL);
1373 ASSERT_TRUE(dc != NULL);
1374 const AudioContentDescription* acd =
1375 static_cast<const AudioContentDescription*>(ac->description);
1376 const VideoContentDescription* vcd =
1377 static_cast<const VideoContentDescription*>(vc->description);
1378 const DataContentDescription* dcd =
1379 static_cast<const DataContentDescription*>(dc->description);
1380 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1381 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1382 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1383
1384 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1385 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1386
1387 const StreamParamsVec& audio_streams = acd->streams();
1388 ASSERT_EQ(2U, audio_streams.size());
1389 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1390 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1391 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1392 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1393 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1394 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1395 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1396
1397 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1398 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1399
1400 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1401 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1402
1403 const StreamParamsVec& video_streams = vcd->streams();
1404 ASSERT_EQ(1U, video_streams.size());
1405 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1406 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1407 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1408 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1409
1410 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1411 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1412
1413 const StreamParamsVec& data_streams = dcd->streams();
1414 ASSERT_EQ(2U, data_streams.size());
1415 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1416 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1417 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1418 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1419 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1420 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1421 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1422
1423 EXPECT_EQ(cricket::kDataMaxBandwidth,
1424 dcd->bandwidth()); // default bandwidth (auto)
1425 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1426
1427 // Update the answer. Add a new video track that is not synched to the
1428 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001429 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1430 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1431 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001432 std::unique_ptr<SessionDescription> updated_answer(
1433 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001434
1435 ASSERT_TRUE(updated_answer.get() != NULL);
1436 ac = updated_answer->GetContentByName("audio");
1437 vc = updated_answer->GetContentByName("video");
1438 dc = updated_answer->GetContentByName("data");
1439 ASSERT_TRUE(ac != NULL);
1440 ASSERT_TRUE(vc != NULL);
1441 ASSERT_TRUE(dc != NULL);
1442 const AudioContentDescription* updated_acd =
1443 static_cast<const AudioContentDescription*>(ac->description);
1444 const VideoContentDescription* updated_vcd =
1445 static_cast<const VideoContentDescription*>(vc->description);
1446 const DataContentDescription* updated_dcd =
1447 static_cast<const DataContentDescription*>(dc->description);
1448
1449 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1450 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1451 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1452 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1453 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1454 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1455
1456 EXPECT_EQ(acd->type(), updated_acd->type());
1457 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1458 EXPECT_EQ(vcd->type(), updated_vcd->type());
1459 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1460 EXPECT_EQ(dcd->type(), updated_dcd->type());
1461 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1462
1463 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1464 ASSERT_EQ(1U, updated_audio_streams.size());
1465 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1466
1467 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1468 ASSERT_EQ(2U, updated_video_streams.size());
1469 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1470 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1471 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1472
1473 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1474 ASSERT_EQ(1U, updated_data_streams.size());
1475 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1476}
1477
1478
1479// Create an updated offer after creating an answer to the original offer and
1480// verify that the codecs that were part of the original answer are not changed
1481// in the updated offer.
1482TEST_F(MediaSessionDescriptionFactoryTest,
1483 RespondentCreatesOfferAfterCreatingAnswer) {
1484 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001485 opts.recv_audio = true;
1486 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001487
kwiberg31022942016-03-11 14:18:21 -08001488 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1489 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001490 f2_.CreateAnswer(offer.get(), opts, NULL));
1491
1492 const AudioContentDescription* acd =
1493 GetFirstAudioContentDescription(answer.get());
1494 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1495
1496 const VideoContentDescription* vcd =
1497 GetFirstVideoContentDescription(answer.get());
1498 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1499
kwiberg31022942016-03-11 14:18:21 -08001500 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001501 f2_.CreateOffer(opts, answer.get()));
1502
1503 // The expected audio codecs are the common audio codecs from the first
1504 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1505 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001506 // TODO(wu): |updated_offer| should not include the codec
1507 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 kAudioCodecsAnswer[0],
1510 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001511 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001512 };
1513
1514 // The expected video codecs are the common video codecs from the first
1515 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1516 // preference order.
1517 const VideoCodec kUpdatedVideoCodecOffer[] = {
1518 kVideoCodecsAnswer[0],
1519 kVideoCodecs2[1],
1520 };
1521
1522 const AudioContentDescription* updated_acd =
1523 GetFirstAudioContentDescription(updated_offer.get());
1524 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1525
1526 const VideoContentDescription* updated_vcd =
1527 GetFirstVideoContentDescription(updated_offer.get());
1528 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1529}
1530
1531// Create an updated offer after creating an answer to the original offer and
1532// verify that the codecs that were part of the original answer are not changed
1533// in the updated offer. In this test Rtx is enabled.
1534TEST_F(MediaSessionDescriptionFactoryTest,
1535 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1536 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001537 opts.recv_video = true;
1538 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001541 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001542 f1_.set_video_codecs(f1_codecs);
1543
1544 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001546 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547 f2_.set_video_codecs(f2_codecs);
1548
kwiberg31022942016-03-11 14:18:21 -08001549 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001551 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552 f2_.CreateAnswer(offer.get(), opts, NULL));
1553
1554 const VideoContentDescription* vcd =
1555 GetFirstVideoContentDescription(answer.get());
1556
1557 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001558 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1559 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001560
1561 EXPECT_EQ(expected_codecs, vcd->codecs());
1562
deadbeef67cf2c12016-04-13 10:07:16 -07001563 // Now, make sure we get same result (except for the order) if |f2_| creates
1564 // an updated offer even though the default payload types between |f1_| and
1565 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001566 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001567 f2_.CreateOffer(opts, answer.get()));
1568 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001569 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001570 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1571
1572 const VideoContentDescription* updated_vcd =
1573 GetFirstVideoContentDescription(updated_answer.get());
1574
1575 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1576}
1577
1578// Create an updated offer that adds video after creating an audio only answer
1579// to the original offer. This test verifies that if a video codec and the RTX
1580// codec have the same default payload type as an audio codec that is already in
1581// use, the added codecs payload types are changed.
1582TEST_F(MediaSessionDescriptionFactoryTest,
1583 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1584 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001586 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001587 f1_.set_video_codecs(f1_codecs);
1588
1589 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001590 opts.recv_audio = true;
1591 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001592
kwiberg31022942016-03-11 14:18:21 -08001593 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1594 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001595 f2_.CreateAnswer(offer.get(), opts, NULL));
1596
1597 const AudioContentDescription* acd =
1598 GetFirstAudioContentDescription(answer.get());
1599 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1600
1601 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1602 // reference be the same as an audio codec that was negotiated in the
1603 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001604 opts.recv_audio = true;
1605 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606
1607 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1608 int used_pl_type = acd->codecs()[0].id;
1609 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001610 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611 f2_.set_video_codecs(f2_codecs);
1612
kwiberg31022942016-03-11 14:18:21 -08001613 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001614 f2_.CreateOffer(opts, answer.get()));
1615 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001616 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1618
1619 const AudioContentDescription* updated_acd =
1620 GetFirstAudioContentDescription(answer.get());
1621 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1622
1623 const VideoContentDescription* updated_vcd =
1624 GetFirstVideoContentDescription(updated_answer.get());
1625
1626 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001627 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1629 EXPECT_NE(used_pl_type, new_h264_pl_type);
1630 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001631 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1633 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1634}
1635
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001636// Create an updated offer with RTX after creating an answer to an offer
1637// without RTX, and with different default payload types.
1638// Verify that the added RTX codec references the correct payload type.
1639TEST_F(MediaSessionDescriptionFactoryTest,
1640 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1641 MediaSessionOptions opts;
1642 opts.recv_video = true;
1643 opts.recv_audio = true;
1644
1645 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1646 // This creates rtx for H264 with the payload type |f2_| uses.
1647 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1648 f2_.set_video_codecs(f2_codecs);
1649
kwiberg31022942016-03-11 14:18:21 -08001650 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001651 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001652 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001653 f2_.CreateAnswer(offer.get(), opts, nullptr));
1654
1655 const VideoContentDescription* vcd =
1656 GetFirstVideoContentDescription(answer.get());
1657
1658 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1659 EXPECT_EQ(expected_codecs, vcd->codecs());
1660
1661 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1662 // updated offer, even though the default payload types are different from
1663 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001664 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001665 f2_.CreateOffer(opts, answer.get()));
1666 ASSERT_TRUE(updated_offer);
1667
1668 const VideoContentDescription* updated_vcd =
1669 GetFirstVideoContentDescription(updated_offer.get());
1670
1671 // New offer should attempt to add H263, and RTX for H264.
1672 expected_codecs.push_back(kVideoCodecs2[1]);
1673 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1674 &expected_codecs);
1675 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1676}
1677
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678// Test that RTX is ignored when there is no associated payload type parameter.
1679TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1680 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001681 opts.recv_video = true;
1682 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001683 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001684 // This creates RTX without associated payload type parameter.
deadbeef67cf2c12016-04-13 10:07:16 -07001685 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001686 f1_.set_video_codecs(f1_codecs);
1687
1688 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001689 // This creates RTX for H264 with the payload type |f2_| uses.
1690 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001691 f2_.set_video_codecs(f2_codecs);
1692
kwiberg31022942016-03-11 14:18:21 -08001693 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001694 ASSERT_TRUE(offer.get() != NULL);
1695 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1696 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1697 // is possible to test that that RTX is dropped when
1698 // kCodecParamAssociatedPayloadType is missing in the offer.
1699 VideoContentDescription* desc =
1700 static_cast<cricket::VideoContentDescription*>(
1701 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1702 ASSERT_TRUE(desc != NULL);
1703 std::vector<VideoCodec> codecs = desc->codecs();
1704 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1705 iter != codecs.end(); ++iter) {
1706 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1707 iter->params.clear();
1708 }
1709 }
1710 desc->set_codecs(codecs);
1711
kwiberg31022942016-03-11 14:18:21 -08001712 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001713 f2_.CreateAnswer(offer.get(), opts, NULL));
1714
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001715 std::vector<std::string> codec_names =
1716 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1717 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1718 cricket::kRtxCodecName));
1719}
1720
1721// Test that RTX will be filtered out in the answer if its associated payload
1722// type doesn't match the local value.
1723TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1724 MediaSessionOptions opts;
1725 opts.recv_video = true;
1726 opts.recv_audio = false;
1727 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1728 // This creates RTX for H264 in sender.
1729 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1730 f1_.set_video_codecs(f1_codecs);
1731
1732 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1733 // This creates RTX for H263 in receiver.
1734 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1735 f2_.set_video_codecs(f2_codecs);
1736
kwiberg31022942016-03-11 14:18:21 -08001737 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001738 ASSERT_TRUE(offer.get() != NULL);
1739 // Associated payload type doesn't match, therefore, RTX codec is removed in
1740 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001741 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001742 f2_.CreateAnswer(offer.get(), opts, NULL));
1743
1744 std::vector<std::string> codec_names =
1745 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1746 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1747 cricket::kRtxCodecName));
1748}
1749
1750// Test that when multiple RTX codecs are offered, only the matched RTX codec
1751// is added in the answer, and the unsupported RTX codec is filtered out.
1752TEST_F(MediaSessionDescriptionFactoryTest,
1753 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1754 MediaSessionOptions opts;
1755 opts.recv_video = true;
1756 opts.recv_audio = false;
1757 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1758 // This creates RTX for H264-SVC in sender.
1759 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1760 f1_.set_video_codecs(f1_codecs);
1761
1762 // This creates RTX for H264 in sender.
1763 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1764 f1_.set_video_codecs(f1_codecs);
1765
1766 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1767 // This creates RTX for H264 in receiver.
1768 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1769 f2_.set_video_codecs(f2_codecs);
1770
1771 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1772 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001773 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001774 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001775 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001776 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001777 const VideoContentDescription* vcd =
1778 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001779 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1780 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1781 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001783 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001784}
1785
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001786// Test that after one RTX codec has been negotiated, a new offer can attempt
1787// to add another.
1788TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1789 MediaSessionOptions opts;
1790 opts.recv_video = true;
1791 opts.recv_audio = false;
1792 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1793 // This creates RTX for H264 for the offerer.
1794 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1795 f1_.set_video_codecs(f1_codecs);
1796
kwiberg31022942016-03-11 14:18:21 -08001797 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001798 ASSERT_TRUE(offer);
1799 const VideoContentDescription* vcd =
1800 GetFirstVideoContentDescription(offer.get());
1801
1802 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1803 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1804 &expected_codecs);
1805 EXPECT_EQ(expected_codecs, vcd->codecs());
1806
1807 // Now, attempt to add RTX for H264-SVC.
1808 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1809 f1_.set_video_codecs(f1_codecs);
1810
kwiberg31022942016-03-11 14:18:21 -08001811 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001812 f1_.CreateOffer(opts, offer.get()));
1813 ASSERT_TRUE(updated_offer);
1814 vcd = GetFirstVideoContentDescription(updated_offer.get());
1815
1816 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1817 &expected_codecs);
1818 EXPECT_EQ(expected_codecs, vcd->codecs());
1819}
1820
Noah Richards2e7a0982015-05-18 14:02:54 -07001821// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1822// generated for each simulcast ssrc and correctly grouped.
1823TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1824 MediaSessionOptions opts;
1825 opts.recv_video = true;
1826 opts.recv_audio = false;
1827
1828 // Add simulcast streams.
1829 opts.AddSendVideoStream("stream1", "stream1label", 3);
1830
1831 // Use a single real codec, and then add RTX for it.
1832 std::vector<VideoCodec> f1_codecs;
deadbeef67cf2c12016-04-13 10:07:16 -07001833 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30));
Noah Richards2e7a0982015-05-18 14:02:54 -07001834 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1835 f1_.set_video_codecs(f1_codecs);
1836
1837 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1838 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001839 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001840 ASSERT_TRUE(offer.get() != NULL);
1841 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1842 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1843 ASSERT_TRUE(desc != NULL);
1844 EXPECT_TRUE(desc->multistream());
1845 const StreamParamsVec& streams = desc->streams();
1846 // Single stream.
1847 ASSERT_EQ(1u, streams.size());
1848 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1849 EXPECT_EQ(6u, streams[0].ssrcs.size());
1850 // And should have a SIM group for the simulcast.
1851 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1852 // And a FID group for RTX.
1853 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02001854 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001855 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1856 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001857 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001858 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1859 EXPECT_EQ(3u, fid_ssrcs.size());
1860}
1861
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862// Create an updated offer after creating an answer to the original offer and
1863// verify that the RTP header extensions that were part of the original answer
1864// are not changed in the updated offer.
1865TEST_F(MediaSessionDescriptionFactoryTest,
1866 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1867 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001868 opts.recv_audio = true;
1869 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870
1871 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1872 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1873 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1874 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1875
kwiberg31022942016-03-11 14:18:21 -08001876 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1877 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001878 f2_.CreateAnswer(offer.get(), opts, NULL));
1879
1880 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1881 GetFirstAudioContentDescription(
1882 answer.get())->rtp_header_extensions());
1883 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1884 GetFirstVideoContentDescription(
1885 answer.get())->rtp_header_extensions());
1886
kwiberg31022942016-03-11 14:18:21 -08001887 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001888 f2_.CreateOffer(opts, answer.get()));
1889
1890 // The expected RTP header extensions in the new offer are the resulting
1891 // extensions from the first offer/answer exchange plus the extensions only
1892 // |f2_| offer.
1893 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001894 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001895 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1896 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001897 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1898 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001899 };
1900
1901 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001902 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001903 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1904 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001905 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1906 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001907 };
1908
1909 const AudioContentDescription* updated_acd =
1910 GetFirstAudioContentDescription(updated_offer.get());
1911 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1912 updated_acd->rtp_header_extensions());
1913
1914 const VideoContentDescription* updated_vcd =
1915 GetFirstVideoContentDescription(updated_offer.get());
1916 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1917 updated_vcd->rtp_header_extensions());
1918}
1919
deadbeefa5b273a2015-08-20 17:30:13 -07001920// Verify that if the same RTP extension URI is used for audio and video, the
1921// same ID is used. Also verify that the ID isn't changed when creating an
1922// updated offer (this was previously a bug).
1923TEST_F(MediaSessionDescriptionFactoryTest,
1924 RtpHeaderExtensionIdReused) {
1925 MediaSessionOptions opts;
1926 opts.recv_audio = true;
1927 opts.recv_video = true;
1928
1929 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1930 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1931
kwiberg31022942016-03-11 14:18:21 -08001932 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07001933
1934 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1935 // the video extensions.
1936 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1937 kVideoRtpExtension3[0],
1938 kAudioRtpExtension3[1],
1939 };
1940
1941 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1942 GetFirstAudioContentDescription(
1943 offer.get())->rtp_header_extensions());
1944 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1945 GetFirstVideoContentDescription(
1946 offer.get())->rtp_header_extensions());
1947
1948 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08001949 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07001950 f1_.CreateOffer(opts, offer.get()));
1951
1952 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1953 GetFirstAudioContentDescription(
1954 updated_offer.get())->rtp_header_extensions());
1955 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1956 GetFirstVideoContentDescription(
1957 updated_offer.get())->rtp_header_extensions());
1958}
1959
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001960TEST(MediaSessionDescription, CopySessionDescription) {
1961 SessionDescription source;
1962 cricket::ContentGroup group(cricket::CN_AUDIO);
1963 source.AddGroup(group);
1964 AudioContentDescription* acd(new AudioContentDescription());
1965 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1966 acd->AddLegacyStream(1);
1967 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1968 VideoContentDescription* vcd(new VideoContentDescription());
1969 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1970 vcd->AddLegacyStream(2);
1971 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1972
kwiberg31022942016-03-11 14:18:21 -08001973 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001974 ASSERT_TRUE(copy.get() != NULL);
1975 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1976 const ContentInfo* ac = copy->GetContentByName("audio");
1977 const ContentInfo* vc = copy->GetContentByName("video");
1978 ASSERT_TRUE(ac != NULL);
1979 ASSERT_TRUE(vc != NULL);
1980 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1981 const AudioContentDescription* acd_copy =
1982 static_cast<const AudioContentDescription*>(ac->description);
1983 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1984 EXPECT_EQ(1u, acd->first_ssrc());
1985
1986 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1987 const VideoContentDescription* vcd_copy =
1988 static_cast<const VideoContentDescription*>(vc->description);
1989 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1990 EXPECT_EQ(2u, vcd->first_ssrc());
1991}
1992
1993// The below TestTransportInfoXXX tests create different offers/answers, and
1994// ensure the TransportInfo in the SessionDescription matches what we expect.
1995TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1996 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001997 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001998 TestTransportInfo(true, options, false);
1999}
2000
2001TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2002 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002003 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004 TestTransportInfo(true, options, true);
2005}
2006
2007TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2008 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002009 options.recv_audio = true;
2010 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002011 options.data_channel_type = cricket::DCT_RTP;
2012 TestTransportInfo(true, options, false);
2013}
2014
2015TEST_F(MediaSessionDescriptionFactoryTest,
2016 TestTransportInfoOfferMultimediaCurrent) {
2017 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002018 options.recv_audio = true;
2019 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002020 options.data_channel_type = cricket::DCT_RTP;
2021 TestTransportInfo(true, options, true);
2022}
2023
2024TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2025 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002026 options.recv_audio = true;
2027 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002028 options.data_channel_type = cricket::DCT_RTP;
2029 options.bundle_enabled = true;
2030 TestTransportInfo(true, options, false);
2031}
2032
2033TEST_F(MediaSessionDescriptionFactoryTest,
2034 TestTransportInfoOfferBundleCurrent) {
2035 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002036 options.recv_audio = true;
2037 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038 options.data_channel_type = cricket::DCT_RTP;
2039 options.bundle_enabled = true;
2040 TestTransportInfo(true, options, true);
2041}
2042
2043TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2044 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002045 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002046 TestTransportInfo(false, options, false);
2047}
2048
2049TEST_F(MediaSessionDescriptionFactoryTest,
2050 TestTransportInfoAnswerAudioCurrent) {
2051 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002052 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002053 TestTransportInfo(false, options, true);
2054}
2055
2056TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2057 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002058 options.recv_audio = true;
2059 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002060 options.data_channel_type = cricket::DCT_RTP;
2061 TestTransportInfo(false, options, false);
2062}
2063
2064TEST_F(MediaSessionDescriptionFactoryTest,
2065 TestTransportInfoAnswerMultimediaCurrent) {
2066 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002067 options.recv_audio = true;
2068 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002069 options.data_channel_type = cricket::DCT_RTP;
2070 TestTransportInfo(false, options, true);
2071}
2072
2073TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2074 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002075 options.recv_audio = true;
2076 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002077 options.data_channel_type = cricket::DCT_RTP;
2078 options.bundle_enabled = true;
2079 TestTransportInfo(false, options, false);
2080}
2081
2082TEST_F(MediaSessionDescriptionFactoryTest,
2083 TestTransportInfoAnswerBundleCurrent) {
2084 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002085 options.recv_audio = true;
2086 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002087 options.data_channel_type = cricket::DCT_RTP;
2088 options.bundle_enabled = true;
2089 TestTransportInfo(false, options, true);
2090}
2091
2092// Create an offer with bundle enabled and verify the crypto parameters are
2093// the common set of the available cryptos.
2094TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2095 TestCryptoWithBundle(true);
2096}
2097
2098// Create an answer with bundle enabled and verify the crypto parameters are
2099// the common set of the available cryptos.
2100TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2101 TestCryptoWithBundle(false);
2102}
2103
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002104// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2105// DTLS is not enabled locally.
2106TEST_F(MediaSessionDescriptionFactoryTest,
2107 TestOfferDtlsSavpfWithoutDtlsFailed) {
2108 f1_.set_secure(SEC_ENABLED);
2109 f2_.set_secure(SEC_ENABLED);
2110 tdf1_.set_secure(SEC_DISABLED);
2111 tdf2_.set_secure(SEC_DISABLED);
2112
kwiberg31022942016-03-11 14:18:21 -08002113 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002114 f1_.CreateOffer(MediaSessionOptions(), NULL));
2115 ASSERT_TRUE(offer.get() != NULL);
2116 ContentInfo* offer_content = offer->GetContentByName("audio");
2117 ASSERT_TRUE(offer_content != NULL);
2118 AudioContentDescription* offer_audio_desc =
2119 static_cast<AudioContentDescription*>(offer_content->description);
2120 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2121
kwiberg31022942016-03-11 14:18:21 -08002122 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002123 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2124 ASSERT_TRUE(answer != NULL);
2125 ContentInfo* answer_content = answer->GetContentByName("audio");
2126 ASSERT_TRUE(answer_content != NULL);
2127
2128 ASSERT_TRUE(answer_content->rejected);
2129}
2130
2131// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2132// UDP/TLS/RTP/SAVPF.
2133TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2134 f1_.set_secure(SEC_ENABLED);
2135 f2_.set_secure(SEC_ENABLED);
2136 tdf1_.set_secure(SEC_ENABLED);
2137 tdf2_.set_secure(SEC_ENABLED);
2138
kwiberg31022942016-03-11 14:18:21 -08002139 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002140 f1_.CreateOffer(MediaSessionOptions(), NULL));
2141 ASSERT_TRUE(offer.get() != NULL);
2142 ContentInfo* offer_content = offer->GetContentByName("audio");
2143 ASSERT_TRUE(offer_content != NULL);
2144 AudioContentDescription* offer_audio_desc =
2145 static_cast<AudioContentDescription*>(offer_content->description);
2146 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2147
kwiberg31022942016-03-11 14:18:21 -08002148 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002149 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2150 ASSERT_TRUE(answer != NULL);
2151
2152 const ContentInfo* answer_content = answer->GetContentByName("audio");
2153 ASSERT_TRUE(answer_content != NULL);
2154 ASSERT_FALSE(answer_content->rejected);
2155
2156 const AudioContentDescription* answer_audio_desc =
2157 static_cast<const AudioContentDescription*>(answer_content->description);
2158 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2159 answer_audio_desc->protocol());
2160}
2161
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162// Test that we include both SDES and DTLS in the offer, but only include SDES
2163// in the answer if DTLS isn't negotiated.
2164TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2165 f1_.set_secure(SEC_ENABLED);
2166 f2_.set_secure(SEC_ENABLED);
2167 tdf1_.set_secure(SEC_ENABLED);
2168 tdf2_.set_secure(SEC_DISABLED);
2169 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002170 options.recv_audio = true;
2171 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002172 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002173 const cricket::MediaContentDescription* audio_media_desc;
2174 const cricket::MediaContentDescription* video_media_desc;
2175 const cricket::TransportDescription* audio_trans_desc;
2176 const cricket::TransportDescription* video_trans_desc;
2177
2178 // Generate an offer with SDES and DTLS support.
2179 offer.reset(f1_.CreateOffer(options, NULL));
2180 ASSERT_TRUE(offer.get() != NULL);
2181
2182 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2183 offer->GetContentDescriptionByName("audio"));
2184 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002185 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002186 offer->GetContentDescriptionByName("video"));
2187 ASSERT_TRUE(video_media_desc != NULL);
2188 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2189 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2190
2191 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2192 ASSERT_TRUE(audio_trans_desc != NULL);
2193 video_trans_desc = offer->GetTransportDescriptionByName("video");
2194 ASSERT_TRUE(video_trans_desc != NULL);
2195 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2196 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2197
2198 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2199 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2200 ASSERT_TRUE(answer.get() != NULL);
2201
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002202 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002203 answer->GetContentDescriptionByName("audio"));
2204 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002205 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002206 answer->GetContentDescriptionByName("video"));
2207 ASSERT_TRUE(video_media_desc != NULL);
2208 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2209 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2210
2211 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2212 ASSERT_TRUE(audio_trans_desc != NULL);
2213 video_trans_desc = answer->GetTransportDescriptionByName("video");
2214 ASSERT_TRUE(video_trans_desc != NULL);
2215 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2216 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2217
2218 // Enable DTLS; the answer should now only have DTLS support.
2219 tdf2_.set_secure(SEC_ENABLED);
2220 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2221 ASSERT_TRUE(answer.get() != NULL);
2222
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002223 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002224 answer->GetContentDescriptionByName("audio"));
2225 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002226 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002227 answer->GetContentDescriptionByName("video"));
2228 ASSERT_TRUE(video_media_desc != NULL);
2229 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2230 EXPECT_TRUE(video_media_desc->cryptos().empty());
2231 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2232 audio_media_desc->protocol());
2233 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2234 video_media_desc->protocol());
2235
2236 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2237 ASSERT_TRUE(audio_trans_desc != NULL);
2238 video_trans_desc = answer->GetTransportDescriptionByName("video");
2239 ASSERT_TRUE(video_trans_desc != NULL);
2240 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2241 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002242
2243 // Try creating offer again. DTLS enabled now, crypto's should be empty
2244 // in new offer.
2245 offer.reset(f1_.CreateOffer(options, offer.get()));
2246 ASSERT_TRUE(offer.get() != NULL);
2247 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2248 offer->GetContentDescriptionByName("audio"));
2249 ASSERT_TRUE(audio_media_desc != NULL);
2250 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2251 offer->GetContentDescriptionByName("video"));
2252 ASSERT_TRUE(video_media_desc != NULL);
2253 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2254 EXPECT_TRUE(video_media_desc->cryptos().empty());
2255
2256 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2257 ASSERT_TRUE(audio_trans_desc != NULL);
2258 video_trans_desc = offer->GetTransportDescriptionByName("video");
2259 ASSERT_TRUE(video_trans_desc != NULL);
2260 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2261 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002262}
2263
2264// Test that an answer can't be created if cryptos are required but the offer is
2265// unsecure.
2266TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2267 MediaSessionOptions options;
2268 f1_.set_secure(SEC_DISABLED);
2269 tdf1_.set_secure(SEC_DISABLED);
2270 f2_.set_secure(SEC_REQUIRED);
2271 tdf1_.set_secure(SEC_ENABLED);
2272
kwiberg31022942016-03-11 14:18:21 -08002273 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002274 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002275 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002276 f2_.CreateAnswer(offer.get(), options, NULL));
2277 EXPECT_TRUE(answer.get() == NULL);
2278}
2279
2280// Test that we accept a DTLS offer without SDES and create an appropriate
2281// answer.
2282TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2283 f1_.set_secure(SEC_DISABLED);
2284 f2_.set_secure(SEC_ENABLED);
2285 tdf1_.set_secure(SEC_ENABLED);
2286 tdf2_.set_secure(SEC_ENABLED);
2287 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002288 options.recv_audio = true;
2289 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002290 options.data_channel_type = cricket::DCT_RTP;
2291
kwiberg31022942016-03-11 14:18:21 -08002292 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002293
2294 // Generate an offer with DTLS but without SDES.
2295 offer.reset(f1_.CreateOffer(options, NULL));
2296 ASSERT_TRUE(offer.get() != NULL);
2297
2298 const AudioContentDescription* audio_offer =
2299 GetFirstAudioContentDescription(offer.get());
2300 ASSERT_TRUE(audio_offer->cryptos().empty());
2301 const VideoContentDescription* video_offer =
2302 GetFirstVideoContentDescription(offer.get());
2303 ASSERT_TRUE(video_offer->cryptos().empty());
2304 const DataContentDescription* data_offer =
2305 GetFirstDataContentDescription(offer.get());
2306 ASSERT_TRUE(data_offer->cryptos().empty());
2307
2308 const cricket::TransportDescription* audio_offer_trans_desc =
2309 offer->GetTransportDescriptionByName("audio");
2310 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2311 const cricket::TransportDescription* video_offer_trans_desc =
2312 offer->GetTransportDescriptionByName("video");
2313 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2314 const cricket::TransportDescription* data_offer_trans_desc =
2315 offer->GetTransportDescriptionByName("data");
2316 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2317
2318 // Generate an answer with DTLS.
2319 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2320 ASSERT_TRUE(answer.get() != NULL);
2321
2322 const cricket::TransportDescription* audio_answer_trans_desc =
2323 answer->GetTransportDescriptionByName("audio");
2324 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2325 const cricket::TransportDescription* video_answer_trans_desc =
2326 answer->GetTransportDescriptionByName("video");
2327 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2328 const cricket::TransportDescription* data_answer_trans_desc =
2329 answer->GetTransportDescriptionByName("data");
2330 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2331}
2332
2333// Verifies if vad_enabled option is set to false, CN codecs are not present in
2334// offer or answer.
2335TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2336 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002337 options.recv_audio = true;
2338 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002339 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002340 ASSERT_TRUE(offer.get() != NULL);
2341 const ContentInfo* audio_content = offer->GetContentByName("audio");
2342 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2343
2344 options.vad_enabled = false;
2345 offer.reset(f1_.CreateOffer(options, NULL));
2346 ASSERT_TRUE(offer.get() != NULL);
2347 audio_content = offer->GetContentByName("audio");
2348 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002349 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002350 f1_.CreateAnswer(offer.get(), options, NULL));
2351 ASSERT_TRUE(answer.get() != NULL);
2352 audio_content = answer->GetContentByName("audio");
2353 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2354}
deadbeef44f08192015-12-15 16:20:09 -08002355
2356// Test that the content name ("mid" in SDP) is unchanged when creating a
2357// new offer.
2358TEST_F(MediaSessionDescriptionFactoryTest,
2359 TestContentNameNotChangedInSubsequentOffers) {
2360 MediaSessionOptions opts;
2361 opts.recv_audio = true;
2362 opts.recv_video = true;
2363 opts.data_channel_type = cricket::DCT_SCTP;
2364 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002365 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002366 for (ContentInfo& content : offer->contents()) {
2367 content.name.append("_modified");
2368 }
2369
kwiberg31022942016-03-11 14:18:21 -08002370 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002371 f1_.CreateOffer(opts, offer.get()));
2372 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2373 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2374 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2375 ASSERT_TRUE(audio_content != nullptr);
2376 ASSERT_TRUE(video_content != nullptr);
2377 ASSERT_TRUE(data_content != nullptr);
2378 EXPECT_EQ("audio_modified", audio_content->name);
2379 EXPECT_EQ("video_modified", video_content->name);
2380 EXPECT_EQ("data_modified", data_content->name);
2381}