blob: ededa8a680df5cef86845d56b5c3eee18255b223 [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
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031#include "talk/media/base/codec.h"
32#include "talk/media/base/testutils.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033#include "webrtc/p2p/base/constants.h"
34#include "webrtc/p2p/base/transportdescription.h"
35#include "webrtc/p2p/base/transportinfo.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036#include "talk/session/media/mediasession.h"
37#include "talk/session/media/srtpfilter.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000038#include "webrtc/base/fakesslidentity.h"
39#include "webrtc/base/gunit.h"
40#include "webrtc/base/messagedigest.h"
41#include "webrtc/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042
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
deadbeefa5b273a2015-08-20 17:30:13 -0700150static const RtpHeaderExtension kAudioRtpExtension3[] = {
151 RtpHeaderExtension("http://google.com/testing/audio_something", 2),
152 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 3),
153};
154
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
156 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
157};
158
159static const RtpHeaderExtension kVideoRtpExtension1[] = {
160 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000161 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000162};
163
164static const RtpHeaderExtension kVideoRtpExtension2[] = {
165 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
166 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000167 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000168};
169
deadbeefa5b273a2015-08-20 17:30:13 -0700170static const RtpHeaderExtension kVideoRtpExtension3[] = {
171 RtpHeaderExtension("http://google.com/testing/video_something", 4),
172 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 5),
173};
174
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
176 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
177};
178
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000179static const uint32 kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
180static const uint32 kSimSsrc[] = {10, 20, 30};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000181static const uint32 kFec1Ssrc[] = {10, 11};
182static const uint32 kFec2Ssrc[] = {20, 21};
183static const uint32 kFec3Ssrc[] = {30, 31};
184
185static const char kMediaStream1[] = "stream_1";
186static const char kMediaStream2[] = "stream_2";
187static const char kVideoTrack1[] = "video_1";
188static const char kVideoTrack2[] = "video_2";
189static const char kAudioTrack1[] = "audio_1";
190static const char kAudioTrack2[] = "audio_2";
191static const char kAudioTrack3[] = "audio_3";
192static const char kDataTrack1[] = "data_1";
193static const char kDataTrack2[] = "data_2";
194static const char kDataTrack3[] = "data_3";
195
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000196static bool IsMediaContentOfType(const ContentInfo* content,
197 MediaType media_type) {
198 const MediaContentDescription* mdesc =
199 static_cast<const MediaContentDescription*>(content->description);
200 return mdesc && mdesc->type() == media_type;
201}
202
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000203static cricket::MediaContentDirection
204GetMediaDirection(const ContentInfo* content) {
205 cricket::MediaContentDescription* desc =
206 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
207 return desc->direction();
208}
209
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000210static void AddRtxCodec(const VideoCodec& rtx_codec,
211 std::vector<VideoCodec>* codecs) {
212 VideoCodec rtx;
213 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
214 codecs->push_back(rtx_codec);
215}
216
217template <class T>
218static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
219 std::vector<std::string> codec_names;
220 for (const auto& codec : codecs) {
221 codec_names.push_back(codec.name);
222 }
223 return codec_names;
224}
225
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226class MediaSessionDescriptionFactoryTest : public testing::Test {
227 public:
228 MediaSessionDescriptionFactoryTest()
229 : f1_(&tdf1_), f2_(&tdf2_), id1_("id1"), id2_("id2") {
230 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
231 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
232 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
233 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
234 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
235 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
236 tdf1_.set_identity(&id1_);
237 tdf2_.set_identity(&id2_);
238 }
239
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000240 // Create a video StreamParamsVec object with:
241 // - one video stream with 3 simulcast streams and FEC,
242 StreamParamsVec CreateComplexVideoStreamParamsVec() {
243 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
244 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
245 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
246 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
247
248 std::vector<SsrcGroup> ssrc_groups;
249 ssrc_groups.push_back(sim_group);
250 ssrc_groups.push_back(fec_group1);
251 ssrc_groups.push_back(fec_group2);
252 ssrc_groups.push_back(fec_group3);
253
254 StreamParams simulcast_params;
255 simulcast_params.id = kVideoTrack1;
256 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
257 simulcast_params.ssrc_groups = ssrc_groups;
258 simulcast_params.cname = "Video_SIM_FEC";
259 simulcast_params.sync_label = kMediaStream1;
260
261 StreamParamsVec video_streams;
262 video_streams.push_back(simulcast_params);
263
264 return video_streams;
265 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000266
267 bool CompareCryptoParams(const CryptoParamsVec& c1,
268 const CryptoParamsVec& c2) {
269 if (c1.size() != c2.size())
270 return false;
271 for (size_t i = 0; i < c1.size(); ++i)
272 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
273 c1[i].key_params != c2[i].key_params ||
274 c1[i].session_params != c2[i].session_params)
275 return false;
276 return true;
277 }
278
279 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
280 bool has_current_desc) {
281 const std::string current_audio_ufrag = "current_audio_ufrag";
282 const std::string current_audio_pwd = "current_audio_pwd";
283 const std::string current_video_ufrag = "current_video_ufrag";
284 const std::string current_video_pwd = "current_video_pwd";
285 const std::string current_data_ufrag = "current_data_ufrag";
286 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000287 rtc::scoped_ptr<SessionDescription> current_desc;
288 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 if (has_current_desc) {
290 current_desc.reset(new SessionDescription());
291 EXPECT_TRUE(current_desc->AddTransportInfo(
292 TransportInfo("audio",
Peter Thatcher081f34b2015-08-19 20:37:54 -0700293 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000294 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295 EXPECT_TRUE(current_desc->AddTransportInfo(
296 TransportInfo("video",
Peter Thatcher081f34b2015-08-19 20:37:54 -0700297 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000298 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000299 EXPECT_TRUE(current_desc->AddTransportInfo(
300 TransportInfo("data",
Peter Thatcher081f34b2015-08-19 20:37:54 -0700301 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000302 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000303 }
304 if (offer) {
305 desc.reset(f1_.CreateOffer(options, current_desc.get()));
306 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000307 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000308 offer.reset(f1_.CreateOffer(options, NULL));
309 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
310 }
311 ASSERT_TRUE(desc.get() != NULL);
312 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000313 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 EXPECT_TRUE(ti_audio != NULL);
315 if (has_current_desc) {
316 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
317 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
318 } else {
319 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
320 ti_audio->description.ice_ufrag.size());
321 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
322 ti_audio->description.ice_pwd.size());
323 }
324
325 } else {
326 EXPECT_TRUE(ti_audio == NULL);
327 }
328 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000329 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000330 EXPECT_TRUE(ti_video != NULL);
331 if (options.bundle_enabled) {
332 EXPECT_EQ(ti_audio->description.ice_ufrag,
333 ti_video->description.ice_ufrag);
334 EXPECT_EQ(ti_audio->description.ice_pwd,
335 ti_video->description.ice_pwd);
336 } else {
337 if (has_current_desc) {
338 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
339 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
340 } else {
341 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
342 ti_video->description.ice_ufrag.size());
343 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
344 ti_video->description.ice_pwd.size());
345 }
346 }
347 } else {
348 EXPECT_TRUE(ti_video == NULL);
349 }
350 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
351 if (options.has_data()) {
352 EXPECT_TRUE(ti_data != NULL);
353 if (options.bundle_enabled) {
354 EXPECT_EQ(ti_audio->description.ice_ufrag,
355 ti_data->description.ice_ufrag);
356 EXPECT_EQ(ti_audio->description.ice_pwd,
357 ti_data->description.ice_pwd);
358 } else {
359 if (has_current_desc) {
360 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
361 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
362 } else {
363 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
364 ti_data->description.ice_ufrag.size());
365 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
366 ti_data->description.ice_pwd.size());
367 }
368 }
369 } else {
370 EXPECT_TRUE(ti_video == NULL);
371 }
372 }
373
374 void TestCryptoWithBundle(bool offer) {
375 f1_.set_secure(SEC_ENABLED);
376 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000377 options.recv_audio = true;
378 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000379 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000380 rtc::scoped_ptr<SessionDescription> ref_desc;
381 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000382 if (offer) {
383 options.bundle_enabled = false;
384 ref_desc.reset(f1_.CreateOffer(options, NULL));
385 options.bundle_enabled = true;
386 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
387 } else {
388 options.bundle_enabled = true;
389 ref_desc.reset(f1_.CreateOffer(options, NULL));
390 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
391 }
392 ASSERT_TRUE(desc.get() != NULL);
393 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000394 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000395 desc.get()->GetContentDescriptionByName("audio"));
396 ASSERT_TRUE(audio_media_desc != NULL);
397 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000398 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000399 desc.get()->GetContentDescriptionByName("video"));
400 ASSERT_TRUE(video_media_desc != NULL);
401 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
402 video_media_desc->cryptos()));
403 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
404 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
405 audio_media_desc->cryptos()[0].cipher_suite);
406
407 // Verify the selected crypto is one from the reference audio
408 // media content.
409 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000410 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000411 ref_desc.get()->GetContentDescriptionByName("audio"));
412 bool found = false;
413 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
414 if (ref_audio_media_desc->cryptos()[i].Matches(
415 audio_media_desc->cryptos()[0])) {
416 found = true;
417 break;
418 }
419 }
420 EXPECT_TRUE(found);
421 }
422
423 // This test that the audio and video media direction is set to
424 // |expected_direction_in_answer| in an answer if the offer direction is set
425 // to |direction_in_offer|.
426 void TestMediaDirectionInAnswer(
427 cricket::MediaContentDirection direction_in_offer,
428 cricket::MediaContentDirection expected_direction_in_answer) {
429 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000430 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000431 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000432 f1_.CreateOffer(opts, NULL));
433 ASSERT_TRUE(offer.get() != NULL);
434 ContentInfo* ac_offer= offer->GetContentByName("audio");
435 ASSERT_TRUE(ac_offer != NULL);
436 AudioContentDescription* acd_offer =
437 static_cast<AudioContentDescription*>(ac_offer->description);
438 acd_offer->set_direction(direction_in_offer);
439 ContentInfo* vc_offer= offer->GetContentByName("video");
440 ASSERT_TRUE(vc_offer != NULL);
441 VideoContentDescription* vcd_offer =
442 static_cast<VideoContentDescription*>(vc_offer->description);
443 vcd_offer->set_direction(direction_in_offer);
444
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000445 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 f2_.CreateAnswer(offer.get(), opts, NULL));
447 const AudioContentDescription* acd_answer =
448 GetFirstAudioContentDescription(answer.get());
449 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
450 const VideoContentDescription* vcd_answer =
451 GetFirstVideoContentDescription(answer.get());
452 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
453 }
454
455 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
456 const cricket::ContentDescription* description = content->description;
457 ASSERT(description != NULL);
458 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000459 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000460 ASSERT(audio_content_desc != NULL);
461 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
462 if (audio_content_desc->codecs()[i].name == "CN")
463 return false;
464 }
465 return true;
466 }
467
468 protected:
469 MediaSessionDescriptionFactory f1_;
470 MediaSessionDescriptionFactory f2_;
471 TransportDescriptionFactory tdf1_;
472 TransportDescriptionFactory tdf2_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000473 rtc::FakeSSLIdentity id1_;
474 rtc::FakeSSLIdentity id2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000475};
476
477// Create a typical audio offer, and ensure it matches what we expect.
478TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
479 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000480 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000481 f1_.CreateOffer(MediaSessionOptions(), NULL));
482 ASSERT_TRUE(offer.get() != NULL);
483 const ContentInfo* ac = offer->GetContentByName("audio");
484 const ContentInfo* vc = offer->GetContentByName("video");
485 ASSERT_TRUE(ac != NULL);
486 ASSERT_TRUE(vc == NULL);
487 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
488 const AudioContentDescription* acd =
489 static_cast<const AudioContentDescription*>(ac->description);
490 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
491 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
492 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
493 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
494 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
495 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
496 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
497}
498
499// Create a typical video offer, and ensure it matches what we expect.
500TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
501 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000502 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000503 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000504 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000505 offer(f1_.CreateOffer(opts, NULL));
506 ASSERT_TRUE(offer.get() != NULL);
507 const ContentInfo* ac = offer->GetContentByName("audio");
508 const ContentInfo* vc = offer->GetContentByName("video");
509 ASSERT_TRUE(ac != NULL);
510 ASSERT_TRUE(vc != NULL);
511 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
512 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
513 const AudioContentDescription* acd =
514 static_cast<const AudioContentDescription*>(ac->description);
515 const VideoContentDescription* vcd =
516 static_cast<const VideoContentDescription*>(vc->description);
517 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
518 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
519 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
520 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
521 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
522 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
523 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
524 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
525 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
526 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
527 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
528 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
529 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
530 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
531}
532
533// Test creating an offer with bundle where the Codecs have the same dynamic
534// RTP playlod type. The test verifies that the offer don't contain the
535// duplicate RTP payload types.
536TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
537 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
538 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
539 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
540 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
541 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
542
543 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000544 opts.recv_audio = true;
545 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000546 opts.data_channel_type = cricket::DCT_RTP;
547 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000548 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 offer(f2_.CreateOffer(opts, NULL));
550 const VideoContentDescription* vcd =
551 GetFirstVideoContentDescription(offer.get());
552 const AudioContentDescription* acd =
553 GetFirstAudioContentDescription(offer.get());
554 const DataContentDescription* dcd =
555 GetFirstDataContentDescription(offer.get());
556 ASSERT_TRUE(NULL != vcd);
557 ASSERT_TRUE(NULL != acd);
558 ASSERT_TRUE(NULL != dcd);
559 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
560 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
561 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
562 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
563 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
564 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
565}
566
567// Test creating an updated offer with with bundle, audio, video and data
568// after an audio only session has been negotiated.
569TEST_F(MediaSessionDescriptionFactoryTest,
570 TestCreateUpdatedVideoOfferWithBundle) {
571 f1_.set_secure(SEC_ENABLED);
572 f2_.set_secure(SEC_ENABLED);
573 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000574 opts.recv_audio = true;
575 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000576 opts.data_channel_type = cricket::DCT_NONE;
577 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000578 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
579 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580 f2_.CreateAnswer(offer.get(), opts, NULL));
581
582 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000583 updated_opts.recv_audio = true;
584 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000585 updated_opts.data_channel_type = cricket::DCT_RTP;
586 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000587 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000588 updated_opts, answer.get()));
589
590 const AudioContentDescription* acd =
591 GetFirstAudioContentDescription(updated_offer.get());
592 const VideoContentDescription* vcd =
593 GetFirstVideoContentDescription(updated_offer.get());
594 const DataContentDescription* dcd =
595 GetFirstDataContentDescription(updated_offer.get());
596 EXPECT_TRUE(NULL != vcd);
597 EXPECT_TRUE(NULL != acd);
598 EXPECT_TRUE(NULL != dcd);
599
600 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
601 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
602 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
603 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
604 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
605 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
606}
wu@webrtc.org78187522013-10-07 23:32:02 +0000607// Create a RTP data offer, and ensure it matches what we expect.
608TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000609 MediaSessionOptions opts;
610 opts.data_channel_type = cricket::DCT_RTP;
611 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000612 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000613 offer(f1_.CreateOffer(opts, NULL));
614 ASSERT_TRUE(offer.get() != NULL);
615 const ContentInfo* ac = offer->GetContentByName("audio");
616 const ContentInfo* dc = offer->GetContentByName("data");
617 ASSERT_TRUE(ac != NULL);
618 ASSERT_TRUE(dc != NULL);
619 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
620 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
621 const AudioContentDescription* acd =
622 static_cast<const AudioContentDescription*>(ac->description);
623 const DataContentDescription* dcd =
624 static_cast<const DataContentDescription*>(dc->description);
625 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
626 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
627 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
628 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
629 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
630 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
631 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
632 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
633 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
634 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
635 EXPECT_EQ(cricket::kDataMaxBandwidth,
636 dcd->bandwidth()); // default bandwidth (auto)
637 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
638 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
639 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
640}
641
wu@webrtc.org78187522013-10-07 23:32:02 +0000642// Create an SCTP data offer with bundle without error.
643TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
644 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000645 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000646 opts.bundle_enabled = true;
647 opts.data_channel_type = cricket::DCT_SCTP;
648 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000649 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000650 EXPECT_TRUE(offer.get() != NULL);
651 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
652}
653
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000654// Test creating an sctp data channel from an already generated offer.
655TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
656 MediaSessionOptions opts;
657 opts.recv_audio = false;
658 opts.bundle_enabled = true;
659 opts.data_channel_type = cricket::DCT_SCTP;
660 f1_.set_secure(SEC_ENABLED);
661 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
662 ASSERT_TRUE(offer1.get() != NULL);
663 const ContentInfo* data = offer1->GetContentByName("data");
664 ASSERT_TRUE(data != NULL);
665 const MediaContentDescription* mdesc =
666 static_cast<const MediaContentDescription*>(data->description);
667 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
668
669 // Now set data_channel_type to 'none' (default) and make sure that the
670 // datachannel type that gets generated from the previous offer, is of the
671 // same type.
672 opts.data_channel_type = cricket::DCT_NONE;
673 rtc::scoped_ptr<SessionDescription> offer2(
674 f1_.CreateOffer(opts, offer1.get()));
675 data = offer2->GetContentByName("data");
676 ASSERT_TRUE(data != NULL);
677 mdesc = static_cast<const MediaContentDescription*>(data->description);
678 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
679}
680
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681// Create an audio, video offer without legacy StreamParams.
682TEST_F(MediaSessionDescriptionFactoryTest,
683 TestCreateOfferWithoutLegacyStreams) {
684 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000685 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000686 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000687 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688 offer(f1_.CreateOffer(opts, NULL));
689 ASSERT_TRUE(offer.get() != NULL);
690 const ContentInfo* ac = offer->GetContentByName("audio");
691 const ContentInfo* vc = offer->GetContentByName("video");
692 ASSERT_TRUE(ac != NULL);
693 ASSERT_TRUE(vc != NULL);
694 const AudioContentDescription* acd =
695 static_cast<const AudioContentDescription*>(ac->description);
696 const VideoContentDescription* vcd =
697 static_cast<const VideoContentDescription*>(vc->description);
698
699 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
700 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
701}
702
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000703// Creates an audio+video sendonly offer.
704TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
705 MediaSessionOptions options;
706 options.recv_audio = false;
707 options.recv_video = false;
708 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
709 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
710
711 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
712 ASSERT_TRUE(offer.get() != NULL);
713 EXPECT_EQ(2u, offer->contents().size());
714 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
715 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
716
717 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
718 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
719}
720
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000721// Verifies that the order of the media contents in the current
722// SessionDescription is preserved in the new SessionDescription.
723TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
724 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000725 opts.recv_audio = false;
726 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000727 opts.data_channel_type = cricket::DCT_SCTP;
728
729 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
730 ASSERT_TRUE(offer1.get() != NULL);
731 EXPECT_EQ(1u, offer1->contents().size());
732 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
733
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000734 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000735 rtc::scoped_ptr<SessionDescription> offer2(
736 f1_.CreateOffer(opts, offer1.get()));
737 ASSERT_TRUE(offer2.get() != NULL);
738 EXPECT_EQ(2u, offer2->contents().size());
739 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
740 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
741
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000742 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000743 rtc::scoped_ptr<SessionDescription> offer3(
744 f1_.CreateOffer(opts, offer2.get()));
745 ASSERT_TRUE(offer3.get() != NULL);
746 EXPECT_EQ(3u, offer3->contents().size());
747 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
748 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
749 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
750
751 // Verifies the default order is audio-video-data, so that the previous checks
752 // didn't pass by accident.
753 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
754 ASSERT_TRUE(offer4.get() != NULL);
755 EXPECT_EQ(3u, offer4->contents().size());
756 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
757 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
758 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
759}
760
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000761// Create a typical audio answer, and ensure it matches what we expect.
762TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
763 f1_.set_secure(SEC_ENABLED);
764 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000765 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000766 f1_.CreateOffer(MediaSessionOptions(), NULL));
767 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000768 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
770 const ContentInfo* ac = answer->GetContentByName("audio");
771 const ContentInfo* vc = answer->GetContentByName("video");
772 ASSERT_TRUE(ac != NULL);
773 ASSERT_TRUE(vc == NULL);
774 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
775 const AudioContentDescription* acd =
776 static_cast<const AudioContentDescription*>(ac->description);
777 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
778 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
779 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
780 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
781 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
782 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
783 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
784}
785
786// Create a typical video answer, and ensure it matches what we expect.
787TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
788 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000789 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000790 f1_.set_secure(SEC_ENABLED);
791 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000792 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000794 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000795 f2_.CreateAnswer(offer.get(), opts, NULL));
796 const ContentInfo* ac = answer->GetContentByName("audio");
797 const ContentInfo* vc = answer->GetContentByName("video");
798 ASSERT_TRUE(ac != NULL);
799 ASSERT_TRUE(vc != NULL);
800 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
801 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
802 const AudioContentDescription* acd =
803 static_cast<const AudioContentDescription*>(ac->description);
804 const VideoContentDescription* vcd =
805 static_cast<const VideoContentDescription*>(vc->description);
806 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
807 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
808 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
809 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
810 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
811 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
812 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
813 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
814 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
815 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
816 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
817 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
818}
819
820TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
821 MediaSessionOptions opts;
822 opts.data_channel_type = cricket::DCT_RTP;
823 f1_.set_secure(SEC_ENABLED);
824 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000825 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000826 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000827 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000828 f2_.CreateAnswer(offer.get(), opts, NULL));
829 const ContentInfo* ac = answer->GetContentByName("audio");
830 const ContentInfo* vc = answer->GetContentByName("data");
831 ASSERT_TRUE(ac != NULL);
832 ASSERT_TRUE(vc != NULL);
833 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
834 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
835 const AudioContentDescription* acd =
836 static_cast<const AudioContentDescription*>(ac->description);
837 const DataContentDescription* vcd =
838 static_cast<const DataContentDescription*>(vc->description);
839 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
840 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
841 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
842 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
843 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
844 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
845 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
846 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
847 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
848 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
849 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
850 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
851}
852
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000853// Verifies that the order of the media contents in the offer is preserved in
854// the answer.
855TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
856 MediaSessionOptions opts;
857
858 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000859 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000860 opts.data_channel_type = cricket::DCT_SCTP;
861 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
862 ASSERT_TRUE(offer1.get() != NULL);
863
864 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000865 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000866 rtc::scoped_ptr<SessionDescription> offer2(
867 f1_.CreateOffer(opts, offer1.get()));
868 ASSERT_TRUE(offer2.get() != NULL);
869
870 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000871 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000872 rtc::scoped_ptr<SessionDescription> offer3(
873 f1_.CreateOffer(opts, offer2.get()));
874 ASSERT_TRUE(offer3.get() != NULL);
875
876 rtc::scoped_ptr<SessionDescription> answer(
877 f2_.CreateAnswer(offer3.get(), opts, NULL));
878 ASSERT_TRUE(answer.get() != NULL);
879 EXPECT_EQ(3u, answer->contents().size());
880 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
881 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
882 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
883}
884
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000885// This test that the media direction is set to send/receive in an answer if
886// the offer is send receive.
887TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
888 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
889}
890
891// This test that the media direction is set to receive only in an answer if
892// the offer is send only.
893TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
894 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
895}
896
897// This test that the media direction is set to send only in an answer if
898// the offer is recv only.
899TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
900 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
901}
902
903// This test that the media direction is set to inactive in an answer if
904// the offer is inactive.
905TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
906 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
907}
908
909// Test that a data content with an unknown protocol is rejected in an answer.
910TEST_F(MediaSessionDescriptionFactoryTest,
911 CreateDataAnswerToOfferWithUnknownProtocol) {
912 MediaSessionOptions opts;
913 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000914 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915 f1_.set_secure(SEC_ENABLED);
916 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000917 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000918 ContentInfo* dc_offer= offer->GetContentByName("data");
919 ASSERT_TRUE(dc_offer != NULL);
920 DataContentDescription* dcd_offer =
921 static_cast<DataContentDescription*>(dc_offer->description);
922 ASSERT_TRUE(dcd_offer != NULL);
923 std::string protocol = "a weird unknown protocol";
924 dcd_offer->set_protocol(protocol);
925
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000926 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000927 f2_.CreateAnswer(offer.get(), opts, NULL));
928
929 const ContentInfo* dc_answer = answer->GetContentByName("data");
930 ASSERT_TRUE(dc_answer != NULL);
931 EXPECT_TRUE(dc_answer->rejected);
932 const DataContentDescription* dcd_answer =
933 static_cast<const DataContentDescription*>(dc_answer->description);
934 ASSERT_TRUE(dcd_answer != NULL);
935 EXPECT_EQ(protocol, dcd_answer->protocol());
936}
937
938// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
939TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
940 MediaSessionOptions opts;
941 f1_.set_secure(SEC_DISABLED);
942 f2_.set_secure(SEC_DISABLED);
943 tdf1_.set_secure(SEC_DISABLED);
944 tdf2_.set_secure(SEC_DISABLED);
945
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000946 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000947 const AudioContentDescription* offer_acd =
948 GetFirstAudioContentDescription(offer.get());
949 ASSERT_TRUE(offer_acd != NULL);
950 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
951
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000952 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000953 f2_.CreateAnswer(offer.get(), opts, NULL));
954
955 const ContentInfo* ac_answer = answer->GetContentByName("audio");
956 ASSERT_TRUE(ac_answer != NULL);
957 EXPECT_FALSE(ac_answer->rejected);
958
959 const AudioContentDescription* answer_acd =
960 GetFirstAudioContentDescription(answer.get());
961 ASSERT_TRUE(answer_acd != NULL);
962 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
963}
964
965// Create a video offer and answer and ensure the RTP header extensions
966// matches what we expect.
967TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
968 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000969 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000970
971 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
972 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
973 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
974 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
975
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000976 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000977 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000978 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000979 f2_.CreateAnswer(offer.get(), opts, NULL));
980
981 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
982 GetFirstAudioContentDescription(
983 offer.get())->rtp_header_extensions());
984 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
985 GetFirstVideoContentDescription(
986 offer.get())->rtp_header_extensions());
987 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
988 GetFirstAudioContentDescription(
989 answer.get())->rtp_header_extensions());
990 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
991 GetFirstVideoContentDescription(
992 answer.get())->rtp_header_extensions());
993}
994
995// Create an audio, video, data answer without legacy StreamParams.
996TEST_F(MediaSessionDescriptionFactoryTest,
997 TestCreateAnswerWithoutLegacyStreams) {
998 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000999 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001000 opts.data_channel_type = cricket::DCT_RTP;
1001 f1_.set_add_legacy_streams(false);
1002 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001003 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001004 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001005 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001006 f2_.CreateAnswer(offer.get(), opts, NULL));
1007 const ContentInfo* ac = answer->GetContentByName("audio");
1008 const ContentInfo* vc = answer->GetContentByName("video");
1009 const ContentInfo* dc = answer->GetContentByName("data");
1010 ASSERT_TRUE(ac != NULL);
1011 ASSERT_TRUE(vc != NULL);
1012 const AudioContentDescription* acd =
1013 static_cast<const AudioContentDescription*>(ac->description);
1014 const VideoContentDescription* vcd =
1015 static_cast<const VideoContentDescription*>(vc->description);
1016 const DataContentDescription* dcd =
1017 static_cast<const DataContentDescription*>(dc->description);
1018
1019 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1020 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1021 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1022}
1023
1024TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1025 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001026 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001027 opts.data_channel_type = cricket::DCT_RTP;
1028 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001029 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001030 offer(f1_.CreateOffer(opts, NULL));
1031 ASSERT_TRUE(offer.get() != NULL);
1032 const ContentInfo* ac = offer->GetContentByName("audio");
1033 const ContentInfo* vc = offer->GetContentByName("video");
1034 const ContentInfo* dc = offer->GetContentByName("data");
1035 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1036 static_cast<const AudioContentDescription*>(ac->description));
1037 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1038 static_cast<const VideoContentDescription*>(vc->description));
1039 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1040 static_cast<const DataContentDescription*>(dc->description));
1041
1042 EXPECT_FALSE(acd->partial()); // default is false.
1043 acd->set_partial(true);
1044 EXPECT_TRUE(acd->partial());
1045 acd->set_partial(false);
1046 EXPECT_FALSE(acd->partial());
1047
1048 EXPECT_FALSE(vcd->partial()); // default is false.
1049 vcd->set_partial(true);
1050 EXPECT_TRUE(vcd->partial());
1051 vcd->set_partial(false);
1052 EXPECT_FALSE(vcd->partial());
1053
1054 EXPECT_FALSE(dcd->partial()); // default is false.
1055 dcd->set_partial(true);
1056 EXPECT_TRUE(dcd->partial());
1057 dcd->set_partial(false);
1058 EXPECT_FALSE(dcd->partial());
1059}
1060
1061// Create a typical video answer, and ensure it matches what we expect.
1062TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1063 MediaSessionOptions offer_opts;
1064 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001065 answer_opts.recv_video = true;
1066 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001067 answer_opts.data_channel_type = cricket::DCT_RTP;
1068 offer_opts.data_channel_type = cricket::DCT_RTP;
1069
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001070 rtc::scoped_ptr<SessionDescription> offer;
1071 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001072
1073 offer_opts.rtcp_mux_enabled = true;
1074 answer_opts.rtcp_mux_enabled = true;
1075
1076 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1077 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1078 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1079 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1080 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1081 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1082 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1083 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1084 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1085 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1086 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1087 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1088 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1089 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1090
1091 offer_opts.rtcp_mux_enabled = true;
1092 answer_opts.rtcp_mux_enabled = false;
1093
1094 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1095 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1096 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1097 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1098 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1099 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1100 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1101 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1102 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1103 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1104 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1105 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1106 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1107 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1108
1109 offer_opts.rtcp_mux_enabled = false;
1110 answer_opts.rtcp_mux_enabled = true;
1111
1112 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1113 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1114 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1115 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1116 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1117 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1118 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1119 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1120 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1121 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1122 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1123 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1124 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1125 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1126
1127 offer_opts.rtcp_mux_enabled = false;
1128 answer_opts.rtcp_mux_enabled = false;
1129
1130 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1131 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1132 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1133 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1134 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1135 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1136 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1137 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1138 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1139 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1140 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1141 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1142 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1143 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1144}
1145
1146// Create an audio-only answer to a video offer.
1147TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1148 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001149 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001150 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 offer(f1_.CreateOffer(opts, NULL));
1152 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001153 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1155 const ContentInfo* ac = answer->GetContentByName("audio");
1156 const ContentInfo* vc = answer->GetContentByName("video");
1157 ASSERT_TRUE(ac != NULL);
1158 ASSERT_TRUE(vc != NULL);
1159 ASSERT_TRUE(vc->description != NULL);
1160 EXPECT_TRUE(vc->rejected);
1161}
1162
1163// Create an audio-only answer to an offer with data.
1164TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1165 MediaSessionOptions opts;
1166 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001167 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001168 offer(f1_.CreateOffer(opts, NULL));
1169 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001170 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001171 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1172 const ContentInfo* ac = answer->GetContentByName("audio");
1173 const ContentInfo* dc = answer->GetContentByName("data");
1174 ASSERT_TRUE(ac != NULL);
1175 ASSERT_TRUE(dc != NULL);
1176 ASSERT_TRUE(dc->description != NULL);
1177 EXPECT_TRUE(dc->rejected);
1178}
1179
1180// Create an answer that rejects the contents which are rejected in the offer.
1181TEST_F(MediaSessionDescriptionFactoryTest,
1182 CreateAnswerToOfferWithRejectedMedia) {
1183 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001184 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001186 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001187 offer(f1_.CreateOffer(opts, NULL));
1188 ASSERT_TRUE(offer.get() != NULL);
1189 ContentInfo* ac = offer->GetContentByName("audio");
1190 ContentInfo* vc = offer->GetContentByName("video");
1191 ContentInfo* dc = offer->GetContentByName("data");
1192 ASSERT_TRUE(ac != NULL);
1193 ASSERT_TRUE(vc != NULL);
1194 ASSERT_TRUE(dc != NULL);
1195 ac->rejected = true;
1196 vc->rejected = true;
1197 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001198 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001199 f2_.CreateAnswer(offer.get(), opts, NULL));
1200 ac = answer->GetContentByName("audio");
1201 vc = answer->GetContentByName("video");
1202 dc = answer->GetContentByName("data");
1203 ASSERT_TRUE(ac != NULL);
1204 ASSERT_TRUE(vc != NULL);
1205 ASSERT_TRUE(dc != NULL);
1206 EXPECT_TRUE(ac->rejected);
1207 EXPECT_TRUE(vc->rejected);
1208 EXPECT_TRUE(dc->rejected);
1209}
1210
1211// Create an audio and video offer with:
1212// - one video track
1213// - two audio tracks
1214// - two data tracks
1215// and ensure it matches what we expect. Also updates the initial offer by
1216// adding a new video track and replaces one of the audio tracks.
1217TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1218 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001219 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1220 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1221 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001222 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001223 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1224 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001225
1226 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001227 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001228
1229 ASSERT_TRUE(offer.get() != NULL);
1230 const ContentInfo* ac = offer->GetContentByName("audio");
1231 const ContentInfo* vc = offer->GetContentByName("video");
1232 const ContentInfo* dc = offer->GetContentByName("data");
1233 ASSERT_TRUE(ac != NULL);
1234 ASSERT_TRUE(vc != NULL);
1235 ASSERT_TRUE(dc != NULL);
1236 const AudioContentDescription* acd =
1237 static_cast<const AudioContentDescription*>(ac->description);
1238 const VideoContentDescription* vcd =
1239 static_cast<const VideoContentDescription*>(vc->description);
1240 const DataContentDescription* dcd =
1241 static_cast<const DataContentDescription*>(dc->description);
1242 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1243 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1244
1245 const StreamParamsVec& audio_streams = acd->streams();
1246 ASSERT_EQ(2U, audio_streams.size());
1247 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1248 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1249 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1250 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1251 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1252 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1253 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1254
1255 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1256 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1257 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1258
1259 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1260 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1261 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1262
1263 const StreamParamsVec& video_streams = vcd->streams();
1264 ASSERT_EQ(1U, video_streams.size());
1265 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1266 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1267 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1268 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1269
1270 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1271 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1272 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1273
1274 const StreamParamsVec& data_streams = dcd->streams();
1275 ASSERT_EQ(2U, data_streams.size());
1276 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1277 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1278 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1279 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1280 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1281 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1282 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1283
1284 EXPECT_EQ(cricket::kDataMaxBandwidth,
1285 dcd->bandwidth()); // default bandwidth (auto)
1286 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1287 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1288
1289
1290 // Update the offer. Add a new video track that is not synched to the
1291 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001292 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1293 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1294 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1295 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1296 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001297 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001298 updated_offer(f1_.CreateOffer(opts, offer.get()));
1299
1300 ASSERT_TRUE(updated_offer.get() != NULL);
1301 ac = updated_offer->GetContentByName("audio");
1302 vc = updated_offer->GetContentByName("video");
1303 dc = updated_offer->GetContentByName("data");
1304 ASSERT_TRUE(ac != NULL);
1305 ASSERT_TRUE(vc != NULL);
1306 ASSERT_TRUE(dc != NULL);
1307 const AudioContentDescription* updated_acd =
1308 static_cast<const AudioContentDescription*>(ac->description);
1309 const VideoContentDescription* updated_vcd =
1310 static_cast<const VideoContentDescription*>(vc->description);
1311 const DataContentDescription* updated_dcd =
1312 static_cast<const DataContentDescription*>(dc->description);
1313
1314 EXPECT_EQ(acd->type(), updated_acd->type());
1315 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1316 EXPECT_EQ(vcd->type(), updated_vcd->type());
1317 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1318 EXPECT_EQ(dcd->type(), updated_dcd->type());
1319 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1320 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1321 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1322 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1323 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1324 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1325 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1326
1327 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1328 ASSERT_EQ(2U, updated_audio_streams.size());
1329 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1330 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1331 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1332 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1333 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1334
1335 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1336 ASSERT_EQ(2U, updated_video_streams.size());
1337 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1338 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1339 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1340
1341 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1342 ASSERT_EQ(2U, updated_data_streams.size());
1343 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1344 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1345 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1346 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1347 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1348}
1349
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001350// Create an offer with simulcast video stream.
1351TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1352 MediaSessionOptions opts;
1353 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001354 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001355 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001356
1357 ASSERT_TRUE(offer.get() != NULL);
1358 const ContentInfo* vc = offer->GetContentByName("video");
1359 ASSERT_TRUE(vc != NULL);
1360 const VideoContentDescription* vcd =
1361 static_cast<const VideoContentDescription*>(vc->description);
1362
1363 const StreamParamsVec& video_streams = vcd->streams();
1364 ASSERT_EQ(1U, video_streams.size());
1365 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1366 const SsrcGroup* sim_ssrc_group =
1367 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1368 ASSERT_TRUE(sim_ssrc_group != NULL);
1369 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1370}
1371
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372// Create an audio and video answer to a standard video offer with:
1373// - one video track
1374// - two audio tracks
1375// - two data tracks
1376// and ensure it matches what we expect. Also updates the initial answer by
1377// adding a new video track and removes one of the audio tracks.
1378TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1379 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001380 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001381 offer_opts.data_channel_type = cricket::DCT_RTP;
1382 f1_.set_secure(SEC_ENABLED);
1383 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001384 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001385 NULL));
1386
1387 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001388 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1389 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1390 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001391 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001392 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1393 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001394
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001395 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001396 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1397
1398 ASSERT_TRUE(answer.get() != NULL);
1399 const ContentInfo* ac = answer->GetContentByName("audio");
1400 const ContentInfo* vc = answer->GetContentByName("video");
1401 const ContentInfo* dc = answer->GetContentByName("data");
1402 ASSERT_TRUE(ac != NULL);
1403 ASSERT_TRUE(vc != NULL);
1404 ASSERT_TRUE(dc != NULL);
1405 const AudioContentDescription* acd =
1406 static_cast<const AudioContentDescription*>(ac->description);
1407 const VideoContentDescription* vcd =
1408 static_cast<const VideoContentDescription*>(vc->description);
1409 const DataContentDescription* dcd =
1410 static_cast<const DataContentDescription*>(dc->description);
1411 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1412 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1413 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1414
1415 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1416 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1417
1418 const StreamParamsVec& audio_streams = acd->streams();
1419 ASSERT_EQ(2U, audio_streams.size());
1420 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1421 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1422 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1423 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1424 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1425 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1426 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1427
1428 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1429 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1430
1431 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1432 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1433
1434 const StreamParamsVec& video_streams = vcd->streams();
1435 ASSERT_EQ(1U, video_streams.size());
1436 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1437 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1438 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1439 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1440
1441 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1442 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1443
1444 const StreamParamsVec& data_streams = dcd->streams();
1445 ASSERT_EQ(2U, data_streams.size());
1446 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1447 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1448 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1449 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1450 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1451 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1452 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1453
1454 EXPECT_EQ(cricket::kDataMaxBandwidth,
1455 dcd->bandwidth()); // default bandwidth (auto)
1456 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1457
1458 // Update the answer. Add a new video track that is not synched to the
1459 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001460 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1461 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1462 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001463 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001464 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1465
1466 ASSERT_TRUE(updated_answer.get() != NULL);
1467 ac = updated_answer->GetContentByName("audio");
1468 vc = updated_answer->GetContentByName("video");
1469 dc = updated_answer->GetContentByName("data");
1470 ASSERT_TRUE(ac != NULL);
1471 ASSERT_TRUE(vc != NULL);
1472 ASSERT_TRUE(dc != NULL);
1473 const AudioContentDescription* updated_acd =
1474 static_cast<const AudioContentDescription*>(ac->description);
1475 const VideoContentDescription* updated_vcd =
1476 static_cast<const VideoContentDescription*>(vc->description);
1477 const DataContentDescription* updated_dcd =
1478 static_cast<const DataContentDescription*>(dc->description);
1479
1480 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1481 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1482 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1483 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1484 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1485 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1486
1487 EXPECT_EQ(acd->type(), updated_acd->type());
1488 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1489 EXPECT_EQ(vcd->type(), updated_vcd->type());
1490 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1491 EXPECT_EQ(dcd->type(), updated_dcd->type());
1492 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1493
1494 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1495 ASSERT_EQ(1U, updated_audio_streams.size());
1496 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1497
1498 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1499 ASSERT_EQ(2U, updated_video_streams.size());
1500 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1501 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1502 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1503
1504 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1505 ASSERT_EQ(1U, updated_data_streams.size());
1506 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1507}
1508
1509
1510// Create an updated offer after creating an answer to the original offer and
1511// verify that the codecs that were part of the original answer are not changed
1512// in the updated offer.
1513TEST_F(MediaSessionDescriptionFactoryTest,
1514 RespondentCreatesOfferAfterCreatingAnswer) {
1515 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001516 opts.recv_audio = true;
1517 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001519 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1520 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521 f2_.CreateAnswer(offer.get(), opts, NULL));
1522
1523 const AudioContentDescription* acd =
1524 GetFirstAudioContentDescription(answer.get());
1525 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1526
1527 const VideoContentDescription* vcd =
1528 GetFirstVideoContentDescription(answer.get());
1529 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1530
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001531 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 f2_.CreateOffer(opts, answer.get()));
1533
1534 // The expected audio codecs are the common audio codecs from the first
1535 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1536 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001537 // TODO(wu): |updated_offer| should not include the codec
1538 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001540 kAudioCodecsAnswer[0],
1541 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001542 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543 };
1544
1545 // The expected video codecs are the common video codecs from the first
1546 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1547 // preference order.
1548 const VideoCodec kUpdatedVideoCodecOffer[] = {
1549 kVideoCodecsAnswer[0],
1550 kVideoCodecs2[1],
1551 };
1552
1553 const AudioContentDescription* updated_acd =
1554 GetFirstAudioContentDescription(updated_offer.get());
1555 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1556
1557 const VideoContentDescription* updated_vcd =
1558 GetFirstVideoContentDescription(updated_offer.get());
1559 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1560}
1561
1562// Create an updated offer after creating an answer to the original offer and
1563// verify that the codecs that were part of the original answer are not changed
1564// in the updated offer. In this test Rtx is enabled.
1565TEST_F(MediaSessionDescriptionFactoryTest,
1566 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1567 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001568 opts.recv_video = true;
1569 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001570 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001572 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573 f1_.set_video_codecs(f1_codecs);
1574
1575 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001577 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001578 f2_.set_video_codecs(f2_codecs);
1579
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001580 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001582 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001583 f2_.CreateAnswer(offer.get(), opts, NULL));
1584
1585 const VideoContentDescription* vcd =
1586 GetFirstVideoContentDescription(answer.get());
1587
1588 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001589 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1590 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591
1592 EXPECT_EQ(expected_codecs, vcd->codecs());
1593
1594 // Now, make sure we get same result, except for the preference order,
1595 // if |f2_| creates an updated offer even though the default payload types
1596 // are different from |f1_|.
1597 expected_codecs[0].preference = f1_codecs[1].preference;
1598
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001599 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001600 f2_.CreateOffer(opts, answer.get()));
1601 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001602 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001603 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1604
1605 const VideoContentDescription* updated_vcd =
1606 GetFirstVideoContentDescription(updated_answer.get());
1607
1608 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1609}
1610
1611// Create an updated offer that adds video after creating an audio only answer
1612// to the original offer. This test verifies that if a video codec and the RTX
1613// codec have the same default payload type as an audio codec that is already in
1614// use, the added codecs payload types are changed.
1615TEST_F(MediaSessionDescriptionFactoryTest,
1616 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1617 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001618 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001619 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620 f1_.set_video_codecs(f1_codecs);
1621
1622 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001623 opts.recv_audio = true;
1624 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001625
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001626 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1627 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628 f2_.CreateAnswer(offer.get(), opts, NULL));
1629
1630 const AudioContentDescription* acd =
1631 GetFirstAudioContentDescription(answer.get());
1632 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1633
1634 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1635 // reference be the same as an audio codec that was negotiated in the
1636 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001637 opts.recv_audio = true;
1638 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001639
1640 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1641 int used_pl_type = acd->codecs()[0].id;
1642 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001643 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001644 f2_.set_video_codecs(f2_codecs);
1645
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001646 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001647 f2_.CreateOffer(opts, answer.get()));
1648 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001649 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1651
1652 const AudioContentDescription* updated_acd =
1653 GetFirstAudioContentDescription(answer.get());
1654 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1655
1656 const VideoContentDescription* updated_vcd =
1657 GetFirstVideoContentDescription(updated_answer.get());
1658
1659 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001660 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001661 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1662 EXPECT_NE(used_pl_type, new_h264_pl_type);
1663 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001664 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1666 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1667}
1668
1669// Test that RTX is ignored when there is no associated payload type parameter.
1670TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1671 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001672 opts.recv_video = true;
1673 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001674 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001675 // This creates RTX without associated payload type parameter.
1676 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001677 f1_.set_video_codecs(f1_codecs);
1678
1679 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001680 // This creates RTX for H264 with the payload type |f2_| uses.
1681 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001682 f2_.set_video_codecs(f2_codecs);
1683
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001684 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001685 ASSERT_TRUE(offer.get() != NULL);
1686 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1687 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1688 // is possible to test that that RTX is dropped when
1689 // kCodecParamAssociatedPayloadType is missing in the offer.
1690 VideoContentDescription* desc =
1691 static_cast<cricket::VideoContentDescription*>(
1692 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1693 ASSERT_TRUE(desc != NULL);
1694 std::vector<VideoCodec> codecs = desc->codecs();
1695 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1696 iter != codecs.end(); ++iter) {
1697 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1698 iter->params.clear();
1699 }
1700 }
1701 desc->set_codecs(codecs);
1702
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001703 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704 f2_.CreateAnswer(offer.get(), opts, NULL));
1705
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001706 std::vector<std::string> codec_names =
1707 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1708 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1709 cricket::kRtxCodecName));
1710}
1711
1712// Test that RTX will be filtered out in the answer if its associated payload
1713// type doesn't match the local value.
1714TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1715 MediaSessionOptions opts;
1716 opts.recv_video = true;
1717 opts.recv_audio = false;
1718 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1719 // This creates RTX for H264 in sender.
1720 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1721 f1_.set_video_codecs(f1_codecs);
1722
1723 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1724 // This creates RTX for H263 in receiver.
1725 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1726 f2_.set_video_codecs(f2_codecs);
1727
1728 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1729 ASSERT_TRUE(offer.get() != NULL);
1730 // Associated payload type doesn't match, therefore, RTX codec is removed in
1731 // the answer.
1732 rtc::scoped_ptr<SessionDescription> answer(
1733 f2_.CreateAnswer(offer.get(), opts, NULL));
1734
1735 std::vector<std::string> codec_names =
1736 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1737 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1738 cricket::kRtxCodecName));
1739}
1740
1741// Test that when multiple RTX codecs are offered, only the matched RTX codec
1742// is added in the answer, and the unsupported RTX codec is filtered out.
1743TEST_F(MediaSessionDescriptionFactoryTest,
1744 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1745 MediaSessionOptions opts;
1746 opts.recv_video = true;
1747 opts.recv_audio = false;
1748 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1749 // This creates RTX for H264-SVC in sender.
1750 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1751 f1_.set_video_codecs(f1_codecs);
1752
1753 // This creates RTX for H264 in sender.
1754 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1755 f1_.set_video_codecs(f1_codecs);
1756
1757 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1758 // This creates RTX for H264 in receiver.
1759 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1760 f2_.set_video_codecs(f2_codecs);
1761
1762 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1763 // for H264-SVC should also be removed.
1764 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1765 ASSERT_TRUE(offer.get() != NULL);
1766 rtc::scoped_ptr<SessionDescription> answer(
1767 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001768 const VideoContentDescription* vcd =
1769 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001770 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1771 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1772 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001773
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001774 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001775}
1776
Noah Richards2e7a0982015-05-18 14:02:54 -07001777// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1778// generated for each simulcast ssrc and correctly grouped.
1779TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1780 MediaSessionOptions opts;
1781 opts.recv_video = true;
1782 opts.recv_audio = false;
1783
1784 // Add simulcast streams.
1785 opts.AddSendVideoStream("stream1", "stream1label", 3);
1786
1787 // Use a single real codec, and then add RTX for it.
1788 std::vector<VideoCodec> f1_codecs;
1789 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30, 1));
1790 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1791 f1_.set_video_codecs(f1_codecs);
1792
1793 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1794 // is a FID ssrc + grouping for each.
1795 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1796 ASSERT_TRUE(offer.get() != NULL);
1797 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1798 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1799 ASSERT_TRUE(desc != NULL);
1800 EXPECT_TRUE(desc->multistream());
1801 const StreamParamsVec& streams = desc->streams();
1802 // Single stream.
1803 ASSERT_EQ(1u, streams.size());
1804 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1805 EXPECT_EQ(6u, streams[0].ssrcs.size());
1806 // And should have a SIM group for the simulcast.
1807 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1808 // And a FID group for RTX.
1809 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
1810 std::vector<uint32> primary_ssrcs;
1811 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1812 EXPECT_EQ(3u, primary_ssrcs.size());
1813 std::vector<uint32> fid_ssrcs;
1814 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1815 EXPECT_EQ(3u, fid_ssrcs.size());
1816}
1817
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001818// Create an updated offer after creating an answer to the original offer and
1819// verify that the RTP header extensions that were part of the original answer
1820// are not changed in the updated offer.
1821TEST_F(MediaSessionDescriptionFactoryTest,
1822 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1823 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001824 opts.recv_audio = true;
1825 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001826
1827 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1828 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1829 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1830 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1831
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001832 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1833 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001834 f2_.CreateAnswer(offer.get(), opts, NULL));
1835
1836 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1837 GetFirstAudioContentDescription(
1838 answer.get())->rtp_header_extensions());
1839 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1840 GetFirstVideoContentDescription(
1841 answer.get())->rtp_header_extensions());
1842
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001843 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001844 f2_.CreateOffer(opts, answer.get()));
1845
1846 // The expected RTP header extensions in the new offer are the resulting
1847 // extensions from the first offer/answer exchange plus the extensions only
1848 // |f2_| offer.
1849 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001850 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001851 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1852 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001853 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1854 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001855 };
1856
1857 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001858 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001859 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1860 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001861 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1862 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001863 };
1864
1865 const AudioContentDescription* updated_acd =
1866 GetFirstAudioContentDescription(updated_offer.get());
1867 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1868 updated_acd->rtp_header_extensions());
1869
1870 const VideoContentDescription* updated_vcd =
1871 GetFirstVideoContentDescription(updated_offer.get());
1872 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1873 updated_vcd->rtp_header_extensions());
1874}
1875
deadbeefa5b273a2015-08-20 17:30:13 -07001876// Verify that if the same RTP extension URI is used for audio and video, the
1877// same ID is used. Also verify that the ID isn't changed when creating an
1878// updated offer (this was previously a bug).
1879TEST_F(MediaSessionDescriptionFactoryTest,
1880 RtpHeaderExtensionIdReused) {
1881 MediaSessionOptions opts;
1882 opts.recv_audio = true;
1883 opts.recv_video = true;
1884
1885 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1886 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1887
1888 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1889
1890 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1891 // the video extensions.
1892 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1893 kVideoRtpExtension3[0],
1894 kAudioRtpExtension3[1],
1895 };
1896
1897 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1898 GetFirstAudioContentDescription(
1899 offer.get())->rtp_header_extensions());
1900 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1901 GetFirstVideoContentDescription(
1902 offer.get())->rtp_header_extensions());
1903
1904 // Nothing should change when creating a new offer
1905 rtc::scoped_ptr<SessionDescription> updated_offer(
1906 f1_.CreateOffer(opts, offer.get()));
1907
1908 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1909 GetFirstAudioContentDescription(
1910 updated_offer.get())->rtp_header_extensions());
1911 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1912 GetFirstVideoContentDescription(
1913 updated_offer.get())->rtp_header_extensions());
1914}
1915
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001916TEST(MediaSessionDescription, CopySessionDescription) {
1917 SessionDescription source;
1918 cricket::ContentGroup group(cricket::CN_AUDIO);
1919 source.AddGroup(group);
1920 AudioContentDescription* acd(new AudioContentDescription());
1921 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1922 acd->AddLegacyStream(1);
1923 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1924 VideoContentDescription* vcd(new VideoContentDescription());
1925 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1926 vcd->AddLegacyStream(2);
1927 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1928
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001929 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001930 ASSERT_TRUE(copy.get() != NULL);
1931 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1932 const ContentInfo* ac = copy->GetContentByName("audio");
1933 const ContentInfo* vc = copy->GetContentByName("video");
1934 ASSERT_TRUE(ac != NULL);
1935 ASSERT_TRUE(vc != NULL);
1936 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1937 const AudioContentDescription* acd_copy =
1938 static_cast<const AudioContentDescription*>(ac->description);
1939 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1940 EXPECT_EQ(1u, acd->first_ssrc());
1941
1942 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1943 const VideoContentDescription* vcd_copy =
1944 static_cast<const VideoContentDescription*>(vc->description);
1945 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1946 EXPECT_EQ(2u, vcd->first_ssrc());
1947}
1948
1949// The below TestTransportInfoXXX tests create different offers/answers, and
1950// ensure the TransportInfo in the SessionDescription matches what we expect.
1951TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1952 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001953 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001954 TestTransportInfo(true, options, false);
1955}
1956
1957TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1958 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001959 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001960 TestTransportInfo(true, options, true);
1961}
1962
1963TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1964 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001965 options.recv_audio = true;
1966 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967 options.data_channel_type = cricket::DCT_RTP;
1968 TestTransportInfo(true, options, false);
1969}
1970
1971TEST_F(MediaSessionDescriptionFactoryTest,
1972 TestTransportInfoOfferMultimediaCurrent) {
1973 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001974 options.recv_audio = true;
1975 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001976 options.data_channel_type = cricket::DCT_RTP;
1977 TestTransportInfo(true, options, true);
1978}
1979
1980TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1981 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001982 options.recv_audio = true;
1983 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001984 options.data_channel_type = cricket::DCT_RTP;
1985 options.bundle_enabled = true;
1986 TestTransportInfo(true, options, false);
1987}
1988
1989TEST_F(MediaSessionDescriptionFactoryTest,
1990 TestTransportInfoOfferBundleCurrent) {
1991 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001992 options.recv_audio = true;
1993 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001994 options.data_channel_type = cricket::DCT_RTP;
1995 options.bundle_enabled = true;
1996 TestTransportInfo(true, options, true);
1997}
1998
1999TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2000 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002001 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002002 TestTransportInfo(false, options, false);
2003}
2004
2005TEST_F(MediaSessionDescriptionFactoryTest,
2006 TestTransportInfoAnswerAudioCurrent) {
2007 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002008 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002009 TestTransportInfo(false, options, true);
2010}
2011
2012TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2013 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002014 options.recv_audio = true;
2015 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 options.data_channel_type = cricket::DCT_RTP;
2017 TestTransportInfo(false, options, false);
2018}
2019
2020TEST_F(MediaSessionDescriptionFactoryTest,
2021 TestTransportInfoAnswerMultimediaCurrent) {
2022 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002023 options.recv_audio = true;
2024 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002025 options.data_channel_type = cricket::DCT_RTP;
2026 TestTransportInfo(false, options, true);
2027}
2028
2029TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2030 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002031 options.recv_audio = true;
2032 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002033 options.data_channel_type = cricket::DCT_RTP;
2034 options.bundle_enabled = true;
2035 TestTransportInfo(false, options, false);
2036}
2037
2038TEST_F(MediaSessionDescriptionFactoryTest,
2039 TestTransportInfoAnswerBundleCurrent) {
2040 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002041 options.recv_audio = true;
2042 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002043 options.data_channel_type = cricket::DCT_RTP;
2044 options.bundle_enabled = true;
2045 TestTransportInfo(false, options, true);
2046}
2047
2048// Create an offer with bundle enabled and verify the crypto parameters are
2049// the common set of the available cryptos.
2050TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2051 TestCryptoWithBundle(true);
2052}
2053
2054// Create an answer with bundle enabled and verify the crypto parameters are
2055// the common set of the available cryptos.
2056TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2057 TestCryptoWithBundle(false);
2058}
2059
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002060// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2061// DTLS is not enabled locally.
2062TEST_F(MediaSessionDescriptionFactoryTest,
2063 TestOfferDtlsSavpfWithoutDtlsFailed) {
2064 f1_.set_secure(SEC_ENABLED);
2065 f2_.set_secure(SEC_ENABLED);
2066 tdf1_.set_secure(SEC_DISABLED);
2067 tdf2_.set_secure(SEC_DISABLED);
2068
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002069 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002070 f1_.CreateOffer(MediaSessionOptions(), NULL));
2071 ASSERT_TRUE(offer.get() != NULL);
2072 ContentInfo* offer_content = offer->GetContentByName("audio");
2073 ASSERT_TRUE(offer_content != NULL);
2074 AudioContentDescription* offer_audio_desc =
2075 static_cast<AudioContentDescription*>(offer_content->description);
2076 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2077
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002078 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002079 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2080 ASSERT_TRUE(answer != NULL);
2081 ContentInfo* answer_content = answer->GetContentByName("audio");
2082 ASSERT_TRUE(answer_content != NULL);
2083
2084 ASSERT_TRUE(answer_content->rejected);
2085}
2086
2087// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2088// UDP/TLS/RTP/SAVPF.
2089TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2090 f1_.set_secure(SEC_ENABLED);
2091 f2_.set_secure(SEC_ENABLED);
2092 tdf1_.set_secure(SEC_ENABLED);
2093 tdf2_.set_secure(SEC_ENABLED);
2094
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002095 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002096 f1_.CreateOffer(MediaSessionOptions(), NULL));
2097 ASSERT_TRUE(offer.get() != NULL);
2098 ContentInfo* offer_content = offer->GetContentByName("audio");
2099 ASSERT_TRUE(offer_content != NULL);
2100 AudioContentDescription* offer_audio_desc =
2101 static_cast<AudioContentDescription*>(offer_content->description);
2102 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2103
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002104 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002105 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2106 ASSERT_TRUE(answer != NULL);
2107
2108 const ContentInfo* answer_content = answer->GetContentByName("audio");
2109 ASSERT_TRUE(answer_content != NULL);
2110 ASSERT_FALSE(answer_content->rejected);
2111
2112 const AudioContentDescription* answer_audio_desc =
2113 static_cast<const AudioContentDescription*>(answer_content->description);
2114 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2115 answer_audio_desc->protocol());
2116}
2117
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002118// Test that we include both SDES and DTLS in the offer, but only include SDES
2119// in the answer if DTLS isn't negotiated.
2120TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2121 f1_.set_secure(SEC_ENABLED);
2122 f2_.set_secure(SEC_ENABLED);
2123 tdf1_.set_secure(SEC_ENABLED);
2124 tdf2_.set_secure(SEC_DISABLED);
2125 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002126 options.recv_audio = true;
2127 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002128 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002129 const cricket::MediaContentDescription* audio_media_desc;
2130 const cricket::MediaContentDescription* video_media_desc;
2131 const cricket::TransportDescription* audio_trans_desc;
2132 const cricket::TransportDescription* video_trans_desc;
2133
2134 // Generate an offer with SDES and DTLS support.
2135 offer.reset(f1_.CreateOffer(options, NULL));
2136 ASSERT_TRUE(offer.get() != NULL);
2137
2138 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2139 offer->GetContentDescriptionByName("audio"));
2140 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002141 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002142 offer->GetContentDescriptionByName("video"));
2143 ASSERT_TRUE(video_media_desc != NULL);
2144 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2145 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2146
2147 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2148 ASSERT_TRUE(audio_trans_desc != NULL);
2149 video_trans_desc = offer->GetTransportDescriptionByName("video");
2150 ASSERT_TRUE(video_trans_desc != NULL);
2151 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2152 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2153
2154 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2155 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2156 ASSERT_TRUE(answer.get() != NULL);
2157
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002158 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 answer->GetContentDescriptionByName("audio"));
2160 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002161 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162 answer->GetContentDescriptionByName("video"));
2163 ASSERT_TRUE(video_media_desc != NULL);
2164 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2165 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2166
2167 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2168 ASSERT_TRUE(audio_trans_desc != NULL);
2169 video_trans_desc = answer->GetTransportDescriptionByName("video");
2170 ASSERT_TRUE(video_trans_desc != NULL);
2171 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2172 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2173
2174 // Enable DTLS; the answer should now only have DTLS support.
2175 tdf2_.set_secure(SEC_ENABLED);
2176 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2177 ASSERT_TRUE(answer.get() != NULL);
2178
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002179 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002180 answer->GetContentDescriptionByName("audio"));
2181 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002182 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002183 answer->GetContentDescriptionByName("video"));
2184 ASSERT_TRUE(video_media_desc != NULL);
2185 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2186 EXPECT_TRUE(video_media_desc->cryptos().empty());
2187 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2188 audio_media_desc->protocol());
2189 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2190 video_media_desc->protocol());
2191
2192 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2193 ASSERT_TRUE(audio_trans_desc != NULL);
2194 video_trans_desc = answer->GetTransportDescriptionByName("video");
2195 ASSERT_TRUE(video_trans_desc != NULL);
2196 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2197 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002198
2199 // Try creating offer again. DTLS enabled now, crypto's should be empty
2200 // in new offer.
2201 offer.reset(f1_.CreateOffer(options, offer.get()));
2202 ASSERT_TRUE(offer.get() != NULL);
2203 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2204 offer->GetContentDescriptionByName("audio"));
2205 ASSERT_TRUE(audio_media_desc != NULL);
2206 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2207 offer->GetContentDescriptionByName("video"));
2208 ASSERT_TRUE(video_media_desc != NULL);
2209 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2210 EXPECT_TRUE(video_media_desc->cryptos().empty());
2211
2212 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2213 ASSERT_TRUE(audio_trans_desc != NULL);
2214 video_trans_desc = offer->GetTransportDescriptionByName("video");
2215 ASSERT_TRUE(video_trans_desc != NULL);
2216 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2217 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218}
2219
2220// Test that an answer can't be created if cryptos are required but the offer is
2221// unsecure.
2222TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2223 MediaSessionOptions options;
2224 f1_.set_secure(SEC_DISABLED);
2225 tdf1_.set_secure(SEC_DISABLED);
2226 f2_.set_secure(SEC_REQUIRED);
2227 tdf1_.set_secure(SEC_ENABLED);
2228
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002229 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230 NULL));
2231 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002232 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002233 f2_.CreateAnswer(offer.get(), options, NULL));
2234 EXPECT_TRUE(answer.get() == NULL);
2235}
2236
2237// Test that we accept a DTLS offer without SDES and create an appropriate
2238// answer.
2239TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2240 f1_.set_secure(SEC_DISABLED);
2241 f2_.set_secure(SEC_ENABLED);
2242 tdf1_.set_secure(SEC_ENABLED);
2243 tdf2_.set_secure(SEC_ENABLED);
2244 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002245 options.recv_audio = true;
2246 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002247 options.data_channel_type = cricket::DCT_RTP;
2248
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002249 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250
2251 // Generate an offer with DTLS but without SDES.
2252 offer.reset(f1_.CreateOffer(options, NULL));
2253 ASSERT_TRUE(offer.get() != NULL);
2254
2255 const AudioContentDescription* audio_offer =
2256 GetFirstAudioContentDescription(offer.get());
2257 ASSERT_TRUE(audio_offer->cryptos().empty());
2258 const VideoContentDescription* video_offer =
2259 GetFirstVideoContentDescription(offer.get());
2260 ASSERT_TRUE(video_offer->cryptos().empty());
2261 const DataContentDescription* data_offer =
2262 GetFirstDataContentDescription(offer.get());
2263 ASSERT_TRUE(data_offer->cryptos().empty());
2264
2265 const cricket::TransportDescription* audio_offer_trans_desc =
2266 offer->GetTransportDescriptionByName("audio");
2267 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2268 const cricket::TransportDescription* video_offer_trans_desc =
2269 offer->GetTransportDescriptionByName("video");
2270 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2271 const cricket::TransportDescription* data_offer_trans_desc =
2272 offer->GetTransportDescriptionByName("data");
2273 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2274
2275 // Generate an answer with DTLS.
2276 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2277 ASSERT_TRUE(answer.get() != NULL);
2278
2279 const cricket::TransportDescription* audio_answer_trans_desc =
2280 answer->GetTransportDescriptionByName("audio");
2281 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2282 const cricket::TransportDescription* video_answer_trans_desc =
2283 answer->GetTransportDescriptionByName("video");
2284 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2285 const cricket::TransportDescription* data_answer_trans_desc =
2286 answer->GetTransportDescriptionByName("data");
2287 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2288}
2289
2290// Verifies if vad_enabled option is set to false, CN codecs are not present in
2291// offer or answer.
2292TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2293 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002294 options.recv_audio = true;
2295 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002296 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002297 f1_.CreateOffer(options, NULL));
2298 ASSERT_TRUE(offer.get() != NULL);
2299 const ContentInfo* audio_content = offer->GetContentByName("audio");
2300 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2301
2302 options.vad_enabled = false;
2303 offer.reset(f1_.CreateOffer(options, NULL));
2304 ASSERT_TRUE(offer.get() != NULL);
2305 audio_content = offer->GetContentByName("audio");
2306 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002307 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002308 f1_.CreateAnswer(offer.get(), options, NULL));
2309 ASSERT_TRUE(answer.get() != NULL);
2310 audio_content = answer->GetContentByName("audio");
2311 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2312}