blob: 3d69465decfe968b7d91dc3ea27563b1e3674dd2 [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;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070087using rtc::CS_AES_CM_128_HMAC_SHA1_32;
88using rtc::CS_AES_CM_128_HMAC_SHA1_80;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089
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()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200229 : f1_(&tdf1_),
230 f2_(&tdf2_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
232 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
233 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
234 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
235 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
236 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200237 tdf1_.set_certificate(rtc::RTCCertificate::Create(
238 rtc::scoped_ptr<rtc::SSLIdentity>(
239 new rtc::FakeSSLIdentity("id1")).Pass()));
240 tdf2_.set_certificate(rtc::RTCCertificate::Create(
241 rtc::scoped_ptr<rtc::SSLIdentity>(
242 new rtc::FakeSSLIdentity("id2")).Pass()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243 }
244
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000245 // Create a video StreamParamsVec object with:
246 // - one video stream with 3 simulcast streams and FEC,
247 StreamParamsVec CreateComplexVideoStreamParamsVec() {
248 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
249 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
250 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
251 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
252
253 std::vector<SsrcGroup> ssrc_groups;
254 ssrc_groups.push_back(sim_group);
255 ssrc_groups.push_back(fec_group1);
256 ssrc_groups.push_back(fec_group2);
257 ssrc_groups.push_back(fec_group3);
258
259 StreamParams simulcast_params;
260 simulcast_params.id = kVideoTrack1;
261 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
262 simulcast_params.ssrc_groups = ssrc_groups;
263 simulcast_params.cname = "Video_SIM_FEC";
264 simulcast_params.sync_label = kMediaStream1;
265
266 StreamParamsVec video_streams;
267 video_streams.push_back(simulcast_params);
268
269 return video_streams;
270 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271
272 bool CompareCryptoParams(const CryptoParamsVec& c1,
273 const CryptoParamsVec& c2) {
274 if (c1.size() != c2.size())
275 return false;
276 for (size_t i = 0; i < c1.size(); ++i)
277 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
278 c1[i].key_params != c2[i].key_params ||
279 c1[i].session_params != c2[i].session_params)
280 return false;
281 return true;
282 }
283
284 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
285 bool has_current_desc) {
286 const std::string current_audio_ufrag = "current_audio_ufrag";
287 const std::string current_audio_pwd = "current_audio_pwd";
288 const std::string current_video_ufrag = "current_video_ufrag";
289 const std::string current_video_pwd = "current_video_pwd";
290 const std::string current_data_ufrag = "current_data_ufrag";
291 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000292 rtc::scoped_ptr<SessionDescription> current_desc;
293 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 if (has_current_desc) {
295 current_desc.reset(new SessionDescription());
296 EXPECT_TRUE(current_desc->AddTransportInfo(
297 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700298 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000299 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000300 EXPECT_TRUE(current_desc->AddTransportInfo(
301 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700302 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000303 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 EXPECT_TRUE(current_desc->AddTransportInfo(
305 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700306 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000307 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000308 }
309 if (offer) {
310 desc.reset(f1_.CreateOffer(options, current_desc.get()));
311 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000312 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000313 offer.reset(f1_.CreateOffer(options, NULL));
314 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
315 }
316 ASSERT_TRUE(desc.get() != NULL);
317 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000318 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000319 EXPECT_TRUE(ti_audio != NULL);
320 if (has_current_desc) {
321 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
322 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
323 } else {
324 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
325 ti_audio->description.ice_ufrag.size());
326 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
327 ti_audio->description.ice_pwd.size());
328 }
329
330 } else {
331 EXPECT_TRUE(ti_audio == NULL);
332 }
333 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000334 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 EXPECT_TRUE(ti_video != NULL);
336 if (options.bundle_enabled) {
337 EXPECT_EQ(ti_audio->description.ice_ufrag,
338 ti_video->description.ice_ufrag);
339 EXPECT_EQ(ti_audio->description.ice_pwd,
340 ti_video->description.ice_pwd);
341 } else {
342 if (has_current_desc) {
343 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
344 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
345 } else {
346 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
347 ti_video->description.ice_ufrag.size());
348 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
349 ti_video->description.ice_pwd.size());
350 }
351 }
352 } else {
353 EXPECT_TRUE(ti_video == NULL);
354 }
355 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
356 if (options.has_data()) {
357 EXPECT_TRUE(ti_data != NULL);
358 if (options.bundle_enabled) {
359 EXPECT_EQ(ti_audio->description.ice_ufrag,
360 ti_data->description.ice_ufrag);
361 EXPECT_EQ(ti_audio->description.ice_pwd,
362 ti_data->description.ice_pwd);
363 } else {
364 if (has_current_desc) {
365 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
366 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
367 } else {
368 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
369 ti_data->description.ice_ufrag.size());
370 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
371 ti_data->description.ice_pwd.size());
372 }
373 }
374 } else {
375 EXPECT_TRUE(ti_video == NULL);
376 }
377 }
378
379 void TestCryptoWithBundle(bool offer) {
380 f1_.set_secure(SEC_ENABLED);
381 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000382 options.recv_audio = true;
383 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000384 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000385 rtc::scoped_ptr<SessionDescription> ref_desc;
386 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 if (offer) {
388 options.bundle_enabled = false;
389 ref_desc.reset(f1_.CreateOffer(options, NULL));
390 options.bundle_enabled = true;
391 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
392 } else {
393 options.bundle_enabled = true;
394 ref_desc.reset(f1_.CreateOffer(options, NULL));
395 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
396 }
397 ASSERT_TRUE(desc.get() != NULL);
398 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000399 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000400 desc.get()->GetContentDescriptionByName("audio"));
401 ASSERT_TRUE(audio_media_desc != NULL);
402 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000403 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000404 desc.get()->GetContentDescriptionByName("video"));
405 ASSERT_TRUE(video_media_desc != NULL);
406 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
407 video_media_desc->cryptos()));
408 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
409 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
410 audio_media_desc->cryptos()[0].cipher_suite);
411
412 // Verify the selected crypto is one from the reference audio
413 // media content.
414 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000415 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000416 ref_desc.get()->GetContentDescriptionByName("audio"));
417 bool found = false;
418 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
419 if (ref_audio_media_desc->cryptos()[i].Matches(
420 audio_media_desc->cryptos()[0])) {
421 found = true;
422 break;
423 }
424 }
425 EXPECT_TRUE(found);
426 }
427
428 // This test that the audio and video media direction is set to
429 // |expected_direction_in_answer| in an answer if the offer direction is set
430 // to |direction_in_offer|.
431 void TestMediaDirectionInAnswer(
432 cricket::MediaContentDirection direction_in_offer,
433 cricket::MediaContentDirection expected_direction_in_answer) {
434 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000435 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000436 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437 f1_.CreateOffer(opts, NULL));
438 ASSERT_TRUE(offer.get() != NULL);
439 ContentInfo* ac_offer= offer->GetContentByName("audio");
440 ASSERT_TRUE(ac_offer != NULL);
441 AudioContentDescription* acd_offer =
442 static_cast<AudioContentDescription*>(ac_offer->description);
443 acd_offer->set_direction(direction_in_offer);
444 ContentInfo* vc_offer= offer->GetContentByName("video");
445 ASSERT_TRUE(vc_offer != NULL);
446 VideoContentDescription* vcd_offer =
447 static_cast<VideoContentDescription*>(vc_offer->description);
448 vcd_offer->set_direction(direction_in_offer);
449
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000450 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000451 f2_.CreateAnswer(offer.get(), opts, NULL));
452 const AudioContentDescription* acd_answer =
453 GetFirstAudioContentDescription(answer.get());
454 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
455 const VideoContentDescription* vcd_answer =
456 GetFirstVideoContentDescription(answer.get());
457 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
458 }
459
460 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
461 const cricket::ContentDescription* description = content->description;
462 ASSERT(description != NULL);
463 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000464 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000465 ASSERT(audio_content_desc != NULL);
466 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
467 if (audio_content_desc->codecs()[i].name == "CN")
468 return false;
469 }
470 return true;
471 }
472
473 protected:
474 MediaSessionDescriptionFactory f1_;
475 MediaSessionDescriptionFactory f2_;
476 TransportDescriptionFactory tdf1_;
477 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000478};
479
480// Create a typical audio offer, and ensure it matches what we expect.
481TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
482 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000483 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000484 f1_.CreateOffer(MediaSessionOptions(), NULL));
485 ASSERT_TRUE(offer.get() != NULL);
486 const ContentInfo* ac = offer->GetContentByName("audio");
487 const ContentInfo* vc = offer->GetContentByName("video");
488 ASSERT_TRUE(ac != NULL);
489 ASSERT_TRUE(vc == NULL);
490 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
491 const AudioContentDescription* acd =
492 static_cast<const AudioContentDescription*>(ac->description);
493 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
494 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
495 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
496 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
497 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
498 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
499 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
500}
501
502// Create a typical video offer, and ensure it matches what we expect.
503TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
504 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000505 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000506 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000507 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000508 offer(f1_.CreateOffer(opts, NULL));
509 ASSERT_TRUE(offer.get() != NULL);
510 const ContentInfo* ac = offer->GetContentByName("audio");
511 const ContentInfo* vc = offer->GetContentByName("video");
512 ASSERT_TRUE(ac != NULL);
513 ASSERT_TRUE(vc != NULL);
514 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
515 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
516 const AudioContentDescription* acd =
517 static_cast<const AudioContentDescription*>(ac->description);
518 const VideoContentDescription* vcd =
519 static_cast<const VideoContentDescription*>(vc->description);
520 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
521 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
522 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
523 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
524 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
525 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
526 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
527 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
528 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
529 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
530 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
531 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
532 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
533 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
534}
535
536// Test creating an offer with bundle where the Codecs have the same dynamic
537// RTP playlod type. The test verifies that the offer don't contain the
538// duplicate RTP payload types.
539TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
540 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
541 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
542 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
543 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
544 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
545
546 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000547 opts.recv_audio = true;
548 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 opts.data_channel_type = cricket::DCT_RTP;
550 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000551 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000552 offer(f2_.CreateOffer(opts, NULL));
553 const VideoContentDescription* vcd =
554 GetFirstVideoContentDescription(offer.get());
555 const AudioContentDescription* acd =
556 GetFirstAudioContentDescription(offer.get());
557 const DataContentDescription* dcd =
558 GetFirstDataContentDescription(offer.get());
559 ASSERT_TRUE(NULL != vcd);
560 ASSERT_TRUE(NULL != acd);
561 ASSERT_TRUE(NULL != dcd);
562 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
563 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
564 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
565 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
566 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
567 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
568}
569
570// Test creating an updated offer with with bundle, audio, video and data
571// after an audio only session has been negotiated.
572TEST_F(MediaSessionDescriptionFactoryTest,
573 TestCreateUpdatedVideoOfferWithBundle) {
574 f1_.set_secure(SEC_ENABLED);
575 f2_.set_secure(SEC_ENABLED);
576 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000577 opts.recv_audio = true;
578 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000579 opts.data_channel_type = cricket::DCT_NONE;
580 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000581 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
582 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000583 f2_.CreateAnswer(offer.get(), opts, NULL));
584
585 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000586 updated_opts.recv_audio = true;
587 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000588 updated_opts.data_channel_type = cricket::DCT_RTP;
589 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000590 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 updated_opts, answer.get()));
592
593 const AudioContentDescription* acd =
594 GetFirstAudioContentDescription(updated_offer.get());
595 const VideoContentDescription* vcd =
596 GetFirstVideoContentDescription(updated_offer.get());
597 const DataContentDescription* dcd =
598 GetFirstDataContentDescription(updated_offer.get());
599 EXPECT_TRUE(NULL != vcd);
600 EXPECT_TRUE(NULL != acd);
601 EXPECT_TRUE(NULL != dcd);
602
603 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
604 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
605 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
606 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
607 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
608 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
609}
wu@webrtc.org78187522013-10-07 23:32:02 +0000610// Create a RTP data offer, and ensure it matches what we expect.
611TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000612 MediaSessionOptions opts;
613 opts.data_channel_type = cricket::DCT_RTP;
614 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000615 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 offer(f1_.CreateOffer(opts, NULL));
617 ASSERT_TRUE(offer.get() != NULL);
618 const ContentInfo* ac = offer->GetContentByName("audio");
619 const ContentInfo* dc = offer->GetContentByName("data");
620 ASSERT_TRUE(ac != NULL);
621 ASSERT_TRUE(dc != NULL);
622 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
623 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
624 const AudioContentDescription* acd =
625 static_cast<const AudioContentDescription*>(ac->description);
626 const DataContentDescription* dcd =
627 static_cast<const DataContentDescription*>(dc->description);
628 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
629 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
630 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
631 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
632 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
633 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
634 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
635 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
636 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
637 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
638 EXPECT_EQ(cricket::kDataMaxBandwidth,
639 dcd->bandwidth()); // default bandwidth (auto)
640 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
641 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
642 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
643}
644
wu@webrtc.org78187522013-10-07 23:32:02 +0000645// Create an SCTP data offer with bundle without error.
646TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
647 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000648 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000649 opts.bundle_enabled = true;
650 opts.data_channel_type = cricket::DCT_SCTP;
651 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000652 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000653 EXPECT_TRUE(offer.get() != NULL);
654 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
655}
656
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000657// Test creating an sctp data channel from an already generated offer.
658TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
659 MediaSessionOptions opts;
660 opts.recv_audio = false;
661 opts.bundle_enabled = true;
662 opts.data_channel_type = cricket::DCT_SCTP;
663 f1_.set_secure(SEC_ENABLED);
664 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
665 ASSERT_TRUE(offer1.get() != NULL);
666 const ContentInfo* data = offer1->GetContentByName("data");
667 ASSERT_TRUE(data != NULL);
668 const MediaContentDescription* mdesc =
669 static_cast<const MediaContentDescription*>(data->description);
670 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
671
672 // Now set data_channel_type to 'none' (default) and make sure that the
673 // datachannel type that gets generated from the previous offer, is of the
674 // same type.
675 opts.data_channel_type = cricket::DCT_NONE;
676 rtc::scoped_ptr<SessionDescription> offer2(
677 f1_.CreateOffer(opts, offer1.get()));
678 data = offer2->GetContentByName("data");
679 ASSERT_TRUE(data != NULL);
680 mdesc = static_cast<const MediaContentDescription*>(data->description);
681 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
682}
683
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684// Create an audio, video offer without legacy StreamParams.
685TEST_F(MediaSessionDescriptionFactoryTest,
686 TestCreateOfferWithoutLegacyStreams) {
687 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000688 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000689 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000690 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000691 offer(f1_.CreateOffer(opts, NULL));
692 ASSERT_TRUE(offer.get() != NULL);
693 const ContentInfo* ac = offer->GetContentByName("audio");
694 const ContentInfo* vc = offer->GetContentByName("video");
695 ASSERT_TRUE(ac != NULL);
696 ASSERT_TRUE(vc != NULL);
697 const AudioContentDescription* acd =
698 static_cast<const AudioContentDescription*>(ac->description);
699 const VideoContentDescription* vcd =
700 static_cast<const VideoContentDescription*>(vc->description);
701
702 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
703 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
704}
705
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000706// Creates an audio+video sendonly offer.
707TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
708 MediaSessionOptions options;
709 options.recv_audio = false;
710 options.recv_video = false;
711 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
712 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
713
714 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
715 ASSERT_TRUE(offer.get() != NULL);
716 EXPECT_EQ(2u, offer->contents().size());
717 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
718 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
719
720 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
721 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
722}
723
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000724// Verifies that the order of the media contents in the current
725// SessionDescription is preserved in the new SessionDescription.
726TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
727 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000728 opts.recv_audio = false;
729 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000730 opts.data_channel_type = cricket::DCT_SCTP;
731
732 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
733 ASSERT_TRUE(offer1.get() != NULL);
734 EXPECT_EQ(1u, offer1->contents().size());
735 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
736
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000737 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000738 rtc::scoped_ptr<SessionDescription> offer2(
739 f1_.CreateOffer(opts, offer1.get()));
740 ASSERT_TRUE(offer2.get() != NULL);
741 EXPECT_EQ(2u, offer2->contents().size());
742 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
743 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
744
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000745 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000746 rtc::scoped_ptr<SessionDescription> offer3(
747 f1_.CreateOffer(opts, offer2.get()));
748 ASSERT_TRUE(offer3.get() != NULL);
749 EXPECT_EQ(3u, offer3->contents().size());
750 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
751 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
752 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
753
754 // Verifies the default order is audio-video-data, so that the previous checks
755 // didn't pass by accident.
756 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
757 ASSERT_TRUE(offer4.get() != NULL);
758 EXPECT_EQ(3u, offer4->contents().size());
759 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
760 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
761 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
762}
763
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000764// Create a typical audio answer, and ensure it matches what we expect.
765TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
766 f1_.set_secure(SEC_ENABLED);
767 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000768 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000769 f1_.CreateOffer(MediaSessionOptions(), NULL));
770 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000771 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000772 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
773 const ContentInfo* ac = answer->GetContentByName("audio");
774 const ContentInfo* vc = answer->GetContentByName("video");
775 ASSERT_TRUE(ac != NULL);
776 ASSERT_TRUE(vc == NULL);
777 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
778 const AudioContentDescription* acd =
779 static_cast<const AudioContentDescription*>(ac->description);
780 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
781 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
782 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
783 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
784 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
785 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
786 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
787}
788
789// Create a typical video answer, and ensure it matches what we expect.
790TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
791 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000792 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000793 f1_.set_secure(SEC_ENABLED);
794 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000795 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000796 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000797 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000798 f2_.CreateAnswer(offer.get(), opts, NULL));
799 const ContentInfo* ac = answer->GetContentByName("audio");
800 const ContentInfo* vc = answer->GetContentByName("video");
801 ASSERT_TRUE(ac != NULL);
802 ASSERT_TRUE(vc != NULL);
803 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
804 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
805 const AudioContentDescription* acd =
806 static_cast<const AudioContentDescription*>(ac->description);
807 const VideoContentDescription* vcd =
808 static_cast<const VideoContentDescription*>(vc->description);
809 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
810 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
811 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
812 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
813 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
814 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
815 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
816 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
817 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
818 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
819 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
820 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
821}
822
823TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
824 MediaSessionOptions opts;
825 opts.data_channel_type = cricket::DCT_RTP;
826 f1_.set_secure(SEC_ENABLED);
827 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000828 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000829 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000830 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000831 f2_.CreateAnswer(offer.get(), opts, NULL));
832 const ContentInfo* ac = answer->GetContentByName("audio");
833 const ContentInfo* vc = answer->GetContentByName("data");
834 ASSERT_TRUE(ac != NULL);
835 ASSERT_TRUE(vc != NULL);
836 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
837 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
838 const AudioContentDescription* acd =
839 static_cast<const AudioContentDescription*>(ac->description);
840 const DataContentDescription* vcd =
841 static_cast<const DataContentDescription*>(vc->description);
842 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
843 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
844 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
845 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
846 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
847 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
848 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
849 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
850 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
851 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
852 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
853 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
854}
855
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000856// Verifies that the order of the media contents in the offer is preserved in
857// the answer.
858TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
859 MediaSessionOptions opts;
860
861 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000862 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000863 opts.data_channel_type = cricket::DCT_SCTP;
864 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
865 ASSERT_TRUE(offer1.get() != NULL);
866
867 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000868 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000869 rtc::scoped_ptr<SessionDescription> offer2(
870 f1_.CreateOffer(opts, offer1.get()));
871 ASSERT_TRUE(offer2.get() != NULL);
872
873 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000874 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000875 rtc::scoped_ptr<SessionDescription> offer3(
876 f1_.CreateOffer(opts, offer2.get()));
877 ASSERT_TRUE(offer3.get() != NULL);
878
879 rtc::scoped_ptr<SessionDescription> answer(
880 f2_.CreateAnswer(offer3.get(), opts, NULL));
881 ASSERT_TRUE(answer.get() != NULL);
882 EXPECT_EQ(3u, answer->contents().size());
883 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
884 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
885 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
886}
887
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000888// This test that the media direction is set to send/receive in an answer if
889// the offer is send receive.
890TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
891 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
892}
893
894// This test that the media direction is set to receive only in an answer if
895// the offer is send only.
896TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
897 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
898}
899
900// This test that the media direction is set to send only in an answer if
901// the offer is recv only.
902TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
903 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
904}
905
906// This test that the media direction is set to inactive in an answer if
907// the offer is inactive.
908TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
909 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
910}
911
912// Test that a data content with an unknown protocol is rejected in an answer.
913TEST_F(MediaSessionDescriptionFactoryTest,
914 CreateDataAnswerToOfferWithUnknownProtocol) {
915 MediaSessionOptions opts;
916 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000917 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000918 f1_.set_secure(SEC_ENABLED);
919 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000920 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000921 ContentInfo* dc_offer= offer->GetContentByName("data");
922 ASSERT_TRUE(dc_offer != NULL);
923 DataContentDescription* dcd_offer =
924 static_cast<DataContentDescription*>(dc_offer->description);
925 ASSERT_TRUE(dcd_offer != NULL);
926 std::string protocol = "a weird unknown protocol";
927 dcd_offer->set_protocol(protocol);
928
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000929 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000930 f2_.CreateAnswer(offer.get(), opts, NULL));
931
932 const ContentInfo* dc_answer = answer->GetContentByName("data");
933 ASSERT_TRUE(dc_answer != NULL);
934 EXPECT_TRUE(dc_answer->rejected);
935 const DataContentDescription* dcd_answer =
936 static_cast<const DataContentDescription*>(dc_answer->description);
937 ASSERT_TRUE(dcd_answer != NULL);
938 EXPECT_EQ(protocol, dcd_answer->protocol());
939}
940
941// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
942TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
943 MediaSessionOptions opts;
944 f1_.set_secure(SEC_DISABLED);
945 f2_.set_secure(SEC_DISABLED);
946 tdf1_.set_secure(SEC_DISABLED);
947 tdf2_.set_secure(SEC_DISABLED);
948
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000949 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 const AudioContentDescription* offer_acd =
951 GetFirstAudioContentDescription(offer.get());
952 ASSERT_TRUE(offer_acd != NULL);
953 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
954
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000955 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000956 f2_.CreateAnswer(offer.get(), opts, NULL));
957
958 const ContentInfo* ac_answer = answer->GetContentByName("audio");
959 ASSERT_TRUE(ac_answer != NULL);
960 EXPECT_FALSE(ac_answer->rejected);
961
962 const AudioContentDescription* answer_acd =
963 GetFirstAudioContentDescription(answer.get());
964 ASSERT_TRUE(answer_acd != NULL);
965 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
966}
967
968// Create a video offer and answer and ensure the RTP header extensions
969// matches what we expect.
970TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
971 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000972 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000973
974 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
975 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
976 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
977 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
978
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000979 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000981 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000982 f2_.CreateAnswer(offer.get(), opts, NULL));
983
984 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
985 GetFirstAudioContentDescription(
986 offer.get())->rtp_header_extensions());
987 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
988 GetFirstVideoContentDescription(
989 offer.get())->rtp_header_extensions());
990 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
991 GetFirstAudioContentDescription(
992 answer.get())->rtp_header_extensions());
993 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
994 GetFirstVideoContentDescription(
995 answer.get())->rtp_header_extensions());
996}
997
998// Create an audio, video, data answer without legacy StreamParams.
999TEST_F(MediaSessionDescriptionFactoryTest,
1000 TestCreateAnswerWithoutLegacyStreams) {
1001 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001002 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001003 opts.data_channel_type = cricket::DCT_RTP;
1004 f1_.set_add_legacy_streams(false);
1005 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001006 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001007 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001008 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001009 f2_.CreateAnswer(offer.get(), opts, NULL));
1010 const ContentInfo* ac = answer->GetContentByName("audio");
1011 const ContentInfo* vc = answer->GetContentByName("video");
1012 const ContentInfo* dc = answer->GetContentByName("data");
1013 ASSERT_TRUE(ac != NULL);
1014 ASSERT_TRUE(vc != NULL);
1015 const AudioContentDescription* acd =
1016 static_cast<const AudioContentDescription*>(ac->description);
1017 const VideoContentDescription* vcd =
1018 static_cast<const VideoContentDescription*>(vc->description);
1019 const DataContentDescription* dcd =
1020 static_cast<const DataContentDescription*>(dc->description);
1021
1022 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1023 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1024 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1025}
1026
1027TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1028 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001029 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001030 opts.data_channel_type = cricket::DCT_RTP;
1031 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001032 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001033 offer(f1_.CreateOffer(opts, NULL));
1034 ASSERT_TRUE(offer.get() != NULL);
1035 const ContentInfo* ac = offer->GetContentByName("audio");
1036 const ContentInfo* vc = offer->GetContentByName("video");
1037 const ContentInfo* dc = offer->GetContentByName("data");
1038 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1039 static_cast<const AudioContentDescription*>(ac->description));
1040 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1041 static_cast<const VideoContentDescription*>(vc->description));
1042 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1043 static_cast<const DataContentDescription*>(dc->description));
1044
1045 EXPECT_FALSE(acd->partial()); // default is false.
1046 acd->set_partial(true);
1047 EXPECT_TRUE(acd->partial());
1048 acd->set_partial(false);
1049 EXPECT_FALSE(acd->partial());
1050
1051 EXPECT_FALSE(vcd->partial()); // default is false.
1052 vcd->set_partial(true);
1053 EXPECT_TRUE(vcd->partial());
1054 vcd->set_partial(false);
1055 EXPECT_FALSE(vcd->partial());
1056
1057 EXPECT_FALSE(dcd->partial()); // default is false.
1058 dcd->set_partial(true);
1059 EXPECT_TRUE(dcd->partial());
1060 dcd->set_partial(false);
1061 EXPECT_FALSE(dcd->partial());
1062}
1063
1064// Create a typical video answer, and ensure it matches what we expect.
1065TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1066 MediaSessionOptions offer_opts;
1067 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001068 answer_opts.recv_video = true;
1069 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001070 answer_opts.data_channel_type = cricket::DCT_RTP;
1071 offer_opts.data_channel_type = cricket::DCT_RTP;
1072
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001073 rtc::scoped_ptr<SessionDescription> offer;
1074 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001075
1076 offer_opts.rtcp_mux_enabled = true;
1077 answer_opts.rtcp_mux_enabled = true;
1078
1079 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1080 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1081 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1082 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1083 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1084 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1085 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1086 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1087 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1088 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1089 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1090 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1091 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1092 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1093
1094 offer_opts.rtcp_mux_enabled = true;
1095 answer_opts.rtcp_mux_enabled = false;
1096
1097 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1098 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1099 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1100 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1101 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1102 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1103 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1104 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1105 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1106 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1107 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1108 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1109 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1110 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1111
1112 offer_opts.rtcp_mux_enabled = false;
1113 answer_opts.rtcp_mux_enabled = true;
1114
1115 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1116 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1117 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1118 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1119 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1120 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1121 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1122 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1123 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1124 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1125 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1126 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1127 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1128 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1129
1130 offer_opts.rtcp_mux_enabled = false;
1131 answer_opts.rtcp_mux_enabled = false;
1132
1133 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1134 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1135 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1136 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1137 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1138 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1139 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1140 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1141 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1142 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1143 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1144 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1145 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1146 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1147}
1148
1149// Create an audio-only answer to a video offer.
1150TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1151 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001152 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001153 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 offer(f1_.CreateOffer(opts, NULL));
1155 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001156 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001157 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1158 const ContentInfo* ac = answer->GetContentByName("audio");
1159 const ContentInfo* vc = answer->GetContentByName("video");
1160 ASSERT_TRUE(ac != NULL);
1161 ASSERT_TRUE(vc != NULL);
1162 ASSERT_TRUE(vc->description != NULL);
1163 EXPECT_TRUE(vc->rejected);
1164}
1165
1166// Create an audio-only answer to an offer with data.
1167TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1168 MediaSessionOptions opts;
1169 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001170 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001171 offer(f1_.CreateOffer(opts, NULL));
1172 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001173 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1175 const ContentInfo* ac = answer->GetContentByName("audio");
1176 const ContentInfo* dc = answer->GetContentByName("data");
1177 ASSERT_TRUE(ac != NULL);
1178 ASSERT_TRUE(dc != NULL);
1179 ASSERT_TRUE(dc->description != NULL);
1180 EXPECT_TRUE(dc->rejected);
1181}
1182
1183// Create an answer that rejects the contents which are rejected in the offer.
1184TEST_F(MediaSessionDescriptionFactoryTest,
1185 CreateAnswerToOfferWithRejectedMedia) {
1186 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001187 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001188 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001189 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001190 offer(f1_.CreateOffer(opts, NULL));
1191 ASSERT_TRUE(offer.get() != NULL);
1192 ContentInfo* ac = offer->GetContentByName("audio");
1193 ContentInfo* vc = offer->GetContentByName("video");
1194 ContentInfo* dc = offer->GetContentByName("data");
1195 ASSERT_TRUE(ac != NULL);
1196 ASSERT_TRUE(vc != NULL);
1197 ASSERT_TRUE(dc != NULL);
1198 ac->rejected = true;
1199 vc->rejected = true;
1200 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001201 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001202 f2_.CreateAnswer(offer.get(), opts, NULL));
1203 ac = answer->GetContentByName("audio");
1204 vc = answer->GetContentByName("video");
1205 dc = answer->GetContentByName("data");
1206 ASSERT_TRUE(ac != NULL);
1207 ASSERT_TRUE(vc != NULL);
1208 ASSERT_TRUE(dc != NULL);
1209 EXPECT_TRUE(ac->rejected);
1210 EXPECT_TRUE(vc->rejected);
1211 EXPECT_TRUE(dc->rejected);
1212}
1213
1214// Create an audio and video offer with:
1215// - one video track
1216// - two audio tracks
1217// - two data tracks
1218// and ensure it matches what we expect. Also updates the initial offer by
1219// adding a new video track and replaces one of the audio tracks.
1220TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1221 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001222 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1223 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1224 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001225 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001226 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1227 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001228
1229 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001230 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001231
1232 ASSERT_TRUE(offer.get() != NULL);
1233 const ContentInfo* ac = offer->GetContentByName("audio");
1234 const ContentInfo* vc = offer->GetContentByName("video");
1235 const ContentInfo* dc = offer->GetContentByName("data");
1236 ASSERT_TRUE(ac != NULL);
1237 ASSERT_TRUE(vc != NULL);
1238 ASSERT_TRUE(dc != NULL);
1239 const AudioContentDescription* acd =
1240 static_cast<const AudioContentDescription*>(ac->description);
1241 const VideoContentDescription* vcd =
1242 static_cast<const VideoContentDescription*>(vc->description);
1243 const DataContentDescription* dcd =
1244 static_cast<const DataContentDescription*>(dc->description);
1245 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1246 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1247
1248 const StreamParamsVec& audio_streams = acd->streams();
1249 ASSERT_EQ(2U, audio_streams.size());
1250 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1251 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1252 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1253 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1254 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1255 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1256 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1257
1258 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1259 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1260 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1261
1262 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1263 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1264 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1265
1266 const StreamParamsVec& video_streams = vcd->streams();
1267 ASSERT_EQ(1U, video_streams.size());
1268 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1269 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1270 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1271 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1272
1273 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1274 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1275 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1276
1277 const StreamParamsVec& data_streams = dcd->streams();
1278 ASSERT_EQ(2U, data_streams.size());
1279 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1280 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1281 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1282 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1283 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1284 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1285 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1286
1287 EXPECT_EQ(cricket::kDataMaxBandwidth,
1288 dcd->bandwidth()); // default bandwidth (auto)
1289 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1290 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1291
1292
1293 // Update the offer. Add a new video track that is not synched to the
1294 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001295 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1296 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1297 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1298 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1299 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001300 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001301 updated_offer(f1_.CreateOffer(opts, offer.get()));
1302
1303 ASSERT_TRUE(updated_offer.get() != NULL);
1304 ac = updated_offer->GetContentByName("audio");
1305 vc = updated_offer->GetContentByName("video");
1306 dc = updated_offer->GetContentByName("data");
1307 ASSERT_TRUE(ac != NULL);
1308 ASSERT_TRUE(vc != NULL);
1309 ASSERT_TRUE(dc != NULL);
1310 const AudioContentDescription* updated_acd =
1311 static_cast<const AudioContentDescription*>(ac->description);
1312 const VideoContentDescription* updated_vcd =
1313 static_cast<const VideoContentDescription*>(vc->description);
1314 const DataContentDescription* updated_dcd =
1315 static_cast<const DataContentDescription*>(dc->description);
1316
1317 EXPECT_EQ(acd->type(), updated_acd->type());
1318 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1319 EXPECT_EQ(vcd->type(), updated_vcd->type());
1320 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1321 EXPECT_EQ(dcd->type(), updated_dcd->type());
1322 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1323 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1324 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1325 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1326 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1327 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1328 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1329
1330 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1331 ASSERT_EQ(2U, updated_audio_streams.size());
1332 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1333 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1334 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1335 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1336 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1337
1338 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1339 ASSERT_EQ(2U, updated_video_streams.size());
1340 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1341 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1342 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1343
1344 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1345 ASSERT_EQ(2U, updated_data_streams.size());
1346 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1347 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1348 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1349 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1350 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1351}
1352
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001353// Create an offer with simulcast video stream.
1354TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1355 MediaSessionOptions opts;
1356 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001357 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001358 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001359
1360 ASSERT_TRUE(offer.get() != NULL);
1361 const ContentInfo* vc = offer->GetContentByName("video");
1362 ASSERT_TRUE(vc != NULL);
1363 const VideoContentDescription* vcd =
1364 static_cast<const VideoContentDescription*>(vc->description);
1365
1366 const StreamParamsVec& video_streams = vcd->streams();
1367 ASSERT_EQ(1U, video_streams.size());
1368 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1369 const SsrcGroup* sim_ssrc_group =
1370 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1371 ASSERT_TRUE(sim_ssrc_group != NULL);
1372 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1373}
1374
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001375// Create an audio and video answer to a standard video offer with:
1376// - one video track
1377// - two audio tracks
1378// - two data tracks
1379// and ensure it matches what we expect. Also updates the initial answer by
1380// adding a new video track and removes one of the audio tracks.
1381TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1382 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001383 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001384 offer_opts.data_channel_type = cricket::DCT_RTP;
1385 f1_.set_secure(SEC_ENABLED);
1386 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001387 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001388 NULL));
1389
1390 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001391 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1392 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1393 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001394 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001395 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1396 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001397
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001398 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001399 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1400
1401 ASSERT_TRUE(answer.get() != NULL);
1402 const ContentInfo* ac = answer->GetContentByName("audio");
1403 const ContentInfo* vc = answer->GetContentByName("video");
1404 const ContentInfo* dc = answer->GetContentByName("data");
1405 ASSERT_TRUE(ac != NULL);
1406 ASSERT_TRUE(vc != NULL);
1407 ASSERT_TRUE(dc != NULL);
1408 const AudioContentDescription* acd =
1409 static_cast<const AudioContentDescription*>(ac->description);
1410 const VideoContentDescription* vcd =
1411 static_cast<const VideoContentDescription*>(vc->description);
1412 const DataContentDescription* dcd =
1413 static_cast<const DataContentDescription*>(dc->description);
1414 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1415 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1416 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1417
1418 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1419 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1420
1421 const StreamParamsVec& audio_streams = acd->streams();
1422 ASSERT_EQ(2U, audio_streams.size());
1423 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1424 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1425 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1426 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1427 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1428 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1429 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1430
1431 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1432 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1433
1434 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1435 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1436
1437 const StreamParamsVec& video_streams = vcd->streams();
1438 ASSERT_EQ(1U, video_streams.size());
1439 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1440 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1441 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1442 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1443
1444 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1445 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1446
1447 const StreamParamsVec& data_streams = dcd->streams();
1448 ASSERT_EQ(2U, data_streams.size());
1449 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1450 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1451 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1452 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1453 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1454 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1455 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1456
1457 EXPECT_EQ(cricket::kDataMaxBandwidth,
1458 dcd->bandwidth()); // default bandwidth (auto)
1459 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1460
1461 // Update the answer. Add a new video track that is not synched to the
1462 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001463 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1464 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1465 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001466 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001467 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1468
1469 ASSERT_TRUE(updated_answer.get() != NULL);
1470 ac = updated_answer->GetContentByName("audio");
1471 vc = updated_answer->GetContentByName("video");
1472 dc = updated_answer->GetContentByName("data");
1473 ASSERT_TRUE(ac != NULL);
1474 ASSERT_TRUE(vc != NULL);
1475 ASSERT_TRUE(dc != NULL);
1476 const AudioContentDescription* updated_acd =
1477 static_cast<const AudioContentDescription*>(ac->description);
1478 const VideoContentDescription* updated_vcd =
1479 static_cast<const VideoContentDescription*>(vc->description);
1480 const DataContentDescription* updated_dcd =
1481 static_cast<const DataContentDescription*>(dc->description);
1482
1483 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1484 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1485 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1486 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1487 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1488 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1489
1490 EXPECT_EQ(acd->type(), updated_acd->type());
1491 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1492 EXPECT_EQ(vcd->type(), updated_vcd->type());
1493 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1494 EXPECT_EQ(dcd->type(), updated_dcd->type());
1495 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1496
1497 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1498 ASSERT_EQ(1U, updated_audio_streams.size());
1499 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1500
1501 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1502 ASSERT_EQ(2U, updated_video_streams.size());
1503 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1504 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1505 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1506
1507 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1508 ASSERT_EQ(1U, updated_data_streams.size());
1509 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1510}
1511
1512
1513// Create an updated offer after creating an answer to the original offer and
1514// verify that the codecs that were part of the original answer are not changed
1515// in the updated offer.
1516TEST_F(MediaSessionDescriptionFactoryTest,
1517 RespondentCreatesOfferAfterCreatingAnswer) {
1518 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001519 opts.recv_audio = true;
1520 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001522 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1523 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 f2_.CreateAnswer(offer.get(), opts, NULL));
1525
1526 const AudioContentDescription* acd =
1527 GetFirstAudioContentDescription(answer.get());
1528 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1529
1530 const VideoContentDescription* vcd =
1531 GetFirstVideoContentDescription(answer.get());
1532 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1533
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001534 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001535 f2_.CreateOffer(opts, answer.get()));
1536
1537 // The expected audio codecs are the common audio codecs from the first
1538 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1539 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001540 // TODO(wu): |updated_offer| should not include the codec
1541 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001542 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543 kAudioCodecsAnswer[0],
1544 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001545 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 };
1547
1548 // The expected video codecs are the common video codecs from the first
1549 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1550 // preference order.
1551 const VideoCodec kUpdatedVideoCodecOffer[] = {
1552 kVideoCodecsAnswer[0],
1553 kVideoCodecs2[1],
1554 };
1555
1556 const AudioContentDescription* updated_acd =
1557 GetFirstAudioContentDescription(updated_offer.get());
1558 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1559
1560 const VideoContentDescription* updated_vcd =
1561 GetFirstVideoContentDescription(updated_offer.get());
1562 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1563}
1564
1565// Create an updated offer after creating an answer to the original offer and
1566// verify that the codecs that were part of the original answer are not changed
1567// in the updated offer. In this test Rtx is enabled.
1568TEST_F(MediaSessionDescriptionFactoryTest,
1569 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1570 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001571 opts.recv_video = true;
1572 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001574 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001575 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576 f1_.set_video_codecs(f1_codecs);
1577
1578 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001580 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001581 f2_.set_video_codecs(f2_codecs);
1582
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001583 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001584 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001585 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586 f2_.CreateAnswer(offer.get(), opts, NULL));
1587
1588 const VideoContentDescription* vcd =
1589 GetFirstVideoContentDescription(answer.get());
1590
1591 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001592 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1593 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001594
1595 EXPECT_EQ(expected_codecs, vcd->codecs());
1596
1597 // Now, make sure we get same result, except for the preference order,
1598 // if |f2_| creates an updated offer even though the default payload types
1599 // are different from |f1_|.
1600 expected_codecs[0].preference = f1_codecs[1].preference;
1601
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001602 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001603 f2_.CreateOffer(opts, answer.get()));
1604 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001605 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1607
1608 const VideoContentDescription* updated_vcd =
1609 GetFirstVideoContentDescription(updated_answer.get());
1610
1611 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1612}
1613
1614// Create an updated offer that adds video after creating an audio only answer
1615// to the original offer. This test verifies that if a video codec and the RTX
1616// codec have the same default payload type as an audio codec that is already in
1617// use, the added codecs payload types are changed.
1618TEST_F(MediaSessionDescriptionFactoryTest,
1619 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1620 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001622 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001623 f1_.set_video_codecs(f1_codecs);
1624
1625 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001626 opts.recv_audio = true;
1627 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001629 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1630 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001631 f2_.CreateAnswer(offer.get(), opts, NULL));
1632
1633 const AudioContentDescription* acd =
1634 GetFirstAudioContentDescription(answer.get());
1635 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1636
1637 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1638 // reference be the same as an audio codec that was negotiated in the
1639 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001640 opts.recv_audio = true;
1641 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642
1643 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1644 int used_pl_type = acd->codecs()[0].id;
1645 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001646 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001647 f2_.set_video_codecs(f2_codecs);
1648
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001649 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 f2_.CreateOffer(opts, answer.get()));
1651 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001652 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001653 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1654
1655 const AudioContentDescription* updated_acd =
1656 GetFirstAudioContentDescription(answer.get());
1657 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1658
1659 const VideoContentDescription* updated_vcd =
1660 GetFirstVideoContentDescription(updated_answer.get());
1661
1662 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001663 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1665 EXPECT_NE(used_pl_type, new_h264_pl_type);
1666 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001667 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1669 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1670}
1671
1672// Test that RTX is ignored when there is no associated payload type parameter.
1673TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1674 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001675 opts.recv_video = true;
1676 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001677 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001678 // This creates RTX without associated payload type parameter.
1679 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001680 f1_.set_video_codecs(f1_codecs);
1681
1682 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001683 // This creates RTX for H264 with the payload type |f2_| uses.
1684 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001685 f2_.set_video_codecs(f2_codecs);
1686
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001687 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001688 ASSERT_TRUE(offer.get() != NULL);
1689 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1690 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1691 // is possible to test that that RTX is dropped when
1692 // kCodecParamAssociatedPayloadType is missing in the offer.
1693 VideoContentDescription* desc =
1694 static_cast<cricket::VideoContentDescription*>(
1695 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1696 ASSERT_TRUE(desc != NULL);
1697 std::vector<VideoCodec> codecs = desc->codecs();
1698 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1699 iter != codecs.end(); ++iter) {
1700 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1701 iter->params.clear();
1702 }
1703 }
1704 desc->set_codecs(codecs);
1705
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001706 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707 f2_.CreateAnswer(offer.get(), opts, NULL));
1708
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001709 std::vector<std::string> codec_names =
1710 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1711 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1712 cricket::kRtxCodecName));
1713}
1714
1715// Test that RTX will be filtered out in the answer if its associated payload
1716// type doesn't match the local value.
1717TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1718 MediaSessionOptions opts;
1719 opts.recv_video = true;
1720 opts.recv_audio = false;
1721 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1722 // This creates RTX for H264 in sender.
1723 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1724 f1_.set_video_codecs(f1_codecs);
1725
1726 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1727 // This creates RTX for H263 in receiver.
1728 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1729 f2_.set_video_codecs(f2_codecs);
1730
1731 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1732 ASSERT_TRUE(offer.get() != NULL);
1733 // Associated payload type doesn't match, therefore, RTX codec is removed in
1734 // the answer.
1735 rtc::scoped_ptr<SessionDescription> answer(
1736 f2_.CreateAnswer(offer.get(), opts, NULL));
1737
1738 std::vector<std::string> codec_names =
1739 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1740 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1741 cricket::kRtxCodecName));
1742}
1743
1744// Test that when multiple RTX codecs are offered, only the matched RTX codec
1745// is added in the answer, and the unsupported RTX codec is filtered out.
1746TEST_F(MediaSessionDescriptionFactoryTest,
1747 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1748 MediaSessionOptions opts;
1749 opts.recv_video = true;
1750 opts.recv_audio = false;
1751 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1752 // This creates RTX for H264-SVC in sender.
1753 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1754 f1_.set_video_codecs(f1_codecs);
1755
1756 // This creates RTX for H264 in sender.
1757 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1758 f1_.set_video_codecs(f1_codecs);
1759
1760 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1761 // This creates RTX for H264 in receiver.
1762 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1763 f2_.set_video_codecs(f2_codecs);
1764
1765 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1766 // for H264-SVC should also be removed.
1767 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1768 ASSERT_TRUE(offer.get() != NULL);
1769 rtc::scoped_ptr<SessionDescription> answer(
1770 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001771 const VideoContentDescription* vcd =
1772 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001773 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1774 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1775 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001776
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001777 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001778}
1779
Noah Richards2e7a0982015-05-18 14:02:54 -07001780// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1781// generated for each simulcast ssrc and correctly grouped.
1782TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1783 MediaSessionOptions opts;
1784 opts.recv_video = true;
1785 opts.recv_audio = false;
1786
1787 // Add simulcast streams.
1788 opts.AddSendVideoStream("stream1", "stream1label", 3);
1789
1790 // Use a single real codec, and then add RTX for it.
1791 std::vector<VideoCodec> f1_codecs;
1792 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30, 1));
1793 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1794 f1_.set_video_codecs(f1_codecs);
1795
1796 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1797 // is a FID ssrc + grouping for each.
1798 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1799 ASSERT_TRUE(offer.get() != NULL);
1800 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1801 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1802 ASSERT_TRUE(desc != NULL);
1803 EXPECT_TRUE(desc->multistream());
1804 const StreamParamsVec& streams = desc->streams();
1805 // Single stream.
1806 ASSERT_EQ(1u, streams.size());
1807 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1808 EXPECT_EQ(6u, streams[0].ssrcs.size());
1809 // And should have a SIM group for the simulcast.
1810 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1811 // And a FID group for RTX.
1812 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
1813 std::vector<uint32> primary_ssrcs;
1814 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1815 EXPECT_EQ(3u, primary_ssrcs.size());
1816 std::vector<uint32> fid_ssrcs;
1817 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1818 EXPECT_EQ(3u, fid_ssrcs.size());
1819}
1820
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001821// Create an updated offer after creating an answer to the original offer and
1822// verify that the RTP header extensions that were part of the original answer
1823// are not changed in the updated offer.
1824TEST_F(MediaSessionDescriptionFactoryTest,
1825 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1826 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001827 opts.recv_audio = true;
1828 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001829
1830 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1831 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1832 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1833 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1834
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001835 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1836 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001837 f2_.CreateAnswer(offer.get(), opts, NULL));
1838
1839 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1840 GetFirstAudioContentDescription(
1841 answer.get())->rtp_header_extensions());
1842 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1843 GetFirstVideoContentDescription(
1844 answer.get())->rtp_header_extensions());
1845
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001846 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 f2_.CreateOffer(opts, answer.get()));
1848
1849 // The expected RTP header extensions in the new offer are the resulting
1850 // extensions from the first offer/answer exchange plus the extensions only
1851 // |f2_| offer.
1852 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001853 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001854 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1855 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001856 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1857 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001858 };
1859
1860 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001861 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1863 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001864 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1865 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866 };
1867
1868 const AudioContentDescription* updated_acd =
1869 GetFirstAudioContentDescription(updated_offer.get());
1870 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1871 updated_acd->rtp_header_extensions());
1872
1873 const VideoContentDescription* updated_vcd =
1874 GetFirstVideoContentDescription(updated_offer.get());
1875 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1876 updated_vcd->rtp_header_extensions());
1877}
1878
deadbeefa5b273a2015-08-20 17:30:13 -07001879// Verify that if the same RTP extension URI is used for audio and video, the
1880// same ID is used. Also verify that the ID isn't changed when creating an
1881// updated offer (this was previously a bug).
1882TEST_F(MediaSessionDescriptionFactoryTest,
1883 RtpHeaderExtensionIdReused) {
1884 MediaSessionOptions opts;
1885 opts.recv_audio = true;
1886 opts.recv_video = true;
1887
1888 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1889 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1890
1891 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1892
1893 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1894 // the video extensions.
1895 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1896 kVideoRtpExtension3[0],
1897 kAudioRtpExtension3[1],
1898 };
1899
1900 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1901 GetFirstAudioContentDescription(
1902 offer.get())->rtp_header_extensions());
1903 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1904 GetFirstVideoContentDescription(
1905 offer.get())->rtp_header_extensions());
1906
1907 // Nothing should change when creating a new offer
1908 rtc::scoped_ptr<SessionDescription> updated_offer(
1909 f1_.CreateOffer(opts, offer.get()));
1910
1911 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1912 GetFirstAudioContentDescription(
1913 updated_offer.get())->rtp_header_extensions());
1914 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1915 GetFirstVideoContentDescription(
1916 updated_offer.get())->rtp_header_extensions());
1917}
1918
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001919TEST(MediaSessionDescription, CopySessionDescription) {
1920 SessionDescription source;
1921 cricket::ContentGroup group(cricket::CN_AUDIO);
1922 source.AddGroup(group);
1923 AudioContentDescription* acd(new AudioContentDescription());
1924 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1925 acd->AddLegacyStream(1);
1926 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1927 VideoContentDescription* vcd(new VideoContentDescription());
1928 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1929 vcd->AddLegacyStream(2);
1930 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1931
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001932 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001933 ASSERT_TRUE(copy.get() != NULL);
1934 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1935 const ContentInfo* ac = copy->GetContentByName("audio");
1936 const ContentInfo* vc = copy->GetContentByName("video");
1937 ASSERT_TRUE(ac != NULL);
1938 ASSERT_TRUE(vc != NULL);
1939 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1940 const AudioContentDescription* acd_copy =
1941 static_cast<const AudioContentDescription*>(ac->description);
1942 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1943 EXPECT_EQ(1u, acd->first_ssrc());
1944
1945 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1946 const VideoContentDescription* vcd_copy =
1947 static_cast<const VideoContentDescription*>(vc->description);
1948 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1949 EXPECT_EQ(2u, vcd->first_ssrc());
1950}
1951
1952// The below TestTransportInfoXXX tests create different offers/answers, and
1953// ensure the TransportInfo in the SessionDescription matches what we expect.
1954TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1955 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001956 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001957 TestTransportInfo(true, options, false);
1958}
1959
1960TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1961 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001962 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001963 TestTransportInfo(true, options, true);
1964}
1965
1966TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1967 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001968 options.recv_audio = true;
1969 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001970 options.data_channel_type = cricket::DCT_RTP;
1971 TestTransportInfo(true, options, false);
1972}
1973
1974TEST_F(MediaSessionDescriptionFactoryTest,
1975 TestTransportInfoOfferMultimediaCurrent) {
1976 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001977 options.recv_audio = true;
1978 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001979 options.data_channel_type = cricket::DCT_RTP;
1980 TestTransportInfo(true, options, true);
1981}
1982
1983TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1984 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001985 options.recv_audio = true;
1986 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001987 options.data_channel_type = cricket::DCT_RTP;
1988 options.bundle_enabled = true;
1989 TestTransportInfo(true, options, false);
1990}
1991
1992TEST_F(MediaSessionDescriptionFactoryTest,
1993 TestTransportInfoOfferBundleCurrent) {
1994 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001995 options.recv_audio = true;
1996 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997 options.data_channel_type = cricket::DCT_RTP;
1998 options.bundle_enabled = true;
1999 TestTransportInfo(true, options, true);
2000}
2001
2002TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2003 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002004 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002005 TestTransportInfo(false, options, false);
2006}
2007
2008TEST_F(MediaSessionDescriptionFactoryTest,
2009 TestTransportInfoAnswerAudioCurrent) {
2010 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002011 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002012 TestTransportInfo(false, options, true);
2013}
2014
2015TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2016 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002017 options.recv_audio = true;
2018 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002019 options.data_channel_type = cricket::DCT_RTP;
2020 TestTransportInfo(false, options, false);
2021}
2022
2023TEST_F(MediaSessionDescriptionFactoryTest,
2024 TestTransportInfoAnswerMultimediaCurrent) {
2025 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002026 options.recv_audio = true;
2027 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002028 options.data_channel_type = cricket::DCT_RTP;
2029 TestTransportInfo(false, options, true);
2030}
2031
2032TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2033 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002034 options.recv_audio = true;
2035 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002036 options.data_channel_type = cricket::DCT_RTP;
2037 options.bundle_enabled = true;
2038 TestTransportInfo(false, options, false);
2039}
2040
2041TEST_F(MediaSessionDescriptionFactoryTest,
2042 TestTransportInfoAnswerBundleCurrent) {
2043 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002044 options.recv_audio = true;
2045 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002046 options.data_channel_type = cricket::DCT_RTP;
2047 options.bundle_enabled = true;
2048 TestTransportInfo(false, options, true);
2049}
2050
2051// Create an offer with bundle enabled and verify the crypto parameters are
2052// the common set of the available cryptos.
2053TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2054 TestCryptoWithBundle(true);
2055}
2056
2057// Create an answer with bundle enabled and verify the crypto parameters are
2058// the common set of the available cryptos.
2059TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2060 TestCryptoWithBundle(false);
2061}
2062
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002063// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2064// DTLS is not enabled locally.
2065TEST_F(MediaSessionDescriptionFactoryTest,
2066 TestOfferDtlsSavpfWithoutDtlsFailed) {
2067 f1_.set_secure(SEC_ENABLED);
2068 f2_.set_secure(SEC_ENABLED);
2069 tdf1_.set_secure(SEC_DISABLED);
2070 tdf2_.set_secure(SEC_DISABLED);
2071
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002072 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002073 f1_.CreateOffer(MediaSessionOptions(), NULL));
2074 ASSERT_TRUE(offer.get() != NULL);
2075 ContentInfo* offer_content = offer->GetContentByName("audio");
2076 ASSERT_TRUE(offer_content != NULL);
2077 AudioContentDescription* offer_audio_desc =
2078 static_cast<AudioContentDescription*>(offer_content->description);
2079 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2080
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002081 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002082 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2083 ASSERT_TRUE(answer != NULL);
2084 ContentInfo* answer_content = answer->GetContentByName("audio");
2085 ASSERT_TRUE(answer_content != NULL);
2086
2087 ASSERT_TRUE(answer_content->rejected);
2088}
2089
2090// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2091// UDP/TLS/RTP/SAVPF.
2092TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2093 f1_.set_secure(SEC_ENABLED);
2094 f2_.set_secure(SEC_ENABLED);
2095 tdf1_.set_secure(SEC_ENABLED);
2096 tdf2_.set_secure(SEC_ENABLED);
2097
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002098 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002099 f1_.CreateOffer(MediaSessionOptions(), NULL));
2100 ASSERT_TRUE(offer.get() != NULL);
2101 ContentInfo* offer_content = offer->GetContentByName("audio");
2102 ASSERT_TRUE(offer_content != NULL);
2103 AudioContentDescription* offer_audio_desc =
2104 static_cast<AudioContentDescription*>(offer_content->description);
2105 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2106
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002107 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002108 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2109 ASSERT_TRUE(answer != NULL);
2110
2111 const ContentInfo* answer_content = answer->GetContentByName("audio");
2112 ASSERT_TRUE(answer_content != NULL);
2113 ASSERT_FALSE(answer_content->rejected);
2114
2115 const AudioContentDescription* answer_audio_desc =
2116 static_cast<const AudioContentDescription*>(answer_content->description);
2117 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2118 answer_audio_desc->protocol());
2119}
2120
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002121// Test that we include both SDES and DTLS in the offer, but only include SDES
2122// in the answer if DTLS isn't negotiated.
2123TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2124 f1_.set_secure(SEC_ENABLED);
2125 f2_.set_secure(SEC_ENABLED);
2126 tdf1_.set_secure(SEC_ENABLED);
2127 tdf2_.set_secure(SEC_DISABLED);
2128 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002129 options.recv_audio = true;
2130 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002131 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002132 const cricket::MediaContentDescription* audio_media_desc;
2133 const cricket::MediaContentDescription* video_media_desc;
2134 const cricket::TransportDescription* audio_trans_desc;
2135 const cricket::TransportDescription* video_trans_desc;
2136
2137 // Generate an offer with SDES and DTLS support.
2138 offer.reset(f1_.CreateOffer(options, NULL));
2139 ASSERT_TRUE(offer.get() != NULL);
2140
2141 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2142 offer->GetContentDescriptionByName("audio"));
2143 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002144 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145 offer->GetContentDescriptionByName("video"));
2146 ASSERT_TRUE(video_media_desc != NULL);
2147 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2148 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2149
2150 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2151 ASSERT_TRUE(audio_trans_desc != NULL);
2152 video_trans_desc = offer->GetTransportDescriptionByName("video");
2153 ASSERT_TRUE(video_trans_desc != NULL);
2154 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2155 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2156
2157 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2158 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2159 ASSERT_TRUE(answer.get() != NULL);
2160
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002161 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162 answer->GetContentDescriptionByName("audio"));
2163 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002164 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002165 answer->GetContentDescriptionByName("video"));
2166 ASSERT_TRUE(video_media_desc != NULL);
2167 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2168 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2169
2170 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2171 ASSERT_TRUE(audio_trans_desc != NULL);
2172 video_trans_desc = answer->GetTransportDescriptionByName("video");
2173 ASSERT_TRUE(video_trans_desc != NULL);
2174 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2175 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2176
2177 // Enable DTLS; the answer should now only have DTLS support.
2178 tdf2_.set_secure(SEC_ENABLED);
2179 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2180 ASSERT_TRUE(answer.get() != NULL);
2181
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002182 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002183 answer->GetContentDescriptionByName("audio"));
2184 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002185 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002186 answer->GetContentDescriptionByName("video"));
2187 ASSERT_TRUE(video_media_desc != NULL);
2188 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2189 EXPECT_TRUE(video_media_desc->cryptos().empty());
2190 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2191 audio_media_desc->protocol());
2192 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2193 video_media_desc->protocol());
2194
2195 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2196 ASSERT_TRUE(audio_trans_desc != NULL);
2197 video_trans_desc = answer->GetTransportDescriptionByName("video");
2198 ASSERT_TRUE(video_trans_desc != NULL);
2199 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2200 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002201
2202 // Try creating offer again. DTLS enabled now, crypto's should be empty
2203 // in new offer.
2204 offer.reset(f1_.CreateOffer(options, offer.get()));
2205 ASSERT_TRUE(offer.get() != NULL);
2206 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2207 offer->GetContentDescriptionByName("audio"));
2208 ASSERT_TRUE(audio_media_desc != NULL);
2209 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2210 offer->GetContentDescriptionByName("video"));
2211 ASSERT_TRUE(video_media_desc != NULL);
2212 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2213 EXPECT_TRUE(video_media_desc->cryptos().empty());
2214
2215 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2216 ASSERT_TRUE(audio_trans_desc != NULL);
2217 video_trans_desc = offer->GetTransportDescriptionByName("video");
2218 ASSERT_TRUE(video_trans_desc != NULL);
2219 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2220 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221}
2222
2223// Test that an answer can't be created if cryptos are required but the offer is
2224// unsecure.
2225TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2226 MediaSessionOptions options;
2227 f1_.set_secure(SEC_DISABLED);
2228 tdf1_.set_secure(SEC_DISABLED);
2229 f2_.set_secure(SEC_REQUIRED);
2230 tdf1_.set_secure(SEC_ENABLED);
2231
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002232 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002233 NULL));
2234 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002235 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002236 f2_.CreateAnswer(offer.get(), options, NULL));
2237 EXPECT_TRUE(answer.get() == NULL);
2238}
2239
2240// Test that we accept a DTLS offer without SDES and create an appropriate
2241// answer.
2242TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2243 f1_.set_secure(SEC_DISABLED);
2244 f2_.set_secure(SEC_ENABLED);
2245 tdf1_.set_secure(SEC_ENABLED);
2246 tdf2_.set_secure(SEC_ENABLED);
2247 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002248 options.recv_audio = true;
2249 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002250 options.data_channel_type = cricket::DCT_RTP;
2251
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002252 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002253
2254 // Generate an offer with DTLS but without SDES.
2255 offer.reset(f1_.CreateOffer(options, NULL));
2256 ASSERT_TRUE(offer.get() != NULL);
2257
2258 const AudioContentDescription* audio_offer =
2259 GetFirstAudioContentDescription(offer.get());
2260 ASSERT_TRUE(audio_offer->cryptos().empty());
2261 const VideoContentDescription* video_offer =
2262 GetFirstVideoContentDescription(offer.get());
2263 ASSERT_TRUE(video_offer->cryptos().empty());
2264 const DataContentDescription* data_offer =
2265 GetFirstDataContentDescription(offer.get());
2266 ASSERT_TRUE(data_offer->cryptos().empty());
2267
2268 const cricket::TransportDescription* audio_offer_trans_desc =
2269 offer->GetTransportDescriptionByName("audio");
2270 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2271 const cricket::TransportDescription* video_offer_trans_desc =
2272 offer->GetTransportDescriptionByName("video");
2273 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2274 const cricket::TransportDescription* data_offer_trans_desc =
2275 offer->GetTransportDescriptionByName("data");
2276 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2277
2278 // Generate an answer with DTLS.
2279 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2280 ASSERT_TRUE(answer.get() != NULL);
2281
2282 const cricket::TransportDescription* audio_answer_trans_desc =
2283 answer->GetTransportDescriptionByName("audio");
2284 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2285 const cricket::TransportDescription* video_answer_trans_desc =
2286 answer->GetTransportDescriptionByName("video");
2287 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2288 const cricket::TransportDescription* data_answer_trans_desc =
2289 answer->GetTransportDescriptionByName("data");
2290 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2291}
2292
2293// Verifies if vad_enabled option is set to false, CN codecs are not present in
2294// offer or answer.
2295TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2296 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002297 options.recv_audio = true;
2298 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002299 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002300 f1_.CreateOffer(options, NULL));
2301 ASSERT_TRUE(offer.get() != NULL);
2302 const ContentInfo* audio_content = offer->GetContentByName("audio");
2303 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2304
2305 options.vad_enabled = false;
2306 offer.reset(f1_.CreateOffer(options, NULL));
2307 ASSERT_TRUE(offer.get() != NULL);
2308 audio_content = offer->GetContentByName("audio");
2309 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002310 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002311 f1_.CreateAnswer(offer.get(), options, NULL));
2312 ASSERT_TRUE(answer.get() != NULL);
2313 audio_content = answer->GetContentByName("audio");
2314 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2315}