blob: 66204b59c71f274ac20025b3780a1c470c8b4ac3 [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
11#include <string>
12#include <vector>
13
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000014#include "webrtc/base/fakesslidentity.h"
15#include "webrtc/base/gunit.h"
16#include "webrtc/base/messagedigest.h"
17#include "webrtc/base/ssladapter.h"
kjellandera96e2d72016-02-04 23:52:28 -080018#include "webrtc/media/base/codec.h"
19#include "webrtc/media/base/testutils.h"
kjellanderf4752772016-03-02 05:42:30 -080020#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080021#include "webrtc/p2p/base/transportdescription.h"
22#include "webrtc/p2p/base/transportinfo.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010023#include "webrtc/pc/mediasession.h"
24#include "webrtc/pc/srtpfilter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000025
26#ifdef HAVE_SRTP
27#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000028 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000029 ASSERT_EQ(s, cd->cryptos().size()); \
30 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
31#else
32#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000033 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034 ASSERT_EQ(0U, cd->cryptos().size());
35#endif
36
37typedef std::vector<cricket::Candidate> Candidates;
38
39using cricket::MediaContentDescription;
40using cricket::MediaSessionDescriptionFactory;
41using cricket::MediaSessionOptions;
42using cricket::MediaType;
43using cricket::SessionDescription;
44using cricket::SsrcGroup;
45using cricket::StreamParams;
46using cricket::StreamParamsVec;
47using cricket::TransportDescription;
48using cricket::TransportDescriptionFactory;
49using cricket::TransportInfo;
50using cricket::ContentInfo;
51using cricket::CryptoParamsVec;
52using cricket::AudioContentDescription;
53using cricket::VideoContentDescription;
54using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080055using cricket::GetFirstAudioContent;
56using cricket::GetFirstVideoContent;
57using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058using cricket::GetFirstAudioContentDescription;
59using cricket::GetFirstVideoContentDescription;
60using cricket::GetFirstDataContentDescription;
61using cricket::kAutoBandwidth;
62using cricket::AudioCodec;
63using cricket::VideoCodec;
64using cricket::DataCodec;
65using cricket::NS_JINGLE_RTP;
66using cricket::MEDIA_TYPE_AUDIO;
67using cricket::MEDIA_TYPE_VIDEO;
68using cricket::MEDIA_TYPE_DATA;
69using cricket::RtpHeaderExtension;
70using cricket::SEC_DISABLED;
71using cricket::SEC_ENABLED;
72using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070073using rtc::CS_AES_CM_128_HMAC_SHA1_32;
74using rtc::CS_AES_CM_128_HMAC_SHA1_80;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075
76static const AudioCodec kAudioCodecs1[] = {
77 AudioCodec(103, "ISAC", 16000, -1, 1, 6),
78 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
79 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
80 AudioCodec(8, "PCMA", 8000, 64000, 1, 3),
81 AudioCodec(117, "red", 8000, 0, 1, 2),
82 AudioCodec(107, "CN", 48000, 0, 1, 1)
83};
84
85static const AudioCodec kAudioCodecs2[] = {
86 AudioCodec(126, "speex", 16000, 22000, 1, 3),
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +000087 AudioCodec(0, "PCMU", 8000, 64000, 1, 2),
88 AudioCodec(127, "iLBC", 8000, 13300, 1, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089};
90
91static const AudioCodec kAudioCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +000092 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
93 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094};
95
96static const VideoCodec kVideoCodecs1[] = {
97 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
98 VideoCodec(97, "H264", 320, 200, 30, 1)
99};
100
101static const VideoCodec kVideoCodecs2[] = {
102 VideoCodec(126, "H264", 320, 200, 30, 2),
103 VideoCodec(127, "H263", 320, 200, 30, 1)
104};
105
106static const VideoCodec kVideoCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000107 VideoCodec(97, "H264", 320, 200, 30, 1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108};
109
110static const DataCodec kDataCodecs1[] = {
111 DataCodec(98, "binary-data", 2),
112 DataCodec(99, "utf8-text", 1)
113};
114
115static const DataCodec kDataCodecs2[] = {
116 DataCodec(126, "binary-data", 2),
117 DataCodec(127, "utf8-text", 1)
118};
119
120static const DataCodec kDataCodecsAnswer[] = {
121 DataCodec(98, "binary-data", 2),
122 DataCodec(99, "utf8-text", 1)
123};
124
125static const RtpHeaderExtension kAudioRtpExtension1[] = {
126 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
127 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
128};
129
130static const RtpHeaderExtension kAudioRtpExtension2[] = {
131 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
132 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000133 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000134};
135
deadbeefa5b273a2015-08-20 17:30:13 -0700136static const RtpHeaderExtension kAudioRtpExtension3[] = {
137 RtpHeaderExtension("http://google.com/testing/audio_something", 2),
138 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 3),
139};
140
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000141static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
142 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
143};
144
145static const RtpHeaderExtension kVideoRtpExtension1[] = {
146 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000147 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148};
149
150static const RtpHeaderExtension kVideoRtpExtension2[] = {
151 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
152 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000153 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000154};
155
deadbeefa5b273a2015-08-20 17:30:13 -0700156static const RtpHeaderExtension kVideoRtpExtension3[] = {
157 RtpHeaderExtension("http://google.com/testing/video_something", 4),
158 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 5),
159};
160
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
162 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
163};
164
Peter Boström0c4e06b2015-10-07 12:23:21 +0200165static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
166static const uint32_t kSimSsrc[] = {10, 20, 30};
167static const uint32_t kFec1Ssrc[] = {10, 11};
168static const uint32_t kFec2Ssrc[] = {20, 21};
169static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000170
171static const char kMediaStream1[] = "stream_1";
172static const char kMediaStream2[] = "stream_2";
173static const char kVideoTrack1[] = "video_1";
174static const char kVideoTrack2[] = "video_2";
175static const char kAudioTrack1[] = "audio_1";
176static const char kAudioTrack2[] = "audio_2";
177static const char kAudioTrack3[] = "audio_3";
178static const char kDataTrack1[] = "data_1";
179static const char kDataTrack2[] = "data_2";
180static const char kDataTrack3[] = "data_3";
181
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000182static bool IsMediaContentOfType(const ContentInfo* content,
183 MediaType media_type) {
184 const MediaContentDescription* mdesc =
185 static_cast<const MediaContentDescription*>(content->description);
186 return mdesc && mdesc->type() == media_type;
187}
188
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000189static cricket::MediaContentDirection
190GetMediaDirection(const ContentInfo* content) {
191 cricket::MediaContentDescription* desc =
192 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
193 return desc->direction();
194}
195
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000196static void AddRtxCodec(const VideoCodec& rtx_codec,
197 std::vector<VideoCodec>* codecs) {
198 VideoCodec rtx;
199 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
200 codecs->push_back(rtx_codec);
201}
202
203template <class T>
204static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
205 std::vector<std::string> codec_names;
206 for (const auto& codec : codecs) {
207 codec_names.push_back(codec.name);
208 }
209 return codec_names;
210}
211
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212class MediaSessionDescriptionFactoryTest : public testing::Test {
213 public:
214 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200215 : f1_(&tdf1_),
216 f2_(&tdf2_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000217 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
218 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
219 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
220 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
221 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
222 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200223 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwiberg0eb15ed2015-12-17 03:04:15 -0800224 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200225 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwiberg0eb15ed2015-12-17 03:04:15 -0800226 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000227 }
228
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000229 // Create a video StreamParamsVec object with:
230 // - one video stream with 3 simulcast streams and FEC,
231 StreamParamsVec CreateComplexVideoStreamParamsVec() {
232 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
233 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
234 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
235 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
236
237 std::vector<SsrcGroup> ssrc_groups;
238 ssrc_groups.push_back(sim_group);
239 ssrc_groups.push_back(fec_group1);
240 ssrc_groups.push_back(fec_group2);
241 ssrc_groups.push_back(fec_group3);
242
243 StreamParams simulcast_params;
244 simulcast_params.id = kVideoTrack1;
245 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
246 simulcast_params.ssrc_groups = ssrc_groups;
247 simulcast_params.cname = "Video_SIM_FEC";
248 simulcast_params.sync_label = kMediaStream1;
249
250 StreamParamsVec video_streams;
251 video_streams.push_back(simulcast_params);
252
253 return video_streams;
254 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000255
256 bool CompareCryptoParams(const CryptoParamsVec& c1,
257 const CryptoParamsVec& c2) {
258 if (c1.size() != c2.size())
259 return false;
260 for (size_t i = 0; i < c1.size(); ++i)
261 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
262 c1[i].key_params != c2[i].key_params ||
263 c1[i].session_params != c2[i].session_params)
264 return false;
265 return true;
266 }
267
268 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
269 bool has_current_desc) {
270 const std::string current_audio_ufrag = "current_audio_ufrag";
271 const std::string current_audio_pwd = "current_audio_pwd";
272 const std::string current_video_ufrag = "current_video_ufrag";
273 const std::string current_video_pwd = "current_video_pwd";
274 const std::string current_data_ufrag = "current_data_ufrag";
275 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000276 rtc::scoped_ptr<SessionDescription> current_desc;
277 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000278 if (has_current_desc) {
279 current_desc.reset(new SessionDescription());
280 EXPECT_TRUE(current_desc->AddTransportInfo(
281 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700282 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000283 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 EXPECT_TRUE(current_desc->AddTransportInfo(
285 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700286 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000287 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000288 EXPECT_TRUE(current_desc->AddTransportInfo(
289 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700290 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000291 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 }
293 if (offer) {
294 desc.reset(f1_.CreateOffer(options, current_desc.get()));
295 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000296 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297 offer.reset(f1_.CreateOffer(options, NULL));
298 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
299 }
300 ASSERT_TRUE(desc.get() != NULL);
301 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000302 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000303 EXPECT_TRUE(ti_audio != NULL);
304 if (has_current_desc) {
305 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
306 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
307 } else {
308 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
309 ti_audio->description.ice_ufrag.size());
310 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
311 ti_audio->description.ice_pwd.size());
312 }
313
314 } else {
315 EXPECT_TRUE(ti_audio == NULL);
316 }
317 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000318 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000319 EXPECT_TRUE(ti_video != NULL);
320 if (options.bundle_enabled) {
321 EXPECT_EQ(ti_audio->description.ice_ufrag,
322 ti_video->description.ice_ufrag);
323 EXPECT_EQ(ti_audio->description.ice_pwd,
324 ti_video->description.ice_pwd);
325 } else {
326 if (has_current_desc) {
327 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
328 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
329 } else {
330 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
331 ti_video->description.ice_ufrag.size());
332 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
333 ti_video->description.ice_pwd.size());
334 }
335 }
336 } else {
337 EXPECT_TRUE(ti_video == NULL);
338 }
339 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
340 if (options.has_data()) {
341 EXPECT_TRUE(ti_data != NULL);
342 if (options.bundle_enabled) {
343 EXPECT_EQ(ti_audio->description.ice_ufrag,
344 ti_data->description.ice_ufrag);
345 EXPECT_EQ(ti_audio->description.ice_pwd,
346 ti_data->description.ice_pwd);
347 } else {
348 if (has_current_desc) {
349 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
350 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
351 } else {
352 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
353 ti_data->description.ice_ufrag.size());
354 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
355 ti_data->description.ice_pwd.size());
356 }
357 }
358 } else {
359 EXPECT_TRUE(ti_video == NULL);
360 }
361 }
362
363 void TestCryptoWithBundle(bool offer) {
364 f1_.set_secure(SEC_ENABLED);
365 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000366 options.recv_audio = true;
367 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000369 rtc::scoped_ptr<SessionDescription> ref_desc;
370 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000371 if (offer) {
372 options.bundle_enabled = false;
373 ref_desc.reset(f1_.CreateOffer(options, NULL));
374 options.bundle_enabled = true;
375 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
376 } else {
377 options.bundle_enabled = true;
378 ref_desc.reset(f1_.CreateOffer(options, NULL));
379 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
380 }
381 ASSERT_TRUE(desc.get() != NULL);
382 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000383 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 desc.get()->GetContentDescriptionByName("audio"));
385 ASSERT_TRUE(audio_media_desc != NULL);
386 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000387 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000388 desc.get()->GetContentDescriptionByName("video"));
389 ASSERT_TRUE(video_media_desc != NULL);
390 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
391 video_media_desc->cryptos()));
392 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
393 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
394 audio_media_desc->cryptos()[0].cipher_suite);
395
396 // Verify the selected crypto is one from the reference audio
397 // media content.
398 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000399 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000400 ref_desc.get()->GetContentDescriptionByName("audio"));
401 bool found = false;
402 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
403 if (ref_audio_media_desc->cryptos()[i].Matches(
404 audio_media_desc->cryptos()[0])) {
405 found = true;
406 break;
407 }
408 }
409 EXPECT_TRUE(found);
410 }
411
412 // This test that the audio and video media direction is set to
413 // |expected_direction_in_answer| in an answer if the offer direction is set
414 // to |direction_in_offer|.
415 void TestMediaDirectionInAnswer(
416 cricket::MediaContentDirection direction_in_offer,
417 cricket::MediaContentDirection expected_direction_in_answer) {
418 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000419 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000420 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000421 f1_.CreateOffer(opts, NULL));
422 ASSERT_TRUE(offer.get() != NULL);
423 ContentInfo* ac_offer= offer->GetContentByName("audio");
424 ASSERT_TRUE(ac_offer != NULL);
425 AudioContentDescription* acd_offer =
426 static_cast<AudioContentDescription*>(ac_offer->description);
427 acd_offer->set_direction(direction_in_offer);
428 ContentInfo* vc_offer= offer->GetContentByName("video");
429 ASSERT_TRUE(vc_offer != NULL);
430 VideoContentDescription* vcd_offer =
431 static_cast<VideoContentDescription*>(vc_offer->description);
432 vcd_offer->set_direction(direction_in_offer);
433
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000434 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 f2_.CreateAnswer(offer.get(), opts, NULL));
436 const AudioContentDescription* acd_answer =
437 GetFirstAudioContentDescription(answer.get());
438 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
439 const VideoContentDescription* vcd_answer =
440 GetFirstVideoContentDescription(answer.get());
441 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
442 }
443
444 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
445 const cricket::ContentDescription* description = content->description;
446 ASSERT(description != NULL);
447 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000448 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000449 ASSERT(audio_content_desc != NULL);
450 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
451 if (audio_content_desc->codecs()[i].name == "CN")
452 return false;
453 }
454 return true;
455 }
456
457 protected:
458 MediaSessionDescriptionFactory f1_;
459 MediaSessionDescriptionFactory f2_;
460 TransportDescriptionFactory tdf1_;
461 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000462};
463
464// Create a typical audio offer, and ensure it matches what we expect.
465TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
466 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000467 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468 f1_.CreateOffer(MediaSessionOptions(), NULL));
469 ASSERT_TRUE(offer.get() != NULL);
470 const ContentInfo* ac = offer->GetContentByName("audio");
471 const ContentInfo* vc = offer->GetContentByName("video");
472 ASSERT_TRUE(ac != NULL);
473 ASSERT_TRUE(vc == NULL);
474 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
475 const AudioContentDescription* acd =
476 static_cast<const AudioContentDescription*>(ac->description);
477 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
478 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
479 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
480 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
481 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
482 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
483 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
484}
485
486// Create a typical video offer, and ensure it matches what we expect.
487TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
488 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000489 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000490 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000491 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000492 offer(f1_.CreateOffer(opts, NULL));
493 ASSERT_TRUE(offer.get() != NULL);
494 const ContentInfo* ac = offer->GetContentByName("audio");
495 const ContentInfo* vc = offer->GetContentByName("video");
496 ASSERT_TRUE(ac != NULL);
497 ASSERT_TRUE(vc != NULL);
498 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
499 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
500 const AudioContentDescription* acd =
501 static_cast<const AudioContentDescription*>(ac->description);
502 const VideoContentDescription* vcd =
503 static_cast<const VideoContentDescription*>(vc->description);
504 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
505 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
506 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
507 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
508 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
509 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
510 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
511 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
512 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
513 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
514 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
515 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
516 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
517 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
518}
519
520// Test creating an offer with bundle where the Codecs have the same dynamic
521// RTP playlod type. The test verifies that the offer don't contain the
522// duplicate RTP payload types.
523TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
524 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
525 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
526 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
527 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
528 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
529
530 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000531 opts.recv_audio = true;
532 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000533 opts.data_channel_type = cricket::DCT_RTP;
534 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000535 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 offer(f2_.CreateOffer(opts, NULL));
537 const VideoContentDescription* vcd =
538 GetFirstVideoContentDescription(offer.get());
539 const AudioContentDescription* acd =
540 GetFirstAudioContentDescription(offer.get());
541 const DataContentDescription* dcd =
542 GetFirstDataContentDescription(offer.get());
543 ASSERT_TRUE(NULL != vcd);
544 ASSERT_TRUE(NULL != acd);
545 ASSERT_TRUE(NULL != dcd);
546 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
547 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
548 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
549 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
550 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
551 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
552}
553
554// Test creating an updated offer with with bundle, audio, video and data
555// after an audio only session has been negotiated.
556TEST_F(MediaSessionDescriptionFactoryTest,
557 TestCreateUpdatedVideoOfferWithBundle) {
558 f1_.set_secure(SEC_ENABLED);
559 f2_.set_secure(SEC_ENABLED);
560 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000561 opts.recv_audio = true;
562 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000563 opts.data_channel_type = cricket::DCT_NONE;
564 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000565 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
566 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000567 f2_.CreateAnswer(offer.get(), opts, NULL));
568
569 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000570 updated_opts.recv_audio = true;
571 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000572 updated_opts.data_channel_type = cricket::DCT_RTP;
573 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000574 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000575 updated_opts, answer.get()));
576
577 const AudioContentDescription* acd =
578 GetFirstAudioContentDescription(updated_offer.get());
579 const VideoContentDescription* vcd =
580 GetFirstVideoContentDescription(updated_offer.get());
581 const DataContentDescription* dcd =
582 GetFirstDataContentDescription(updated_offer.get());
583 EXPECT_TRUE(NULL != vcd);
584 EXPECT_TRUE(NULL != acd);
585 EXPECT_TRUE(NULL != dcd);
586
587 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
588 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
589 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
590 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
591 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
592 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
593}
deadbeef44f08192015-12-15 16:20:09 -0800594
wu@webrtc.org78187522013-10-07 23:32:02 +0000595// Create a RTP data offer, and ensure it matches what we expect.
596TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000597 MediaSessionOptions opts;
598 opts.data_channel_type = cricket::DCT_RTP;
599 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000600 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 offer(f1_.CreateOffer(opts, NULL));
602 ASSERT_TRUE(offer.get() != NULL);
603 const ContentInfo* ac = offer->GetContentByName("audio");
604 const ContentInfo* dc = offer->GetContentByName("data");
605 ASSERT_TRUE(ac != NULL);
606 ASSERT_TRUE(dc != NULL);
607 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
608 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
609 const AudioContentDescription* acd =
610 static_cast<const AudioContentDescription*>(ac->description);
611 const DataContentDescription* dcd =
612 static_cast<const DataContentDescription*>(dc->description);
613 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
614 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
615 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
616 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
617 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
618 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
619 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
620 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
621 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
622 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
623 EXPECT_EQ(cricket::kDataMaxBandwidth,
624 dcd->bandwidth()); // default bandwidth (auto)
625 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
626 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
627 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
628}
629
wu@webrtc.org78187522013-10-07 23:32:02 +0000630// Create an SCTP data offer with bundle without error.
631TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
632 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000633 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000634 opts.bundle_enabled = true;
635 opts.data_channel_type = cricket::DCT_SCTP;
636 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000637 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000638 EXPECT_TRUE(offer.get() != NULL);
639 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
640}
641
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000642// Test creating an sctp data channel from an already generated offer.
643TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
644 MediaSessionOptions opts;
645 opts.recv_audio = false;
646 opts.bundle_enabled = true;
647 opts.data_channel_type = cricket::DCT_SCTP;
648 f1_.set_secure(SEC_ENABLED);
649 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
650 ASSERT_TRUE(offer1.get() != NULL);
651 const ContentInfo* data = offer1->GetContentByName("data");
652 ASSERT_TRUE(data != NULL);
653 const MediaContentDescription* mdesc =
654 static_cast<const MediaContentDescription*>(data->description);
655 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
656
657 // Now set data_channel_type to 'none' (default) and make sure that the
658 // datachannel type that gets generated from the previous offer, is of the
659 // same type.
660 opts.data_channel_type = cricket::DCT_NONE;
661 rtc::scoped_ptr<SessionDescription> offer2(
662 f1_.CreateOffer(opts, offer1.get()));
663 data = offer2->GetContentByName("data");
664 ASSERT_TRUE(data != NULL);
665 mdesc = static_cast<const MediaContentDescription*>(data->description);
666 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
667}
668
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669// Create an audio, video offer without legacy StreamParams.
670TEST_F(MediaSessionDescriptionFactoryTest,
671 TestCreateOfferWithoutLegacyStreams) {
672 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000673 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000675 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000676 offer(f1_.CreateOffer(opts, NULL));
677 ASSERT_TRUE(offer.get() != NULL);
678 const ContentInfo* ac = offer->GetContentByName("audio");
679 const ContentInfo* vc = offer->GetContentByName("video");
680 ASSERT_TRUE(ac != NULL);
681 ASSERT_TRUE(vc != NULL);
682 const AudioContentDescription* acd =
683 static_cast<const AudioContentDescription*>(ac->description);
684 const VideoContentDescription* vcd =
685 static_cast<const VideoContentDescription*>(vc->description);
686
687 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
688 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
689}
690
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000691// Creates an audio+video sendonly offer.
692TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
693 MediaSessionOptions options;
694 options.recv_audio = false;
695 options.recv_video = false;
696 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
697 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
698
699 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
700 ASSERT_TRUE(offer.get() != NULL);
701 EXPECT_EQ(2u, offer->contents().size());
702 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
703 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
704
705 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
706 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
707}
708
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000709// Verifies that the order of the media contents in the current
710// SessionDescription is preserved in the new SessionDescription.
711TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
712 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000713 opts.recv_audio = false;
714 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000715 opts.data_channel_type = cricket::DCT_SCTP;
716
717 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
718 ASSERT_TRUE(offer1.get() != NULL);
719 EXPECT_EQ(1u, offer1->contents().size());
720 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
721
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000722 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000723 rtc::scoped_ptr<SessionDescription> offer2(
724 f1_.CreateOffer(opts, offer1.get()));
725 ASSERT_TRUE(offer2.get() != NULL);
726 EXPECT_EQ(2u, offer2->contents().size());
727 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
728 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
729
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000730 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000731 rtc::scoped_ptr<SessionDescription> offer3(
732 f1_.CreateOffer(opts, offer2.get()));
733 ASSERT_TRUE(offer3.get() != NULL);
734 EXPECT_EQ(3u, offer3->contents().size());
735 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
736 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
737 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
738
739 // Verifies the default order is audio-video-data, so that the previous checks
740 // didn't pass by accident.
741 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
742 ASSERT_TRUE(offer4.get() != NULL);
743 EXPECT_EQ(3u, offer4->contents().size());
744 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
745 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
746 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
747}
748
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000749// Create a typical audio answer, and ensure it matches what we expect.
750TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
751 f1_.set_secure(SEC_ENABLED);
752 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000753 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000754 f1_.CreateOffer(MediaSessionOptions(), NULL));
755 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000756 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000757 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
758 const ContentInfo* ac = answer->GetContentByName("audio");
759 const ContentInfo* vc = answer->GetContentByName("video");
760 ASSERT_TRUE(ac != NULL);
761 ASSERT_TRUE(vc == NULL);
762 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
763 const AudioContentDescription* acd =
764 static_cast<const AudioContentDescription*>(ac->description);
765 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
766 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
767 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
768 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
769 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
770 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
771 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
772}
773
774// Create a typical video answer, and ensure it matches what we expect.
775TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
776 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000777 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000778 f1_.set_secure(SEC_ENABLED);
779 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000780 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000781 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000782 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783 f2_.CreateAnswer(offer.get(), opts, NULL));
784 const ContentInfo* ac = answer->GetContentByName("audio");
785 const ContentInfo* vc = answer->GetContentByName("video");
786 ASSERT_TRUE(ac != NULL);
787 ASSERT_TRUE(vc != NULL);
788 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
789 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
790 const AudioContentDescription* acd =
791 static_cast<const AudioContentDescription*>(ac->description);
792 const VideoContentDescription* vcd =
793 static_cast<const VideoContentDescription*>(vc->description);
794 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
795 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
796 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
797 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
798 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
799 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
800 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
801 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
802 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
803 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
804 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
805 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
806}
807
808TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
809 MediaSessionOptions opts;
810 opts.data_channel_type = cricket::DCT_RTP;
811 f1_.set_secure(SEC_ENABLED);
812 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000813 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000814 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000815 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000816 f2_.CreateAnswer(offer.get(), opts, NULL));
817 const ContentInfo* ac = answer->GetContentByName("audio");
818 const ContentInfo* vc = answer->GetContentByName("data");
819 ASSERT_TRUE(ac != NULL);
820 ASSERT_TRUE(vc != NULL);
821 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
822 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
823 const AudioContentDescription* acd =
824 static_cast<const AudioContentDescription*>(ac->description);
825 const DataContentDescription* vcd =
826 static_cast<const DataContentDescription*>(vc->description);
827 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
828 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
829 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
830 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
831 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
832 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
833 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
834 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
835 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
836 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
837 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
838 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
839}
840
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000841// Verifies that the order of the media contents in the offer is preserved in
842// the answer.
843TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
844 MediaSessionOptions opts;
845
846 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000847 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000848 opts.data_channel_type = cricket::DCT_SCTP;
849 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
850 ASSERT_TRUE(offer1.get() != NULL);
851
852 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000853 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000854 rtc::scoped_ptr<SessionDescription> offer2(
855 f1_.CreateOffer(opts, offer1.get()));
856 ASSERT_TRUE(offer2.get() != NULL);
857
858 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000859 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000860 rtc::scoped_ptr<SessionDescription> offer3(
861 f1_.CreateOffer(opts, offer2.get()));
862 ASSERT_TRUE(offer3.get() != NULL);
863
864 rtc::scoped_ptr<SessionDescription> answer(
865 f2_.CreateAnswer(offer3.get(), opts, NULL));
866 ASSERT_TRUE(answer.get() != NULL);
867 EXPECT_EQ(3u, answer->contents().size());
868 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
869 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
870 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
871}
872
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000873// This test that the media direction is set to send/receive in an answer if
874// the offer is send receive.
875TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
876 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
877}
878
879// This test that the media direction is set to receive only in an answer if
880// the offer is send only.
881TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
882 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
883}
884
885// This test that the media direction is set to send only in an answer if
886// the offer is recv only.
887TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
888 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
889}
890
891// This test that the media direction is set to inactive in an answer if
892// the offer is inactive.
893TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
894 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
895}
896
897// Test that a data content with an unknown protocol is rejected in an answer.
898TEST_F(MediaSessionDescriptionFactoryTest,
899 CreateDataAnswerToOfferWithUnknownProtocol) {
900 MediaSessionOptions opts;
901 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000902 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000903 f1_.set_secure(SEC_ENABLED);
904 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000905 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000906 ContentInfo* dc_offer= offer->GetContentByName("data");
907 ASSERT_TRUE(dc_offer != NULL);
908 DataContentDescription* dcd_offer =
909 static_cast<DataContentDescription*>(dc_offer->description);
910 ASSERT_TRUE(dcd_offer != NULL);
911 std::string protocol = "a weird unknown protocol";
912 dcd_offer->set_protocol(protocol);
913
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000914 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915 f2_.CreateAnswer(offer.get(), opts, NULL));
916
917 const ContentInfo* dc_answer = answer->GetContentByName("data");
918 ASSERT_TRUE(dc_answer != NULL);
919 EXPECT_TRUE(dc_answer->rejected);
920 const DataContentDescription* dcd_answer =
921 static_cast<const DataContentDescription*>(dc_answer->description);
922 ASSERT_TRUE(dcd_answer != NULL);
923 EXPECT_EQ(protocol, dcd_answer->protocol());
924}
925
926// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
927TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
928 MediaSessionOptions opts;
929 f1_.set_secure(SEC_DISABLED);
930 f2_.set_secure(SEC_DISABLED);
931 tdf1_.set_secure(SEC_DISABLED);
932 tdf2_.set_secure(SEC_DISABLED);
933
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000934 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000935 const AudioContentDescription* offer_acd =
936 GetFirstAudioContentDescription(offer.get());
937 ASSERT_TRUE(offer_acd != NULL);
938 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
939
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000940 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000941 f2_.CreateAnswer(offer.get(), opts, NULL));
942
943 const ContentInfo* ac_answer = answer->GetContentByName("audio");
944 ASSERT_TRUE(ac_answer != NULL);
945 EXPECT_FALSE(ac_answer->rejected);
946
947 const AudioContentDescription* answer_acd =
948 GetFirstAudioContentDescription(answer.get());
949 ASSERT_TRUE(answer_acd != NULL);
950 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
951}
952
953// Create a video offer and answer and ensure the RTP header extensions
954// matches what we expect.
955TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
956 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000957 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000958
959 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
960 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
961 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
962 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
963
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000964 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000965 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000966 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967 f2_.CreateAnswer(offer.get(), opts, NULL));
968
969 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
970 GetFirstAudioContentDescription(
971 offer.get())->rtp_header_extensions());
972 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
973 GetFirstVideoContentDescription(
974 offer.get())->rtp_header_extensions());
975 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
976 GetFirstAudioContentDescription(
977 answer.get())->rtp_header_extensions());
978 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
979 GetFirstVideoContentDescription(
980 answer.get())->rtp_header_extensions());
981}
982
983// Create an audio, video, data answer without legacy StreamParams.
984TEST_F(MediaSessionDescriptionFactoryTest,
985 TestCreateAnswerWithoutLegacyStreams) {
986 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000987 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000988 opts.data_channel_type = cricket::DCT_RTP;
989 f1_.set_add_legacy_streams(false);
990 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000991 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000992 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000993 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994 f2_.CreateAnswer(offer.get(), opts, NULL));
995 const ContentInfo* ac = answer->GetContentByName("audio");
996 const ContentInfo* vc = answer->GetContentByName("video");
997 const ContentInfo* dc = answer->GetContentByName("data");
998 ASSERT_TRUE(ac != NULL);
999 ASSERT_TRUE(vc != NULL);
1000 const AudioContentDescription* acd =
1001 static_cast<const AudioContentDescription*>(ac->description);
1002 const VideoContentDescription* vcd =
1003 static_cast<const VideoContentDescription*>(vc->description);
1004 const DataContentDescription* dcd =
1005 static_cast<const DataContentDescription*>(dc->description);
1006
1007 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1008 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1009 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1010}
1011
1012TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1013 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001014 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001015 opts.data_channel_type = cricket::DCT_RTP;
1016 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001017 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001018 offer(f1_.CreateOffer(opts, NULL));
1019 ASSERT_TRUE(offer.get() != NULL);
1020 const ContentInfo* ac = offer->GetContentByName("audio");
1021 const ContentInfo* vc = offer->GetContentByName("video");
1022 const ContentInfo* dc = offer->GetContentByName("data");
1023 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1024 static_cast<const AudioContentDescription*>(ac->description));
1025 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1026 static_cast<const VideoContentDescription*>(vc->description));
1027 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1028 static_cast<const DataContentDescription*>(dc->description));
1029
1030 EXPECT_FALSE(acd->partial()); // default is false.
1031 acd->set_partial(true);
1032 EXPECT_TRUE(acd->partial());
1033 acd->set_partial(false);
1034 EXPECT_FALSE(acd->partial());
1035
1036 EXPECT_FALSE(vcd->partial()); // default is false.
1037 vcd->set_partial(true);
1038 EXPECT_TRUE(vcd->partial());
1039 vcd->set_partial(false);
1040 EXPECT_FALSE(vcd->partial());
1041
1042 EXPECT_FALSE(dcd->partial()); // default is false.
1043 dcd->set_partial(true);
1044 EXPECT_TRUE(dcd->partial());
1045 dcd->set_partial(false);
1046 EXPECT_FALSE(dcd->partial());
1047}
1048
1049// Create a typical video answer, and ensure it matches what we expect.
1050TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1051 MediaSessionOptions offer_opts;
1052 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001053 answer_opts.recv_video = true;
1054 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001055 answer_opts.data_channel_type = cricket::DCT_RTP;
1056 offer_opts.data_channel_type = cricket::DCT_RTP;
1057
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001058 rtc::scoped_ptr<SessionDescription> offer;
1059 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060
1061 offer_opts.rtcp_mux_enabled = true;
1062 answer_opts.rtcp_mux_enabled = true;
1063
1064 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1065 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1066 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1067 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1068 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1069 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1070 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1071 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1072 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1073 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1074 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1075 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1076 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1077 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1078
1079 offer_opts.rtcp_mux_enabled = true;
1080 answer_opts.rtcp_mux_enabled = false;
1081
1082 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1083 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1084 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1085 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1086 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1087 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1088 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1089 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1090 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1091 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1092 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1093 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1094 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1095 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1096
1097 offer_opts.rtcp_mux_enabled = false;
1098 answer_opts.rtcp_mux_enabled = true;
1099
1100 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1101 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1102 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1103 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1104 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1105 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1106 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1107 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1108 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1109 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1110 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1111 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1112 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1113 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1114
1115 offer_opts.rtcp_mux_enabled = false;
1116 answer_opts.rtcp_mux_enabled = false;
1117
1118 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1119 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1120 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1121 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1122 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1123 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1124 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1125 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1126 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1127 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1128 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1129 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1130 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1131 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1132}
1133
1134// Create an audio-only answer to a video offer.
1135TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1136 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001137 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001138 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001139 offer(f1_.CreateOffer(opts, NULL));
1140 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001141 rtc::scoped_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* vc = answer->GetContentByName("video");
1145 ASSERT_TRUE(ac != NULL);
1146 ASSERT_TRUE(vc != NULL);
1147 ASSERT_TRUE(vc->description != NULL);
1148 EXPECT_TRUE(vc->rejected);
1149}
1150
1151// Create an audio-only answer to an offer with data.
1152TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1153 MediaSessionOptions opts;
1154 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001155 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 offer(f1_.CreateOffer(opts, NULL));
1157 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001158 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001159 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1160 const ContentInfo* ac = answer->GetContentByName("audio");
1161 const ContentInfo* dc = answer->GetContentByName("data");
1162 ASSERT_TRUE(ac != NULL);
1163 ASSERT_TRUE(dc != NULL);
1164 ASSERT_TRUE(dc->description != NULL);
1165 EXPECT_TRUE(dc->rejected);
1166}
1167
1168// Create an answer that rejects the contents which are rejected in the offer.
1169TEST_F(MediaSessionDescriptionFactoryTest,
1170 CreateAnswerToOfferWithRejectedMedia) {
1171 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001172 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001173 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001174 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 offer(f1_.CreateOffer(opts, NULL));
1176 ASSERT_TRUE(offer.get() != NULL);
1177 ContentInfo* ac = offer->GetContentByName("audio");
1178 ContentInfo* vc = offer->GetContentByName("video");
1179 ContentInfo* dc = offer->GetContentByName("data");
1180 ASSERT_TRUE(ac != NULL);
1181 ASSERT_TRUE(vc != NULL);
1182 ASSERT_TRUE(dc != NULL);
1183 ac->rejected = true;
1184 vc->rejected = true;
1185 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001186 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187 f2_.CreateAnswer(offer.get(), opts, NULL));
1188 ac = answer->GetContentByName("audio");
1189 vc = answer->GetContentByName("video");
1190 dc = answer->GetContentByName("data");
1191 ASSERT_TRUE(ac != NULL);
1192 ASSERT_TRUE(vc != NULL);
1193 ASSERT_TRUE(dc != NULL);
1194 EXPECT_TRUE(ac->rejected);
1195 EXPECT_TRUE(vc->rejected);
1196 EXPECT_TRUE(dc->rejected);
1197}
1198
1199// Create an audio and video offer with:
1200// - one video track
1201// - two audio tracks
1202// - two data tracks
1203// and ensure it matches what we expect. Also updates the initial offer by
1204// adding a new video track and replaces one of the audio tracks.
1205TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1206 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001207 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1208 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1209 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001210 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001211 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1212 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001213
1214 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001215 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001216
1217 ASSERT_TRUE(offer.get() != NULL);
1218 const ContentInfo* ac = offer->GetContentByName("audio");
1219 const ContentInfo* vc = offer->GetContentByName("video");
1220 const ContentInfo* dc = offer->GetContentByName("data");
1221 ASSERT_TRUE(ac != NULL);
1222 ASSERT_TRUE(vc != NULL);
1223 ASSERT_TRUE(dc != NULL);
1224 const AudioContentDescription* acd =
1225 static_cast<const AudioContentDescription*>(ac->description);
1226 const VideoContentDescription* vcd =
1227 static_cast<const VideoContentDescription*>(vc->description);
1228 const DataContentDescription* dcd =
1229 static_cast<const DataContentDescription*>(dc->description);
1230 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1231 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1232
1233 const StreamParamsVec& audio_streams = acd->streams();
1234 ASSERT_EQ(2U, audio_streams.size());
1235 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1236 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1237 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1238 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1239 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1240 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1241 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1242
1243 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1244 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1245 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1246
1247 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1248 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1249 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1250
1251 const StreamParamsVec& video_streams = vcd->streams();
1252 ASSERT_EQ(1U, video_streams.size());
1253 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1254 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1255 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1256 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1257
1258 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1259 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1260 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1261
1262 const StreamParamsVec& data_streams = dcd->streams();
1263 ASSERT_EQ(2U, data_streams.size());
1264 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1265 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1266 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1267 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1268 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1269 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1270 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1271
1272 EXPECT_EQ(cricket::kDataMaxBandwidth,
1273 dcd->bandwidth()); // default bandwidth (auto)
1274 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1275 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1276
1277
1278 // Update the offer. Add a new video track that is not synched to the
1279 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001280 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1281 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1282 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1283 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1284 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001285 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001286 updated_offer(f1_.CreateOffer(opts, offer.get()));
1287
1288 ASSERT_TRUE(updated_offer.get() != NULL);
1289 ac = updated_offer->GetContentByName("audio");
1290 vc = updated_offer->GetContentByName("video");
1291 dc = updated_offer->GetContentByName("data");
1292 ASSERT_TRUE(ac != NULL);
1293 ASSERT_TRUE(vc != NULL);
1294 ASSERT_TRUE(dc != NULL);
1295 const AudioContentDescription* updated_acd =
1296 static_cast<const AudioContentDescription*>(ac->description);
1297 const VideoContentDescription* updated_vcd =
1298 static_cast<const VideoContentDescription*>(vc->description);
1299 const DataContentDescription* updated_dcd =
1300 static_cast<const DataContentDescription*>(dc->description);
1301
1302 EXPECT_EQ(acd->type(), updated_acd->type());
1303 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1304 EXPECT_EQ(vcd->type(), updated_vcd->type());
1305 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1306 EXPECT_EQ(dcd->type(), updated_dcd->type());
1307 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1308 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1309 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1310 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1311 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1312 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1313 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1314
1315 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1316 ASSERT_EQ(2U, updated_audio_streams.size());
1317 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1318 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1319 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1320 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1321 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1322
1323 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1324 ASSERT_EQ(2U, updated_video_streams.size());
1325 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1326 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1327 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1328
1329 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1330 ASSERT_EQ(2U, updated_data_streams.size());
1331 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1332 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1333 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1334 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1335 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1336}
1337
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001338// Create an offer with simulcast video stream.
1339TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1340 MediaSessionOptions opts;
1341 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001342 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001343 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001344
1345 ASSERT_TRUE(offer.get() != NULL);
1346 const ContentInfo* vc = offer->GetContentByName("video");
1347 ASSERT_TRUE(vc != NULL);
1348 const VideoContentDescription* vcd =
1349 static_cast<const VideoContentDescription*>(vc->description);
1350
1351 const StreamParamsVec& video_streams = vcd->streams();
1352 ASSERT_EQ(1U, video_streams.size());
1353 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1354 const SsrcGroup* sim_ssrc_group =
1355 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1356 ASSERT_TRUE(sim_ssrc_group != NULL);
1357 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1358}
1359
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001360// Create an audio and video answer to a standard video offer with:
1361// - one video track
1362// - two audio tracks
1363// - two data tracks
1364// and ensure it matches what we expect. Also updates the initial answer by
1365// adding a new video track and removes one of the audio tracks.
1366TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1367 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001368 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001369 offer_opts.data_channel_type = cricket::DCT_RTP;
1370 f1_.set_secure(SEC_ENABLED);
1371 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001372 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001373 NULL));
1374
1375 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001376 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1377 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1378 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001379 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001380 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1381 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001382
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001383 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001384 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1385
1386 ASSERT_TRUE(answer.get() != NULL);
1387 const ContentInfo* ac = answer->GetContentByName("audio");
1388 const ContentInfo* vc = answer->GetContentByName("video");
1389 const ContentInfo* dc = answer->GetContentByName("data");
1390 ASSERT_TRUE(ac != NULL);
1391 ASSERT_TRUE(vc != NULL);
1392 ASSERT_TRUE(dc != NULL);
1393 const AudioContentDescription* acd =
1394 static_cast<const AudioContentDescription*>(ac->description);
1395 const VideoContentDescription* vcd =
1396 static_cast<const VideoContentDescription*>(vc->description);
1397 const DataContentDescription* dcd =
1398 static_cast<const DataContentDescription*>(dc->description);
1399 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1400 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1401 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1402
1403 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1404 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1405
1406 const StreamParamsVec& audio_streams = acd->streams();
1407 ASSERT_EQ(2U, audio_streams.size());
1408 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1409 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1410 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1411 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1412 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1413 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1414 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1415
1416 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1417 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1418
1419 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1420 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1421
1422 const StreamParamsVec& video_streams = vcd->streams();
1423 ASSERT_EQ(1U, video_streams.size());
1424 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1425 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1426 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1427 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1428
1429 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1430 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1431
1432 const StreamParamsVec& data_streams = dcd->streams();
1433 ASSERT_EQ(2U, data_streams.size());
1434 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1435 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1436 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1437 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1438 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1439 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1440 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1441
1442 EXPECT_EQ(cricket::kDataMaxBandwidth,
1443 dcd->bandwidth()); // default bandwidth (auto)
1444 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1445
1446 // Update the answer. Add a new video track that is not synched to the
1447 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001448 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1449 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1450 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001451 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001452 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1453
1454 ASSERT_TRUE(updated_answer.get() != NULL);
1455 ac = updated_answer->GetContentByName("audio");
1456 vc = updated_answer->GetContentByName("video");
1457 dc = updated_answer->GetContentByName("data");
1458 ASSERT_TRUE(ac != NULL);
1459 ASSERT_TRUE(vc != NULL);
1460 ASSERT_TRUE(dc != NULL);
1461 const AudioContentDescription* updated_acd =
1462 static_cast<const AudioContentDescription*>(ac->description);
1463 const VideoContentDescription* updated_vcd =
1464 static_cast<const VideoContentDescription*>(vc->description);
1465 const DataContentDescription* updated_dcd =
1466 static_cast<const DataContentDescription*>(dc->description);
1467
1468 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1469 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1470 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1471 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1472 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1473 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1474
1475 EXPECT_EQ(acd->type(), updated_acd->type());
1476 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1477 EXPECT_EQ(vcd->type(), updated_vcd->type());
1478 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1479 EXPECT_EQ(dcd->type(), updated_dcd->type());
1480 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1481
1482 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1483 ASSERT_EQ(1U, updated_audio_streams.size());
1484 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1485
1486 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1487 ASSERT_EQ(2U, updated_video_streams.size());
1488 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1489 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1490 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1491
1492 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1493 ASSERT_EQ(1U, updated_data_streams.size());
1494 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1495}
1496
1497
1498// Create an updated offer after creating an answer to the original offer and
1499// verify that the codecs that were part of the original answer are not changed
1500// in the updated offer.
1501TEST_F(MediaSessionDescriptionFactoryTest,
1502 RespondentCreatesOfferAfterCreatingAnswer) {
1503 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001504 opts.recv_audio = true;
1505 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001507 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1508 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001509 f2_.CreateAnswer(offer.get(), opts, NULL));
1510
1511 const AudioContentDescription* acd =
1512 GetFirstAudioContentDescription(answer.get());
1513 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1514
1515 const VideoContentDescription* vcd =
1516 GetFirstVideoContentDescription(answer.get());
1517 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1518
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001519 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 f2_.CreateOffer(opts, answer.get()));
1521
1522 // The expected audio codecs are the common audio codecs from the first
1523 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1524 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001525 // TODO(wu): |updated_offer| should not include the codec
1526 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001527 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 kAudioCodecsAnswer[0],
1529 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001530 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001531 };
1532
1533 // The expected video codecs are the common video codecs from the first
1534 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1535 // preference order.
1536 const VideoCodec kUpdatedVideoCodecOffer[] = {
1537 kVideoCodecsAnswer[0],
1538 kVideoCodecs2[1],
1539 };
1540
1541 const AudioContentDescription* updated_acd =
1542 GetFirstAudioContentDescription(updated_offer.get());
1543 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1544
1545 const VideoContentDescription* updated_vcd =
1546 GetFirstVideoContentDescription(updated_offer.get());
1547 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1548}
1549
1550// Create an updated offer after creating an answer to the original offer and
1551// verify that the codecs that were part of the original answer are not changed
1552// in the updated offer. In this test Rtx is enabled.
1553TEST_F(MediaSessionDescriptionFactoryTest,
1554 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1555 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001556 opts.recv_video = true;
1557 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001560 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561 f1_.set_video_codecs(f1_codecs);
1562
1563 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001565 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566 f2_.set_video_codecs(f2_codecs);
1567
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001568 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001570 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571 f2_.CreateAnswer(offer.get(), opts, NULL));
1572
1573 const VideoContentDescription* vcd =
1574 GetFirstVideoContentDescription(answer.get());
1575
1576 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001577 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1578 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579
1580 EXPECT_EQ(expected_codecs, vcd->codecs());
1581
1582 // Now, make sure we get same result, except for the preference order,
1583 // if |f2_| creates an updated offer even though the default payload types
1584 // are different from |f1_|.
1585 expected_codecs[0].preference = f1_codecs[1].preference;
1586
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001587 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588 f2_.CreateOffer(opts, answer.get()));
1589 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001590 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1592
1593 const VideoContentDescription* updated_vcd =
1594 GetFirstVideoContentDescription(updated_answer.get());
1595
1596 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1597}
1598
1599// Create an updated offer that adds video after creating an audio only answer
1600// to the original offer. This test verifies that if a video codec and the RTX
1601// codec have the same default payload type as an audio codec that is already in
1602// use, the added codecs payload types are changed.
1603TEST_F(MediaSessionDescriptionFactoryTest,
1604 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1605 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001607 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001608 f1_.set_video_codecs(f1_codecs);
1609
1610 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001611 opts.recv_audio = true;
1612 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001613
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001614 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1615 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001616 f2_.CreateAnswer(offer.get(), opts, NULL));
1617
1618 const AudioContentDescription* acd =
1619 GetFirstAudioContentDescription(answer.get());
1620 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1621
1622 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1623 // reference be the same as an audio codec that was negotiated in the
1624 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001625 opts.recv_audio = true;
1626 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627
1628 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1629 int used_pl_type = acd->codecs()[0].id;
1630 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001631 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632 f2_.set_video_codecs(f2_codecs);
1633
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001634 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 f2_.CreateOffer(opts, answer.get()));
1636 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001637 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1639
1640 const AudioContentDescription* updated_acd =
1641 GetFirstAudioContentDescription(answer.get());
1642 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1643
1644 const VideoContentDescription* updated_vcd =
1645 GetFirstVideoContentDescription(updated_answer.get());
1646
1647 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001648 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001649 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1650 EXPECT_NE(used_pl_type, new_h264_pl_type);
1651 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001652 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001653 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1654 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1655}
1656
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001657// Create an updated offer with RTX after creating an answer to an offer
1658// without RTX, and with different default payload types.
1659// Verify that the added RTX codec references the correct payload type.
1660TEST_F(MediaSessionDescriptionFactoryTest,
1661 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1662 MediaSessionOptions opts;
1663 opts.recv_video = true;
1664 opts.recv_audio = true;
1665
1666 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1667 // This creates rtx for H264 with the payload type |f2_| uses.
1668 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1669 f2_.set_video_codecs(f2_codecs);
1670
1671 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1672 ASSERT_TRUE(offer.get() != nullptr);
1673 rtc::scoped_ptr<SessionDescription> answer(
1674 f2_.CreateAnswer(offer.get(), opts, nullptr));
1675
1676 const VideoContentDescription* vcd =
1677 GetFirstVideoContentDescription(answer.get());
1678
1679 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1680 EXPECT_EQ(expected_codecs, vcd->codecs());
1681
1682 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1683 // updated offer, even though the default payload types are different from
1684 // those of |f1_|.
1685 rtc::scoped_ptr<SessionDescription> updated_offer(
1686 f2_.CreateOffer(opts, answer.get()));
1687 ASSERT_TRUE(updated_offer);
1688
1689 const VideoContentDescription* updated_vcd =
1690 GetFirstVideoContentDescription(updated_offer.get());
1691
1692 // New offer should attempt to add H263, and RTX for H264.
1693 expected_codecs.push_back(kVideoCodecs2[1]);
1694 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1695 &expected_codecs);
1696 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1697}
1698
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001699// Test that RTX is ignored when there is no associated payload type parameter.
1700TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1701 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001702 opts.recv_video = true;
1703 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001705 // This creates RTX without associated payload type parameter.
1706 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707 f1_.set_video_codecs(f1_codecs);
1708
1709 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001710 // This creates RTX for H264 with the payload type |f2_| uses.
1711 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 f2_.set_video_codecs(f2_codecs);
1713
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001714 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715 ASSERT_TRUE(offer.get() != NULL);
1716 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1717 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1718 // is possible to test that that RTX is dropped when
1719 // kCodecParamAssociatedPayloadType is missing in the offer.
1720 VideoContentDescription* desc =
1721 static_cast<cricket::VideoContentDescription*>(
1722 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1723 ASSERT_TRUE(desc != NULL);
1724 std::vector<VideoCodec> codecs = desc->codecs();
1725 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1726 iter != codecs.end(); ++iter) {
1727 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1728 iter->params.clear();
1729 }
1730 }
1731 desc->set_codecs(codecs);
1732
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001733 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001734 f2_.CreateAnswer(offer.get(), opts, NULL));
1735
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001736 std::vector<std::string> codec_names =
1737 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1738 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1739 cricket::kRtxCodecName));
1740}
1741
1742// Test that RTX will be filtered out in the answer if its associated payload
1743// type doesn't match the local value.
1744TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1745 MediaSessionOptions opts;
1746 opts.recv_video = true;
1747 opts.recv_audio = false;
1748 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1749 // This creates RTX for H264 in sender.
1750 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1751 f1_.set_video_codecs(f1_codecs);
1752
1753 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1754 // This creates RTX for H263 in receiver.
1755 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1756 f2_.set_video_codecs(f2_codecs);
1757
1758 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1759 ASSERT_TRUE(offer.get() != NULL);
1760 // Associated payload type doesn't match, therefore, RTX codec is removed in
1761 // the answer.
1762 rtc::scoped_ptr<SessionDescription> answer(
1763 f2_.CreateAnswer(offer.get(), opts, NULL));
1764
1765 std::vector<std::string> codec_names =
1766 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1767 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1768 cricket::kRtxCodecName));
1769}
1770
1771// Test that when multiple RTX codecs are offered, only the matched RTX codec
1772// is added in the answer, and the unsupported RTX codec is filtered out.
1773TEST_F(MediaSessionDescriptionFactoryTest,
1774 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1775 MediaSessionOptions opts;
1776 opts.recv_video = true;
1777 opts.recv_audio = false;
1778 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1779 // This creates RTX for H264-SVC in sender.
1780 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1781 f1_.set_video_codecs(f1_codecs);
1782
1783 // This creates RTX for H264 in sender.
1784 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1785 f1_.set_video_codecs(f1_codecs);
1786
1787 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1788 // This creates RTX for H264 in receiver.
1789 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1790 f2_.set_video_codecs(f2_codecs);
1791
1792 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1793 // for H264-SVC should also be removed.
1794 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1795 ASSERT_TRUE(offer.get() != NULL);
1796 rtc::scoped_ptr<SessionDescription> answer(
1797 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001798 const VideoContentDescription* vcd =
1799 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001800 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1801 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1802 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001804 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001805}
1806
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001807// Test that after one RTX codec has been negotiated, a new offer can attempt
1808// to add another.
1809TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1810 MediaSessionOptions opts;
1811 opts.recv_video = true;
1812 opts.recv_audio = false;
1813 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1814 // This creates RTX for H264 for the offerer.
1815 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1816 f1_.set_video_codecs(f1_codecs);
1817
1818 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
1819 ASSERT_TRUE(offer);
1820 const VideoContentDescription* vcd =
1821 GetFirstVideoContentDescription(offer.get());
1822
1823 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1824 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1825 &expected_codecs);
1826 EXPECT_EQ(expected_codecs, vcd->codecs());
1827
1828 // Now, attempt to add RTX for H264-SVC.
1829 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1830 f1_.set_video_codecs(f1_codecs);
1831
1832 rtc::scoped_ptr<SessionDescription> updated_offer(
1833 f1_.CreateOffer(opts, offer.get()));
1834 ASSERT_TRUE(updated_offer);
1835 vcd = GetFirstVideoContentDescription(updated_offer.get());
1836
1837 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1838 &expected_codecs);
1839 EXPECT_EQ(expected_codecs, vcd->codecs());
1840}
1841
Noah Richards2e7a0982015-05-18 14:02:54 -07001842// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1843// generated for each simulcast ssrc and correctly grouped.
1844TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1845 MediaSessionOptions opts;
1846 opts.recv_video = true;
1847 opts.recv_audio = false;
1848
1849 // Add simulcast streams.
1850 opts.AddSendVideoStream("stream1", "stream1label", 3);
1851
1852 // Use a single real codec, and then add RTX for it.
1853 std::vector<VideoCodec> f1_codecs;
1854 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30, 1));
1855 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1856 f1_.set_video_codecs(f1_codecs);
1857
1858 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1859 // is a FID ssrc + grouping for each.
1860 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1861 ASSERT_TRUE(offer.get() != NULL);
1862 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1863 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1864 ASSERT_TRUE(desc != NULL);
1865 EXPECT_TRUE(desc->multistream());
1866 const StreamParamsVec& streams = desc->streams();
1867 // Single stream.
1868 ASSERT_EQ(1u, streams.size());
1869 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1870 EXPECT_EQ(6u, streams[0].ssrcs.size());
1871 // And should have a SIM group for the simulcast.
1872 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1873 // And a FID group for RTX.
1874 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02001875 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001876 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1877 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001878 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001879 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1880 EXPECT_EQ(3u, fid_ssrcs.size());
1881}
1882
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001883// Create an updated offer after creating an answer to the original offer and
1884// verify that the RTP header extensions that were part of the original answer
1885// are not changed in the updated offer.
1886TEST_F(MediaSessionDescriptionFactoryTest,
1887 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1888 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001889 opts.recv_audio = true;
1890 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001891
1892 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1893 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1894 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1895 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1896
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001897 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1898 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001899 f2_.CreateAnswer(offer.get(), opts, NULL));
1900
1901 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1902 GetFirstAudioContentDescription(
1903 answer.get())->rtp_header_extensions());
1904 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1905 GetFirstVideoContentDescription(
1906 answer.get())->rtp_header_extensions());
1907
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001908 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001909 f2_.CreateOffer(opts, answer.get()));
1910
1911 // The expected RTP header extensions in the new offer are the resulting
1912 // extensions from the first offer/answer exchange plus the extensions only
1913 // |f2_| offer.
1914 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001915 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001916 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1917 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001918 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1919 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001920 };
1921
1922 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001923 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001924 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1925 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001926 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1927 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928 };
1929
1930 const AudioContentDescription* updated_acd =
1931 GetFirstAudioContentDescription(updated_offer.get());
1932 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1933 updated_acd->rtp_header_extensions());
1934
1935 const VideoContentDescription* updated_vcd =
1936 GetFirstVideoContentDescription(updated_offer.get());
1937 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1938 updated_vcd->rtp_header_extensions());
1939}
1940
deadbeefa5b273a2015-08-20 17:30:13 -07001941// Verify that if the same RTP extension URI is used for audio and video, the
1942// same ID is used. Also verify that the ID isn't changed when creating an
1943// updated offer (this was previously a bug).
1944TEST_F(MediaSessionDescriptionFactoryTest,
1945 RtpHeaderExtensionIdReused) {
1946 MediaSessionOptions opts;
1947 opts.recv_audio = true;
1948 opts.recv_video = true;
1949
1950 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1951 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1952
1953 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1954
1955 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1956 // the video extensions.
1957 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1958 kVideoRtpExtension3[0],
1959 kAudioRtpExtension3[1],
1960 };
1961
1962 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1963 GetFirstAudioContentDescription(
1964 offer.get())->rtp_header_extensions());
1965 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1966 GetFirstVideoContentDescription(
1967 offer.get())->rtp_header_extensions());
1968
1969 // Nothing should change when creating a new offer
1970 rtc::scoped_ptr<SessionDescription> updated_offer(
1971 f1_.CreateOffer(opts, offer.get()));
1972
1973 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1974 GetFirstAudioContentDescription(
1975 updated_offer.get())->rtp_header_extensions());
1976 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1977 GetFirstVideoContentDescription(
1978 updated_offer.get())->rtp_header_extensions());
1979}
1980
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001981TEST(MediaSessionDescription, CopySessionDescription) {
1982 SessionDescription source;
1983 cricket::ContentGroup group(cricket::CN_AUDIO);
1984 source.AddGroup(group);
1985 AudioContentDescription* acd(new AudioContentDescription());
1986 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1987 acd->AddLegacyStream(1);
1988 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1989 VideoContentDescription* vcd(new VideoContentDescription());
1990 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1991 vcd->AddLegacyStream(2);
1992 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1993
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001994 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001995 ASSERT_TRUE(copy.get() != NULL);
1996 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1997 const ContentInfo* ac = copy->GetContentByName("audio");
1998 const ContentInfo* vc = copy->GetContentByName("video");
1999 ASSERT_TRUE(ac != NULL);
2000 ASSERT_TRUE(vc != NULL);
2001 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
2002 const AudioContentDescription* acd_copy =
2003 static_cast<const AudioContentDescription*>(ac->description);
2004 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2005 EXPECT_EQ(1u, acd->first_ssrc());
2006
2007 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
2008 const VideoContentDescription* vcd_copy =
2009 static_cast<const VideoContentDescription*>(vc->description);
2010 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2011 EXPECT_EQ(2u, vcd->first_ssrc());
2012}
2013
2014// The below TestTransportInfoXXX tests create different offers/answers, and
2015// ensure the TransportInfo in the SessionDescription matches what we expect.
2016TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2017 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002018 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002019 TestTransportInfo(true, options, false);
2020}
2021
2022TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2023 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002024 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025 TestTransportInfo(true, options, true);
2026}
2027
2028TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2029 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002030 options.recv_audio = true;
2031 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 options.data_channel_type = cricket::DCT_RTP;
2033 TestTransportInfo(true, options, false);
2034}
2035
2036TEST_F(MediaSessionDescriptionFactoryTest,
2037 TestTransportInfoOfferMultimediaCurrent) {
2038 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002039 options.recv_audio = true;
2040 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002041 options.data_channel_type = cricket::DCT_RTP;
2042 TestTransportInfo(true, options, true);
2043}
2044
2045TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2046 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002047 options.recv_audio = true;
2048 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002049 options.data_channel_type = cricket::DCT_RTP;
2050 options.bundle_enabled = true;
2051 TestTransportInfo(true, options, false);
2052}
2053
2054TEST_F(MediaSessionDescriptionFactoryTest,
2055 TestTransportInfoOfferBundleCurrent) {
2056 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002057 options.recv_audio = true;
2058 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002059 options.data_channel_type = cricket::DCT_RTP;
2060 options.bundle_enabled = true;
2061 TestTransportInfo(true, options, true);
2062}
2063
2064TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2065 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002066 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002067 TestTransportInfo(false, options, false);
2068}
2069
2070TEST_F(MediaSessionDescriptionFactoryTest,
2071 TestTransportInfoAnswerAudioCurrent) {
2072 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002073 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074 TestTransportInfo(false, options, true);
2075}
2076
2077TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2078 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002079 options.recv_audio = true;
2080 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002081 options.data_channel_type = cricket::DCT_RTP;
2082 TestTransportInfo(false, options, false);
2083}
2084
2085TEST_F(MediaSessionDescriptionFactoryTest,
2086 TestTransportInfoAnswerMultimediaCurrent) {
2087 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002088 options.recv_audio = true;
2089 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002090 options.data_channel_type = cricket::DCT_RTP;
2091 TestTransportInfo(false, options, true);
2092}
2093
2094TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2095 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002096 options.recv_audio = true;
2097 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002098 options.data_channel_type = cricket::DCT_RTP;
2099 options.bundle_enabled = true;
2100 TestTransportInfo(false, options, false);
2101}
2102
2103TEST_F(MediaSessionDescriptionFactoryTest,
2104 TestTransportInfoAnswerBundleCurrent) {
2105 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002106 options.recv_audio = true;
2107 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002108 options.data_channel_type = cricket::DCT_RTP;
2109 options.bundle_enabled = true;
2110 TestTransportInfo(false, options, true);
2111}
2112
2113// Create an offer with bundle enabled and verify the crypto parameters are
2114// the common set of the available cryptos.
2115TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2116 TestCryptoWithBundle(true);
2117}
2118
2119// Create an answer with bundle enabled and verify the crypto parameters are
2120// the common set of the available cryptos.
2121TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2122 TestCryptoWithBundle(false);
2123}
2124
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002125// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2126// DTLS is not enabled locally.
2127TEST_F(MediaSessionDescriptionFactoryTest,
2128 TestOfferDtlsSavpfWithoutDtlsFailed) {
2129 f1_.set_secure(SEC_ENABLED);
2130 f2_.set_secure(SEC_ENABLED);
2131 tdf1_.set_secure(SEC_DISABLED);
2132 tdf2_.set_secure(SEC_DISABLED);
2133
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002134 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002135 f1_.CreateOffer(MediaSessionOptions(), NULL));
2136 ASSERT_TRUE(offer.get() != NULL);
2137 ContentInfo* offer_content = offer->GetContentByName("audio");
2138 ASSERT_TRUE(offer_content != NULL);
2139 AudioContentDescription* offer_audio_desc =
2140 static_cast<AudioContentDescription*>(offer_content->description);
2141 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2142
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002143 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002144 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2145 ASSERT_TRUE(answer != NULL);
2146 ContentInfo* answer_content = answer->GetContentByName("audio");
2147 ASSERT_TRUE(answer_content != NULL);
2148
2149 ASSERT_TRUE(answer_content->rejected);
2150}
2151
2152// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2153// UDP/TLS/RTP/SAVPF.
2154TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2155 f1_.set_secure(SEC_ENABLED);
2156 f2_.set_secure(SEC_ENABLED);
2157 tdf1_.set_secure(SEC_ENABLED);
2158 tdf2_.set_secure(SEC_ENABLED);
2159
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002160 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002161 f1_.CreateOffer(MediaSessionOptions(), NULL));
2162 ASSERT_TRUE(offer.get() != NULL);
2163 ContentInfo* offer_content = offer->GetContentByName("audio");
2164 ASSERT_TRUE(offer_content != NULL);
2165 AudioContentDescription* offer_audio_desc =
2166 static_cast<AudioContentDescription*>(offer_content->description);
2167 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2168
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002169 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002170 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2171 ASSERT_TRUE(answer != NULL);
2172
2173 const ContentInfo* answer_content = answer->GetContentByName("audio");
2174 ASSERT_TRUE(answer_content != NULL);
2175 ASSERT_FALSE(answer_content->rejected);
2176
2177 const AudioContentDescription* answer_audio_desc =
2178 static_cast<const AudioContentDescription*>(answer_content->description);
2179 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2180 answer_audio_desc->protocol());
2181}
2182
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002183// Test that we include both SDES and DTLS in the offer, but only include SDES
2184// in the answer if DTLS isn't negotiated.
2185TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2186 f1_.set_secure(SEC_ENABLED);
2187 f2_.set_secure(SEC_ENABLED);
2188 tdf1_.set_secure(SEC_ENABLED);
2189 tdf2_.set_secure(SEC_DISABLED);
2190 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002191 options.recv_audio = true;
2192 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002193 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002194 const cricket::MediaContentDescription* audio_media_desc;
2195 const cricket::MediaContentDescription* video_media_desc;
2196 const cricket::TransportDescription* audio_trans_desc;
2197 const cricket::TransportDescription* video_trans_desc;
2198
2199 // Generate an offer with SDES and DTLS support.
2200 offer.reset(f1_.CreateOffer(options, NULL));
2201 ASSERT_TRUE(offer.get() != NULL);
2202
2203 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2204 offer->GetContentDescriptionByName("audio"));
2205 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002206 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002207 offer->GetContentDescriptionByName("video"));
2208 ASSERT_TRUE(video_media_desc != NULL);
2209 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2210 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2211
2212 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2213 ASSERT_TRUE(audio_trans_desc != NULL);
2214 video_trans_desc = offer->GetTransportDescriptionByName("video");
2215 ASSERT_TRUE(video_trans_desc != NULL);
2216 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2217 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2218
2219 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
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_EQ(1u, audio_media_desc->cryptos().size());
2230 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2231
2232 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2233 ASSERT_TRUE(audio_trans_desc != NULL);
2234 video_trans_desc = answer->GetTransportDescriptionByName("video");
2235 ASSERT_TRUE(video_trans_desc != NULL);
2236 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2237 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2238
2239 // Enable DTLS; the answer should now only have DTLS support.
2240 tdf2_.set_secure(SEC_ENABLED);
2241 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2242 ASSERT_TRUE(answer.get() != NULL);
2243
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002244 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 answer->GetContentDescriptionByName("audio"));
2246 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002247 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002248 answer->GetContentDescriptionByName("video"));
2249 ASSERT_TRUE(video_media_desc != NULL);
2250 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2251 EXPECT_TRUE(video_media_desc->cryptos().empty());
2252 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2253 audio_media_desc->protocol());
2254 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2255 video_media_desc->protocol());
2256
2257 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2258 ASSERT_TRUE(audio_trans_desc != NULL);
2259 video_trans_desc = answer->GetTransportDescriptionByName("video");
2260 ASSERT_TRUE(video_trans_desc != NULL);
2261 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2262 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002263
2264 // Try creating offer again. DTLS enabled now, crypto's should be empty
2265 // in new offer.
2266 offer.reset(f1_.CreateOffer(options, offer.get()));
2267 ASSERT_TRUE(offer.get() != NULL);
2268 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2269 offer->GetContentDescriptionByName("audio"));
2270 ASSERT_TRUE(audio_media_desc != NULL);
2271 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2272 offer->GetContentDescriptionByName("video"));
2273 ASSERT_TRUE(video_media_desc != NULL);
2274 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2275 EXPECT_TRUE(video_media_desc->cryptos().empty());
2276
2277 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2278 ASSERT_TRUE(audio_trans_desc != NULL);
2279 video_trans_desc = offer->GetTransportDescriptionByName("video");
2280 ASSERT_TRUE(video_trans_desc != NULL);
2281 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2282 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002283}
2284
2285// Test that an answer can't be created if cryptos are required but the offer is
2286// unsecure.
2287TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2288 MediaSessionOptions options;
2289 f1_.set_secure(SEC_DISABLED);
2290 tdf1_.set_secure(SEC_DISABLED);
2291 f2_.set_secure(SEC_REQUIRED);
2292 tdf1_.set_secure(SEC_ENABLED);
2293
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002294 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002295 NULL));
2296 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002297 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002298 f2_.CreateAnswer(offer.get(), options, NULL));
2299 EXPECT_TRUE(answer.get() == NULL);
2300}
2301
2302// Test that we accept a DTLS offer without SDES and create an appropriate
2303// answer.
2304TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2305 f1_.set_secure(SEC_DISABLED);
2306 f2_.set_secure(SEC_ENABLED);
2307 tdf1_.set_secure(SEC_ENABLED);
2308 tdf2_.set_secure(SEC_ENABLED);
2309 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002310 options.recv_audio = true;
2311 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002312 options.data_channel_type = cricket::DCT_RTP;
2313
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002314 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002315
2316 // Generate an offer with DTLS but without SDES.
2317 offer.reset(f1_.CreateOffer(options, NULL));
2318 ASSERT_TRUE(offer.get() != NULL);
2319
2320 const AudioContentDescription* audio_offer =
2321 GetFirstAudioContentDescription(offer.get());
2322 ASSERT_TRUE(audio_offer->cryptos().empty());
2323 const VideoContentDescription* video_offer =
2324 GetFirstVideoContentDescription(offer.get());
2325 ASSERT_TRUE(video_offer->cryptos().empty());
2326 const DataContentDescription* data_offer =
2327 GetFirstDataContentDescription(offer.get());
2328 ASSERT_TRUE(data_offer->cryptos().empty());
2329
2330 const cricket::TransportDescription* audio_offer_trans_desc =
2331 offer->GetTransportDescriptionByName("audio");
2332 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2333 const cricket::TransportDescription* video_offer_trans_desc =
2334 offer->GetTransportDescriptionByName("video");
2335 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2336 const cricket::TransportDescription* data_offer_trans_desc =
2337 offer->GetTransportDescriptionByName("data");
2338 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2339
2340 // Generate an answer with DTLS.
2341 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2342 ASSERT_TRUE(answer.get() != NULL);
2343
2344 const cricket::TransportDescription* audio_answer_trans_desc =
2345 answer->GetTransportDescriptionByName("audio");
2346 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2347 const cricket::TransportDescription* video_answer_trans_desc =
2348 answer->GetTransportDescriptionByName("video");
2349 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2350 const cricket::TransportDescription* data_answer_trans_desc =
2351 answer->GetTransportDescriptionByName("data");
2352 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2353}
2354
2355// Verifies if vad_enabled option is set to false, CN codecs are not present in
2356// offer or answer.
2357TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2358 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002359 options.recv_audio = true;
2360 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002361 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002362 f1_.CreateOffer(options, NULL));
2363 ASSERT_TRUE(offer.get() != NULL);
2364 const ContentInfo* audio_content = offer->GetContentByName("audio");
2365 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2366
2367 options.vad_enabled = false;
2368 offer.reset(f1_.CreateOffer(options, NULL));
2369 ASSERT_TRUE(offer.get() != NULL);
2370 audio_content = offer->GetContentByName("audio");
2371 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002372 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002373 f1_.CreateAnswer(offer.get(), options, NULL));
2374 ASSERT_TRUE(answer.get() != NULL);
2375 audio_content = answer->GetContentByName("audio");
2376 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2377}
deadbeef44f08192015-12-15 16:20:09 -08002378
2379// Test that the content name ("mid" in SDP) is unchanged when creating a
2380// new offer.
2381TEST_F(MediaSessionDescriptionFactoryTest,
2382 TestContentNameNotChangedInSubsequentOffers) {
2383 MediaSessionOptions opts;
2384 opts.recv_audio = true;
2385 opts.recv_video = true;
2386 opts.data_channel_type = cricket::DCT_SCTP;
2387 // Create offer and modify the default content names.
2388 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2389 for (ContentInfo& content : offer->contents()) {
2390 content.name.append("_modified");
2391 }
2392
2393 rtc::scoped_ptr<SessionDescription> updated_offer(
2394 f1_.CreateOffer(opts, offer.get()));
2395 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2396 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2397 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2398 ASSERT_TRUE(audio_content != nullptr);
2399 ASSERT_TRUE(video_content != nullptr);
2400 ASSERT_TRUE(data_content != nullptr);
2401 EXPECT_EQ("audio_modified", audio_content->name);
2402 EXPECT_EQ("video_modified", video_content->name);
2403 EXPECT_EQ("data_modified", data_content->name);
2404}