blob: 5505fbb5098822938fcbf03bdd2bebdf73e00394 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <string>
29#include <vector>
30
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000031#include "webrtc/base/gunit.h"
32#include "webrtc/base/fakesslidentity.h"
33#include "webrtc/base/messagedigest.h"
34#include "webrtc/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035#include "talk/media/base/codec.h"
36#include "talk/media/base/testutils.h"
37#include "talk/p2p/base/constants.h"
38#include "talk/p2p/base/transportdescription.h"
39#include "talk/p2p/base/transportinfo.h"
40#include "talk/session/media/mediasession.h"
41#include "talk/session/media/srtpfilter.h"
42
43#ifdef HAVE_SRTP
44#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000045 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046 ASSERT_EQ(s, cd->cryptos().size()); \
47 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
48#else
49#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000050 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051 ASSERT_EQ(0U, cd->cryptos().size());
52#endif
53
54typedef std::vector<cricket::Candidate> Candidates;
55
56using cricket::MediaContentDescription;
57using cricket::MediaSessionDescriptionFactory;
58using cricket::MediaSessionOptions;
59using cricket::MediaType;
60using cricket::SessionDescription;
61using cricket::SsrcGroup;
62using cricket::StreamParams;
63using cricket::StreamParamsVec;
64using cricket::TransportDescription;
65using cricket::TransportDescriptionFactory;
66using cricket::TransportInfo;
67using cricket::ContentInfo;
68using cricket::CryptoParamsVec;
69using cricket::AudioContentDescription;
70using cricket::VideoContentDescription;
71using cricket::DataContentDescription;
72using cricket::GetFirstAudioContentDescription;
73using cricket::GetFirstVideoContentDescription;
74using cricket::GetFirstDataContentDescription;
75using cricket::kAutoBandwidth;
76using cricket::AudioCodec;
77using cricket::VideoCodec;
78using cricket::DataCodec;
79using cricket::NS_JINGLE_RTP;
80using cricket::MEDIA_TYPE_AUDIO;
81using cricket::MEDIA_TYPE_VIDEO;
82using cricket::MEDIA_TYPE_DATA;
83using cricket::RtpHeaderExtension;
84using cricket::SEC_DISABLED;
85using cricket::SEC_ENABLED;
86using cricket::SEC_REQUIRED;
87using cricket::CS_AES_CM_128_HMAC_SHA1_32;
88using cricket::CS_AES_CM_128_HMAC_SHA1_80;
89
90static const AudioCodec kAudioCodecs1[] = {
91 AudioCodec(103, "ISAC", 16000, -1, 1, 6),
92 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
93 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
94 AudioCodec(8, "PCMA", 8000, 64000, 1, 3),
95 AudioCodec(117, "red", 8000, 0, 1, 2),
96 AudioCodec(107, "CN", 48000, 0, 1, 1)
97};
98
99static const AudioCodec kAudioCodecs2[] = {
100 AudioCodec(126, "speex", 16000, 22000, 1, 3),
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000101 AudioCodec(0, "PCMU", 8000, 64000, 1, 2),
102 AudioCodec(127, "iLBC", 8000, 13300, 1, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103};
104
105static const AudioCodec kAudioCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000106 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
107 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108};
109
110static const VideoCodec kVideoCodecs1[] = {
111 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
112 VideoCodec(97, "H264", 320, 200, 30, 1)
113};
114
115static const VideoCodec kVideoCodecs2[] = {
116 VideoCodec(126, "H264", 320, 200, 30, 2),
117 VideoCodec(127, "H263", 320, 200, 30, 1)
118};
119
120static const VideoCodec kVideoCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000121 VideoCodec(97, "H264", 320, 200, 30, 1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122};
123
124static const DataCodec kDataCodecs1[] = {
125 DataCodec(98, "binary-data", 2),
126 DataCodec(99, "utf8-text", 1)
127};
128
129static const DataCodec kDataCodecs2[] = {
130 DataCodec(126, "binary-data", 2),
131 DataCodec(127, "utf8-text", 1)
132};
133
134static const DataCodec kDataCodecsAnswer[] = {
135 DataCodec(98, "binary-data", 2),
136 DataCodec(99, "utf8-text", 1)
137};
138
139static const RtpHeaderExtension kAudioRtpExtension1[] = {
140 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
141 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
142};
143
144static const RtpHeaderExtension kAudioRtpExtension2[] = {
145 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
146 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000147 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148};
149
150static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
151 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
152};
153
154static const RtpHeaderExtension kVideoRtpExtension1[] = {
155 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000156 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157};
158
159static const RtpHeaderExtension kVideoRtpExtension2[] = {
160 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
161 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000162 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163};
164
165static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
166 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
167};
168
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000169static const uint32 kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
170static const uint32 kSimSsrc[] = {10, 20, 30};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171static const uint32 kFec1Ssrc[] = {10, 11};
172static const uint32 kFec2Ssrc[] = {20, 21};
173static const uint32 kFec3Ssrc[] = {30, 31};
174
175static const char kMediaStream1[] = "stream_1";
176static const char kMediaStream2[] = "stream_2";
177static const char kVideoTrack1[] = "video_1";
178static const char kVideoTrack2[] = "video_2";
179static const char kAudioTrack1[] = "audio_1";
180static const char kAudioTrack2[] = "audio_2";
181static const char kAudioTrack3[] = "audio_3";
182static const char kDataTrack1[] = "data_1";
183static const char kDataTrack2[] = "data_2";
184static const char kDataTrack3[] = "data_3";
185
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000186static bool IsMediaContentOfType(const ContentInfo* content,
187 MediaType media_type) {
188 const MediaContentDescription* mdesc =
189 static_cast<const MediaContentDescription*>(content->description);
190 return mdesc && mdesc->type() == media_type;
191}
192
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000193class MediaSessionDescriptionFactoryTest : public testing::Test {
194 public:
195 MediaSessionDescriptionFactoryTest()
196 : f1_(&tdf1_), f2_(&tdf2_), id1_("id1"), id2_("id2") {
197 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
198 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
199 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
200 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
201 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
202 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
203 tdf1_.set_identity(&id1_);
204 tdf2_.set_identity(&id2_);
205 }
206
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000207 static void SetUpTestCase() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000208 rtc::InitializeSSL();
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000209 }
210
211 static void TearDownTestCase() {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000212 rtc::CleanupSSL();
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000213 }
214
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000215 // Create a video StreamParamsVec object with:
216 // - one video stream with 3 simulcast streams and FEC,
217 StreamParamsVec CreateComplexVideoStreamParamsVec() {
218 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
219 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
220 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
221 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
222
223 std::vector<SsrcGroup> ssrc_groups;
224 ssrc_groups.push_back(sim_group);
225 ssrc_groups.push_back(fec_group1);
226 ssrc_groups.push_back(fec_group2);
227 ssrc_groups.push_back(fec_group3);
228
229 StreamParams simulcast_params;
230 simulcast_params.id = kVideoTrack1;
231 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
232 simulcast_params.ssrc_groups = ssrc_groups;
233 simulcast_params.cname = "Video_SIM_FEC";
234 simulcast_params.sync_label = kMediaStream1;
235
236 StreamParamsVec video_streams;
237 video_streams.push_back(simulcast_params);
238
239 return video_streams;
240 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241
242 bool CompareCryptoParams(const CryptoParamsVec& c1,
243 const CryptoParamsVec& c2) {
244 if (c1.size() != c2.size())
245 return false;
246 for (size_t i = 0; i < c1.size(); ++i)
247 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
248 c1[i].key_params != c2[i].key_params ||
249 c1[i].session_params != c2[i].session_params)
250 return false;
251 return true;
252 }
253
254 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
255 bool has_current_desc) {
256 const std::string current_audio_ufrag = "current_audio_ufrag";
257 const std::string current_audio_pwd = "current_audio_pwd";
258 const std::string current_video_ufrag = "current_video_ufrag";
259 const std::string current_video_pwd = "current_video_pwd";
260 const std::string current_data_ufrag = "current_data_ufrag";
261 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000262 rtc::scoped_ptr<SessionDescription> current_desc;
263 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000264 if (has_current_desc) {
265 current_desc.reset(new SessionDescription());
266 EXPECT_TRUE(current_desc->AddTransportInfo(
267 TransportInfo("audio",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000268 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000269 current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000270 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271 EXPECT_TRUE(current_desc->AddTransportInfo(
272 TransportInfo("video",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000273 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274 current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000275 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 EXPECT_TRUE(current_desc->AddTransportInfo(
277 TransportInfo("data",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000278 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279 current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000280 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 }
282 if (offer) {
283 desc.reset(f1_.CreateOffer(options, current_desc.get()));
284 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000285 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 offer.reset(f1_.CreateOffer(options, NULL));
287 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
288 }
289 ASSERT_TRUE(desc.get() != NULL);
290 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
291 if (options.has_audio) {
292 EXPECT_TRUE(ti_audio != NULL);
293 if (has_current_desc) {
294 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
295 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
296 } else {
297 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
298 ti_audio->description.ice_ufrag.size());
299 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
300 ti_audio->description.ice_pwd.size());
301 }
302
303 } else {
304 EXPECT_TRUE(ti_audio == NULL);
305 }
306 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
307 if (options.has_video) {
308 EXPECT_TRUE(ti_video != NULL);
309 if (options.bundle_enabled) {
310 EXPECT_EQ(ti_audio->description.ice_ufrag,
311 ti_video->description.ice_ufrag);
312 EXPECT_EQ(ti_audio->description.ice_pwd,
313 ti_video->description.ice_pwd);
314 } else {
315 if (has_current_desc) {
316 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
317 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
318 } else {
319 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
320 ti_video->description.ice_ufrag.size());
321 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
322 ti_video->description.ice_pwd.size());
323 }
324 }
325 } else {
326 EXPECT_TRUE(ti_video == NULL);
327 }
328 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
329 if (options.has_data()) {
330 EXPECT_TRUE(ti_data != NULL);
331 if (options.bundle_enabled) {
332 EXPECT_EQ(ti_audio->description.ice_ufrag,
333 ti_data->description.ice_ufrag);
334 EXPECT_EQ(ti_audio->description.ice_pwd,
335 ti_data->description.ice_pwd);
336 } else {
337 if (has_current_desc) {
338 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
339 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
340 } else {
341 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
342 ti_data->description.ice_ufrag.size());
343 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
344 ti_data->description.ice_pwd.size());
345 }
346 }
347 } else {
348 EXPECT_TRUE(ti_video == NULL);
349 }
350 }
351
352 void TestCryptoWithBundle(bool offer) {
353 f1_.set_secure(SEC_ENABLED);
354 MediaSessionOptions options;
355 options.has_audio = true;
356 options.has_video = true;
357 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000358 rtc::scoped_ptr<SessionDescription> ref_desc;
359 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000360 if (offer) {
361 options.bundle_enabled = false;
362 ref_desc.reset(f1_.CreateOffer(options, NULL));
363 options.bundle_enabled = true;
364 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
365 } else {
366 options.bundle_enabled = true;
367 ref_desc.reset(f1_.CreateOffer(options, NULL));
368 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
369 }
370 ASSERT_TRUE(desc.get() != NULL);
371 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000372 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000373 desc.get()->GetContentDescriptionByName("audio"));
374 ASSERT_TRUE(audio_media_desc != NULL);
375 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000376 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000377 desc.get()->GetContentDescriptionByName("video"));
378 ASSERT_TRUE(video_media_desc != NULL);
379 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
380 video_media_desc->cryptos()));
381 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
382 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
383 audio_media_desc->cryptos()[0].cipher_suite);
384
385 // Verify the selected crypto is one from the reference audio
386 // media content.
387 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000388 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000389 ref_desc.get()->GetContentDescriptionByName("audio"));
390 bool found = false;
391 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
392 if (ref_audio_media_desc->cryptos()[i].Matches(
393 audio_media_desc->cryptos()[0])) {
394 found = true;
395 break;
396 }
397 }
398 EXPECT_TRUE(found);
399 }
400
401 // This test that the audio and video media direction is set to
402 // |expected_direction_in_answer| in an answer if the offer direction is set
403 // to |direction_in_offer|.
404 void TestMediaDirectionInAnswer(
405 cricket::MediaContentDirection direction_in_offer,
406 cricket::MediaContentDirection expected_direction_in_answer) {
407 MediaSessionOptions opts;
408 opts.has_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000409 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000410 f1_.CreateOffer(opts, NULL));
411 ASSERT_TRUE(offer.get() != NULL);
412 ContentInfo* ac_offer= offer->GetContentByName("audio");
413 ASSERT_TRUE(ac_offer != NULL);
414 AudioContentDescription* acd_offer =
415 static_cast<AudioContentDescription*>(ac_offer->description);
416 acd_offer->set_direction(direction_in_offer);
417 ContentInfo* vc_offer= offer->GetContentByName("video");
418 ASSERT_TRUE(vc_offer != NULL);
419 VideoContentDescription* vcd_offer =
420 static_cast<VideoContentDescription*>(vc_offer->description);
421 vcd_offer->set_direction(direction_in_offer);
422
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000423 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000424 f2_.CreateAnswer(offer.get(), opts, NULL));
425 const AudioContentDescription* acd_answer =
426 GetFirstAudioContentDescription(answer.get());
427 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
428 const VideoContentDescription* vcd_answer =
429 GetFirstVideoContentDescription(answer.get());
430 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
431 }
432
433 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
434 const cricket::ContentDescription* description = content->description;
435 ASSERT(description != NULL);
436 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000437 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 ASSERT(audio_content_desc != NULL);
439 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
440 if (audio_content_desc->codecs()[i].name == "CN")
441 return false;
442 }
443 return true;
444 }
445
446 protected:
447 MediaSessionDescriptionFactory f1_;
448 MediaSessionDescriptionFactory f2_;
449 TransportDescriptionFactory tdf1_;
450 TransportDescriptionFactory tdf2_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000451 rtc::FakeSSLIdentity id1_;
452 rtc::FakeSSLIdentity id2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453};
454
455// Create a typical audio offer, and ensure it matches what we expect.
456TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
457 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000458 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000459 f1_.CreateOffer(MediaSessionOptions(), NULL));
460 ASSERT_TRUE(offer.get() != NULL);
461 const ContentInfo* ac = offer->GetContentByName("audio");
462 const ContentInfo* vc = offer->GetContentByName("video");
463 ASSERT_TRUE(ac != NULL);
464 ASSERT_TRUE(vc == NULL);
465 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
466 const AudioContentDescription* acd =
467 static_cast<const AudioContentDescription*>(ac->description);
468 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
469 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
470 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
471 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
472 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
473 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
474 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
475}
476
477// Create a typical video offer, and ensure it matches what we expect.
478TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
479 MediaSessionOptions opts;
480 opts.has_video = true;
481 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000482 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000483 offer(f1_.CreateOffer(opts, NULL));
484 ASSERT_TRUE(offer.get() != NULL);
485 const ContentInfo* ac = offer->GetContentByName("audio");
486 const ContentInfo* vc = offer->GetContentByName("video");
487 ASSERT_TRUE(ac != NULL);
488 ASSERT_TRUE(vc != NULL);
489 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
490 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
491 const AudioContentDescription* acd =
492 static_cast<const AudioContentDescription*>(ac->description);
493 const VideoContentDescription* vcd =
494 static_cast<const VideoContentDescription*>(vc->description);
495 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
496 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
497 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
498 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
499 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
500 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
501 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
502 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
503 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
504 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
505 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
506 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
507 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
508 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
509}
510
511// Test creating an offer with bundle where the Codecs have the same dynamic
512// RTP playlod type. The test verifies that the offer don't contain the
513// duplicate RTP payload types.
514TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
515 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
516 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
517 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
518 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
519 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
520
521 MediaSessionOptions opts;
522 opts.has_audio = true;
523 opts.has_video = true;
524 opts.data_channel_type = cricket::DCT_RTP;
525 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000526 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000527 offer(f2_.CreateOffer(opts, NULL));
528 const VideoContentDescription* vcd =
529 GetFirstVideoContentDescription(offer.get());
530 const AudioContentDescription* acd =
531 GetFirstAudioContentDescription(offer.get());
532 const DataContentDescription* dcd =
533 GetFirstDataContentDescription(offer.get());
534 ASSERT_TRUE(NULL != vcd);
535 ASSERT_TRUE(NULL != acd);
536 ASSERT_TRUE(NULL != dcd);
537 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
538 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
539 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
540 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
541 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
542 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
543}
544
545// Test creating an updated offer with with bundle, audio, video and data
546// after an audio only session has been negotiated.
547TEST_F(MediaSessionDescriptionFactoryTest,
548 TestCreateUpdatedVideoOfferWithBundle) {
549 f1_.set_secure(SEC_ENABLED);
550 f2_.set_secure(SEC_ENABLED);
551 MediaSessionOptions opts;
552 opts.has_audio = true;
553 opts.has_video = false;
554 opts.data_channel_type = cricket::DCT_NONE;
555 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000556 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
557 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000558 f2_.CreateAnswer(offer.get(), opts, NULL));
559
560 MediaSessionOptions updated_opts;
561 updated_opts.has_audio = true;
562 updated_opts.has_video = true;
563 updated_opts.data_channel_type = cricket::DCT_RTP;
564 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000565 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000566 updated_opts, answer.get()));
567
568 const AudioContentDescription* acd =
569 GetFirstAudioContentDescription(updated_offer.get());
570 const VideoContentDescription* vcd =
571 GetFirstVideoContentDescription(updated_offer.get());
572 const DataContentDescription* dcd =
573 GetFirstDataContentDescription(updated_offer.get());
574 EXPECT_TRUE(NULL != vcd);
575 EXPECT_TRUE(NULL != acd);
576 EXPECT_TRUE(NULL != dcd);
577
578 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
579 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
580 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
581 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
582 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
583 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
584}
wu@webrtc.org78187522013-10-07 23:32:02 +0000585// Create a RTP data offer, and ensure it matches what we expect.
586TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587 MediaSessionOptions opts;
588 opts.data_channel_type = cricket::DCT_RTP;
589 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000590 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 offer(f1_.CreateOffer(opts, NULL));
592 ASSERT_TRUE(offer.get() != NULL);
593 const ContentInfo* ac = offer->GetContentByName("audio");
594 const ContentInfo* dc = offer->GetContentByName("data");
595 ASSERT_TRUE(ac != NULL);
596 ASSERT_TRUE(dc != NULL);
597 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
598 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
599 const AudioContentDescription* acd =
600 static_cast<const AudioContentDescription*>(ac->description);
601 const DataContentDescription* dcd =
602 static_cast<const DataContentDescription*>(dc->description);
603 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
604 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
605 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
606 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
607 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
608 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
609 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
610 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
611 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
612 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
613 EXPECT_EQ(cricket::kDataMaxBandwidth,
614 dcd->bandwidth()); // default bandwidth (auto)
615 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
616 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
617 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
618}
619
wu@webrtc.org78187522013-10-07 23:32:02 +0000620// Create an SCTP data offer with bundle without error.
621TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
622 MediaSessionOptions opts;
623 opts.has_audio = false;
624 opts.bundle_enabled = true;
625 opts.data_channel_type = cricket::DCT_SCTP;
626 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000627 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000628 EXPECT_TRUE(offer.get() != NULL);
629 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
630}
631
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000632// Create an audio, video offer without legacy StreamParams.
633TEST_F(MediaSessionDescriptionFactoryTest,
634 TestCreateOfferWithoutLegacyStreams) {
635 MediaSessionOptions opts;
636 opts.has_video = true;
637 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000638 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000639 offer(f1_.CreateOffer(opts, NULL));
640 ASSERT_TRUE(offer.get() != NULL);
641 const ContentInfo* ac = offer->GetContentByName("audio");
642 const ContentInfo* vc = offer->GetContentByName("video");
643 ASSERT_TRUE(ac != NULL);
644 ASSERT_TRUE(vc != NULL);
645 const AudioContentDescription* acd =
646 static_cast<const AudioContentDescription*>(ac->description);
647 const VideoContentDescription* vcd =
648 static_cast<const VideoContentDescription*>(vc->description);
649
650 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
651 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
652}
653
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000654// Verifies that the order of the media contents in the current
655// SessionDescription is preserved in the new SessionDescription.
656TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
657 MediaSessionOptions opts;
658 opts.has_audio = false;
659 opts.has_video = false;
660 opts.data_channel_type = cricket::DCT_SCTP;
661
662 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
663 ASSERT_TRUE(offer1.get() != NULL);
664 EXPECT_EQ(1u, offer1->contents().size());
665 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
666
667 opts.has_video = true;
668 rtc::scoped_ptr<SessionDescription> offer2(
669 f1_.CreateOffer(opts, offer1.get()));
670 ASSERT_TRUE(offer2.get() != NULL);
671 EXPECT_EQ(2u, offer2->contents().size());
672 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
673 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
674
675 opts.has_audio = true;
676 rtc::scoped_ptr<SessionDescription> offer3(
677 f1_.CreateOffer(opts, offer2.get()));
678 ASSERT_TRUE(offer3.get() != NULL);
679 EXPECT_EQ(3u, offer3->contents().size());
680 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
681 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
682 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
683
684 // Verifies the default order is audio-video-data, so that the previous checks
685 // didn't pass by accident.
686 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
687 ASSERT_TRUE(offer4.get() != NULL);
688 EXPECT_EQ(3u, offer4->contents().size());
689 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
690 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
691 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
692}
693
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000694// Create a typical audio answer, and ensure it matches what we expect.
695TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
696 f1_.set_secure(SEC_ENABLED);
697 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000698 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000699 f1_.CreateOffer(MediaSessionOptions(), NULL));
700 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000701 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000702 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
703 const ContentInfo* ac = answer->GetContentByName("audio");
704 const ContentInfo* vc = answer->GetContentByName("video");
705 ASSERT_TRUE(ac != NULL);
706 ASSERT_TRUE(vc == NULL);
707 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
708 const AudioContentDescription* acd =
709 static_cast<const AudioContentDescription*>(ac->description);
710 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
711 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
712 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
713 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
714 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
715 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
716 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
717}
718
719// Create a typical video answer, and ensure it matches what we expect.
720TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
721 MediaSessionOptions opts;
722 opts.has_video = true;
723 f1_.set_secure(SEC_ENABLED);
724 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000725 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000726 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000727 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 f2_.CreateAnswer(offer.get(), opts, NULL));
729 const ContentInfo* ac = answer->GetContentByName("audio");
730 const ContentInfo* vc = answer->GetContentByName("video");
731 ASSERT_TRUE(ac != NULL);
732 ASSERT_TRUE(vc != NULL);
733 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
734 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
735 const AudioContentDescription* acd =
736 static_cast<const AudioContentDescription*>(ac->description);
737 const VideoContentDescription* vcd =
738 static_cast<const VideoContentDescription*>(vc->description);
739 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
740 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
741 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
742 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
743 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
744 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
745 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
746 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
747 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
748 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
749 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
750 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
751}
752
753TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
754 MediaSessionOptions opts;
755 opts.data_channel_type = cricket::DCT_RTP;
756 f1_.set_secure(SEC_ENABLED);
757 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000758 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000760 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761 f2_.CreateAnswer(offer.get(), opts, NULL));
762 const ContentInfo* ac = answer->GetContentByName("audio");
763 const ContentInfo* vc = answer->GetContentByName("data");
764 ASSERT_TRUE(ac != NULL);
765 ASSERT_TRUE(vc != NULL);
766 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
767 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
768 const AudioContentDescription* acd =
769 static_cast<const AudioContentDescription*>(ac->description);
770 const DataContentDescription* vcd =
771 static_cast<const DataContentDescription*>(vc->description);
772 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
773 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
774 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
775 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
776 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
777 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
778 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
779 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
780 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
781 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
782 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
783 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
784}
785
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000786// Verifies that the order of the media contents in the offer is preserved in
787// the answer.
788TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
789 MediaSessionOptions opts;
790
791 // Creates a data only offer.
792 opts.has_audio = false;
793 opts.data_channel_type = cricket::DCT_SCTP;
794 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
795 ASSERT_TRUE(offer1.get() != NULL);
796
797 // Appends audio to the offer.
798 opts.has_audio = true;
799 rtc::scoped_ptr<SessionDescription> offer2(
800 f1_.CreateOffer(opts, offer1.get()));
801 ASSERT_TRUE(offer2.get() != NULL);
802
803 // Appends video to the offer.
804 opts.has_video = true;
805 rtc::scoped_ptr<SessionDescription> offer3(
806 f1_.CreateOffer(opts, offer2.get()));
807 ASSERT_TRUE(offer3.get() != NULL);
808
809 rtc::scoped_ptr<SessionDescription> answer(
810 f2_.CreateAnswer(offer3.get(), opts, NULL));
811 ASSERT_TRUE(answer.get() != NULL);
812 EXPECT_EQ(3u, answer->contents().size());
813 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
814 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
815 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
816}
817
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818// This test that the media direction is set to send/receive in an answer if
819// the offer is send receive.
820TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
821 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
822}
823
824// This test that the media direction is set to receive only in an answer if
825// the offer is send only.
826TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
827 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
828}
829
830// This test that the media direction is set to send only in an answer if
831// the offer is recv only.
832TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
833 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
834}
835
836// This test that the media direction is set to inactive in an answer if
837// the offer is inactive.
838TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
839 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
840}
841
842// Test that a data content with an unknown protocol is rejected in an answer.
843TEST_F(MediaSessionDescriptionFactoryTest,
844 CreateDataAnswerToOfferWithUnknownProtocol) {
845 MediaSessionOptions opts;
846 opts.data_channel_type = cricket::DCT_RTP;
847 opts.has_audio = false;
848 f1_.set_secure(SEC_ENABLED);
849 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000850 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000851 ContentInfo* dc_offer= offer->GetContentByName("data");
852 ASSERT_TRUE(dc_offer != NULL);
853 DataContentDescription* dcd_offer =
854 static_cast<DataContentDescription*>(dc_offer->description);
855 ASSERT_TRUE(dcd_offer != NULL);
856 std::string protocol = "a weird unknown protocol";
857 dcd_offer->set_protocol(protocol);
858
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000859 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000860 f2_.CreateAnswer(offer.get(), opts, NULL));
861
862 const ContentInfo* dc_answer = answer->GetContentByName("data");
863 ASSERT_TRUE(dc_answer != NULL);
864 EXPECT_TRUE(dc_answer->rejected);
865 const DataContentDescription* dcd_answer =
866 static_cast<const DataContentDescription*>(dc_answer->description);
867 ASSERT_TRUE(dcd_answer != NULL);
868 EXPECT_EQ(protocol, dcd_answer->protocol());
869}
870
871// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
872TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
873 MediaSessionOptions opts;
874 f1_.set_secure(SEC_DISABLED);
875 f2_.set_secure(SEC_DISABLED);
876 tdf1_.set_secure(SEC_DISABLED);
877 tdf2_.set_secure(SEC_DISABLED);
878
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000879 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000880 const AudioContentDescription* offer_acd =
881 GetFirstAudioContentDescription(offer.get());
882 ASSERT_TRUE(offer_acd != NULL);
883 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
884
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000885 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000886 f2_.CreateAnswer(offer.get(), opts, NULL));
887
888 const ContentInfo* ac_answer = answer->GetContentByName("audio");
889 ASSERT_TRUE(ac_answer != NULL);
890 EXPECT_FALSE(ac_answer->rejected);
891
892 const AudioContentDescription* answer_acd =
893 GetFirstAudioContentDescription(answer.get());
894 ASSERT_TRUE(answer_acd != NULL);
895 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
896}
897
898// Create a video offer and answer and ensure the RTP header extensions
899// matches what we expect.
900TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
901 MediaSessionOptions opts;
902 opts.has_video = true;
903
904 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
905 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
906 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
907 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
908
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000909 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000910 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000911 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000912 f2_.CreateAnswer(offer.get(), opts, NULL));
913
914 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
915 GetFirstAudioContentDescription(
916 offer.get())->rtp_header_extensions());
917 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
918 GetFirstVideoContentDescription(
919 offer.get())->rtp_header_extensions());
920 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
921 GetFirstAudioContentDescription(
922 answer.get())->rtp_header_extensions());
923 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
924 GetFirstVideoContentDescription(
925 answer.get())->rtp_header_extensions());
926}
927
928// Create an audio, video, data answer without legacy StreamParams.
929TEST_F(MediaSessionDescriptionFactoryTest,
930 TestCreateAnswerWithoutLegacyStreams) {
931 MediaSessionOptions opts;
932 opts.has_video = true;
933 opts.data_channel_type = cricket::DCT_RTP;
934 f1_.set_add_legacy_streams(false);
935 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000936 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000938 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000939 f2_.CreateAnswer(offer.get(), opts, NULL));
940 const ContentInfo* ac = answer->GetContentByName("audio");
941 const ContentInfo* vc = answer->GetContentByName("video");
942 const ContentInfo* dc = answer->GetContentByName("data");
943 ASSERT_TRUE(ac != NULL);
944 ASSERT_TRUE(vc != NULL);
945 const AudioContentDescription* acd =
946 static_cast<const AudioContentDescription*>(ac->description);
947 const VideoContentDescription* vcd =
948 static_cast<const VideoContentDescription*>(vc->description);
949 const DataContentDescription* dcd =
950 static_cast<const DataContentDescription*>(dc->description);
951
952 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
953 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
954 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
955}
956
957TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
958 MediaSessionOptions opts;
959 opts.has_video = true;
960 opts.data_channel_type = cricket::DCT_RTP;
961 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000962 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963 offer(f1_.CreateOffer(opts, NULL));
964 ASSERT_TRUE(offer.get() != NULL);
965 const ContentInfo* ac = offer->GetContentByName("audio");
966 const ContentInfo* vc = offer->GetContentByName("video");
967 const ContentInfo* dc = offer->GetContentByName("data");
968 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
969 static_cast<const AudioContentDescription*>(ac->description));
970 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
971 static_cast<const VideoContentDescription*>(vc->description));
972 DataContentDescription* dcd = const_cast<DataContentDescription*>(
973 static_cast<const DataContentDescription*>(dc->description));
974
975 EXPECT_FALSE(acd->partial()); // default is false.
976 acd->set_partial(true);
977 EXPECT_TRUE(acd->partial());
978 acd->set_partial(false);
979 EXPECT_FALSE(acd->partial());
980
981 EXPECT_FALSE(vcd->partial()); // default is false.
982 vcd->set_partial(true);
983 EXPECT_TRUE(vcd->partial());
984 vcd->set_partial(false);
985 EXPECT_FALSE(vcd->partial());
986
987 EXPECT_FALSE(dcd->partial()); // default is false.
988 dcd->set_partial(true);
989 EXPECT_TRUE(dcd->partial());
990 dcd->set_partial(false);
991 EXPECT_FALSE(dcd->partial());
992}
993
994// Create a typical video answer, and ensure it matches what we expect.
995TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
996 MediaSessionOptions offer_opts;
997 MediaSessionOptions answer_opts;
998 answer_opts.has_video = true;
999 offer_opts.has_video = true;
1000 answer_opts.data_channel_type = cricket::DCT_RTP;
1001 offer_opts.data_channel_type = cricket::DCT_RTP;
1002
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001003 rtc::scoped_ptr<SessionDescription> offer;
1004 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001005
1006 offer_opts.rtcp_mux_enabled = true;
1007 answer_opts.rtcp_mux_enabled = true;
1008
1009 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1010 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1011 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1012 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1013 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1014 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1015 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1016 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1017 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1018 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1019 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1020 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1021 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1022 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1023
1024 offer_opts.rtcp_mux_enabled = true;
1025 answer_opts.rtcp_mux_enabled = false;
1026
1027 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1028 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1029 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1030 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1031 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1032 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1033 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1034 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1035 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1036 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1037 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1038 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1039 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1040 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1041
1042 offer_opts.rtcp_mux_enabled = false;
1043 answer_opts.rtcp_mux_enabled = true;
1044
1045 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1046 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1047 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1048 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1049 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1050 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1051 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1052 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1053 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1054 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1055 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1056 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1057 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1058 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1059
1060 offer_opts.rtcp_mux_enabled = false;
1061 answer_opts.rtcp_mux_enabled = false;
1062
1063 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1064 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1065 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1066 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1067 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1068 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1069 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1070 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1071 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1072 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1073 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1074 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1075 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1076 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1077}
1078
1079// Create an audio-only answer to a video offer.
1080TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1081 MediaSessionOptions opts;
1082 opts.has_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001083 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001084 offer(f1_.CreateOffer(opts, NULL));
1085 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001086 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001087 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1088 const ContentInfo* ac = answer->GetContentByName("audio");
1089 const ContentInfo* vc = answer->GetContentByName("video");
1090 ASSERT_TRUE(ac != NULL);
1091 ASSERT_TRUE(vc != NULL);
1092 ASSERT_TRUE(vc->description != NULL);
1093 EXPECT_TRUE(vc->rejected);
1094}
1095
1096// Create an audio-only answer to an offer with data.
1097TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1098 MediaSessionOptions opts;
1099 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001100 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 offer(f1_.CreateOffer(opts, NULL));
1102 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001103 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1105 const ContentInfo* ac = answer->GetContentByName("audio");
1106 const ContentInfo* dc = answer->GetContentByName("data");
1107 ASSERT_TRUE(ac != NULL);
1108 ASSERT_TRUE(dc != NULL);
1109 ASSERT_TRUE(dc->description != NULL);
1110 EXPECT_TRUE(dc->rejected);
1111}
1112
1113// Create an answer that rejects the contents which are rejected in the offer.
1114TEST_F(MediaSessionDescriptionFactoryTest,
1115 CreateAnswerToOfferWithRejectedMedia) {
1116 MediaSessionOptions opts;
1117 opts.has_video = true;
1118 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001119 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001120 offer(f1_.CreateOffer(opts, NULL));
1121 ASSERT_TRUE(offer.get() != NULL);
1122 ContentInfo* ac = offer->GetContentByName("audio");
1123 ContentInfo* vc = offer->GetContentByName("video");
1124 ContentInfo* dc = offer->GetContentByName("data");
1125 ASSERT_TRUE(ac != NULL);
1126 ASSERT_TRUE(vc != NULL);
1127 ASSERT_TRUE(dc != NULL);
1128 ac->rejected = true;
1129 vc->rejected = true;
1130 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001131 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001132 f2_.CreateAnswer(offer.get(), opts, NULL));
1133 ac = answer->GetContentByName("audio");
1134 vc = answer->GetContentByName("video");
1135 dc = answer->GetContentByName("data");
1136 ASSERT_TRUE(ac != NULL);
1137 ASSERT_TRUE(vc != NULL);
1138 ASSERT_TRUE(dc != NULL);
1139 EXPECT_TRUE(ac->rejected);
1140 EXPECT_TRUE(vc->rejected);
1141 EXPECT_TRUE(dc->rejected);
1142}
1143
1144// Create an audio and video offer with:
1145// - one video track
1146// - two audio tracks
1147// - two data tracks
1148// and ensure it matches what we expect. Also updates the initial offer by
1149// adding a new video track and replaces one of the audio tracks.
1150TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1151 MediaSessionOptions opts;
1152 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1153 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1154 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
1155 opts.data_channel_type = cricket::DCT_RTP;
1156 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1157 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
1158
1159 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001160 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161
1162 ASSERT_TRUE(offer.get() != NULL);
1163 const ContentInfo* ac = offer->GetContentByName("audio");
1164 const ContentInfo* vc = offer->GetContentByName("video");
1165 const ContentInfo* dc = offer->GetContentByName("data");
1166 ASSERT_TRUE(ac != NULL);
1167 ASSERT_TRUE(vc != NULL);
1168 ASSERT_TRUE(dc != NULL);
1169 const AudioContentDescription* acd =
1170 static_cast<const AudioContentDescription*>(ac->description);
1171 const VideoContentDescription* vcd =
1172 static_cast<const VideoContentDescription*>(vc->description);
1173 const DataContentDescription* dcd =
1174 static_cast<const DataContentDescription*>(dc->description);
1175 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1176 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1177
1178 const StreamParamsVec& audio_streams = acd->streams();
1179 ASSERT_EQ(2U, audio_streams.size());
1180 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1181 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1182 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1183 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1184 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1185 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1186 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1187
1188 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1189 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1190 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1191
1192 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1193 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1194 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1195
1196 const StreamParamsVec& video_streams = vcd->streams();
1197 ASSERT_EQ(1U, video_streams.size());
1198 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1199 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1200 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1201 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1202
1203 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1204 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1205 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1206
1207 const StreamParamsVec& data_streams = dcd->streams();
1208 ASSERT_EQ(2U, data_streams.size());
1209 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1210 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1211 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1212 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1213 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1214 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1215 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1216
1217 EXPECT_EQ(cricket::kDataMaxBandwidth,
1218 dcd->bandwidth()); // default bandwidth (auto)
1219 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1220 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1221
1222
1223 // Update the offer. Add a new video track that is not synched to the
1224 // other tracks and replace audio track 2 with audio track 3.
1225 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1226 opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1227 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1228 opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
1229 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001230 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001231 updated_offer(f1_.CreateOffer(opts, offer.get()));
1232
1233 ASSERT_TRUE(updated_offer.get() != NULL);
1234 ac = updated_offer->GetContentByName("audio");
1235 vc = updated_offer->GetContentByName("video");
1236 dc = updated_offer->GetContentByName("data");
1237 ASSERT_TRUE(ac != NULL);
1238 ASSERT_TRUE(vc != NULL);
1239 ASSERT_TRUE(dc != NULL);
1240 const AudioContentDescription* updated_acd =
1241 static_cast<const AudioContentDescription*>(ac->description);
1242 const VideoContentDescription* updated_vcd =
1243 static_cast<const VideoContentDescription*>(vc->description);
1244 const DataContentDescription* updated_dcd =
1245 static_cast<const DataContentDescription*>(dc->description);
1246
1247 EXPECT_EQ(acd->type(), updated_acd->type());
1248 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1249 EXPECT_EQ(vcd->type(), updated_vcd->type());
1250 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1251 EXPECT_EQ(dcd->type(), updated_dcd->type());
1252 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1253 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1254 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1255 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1256 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1257 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1258 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1259
1260 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1261 ASSERT_EQ(2U, updated_audio_streams.size());
1262 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1263 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1264 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1265 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1266 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1267
1268 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1269 ASSERT_EQ(2U, updated_video_streams.size());
1270 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1271 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1272 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1273
1274 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1275 ASSERT_EQ(2U, updated_data_streams.size());
1276 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1277 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1278 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1279 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1280 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1281}
1282
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001283// Create an offer with simulcast video stream.
1284TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1285 MediaSessionOptions opts;
1286 const int num_sim_layers = 3;
1287 opts.AddVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001288 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001289
1290 ASSERT_TRUE(offer.get() != NULL);
1291 const ContentInfo* vc = offer->GetContentByName("video");
1292 ASSERT_TRUE(vc != NULL);
1293 const VideoContentDescription* vcd =
1294 static_cast<const VideoContentDescription*>(vc->description);
1295
1296 const StreamParamsVec& video_streams = vcd->streams();
1297 ASSERT_EQ(1U, video_streams.size());
1298 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1299 const SsrcGroup* sim_ssrc_group =
1300 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1301 ASSERT_TRUE(sim_ssrc_group != NULL);
1302 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1303}
1304
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001305// Create an audio and video answer to a standard video offer with:
1306// - one video track
1307// - two audio tracks
1308// - two data tracks
1309// and ensure it matches what we expect. Also updates the initial answer by
1310// adding a new video track and removes one of the audio tracks.
1311TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1312 MediaSessionOptions offer_opts;
1313 offer_opts.has_video = true;
1314 offer_opts.data_channel_type = cricket::DCT_RTP;
1315 f1_.set_secure(SEC_ENABLED);
1316 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001317 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001318 NULL));
1319
1320 MediaSessionOptions opts;
1321 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1322 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1323 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
1324 opts.data_channel_type = cricket::DCT_RTP;
1325 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1326 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
1327
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001328 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1330
1331 ASSERT_TRUE(answer.get() != NULL);
1332 const ContentInfo* ac = answer->GetContentByName("audio");
1333 const ContentInfo* vc = answer->GetContentByName("video");
1334 const ContentInfo* dc = answer->GetContentByName("data");
1335 ASSERT_TRUE(ac != NULL);
1336 ASSERT_TRUE(vc != NULL);
1337 ASSERT_TRUE(dc != NULL);
1338 const AudioContentDescription* acd =
1339 static_cast<const AudioContentDescription*>(ac->description);
1340 const VideoContentDescription* vcd =
1341 static_cast<const VideoContentDescription*>(vc->description);
1342 const DataContentDescription* dcd =
1343 static_cast<const DataContentDescription*>(dc->description);
1344 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1345 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1346 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1347
1348 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1349 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1350
1351 const StreamParamsVec& audio_streams = acd->streams();
1352 ASSERT_EQ(2U, audio_streams.size());
1353 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1354 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1355 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1356 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1357 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1358 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1359 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1360
1361 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1362 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1363
1364 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1365 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1366
1367 const StreamParamsVec& video_streams = vcd->streams();
1368 ASSERT_EQ(1U, video_streams.size());
1369 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1370 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1371 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1372 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1373
1374 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1375 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1376
1377 const StreamParamsVec& data_streams = dcd->streams();
1378 ASSERT_EQ(2U, data_streams.size());
1379 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1380 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1381 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1382 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1383 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1384 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1385 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1386
1387 EXPECT_EQ(cricket::kDataMaxBandwidth,
1388 dcd->bandwidth()); // default bandwidth (auto)
1389 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1390
1391 // Update the answer. Add a new video track that is not synched to the
1392 // other traacks and remove 1 audio track.
1393 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1394 opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1395 opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001396 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001397 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1398
1399 ASSERT_TRUE(updated_answer.get() != NULL);
1400 ac = updated_answer->GetContentByName("audio");
1401 vc = updated_answer->GetContentByName("video");
1402 dc = updated_answer->GetContentByName("data");
1403 ASSERT_TRUE(ac != NULL);
1404 ASSERT_TRUE(vc != NULL);
1405 ASSERT_TRUE(dc != NULL);
1406 const AudioContentDescription* updated_acd =
1407 static_cast<const AudioContentDescription*>(ac->description);
1408 const VideoContentDescription* updated_vcd =
1409 static_cast<const VideoContentDescription*>(vc->description);
1410 const DataContentDescription* updated_dcd =
1411 static_cast<const DataContentDescription*>(dc->description);
1412
1413 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1414 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1415 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1416 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1417 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1418 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1419
1420 EXPECT_EQ(acd->type(), updated_acd->type());
1421 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1422 EXPECT_EQ(vcd->type(), updated_vcd->type());
1423 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1424 EXPECT_EQ(dcd->type(), updated_dcd->type());
1425 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1426
1427 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1428 ASSERT_EQ(1U, updated_audio_streams.size());
1429 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1430
1431 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1432 ASSERT_EQ(2U, updated_video_streams.size());
1433 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1434 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1435 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1436
1437 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1438 ASSERT_EQ(1U, updated_data_streams.size());
1439 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1440}
1441
1442
1443// Create an updated offer after creating an answer to the original offer and
1444// verify that the codecs that were part of the original answer are not changed
1445// in the updated offer.
1446TEST_F(MediaSessionDescriptionFactoryTest,
1447 RespondentCreatesOfferAfterCreatingAnswer) {
1448 MediaSessionOptions opts;
1449 opts.has_audio = true;
1450 opts.has_video = true;
1451
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001452 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1453 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001454 f2_.CreateAnswer(offer.get(), opts, NULL));
1455
1456 const AudioContentDescription* acd =
1457 GetFirstAudioContentDescription(answer.get());
1458 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1459
1460 const VideoContentDescription* vcd =
1461 GetFirstVideoContentDescription(answer.get());
1462 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1463
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001464 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001465 f2_.CreateOffer(opts, answer.get()));
1466
1467 // The expected audio codecs are the common audio codecs from the first
1468 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1469 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001470 // TODO(wu): |updated_offer| should not include the codec
1471 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001472 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001473 kAudioCodecsAnswer[0],
1474 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001475 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001476 };
1477
1478 // The expected video codecs are the common video codecs from the first
1479 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1480 // preference order.
1481 const VideoCodec kUpdatedVideoCodecOffer[] = {
1482 kVideoCodecsAnswer[0],
1483 kVideoCodecs2[1],
1484 };
1485
1486 const AudioContentDescription* updated_acd =
1487 GetFirstAudioContentDescription(updated_offer.get());
1488 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1489
1490 const VideoContentDescription* updated_vcd =
1491 GetFirstVideoContentDescription(updated_offer.get());
1492 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1493}
1494
1495// Create an updated offer after creating an answer to the original offer and
1496// verify that the codecs that were part of the original answer are not changed
1497// in the updated offer. In this test Rtx is enabled.
1498TEST_F(MediaSessionDescriptionFactoryTest,
1499 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1500 MediaSessionOptions opts;
1501 opts.has_video = true;
1502 opts.has_audio = false;
1503 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1504 VideoCodec rtx_f1;
1505 rtx_f1.id = 126;
1506 rtx_f1.name = cricket::kRtxCodecName;
1507
1508 // This creates rtx for H264 with the payload type |f1_| uses.
1509 rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001510 rtc::ToString<int>(kVideoCodecs1[1].id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511 f1_codecs.push_back(rtx_f1);
1512 f1_.set_video_codecs(f1_codecs);
1513
1514 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1515 VideoCodec rtx_f2;
1516 rtx_f2.id = 127;
1517 rtx_f2.name = cricket::kRtxCodecName;
1518
1519 // This creates rtx for H264 with the payload type |f2_| uses.
1520 rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001521 rtc::ToString<int>(kVideoCodecs2[0].id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001522 f2_codecs.push_back(rtx_f2);
1523 f2_.set_video_codecs(f2_codecs);
1524
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001525 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001526 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001527 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 f2_.CreateAnswer(offer.get(), opts, NULL));
1529
1530 const VideoContentDescription* vcd =
1531 GetFirstVideoContentDescription(answer.get());
1532
1533 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1534 expected_codecs.push_back(rtx_f1);
1535
1536 EXPECT_EQ(expected_codecs, vcd->codecs());
1537
1538 // Now, make sure we get same result, except for the preference order,
1539 // if |f2_| creates an updated offer even though the default payload types
1540 // are different from |f1_|.
1541 expected_codecs[0].preference = f1_codecs[1].preference;
1542
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001543 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001544 f2_.CreateOffer(opts, answer.get()));
1545 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001546 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1548
1549 const VideoContentDescription* updated_vcd =
1550 GetFirstVideoContentDescription(updated_answer.get());
1551
1552 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1553}
1554
1555// Create an updated offer that adds video after creating an audio only answer
1556// to the original offer. This test verifies that if a video codec and the RTX
1557// codec have the same default payload type as an audio codec that is already in
1558// use, the added codecs payload types are changed.
1559TEST_F(MediaSessionDescriptionFactoryTest,
1560 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1561 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1562 VideoCodec rtx_f1;
1563 rtx_f1.id = 126;
1564 rtx_f1.name = cricket::kRtxCodecName;
1565
1566 // This creates rtx for H264 with the payload type |f1_| uses.
1567 rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001568 rtc::ToString<int>(kVideoCodecs1[1].id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 f1_codecs.push_back(rtx_f1);
1570 f1_.set_video_codecs(f1_codecs);
1571
1572 MediaSessionOptions opts;
1573 opts.has_audio = true;
1574 opts.has_video = false;
1575
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001576 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1577 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001578 f2_.CreateAnswer(offer.get(), opts, NULL));
1579
1580 const AudioContentDescription* acd =
1581 GetFirstAudioContentDescription(answer.get());
1582 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1583
1584 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1585 // reference be the same as an audio codec that was negotiated in the
1586 // first offer/answer exchange.
1587 opts.has_audio = true;
1588 opts.has_video = true;
1589
1590 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1591 int used_pl_type = acd->codecs()[0].id;
1592 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
1593 VideoCodec rtx_f2;
1594 rtx_f2.id = 127;
1595 rtx_f2.name = cricket::kRtxCodecName;
1596 rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001597 rtc::ToString<int>(used_pl_type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001598 f2_codecs.push_back(rtx_f2);
1599 f2_.set_video_codecs(f2_codecs);
1600
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001601 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001602 f2_.CreateOffer(opts, answer.get()));
1603 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001604 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1606
1607 const AudioContentDescription* updated_acd =
1608 GetFirstAudioContentDescription(answer.get());
1609 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1610
1611 const VideoContentDescription* updated_vcd =
1612 GetFirstVideoContentDescription(updated_answer.get());
1613
1614 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001615 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001616 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1617 EXPECT_NE(used_pl_type, new_h264_pl_type);
1618 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001619 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1621 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1622}
1623
1624// Test that RTX is ignored when there is no associated payload type parameter.
1625TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1626 MediaSessionOptions opts;
1627 opts.has_video = true;
1628 opts.has_audio = false;
1629 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1630 VideoCodec rtx_f1;
1631 rtx_f1.id = 126;
1632 rtx_f1.name = cricket::kRtxCodecName;
1633
1634 f1_codecs.push_back(rtx_f1);
1635 f1_.set_video_codecs(f1_codecs);
1636
1637 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1638 VideoCodec rtx_f2;
1639 rtx_f2.id = 127;
1640 rtx_f2.name = cricket::kRtxCodecName;
1641
1642 // This creates rtx for H264 with the payload type |f2_| uses.
1643 rtx_f2.SetParam(cricket::kCodecParamAssociatedPayloadType,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001644 rtc::ToString<int>(kVideoCodecs2[0].id));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001645 f2_codecs.push_back(rtx_f2);
1646 f2_.set_video_codecs(f2_codecs);
1647
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001648 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001649 ASSERT_TRUE(offer.get() != NULL);
1650 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1651 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1652 // is possible to test that that RTX is dropped when
1653 // kCodecParamAssociatedPayloadType is missing in the offer.
1654 VideoContentDescription* desc =
1655 static_cast<cricket::VideoContentDescription*>(
1656 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1657 ASSERT_TRUE(desc != NULL);
1658 std::vector<VideoCodec> codecs = desc->codecs();
1659 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1660 iter != codecs.end(); ++iter) {
1661 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1662 iter->params.clear();
1663 }
1664 }
1665 desc->set_codecs(codecs);
1666
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001667 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 f2_.CreateAnswer(offer.get(), opts, NULL));
1669
1670 const VideoContentDescription* vcd =
1671 GetFirstVideoContentDescription(answer.get());
1672
1673 for (std::vector<VideoCodec>::const_iterator iter = vcd->codecs().begin();
1674 iter != vcd->codecs().end(); ++iter) {
1675 ASSERT_STRNE(iter->name.c_str(), cricket::kRtxCodecName);
1676 }
1677}
1678
1679// Create an updated offer after creating an answer to the original offer and
1680// verify that the RTP header extensions that were part of the original answer
1681// are not changed in the updated offer.
1682TEST_F(MediaSessionDescriptionFactoryTest,
1683 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1684 MediaSessionOptions opts;
1685 opts.has_audio = true;
1686 opts.has_video = true;
1687
1688 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1689 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1690 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1691 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1692
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001693 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1694 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 f2_.CreateAnswer(offer.get(), opts, NULL));
1696
1697 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1698 GetFirstAudioContentDescription(
1699 answer.get())->rtp_header_extensions());
1700 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1701 GetFirstVideoContentDescription(
1702 answer.get())->rtp_header_extensions());
1703
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001704 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 f2_.CreateOffer(opts, answer.get()));
1706
1707 // The expected RTP header extensions in the new offer are the resulting
1708 // extensions from the first offer/answer exchange plus the extensions only
1709 // |f2_| offer.
1710 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001711 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1713 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001714 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1715 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001716 };
1717
1718 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001719 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001720 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1721 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001722 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1723 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001724 };
1725
1726 const AudioContentDescription* updated_acd =
1727 GetFirstAudioContentDescription(updated_offer.get());
1728 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1729 updated_acd->rtp_header_extensions());
1730
1731 const VideoContentDescription* updated_vcd =
1732 GetFirstVideoContentDescription(updated_offer.get());
1733 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1734 updated_vcd->rtp_header_extensions());
1735}
1736
1737TEST(MediaSessionDescription, CopySessionDescription) {
1738 SessionDescription source;
1739 cricket::ContentGroup group(cricket::CN_AUDIO);
1740 source.AddGroup(group);
1741 AudioContentDescription* acd(new AudioContentDescription());
1742 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1743 acd->AddLegacyStream(1);
1744 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1745 VideoContentDescription* vcd(new VideoContentDescription());
1746 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1747 vcd->AddLegacyStream(2);
1748 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1749
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001750 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001751 ASSERT_TRUE(copy.get() != NULL);
1752 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1753 const ContentInfo* ac = copy->GetContentByName("audio");
1754 const ContentInfo* vc = copy->GetContentByName("video");
1755 ASSERT_TRUE(ac != NULL);
1756 ASSERT_TRUE(vc != NULL);
1757 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1758 const AudioContentDescription* acd_copy =
1759 static_cast<const AudioContentDescription*>(ac->description);
1760 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1761 EXPECT_EQ(1u, acd->first_ssrc());
1762
1763 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1764 const VideoContentDescription* vcd_copy =
1765 static_cast<const VideoContentDescription*>(vc->description);
1766 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1767 EXPECT_EQ(2u, vcd->first_ssrc());
1768}
1769
1770// The below TestTransportInfoXXX tests create different offers/answers, and
1771// ensure the TransportInfo in the SessionDescription matches what we expect.
1772TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1773 MediaSessionOptions options;
1774 options.has_audio = true;
1775 TestTransportInfo(true, options, false);
1776}
1777
1778TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1779 MediaSessionOptions options;
1780 options.has_audio = true;
1781 TestTransportInfo(true, options, true);
1782}
1783
1784TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1785 MediaSessionOptions options;
1786 options.has_audio = true;
1787 options.has_video = true;
1788 options.data_channel_type = cricket::DCT_RTP;
1789 TestTransportInfo(true, options, false);
1790}
1791
1792TEST_F(MediaSessionDescriptionFactoryTest,
1793 TestTransportInfoOfferMultimediaCurrent) {
1794 MediaSessionOptions options;
1795 options.has_audio = true;
1796 options.has_video = true;
1797 options.data_channel_type = cricket::DCT_RTP;
1798 TestTransportInfo(true, options, true);
1799}
1800
1801TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1802 MediaSessionOptions options;
1803 options.has_audio = true;
1804 options.has_video = true;
1805 options.data_channel_type = cricket::DCT_RTP;
1806 options.bundle_enabled = true;
1807 TestTransportInfo(true, options, false);
1808}
1809
1810TEST_F(MediaSessionDescriptionFactoryTest,
1811 TestTransportInfoOfferBundleCurrent) {
1812 MediaSessionOptions options;
1813 options.has_audio = true;
1814 options.has_video = true;
1815 options.data_channel_type = cricket::DCT_RTP;
1816 options.bundle_enabled = true;
1817 TestTransportInfo(true, options, true);
1818}
1819
1820TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
1821 MediaSessionOptions options;
1822 options.has_audio = true;
1823 TestTransportInfo(false, options, false);
1824}
1825
1826TEST_F(MediaSessionDescriptionFactoryTest,
1827 TestTransportInfoAnswerAudioCurrent) {
1828 MediaSessionOptions options;
1829 options.has_audio = true;
1830 TestTransportInfo(false, options, true);
1831}
1832
1833TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
1834 MediaSessionOptions options;
1835 options.has_audio = true;
1836 options.has_video = true;
1837 options.data_channel_type = cricket::DCT_RTP;
1838 TestTransportInfo(false, options, false);
1839}
1840
1841TEST_F(MediaSessionDescriptionFactoryTest,
1842 TestTransportInfoAnswerMultimediaCurrent) {
1843 MediaSessionOptions options;
1844 options.has_audio = true;
1845 options.has_video = true;
1846 options.data_channel_type = cricket::DCT_RTP;
1847 TestTransportInfo(false, options, true);
1848}
1849
1850TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
1851 MediaSessionOptions options;
1852 options.has_audio = true;
1853 options.has_video = true;
1854 options.data_channel_type = cricket::DCT_RTP;
1855 options.bundle_enabled = true;
1856 TestTransportInfo(false, options, false);
1857}
1858
1859TEST_F(MediaSessionDescriptionFactoryTest,
1860 TestTransportInfoAnswerBundleCurrent) {
1861 MediaSessionOptions options;
1862 options.has_audio = true;
1863 options.has_video = true;
1864 options.data_channel_type = cricket::DCT_RTP;
1865 options.bundle_enabled = true;
1866 TestTransportInfo(false, options, true);
1867}
1868
1869// Create an offer with bundle enabled and verify the crypto parameters are
1870// the common set of the available cryptos.
1871TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
1872 TestCryptoWithBundle(true);
1873}
1874
1875// Create an answer with bundle enabled and verify the crypto parameters are
1876// the common set of the available cryptos.
1877TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
1878 TestCryptoWithBundle(false);
1879}
1880
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001881// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
1882// DTLS is not enabled locally.
1883TEST_F(MediaSessionDescriptionFactoryTest,
1884 TestOfferDtlsSavpfWithoutDtlsFailed) {
1885 f1_.set_secure(SEC_ENABLED);
1886 f2_.set_secure(SEC_ENABLED);
1887 tdf1_.set_secure(SEC_DISABLED);
1888 tdf2_.set_secure(SEC_DISABLED);
1889
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001890 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001891 f1_.CreateOffer(MediaSessionOptions(), NULL));
1892 ASSERT_TRUE(offer.get() != NULL);
1893 ContentInfo* offer_content = offer->GetContentByName("audio");
1894 ASSERT_TRUE(offer_content != NULL);
1895 AudioContentDescription* offer_audio_desc =
1896 static_cast<AudioContentDescription*>(offer_content->description);
1897 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1898
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001899 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001900 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1901 ASSERT_TRUE(answer != NULL);
1902 ContentInfo* answer_content = answer->GetContentByName("audio");
1903 ASSERT_TRUE(answer_content != NULL);
1904
1905 ASSERT_TRUE(answer_content->rejected);
1906}
1907
1908// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
1909// UDP/TLS/RTP/SAVPF.
1910TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
1911 f1_.set_secure(SEC_ENABLED);
1912 f2_.set_secure(SEC_ENABLED);
1913 tdf1_.set_secure(SEC_ENABLED);
1914 tdf2_.set_secure(SEC_ENABLED);
1915
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001916 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001917 f1_.CreateOffer(MediaSessionOptions(), NULL));
1918 ASSERT_TRUE(offer.get() != NULL);
1919 ContentInfo* offer_content = offer->GetContentByName("audio");
1920 ASSERT_TRUE(offer_content != NULL);
1921 AudioContentDescription* offer_audio_desc =
1922 static_cast<AudioContentDescription*>(offer_content->description);
1923 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1924
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001925 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001926 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1927 ASSERT_TRUE(answer != NULL);
1928
1929 const ContentInfo* answer_content = answer->GetContentByName("audio");
1930 ASSERT_TRUE(answer_content != NULL);
1931 ASSERT_FALSE(answer_content->rejected);
1932
1933 const AudioContentDescription* answer_audio_desc =
1934 static_cast<const AudioContentDescription*>(answer_content->description);
1935 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
1936 answer_audio_desc->protocol());
1937}
1938
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001939// Test that we include both SDES and DTLS in the offer, but only include SDES
1940// in the answer if DTLS isn't negotiated.
1941TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
1942 f1_.set_secure(SEC_ENABLED);
1943 f2_.set_secure(SEC_ENABLED);
1944 tdf1_.set_secure(SEC_ENABLED);
1945 tdf2_.set_secure(SEC_DISABLED);
1946 MediaSessionOptions options;
1947 options.has_audio = true;
1948 options.has_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001949 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001950 const cricket::MediaContentDescription* audio_media_desc;
1951 const cricket::MediaContentDescription* video_media_desc;
1952 const cricket::TransportDescription* audio_trans_desc;
1953 const cricket::TransportDescription* video_trans_desc;
1954
1955 // Generate an offer with SDES and DTLS support.
1956 offer.reset(f1_.CreateOffer(options, NULL));
1957 ASSERT_TRUE(offer.get() != NULL);
1958
1959 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1960 offer->GetContentDescriptionByName("audio"));
1961 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001962 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001963 offer->GetContentDescriptionByName("video"));
1964 ASSERT_TRUE(video_media_desc != NULL);
1965 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
1966 EXPECT_EQ(1u, video_media_desc->cryptos().size());
1967
1968 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
1969 ASSERT_TRUE(audio_trans_desc != NULL);
1970 video_trans_desc = offer->GetTransportDescriptionByName("video");
1971 ASSERT_TRUE(video_trans_desc != NULL);
1972 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
1973 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
1974
1975 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
1976 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1977 ASSERT_TRUE(answer.get() != NULL);
1978
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001979 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 answer->GetContentDescriptionByName("audio"));
1981 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001982 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 answer->GetContentDescriptionByName("video"));
1984 ASSERT_TRUE(video_media_desc != NULL);
1985 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
1986 EXPECT_EQ(1u, video_media_desc->cryptos().size());
1987
1988 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
1989 ASSERT_TRUE(audio_trans_desc != NULL);
1990 video_trans_desc = answer->GetTransportDescriptionByName("video");
1991 ASSERT_TRUE(video_trans_desc != NULL);
1992 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
1993 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
1994
1995 // Enable DTLS; the answer should now only have DTLS support.
1996 tdf2_.set_secure(SEC_ENABLED);
1997 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1998 ASSERT_TRUE(answer.get() != NULL);
1999
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002000 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002001 answer->GetContentDescriptionByName("audio"));
2002 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002003 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004 answer->GetContentDescriptionByName("video"));
2005 ASSERT_TRUE(video_media_desc != NULL);
2006 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2007 EXPECT_TRUE(video_media_desc->cryptos().empty());
2008 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2009 audio_media_desc->protocol());
2010 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2011 video_media_desc->protocol());
2012
2013 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2014 ASSERT_TRUE(audio_trans_desc != NULL);
2015 video_trans_desc = answer->GetTransportDescriptionByName("video");
2016 ASSERT_TRUE(video_trans_desc != NULL);
2017 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2018 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002019
2020 // Try creating offer again. DTLS enabled now, crypto's should be empty
2021 // in new offer.
2022 offer.reset(f1_.CreateOffer(options, offer.get()));
2023 ASSERT_TRUE(offer.get() != NULL);
2024 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2025 offer->GetContentDescriptionByName("audio"));
2026 ASSERT_TRUE(audio_media_desc != NULL);
2027 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2028 offer->GetContentDescriptionByName("video"));
2029 ASSERT_TRUE(video_media_desc != NULL);
2030 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2031 EXPECT_TRUE(video_media_desc->cryptos().empty());
2032
2033 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2034 ASSERT_TRUE(audio_trans_desc != NULL);
2035 video_trans_desc = offer->GetTransportDescriptionByName("video");
2036 ASSERT_TRUE(video_trans_desc != NULL);
2037 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2038 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002039}
2040
2041// Test that an answer can't be created if cryptos are required but the offer is
2042// unsecure.
2043TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2044 MediaSessionOptions options;
2045 f1_.set_secure(SEC_DISABLED);
2046 tdf1_.set_secure(SEC_DISABLED);
2047 f2_.set_secure(SEC_REQUIRED);
2048 tdf1_.set_secure(SEC_ENABLED);
2049
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002050 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002051 NULL));
2052 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002053 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002054 f2_.CreateAnswer(offer.get(), options, NULL));
2055 EXPECT_TRUE(answer.get() == NULL);
2056}
2057
2058// Test that we accept a DTLS offer without SDES and create an appropriate
2059// answer.
2060TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2061 f1_.set_secure(SEC_DISABLED);
2062 f2_.set_secure(SEC_ENABLED);
2063 tdf1_.set_secure(SEC_ENABLED);
2064 tdf2_.set_secure(SEC_ENABLED);
2065 MediaSessionOptions options;
2066 options.has_audio = true;
2067 options.has_video = true;
2068 options.data_channel_type = cricket::DCT_RTP;
2069
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002070 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002071
2072 // Generate an offer with DTLS but without SDES.
2073 offer.reset(f1_.CreateOffer(options, NULL));
2074 ASSERT_TRUE(offer.get() != NULL);
2075
2076 const AudioContentDescription* audio_offer =
2077 GetFirstAudioContentDescription(offer.get());
2078 ASSERT_TRUE(audio_offer->cryptos().empty());
2079 const VideoContentDescription* video_offer =
2080 GetFirstVideoContentDescription(offer.get());
2081 ASSERT_TRUE(video_offer->cryptos().empty());
2082 const DataContentDescription* data_offer =
2083 GetFirstDataContentDescription(offer.get());
2084 ASSERT_TRUE(data_offer->cryptos().empty());
2085
2086 const cricket::TransportDescription* audio_offer_trans_desc =
2087 offer->GetTransportDescriptionByName("audio");
2088 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2089 const cricket::TransportDescription* video_offer_trans_desc =
2090 offer->GetTransportDescriptionByName("video");
2091 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2092 const cricket::TransportDescription* data_offer_trans_desc =
2093 offer->GetTransportDescriptionByName("data");
2094 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2095
2096 // Generate an answer with DTLS.
2097 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2098 ASSERT_TRUE(answer.get() != NULL);
2099
2100 const cricket::TransportDescription* audio_answer_trans_desc =
2101 answer->GetTransportDescriptionByName("audio");
2102 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2103 const cricket::TransportDescription* video_answer_trans_desc =
2104 answer->GetTransportDescriptionByName("video");
2105 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2106 const cricket::TransportDescription* data_answer_trans_desc =
2107 answer->GetTransportDescriptionByName("data");
2108 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2109}
2110
2111// Verifies if vad_enabled option is set to false, CN codecs are not present in
2112// offer or answer.
2113TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2114 MediaSessionOptions options;
2115 options.has_audio = true;
2116 options.has_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002117 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002118 f1_.CreateOffer(options, NULL));
2119 ASSERT_TRUE(offer.get() != NULL);
2120 const ContentInfo* audio_content = offer->GetContentByName("audio");
2121 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2122
2123 options.vad_enabled = false;
2124 offer.reset(f1_.CreateOffer(options, NULL));
2125 ASSERT_TRUE(offer.get() != NULL);
2126 audio_content = offer->GetContentByName("audio");
2127 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002128 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002129 f1_.CreateAnswer(offer.get(), options, NULL));
2130 ASSERT_TRUE(answer.get() != NULL);
2131 audio_content = answer->GetContentByName("audio");
2132 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2133}