blob: ef155f08789d7a8a803c0a422a2252b49587dd3d [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"
33#include "talk/p2p/base/constants.h"
34#include "talk/p2p/base/transportdescription.h"
35#include "talk/p2p/base/transportinfo.h"
36#include "talk/session/media/mediasession.h"
37#include "talk/session/media/srtpfilter.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000038#include "webrtc/base/fakesslidentity.h"
39#include "webrtc/base/gunit.h"
40#include "webrtc/base/messagedigest.h"
41#include "webrtc/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042
43#ifdef HAVE_SRTP
44#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000045 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046 ASSERT_EQ(s, cd->cryptos().size()); \
47 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
48#else
49#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000050 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051 ASSERT_EQ(0U, cd->cryptos().size());
52#endif
53
54typedef std::vector<cricket::Candidate> Candidates;
55
56using cricket::MediaContentDescription;
57using cricket::MediaSessionDescriptionFactory;
58using cricket::MediaSessionOptions;
59using cricket::MediaType;
60using cricket::SessionDescription;
61using cricket::SsrcGroup;
62using cricket::StreamParams;
63using cricket::StreamParamsVec;
64using cricket::TransportDescription;
65using cricket::TransportDescriptionFactory;
66using cricket::TransportInfo;
67using cricket::ContentInfo;
68using cricket::CryptoParamsVec;
69using cricket::AudioContentDescription;
70using cricket::VideoContentDescription;
71using cricket::DataContentDescription;
72using cricket::GetFirstAudioContentDescription;
73using cricket::GetFirstVideoContentDescription;
74using cricket::GetFirstDataContentDescription;
75using cricket::kAutoBandwidth;
76using cricket::AudioCodec;
77using cricket::VideoCodec;
78using cricket::DataCodec;
79using cricket::NS_JINGLE_RTP;
80using cricket::MEDIA_TYPE_AUDIO;
81using cricket::MEDIA_TYPE_VIDEO;
82using cricket::MEDIA_TYPE_DATA;
83using cricket::RtpHeaderExtension;
84using cricket::SEC_DISABLED;
85using cricket::SEC_ENABLED;
86using cricket::SEC_REQUIRED;
87using cricket::CS_AES_CM_128_HMAC_SHA1_32;
88using cricket::CS_AES_CM_128_HMAC_SHA1_80;
89
90static const AudioCodec kAudioCodecs1[] = {
91 AudioCodec(103, "ISAC", 16000, -1, 1, 6),
92 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
93 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
94 AudioCodec(8, "PCMA", 8000, 64000, 1, 3),
95 AudioCodec(117, "red", 8000, 0, 1, 2),
96 AudioCodec(107, "CN", 48000, 0, 1, 1)
97};
98
99static const AudioCodec kAudioCodecs2[] = {
100 AudioCodec(126, "speex", 16000, 22000, 1, 3),
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000101 AudioCodec(0, "PCMU", 8000, 64000, 1, 2),
102 AudioCodec(127, "iLBC", 8000, 13300, 1, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103};
104
105static const AudioCodec kAudioCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000106 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
107 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108};
109
110static const VideoCodec kVideoCodecs1[] = {
111 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
112 VideoCodec(97, "H264", 320, 200, 30, 1)
113};
114
115static const VideoCodec kVideoCodecs2[] = {
116 VideoCodec(126, "H264", 320, 200, 30, 2),
117 VideoCodec(127, "H263", 320, 200, 30, 1)
118};
119
120static const VideoCodec kVideoCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000121 VideoCodec(97, "H264", 320, 200, 30, 1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122};
123
124static const DataCodec kDataCodecs1[] = {
125 DataCodec(98, "binary-data", 2),
126 DataCodec(99, "utf8-text", 1)
127};
128
129static const DataCodec kDataCodecs2[] = {
130 DataCodec(126, "binary-data", 2),
131 DataCodec(127, "utf8-text", 1)
132};
133
134static const DataCodec kDataCodecsAnswer[] = {
135 DataCodec(98, "binary-data", 2),
136 DataCodec(99, "utf8-text", 1)
137};
138
139static const RtpHeaderExtension kAudioRtpExtension1[] = {
140 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
141 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
142};
143
144static const RtpHeaderExtension kAudioRtpExtension2[] = {
145 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
146 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000147 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148};
149
150static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
151 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
152};
153
154static const RtpHeaderExtension kVideoRtpExtension1[] = {
155 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000156 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157};
158
159static const RtpHeaderExtension kVideoRtpExtension2[] = {
160 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
161 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000162 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163};
164
165static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
166 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
167};
168
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000169static const uint32 kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
170static const uint32 kSimSsrc[] = {10, 20, 30};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171static const uint32 kFec1Ssrc[] = {10, 11};
172static const uint32 kFec2Ssrc[] = {20, 21};
173static const uint32 kFec3Ssrc[] = {30, 31};
174
175static const char kMediaStream1[] = "stream_1";
176static const char kMediaStream2[] = "stream_2";
177static const char kVideoTrack1[] = "video_1";
178static const char kVideoTrack2[] = "video_2";
179static const char kAudioTrack1[] = "audio_1";
180static const char kAudioTrack2[] = "audio_2";
181static const char kAudioTrack3[] = "audio_3";
182static const char kDataTrack1[] = "data_1";
183static const char kDataTrack2[] = "data_2";
184static const char kDataTrack3[] = "data_3";
185
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000186static bool IsMediaContentOfType(const ContentInfo* content,
187 MediaType media_type) {
188 const MediaContentDescription* mdesc =
189 static_cast<const MediaContentDescription*>(content->description);
190 return mdesc && mdesc->type() == media_type;
191}
192
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000193static cricket::MediaContentDirection
194GetMediaDirection(const ContentInfo* content) {
195 cricket::MediaContentDescription* desc =
196 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
197 return desc->direction();
198}
199
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000200class MediaSessionDescriptionFactoryTest : public testing::Test {
201 public:
202 MediaSessionDescriptionFactoryTest()
203 : f1_(&tdf1_), f2_(&tdf2_), id1_("id1"), id2_("id2") {
204 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
205 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
206 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
207 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
208 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
209 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
210 tdf1_.set_identity(&id1_);
211 tdf2_.set_identity(&id2_);
212 }
213
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000214 // Create a video StreamParamsVec object with:
215 // - one video stream with 3 simulcast streams and FEC,
216 StreamParamsVec CreateComplexVideoStreamParamsVec() {
217 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
218 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
219 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
220 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
221
222 std::vector<SsrcGroup> ssrc_groups;
223 ssrc_groups.push_back(sim_group);
224 ssrc_groups.push_back(fec_group1);
225 ssrc_groups.push_back(fec_group2);
226 ssrc_groups.push_back(fec_group3);
227
228 StreamParams simulcast_params;
229 simulcast_params.id = kVideoTrack1;
230 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
231 simulcast_params.ssrc_groups = ssrc_groups;
232 simulcast_params.cname = "Video_SIM_FEC";
233 simulcast_params.sync_label = kMediaStream1;
234
235 StreamParamsVec video_streams;
236 video_streams.push_back(simulcast_params);
237
238 return video_streams;
239 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240
241 bool CompareCryptoParams(const CryptoParamsVec& c1,
242 const CryptoParamsVec& c2) {
243 if (c1.size() != c2.size())
244 return false;
245 for (size_t i = 0; i < c1.size(); ++i)
246 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
247 c1[i].key_params != c2[i].key_params ||
248 c1[i].session_params != c2[i].session_params)
249 return false;
250 return true;
251 }
252
253 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
254 bool has_current_desc) {
255 const std::string current_audio_ufrag = "current_audio_ufrag";
256 const std::string current_audio_pwd = "current_audio_pwd";
257 const std::string current_video_ufrag = "current_video_ufrag";
258 const std::string current_video_pwd = "current_video_pwd";
259 const std::string current_data_ufrag = "current_data_ufrag";
260 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000261 rtc::scoped_ptr<SessionDescription> current_desc;
262 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000263 if (has_current_desc) {
264 current_desc.reset(new SessionDescription());
265 EXPECT_TRUE(current_desc->AddTransportInfo(
266 TransportInfo("audio",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000267 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000268 current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000269 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000270 EXPECT_TRUE(current_desc->AddTransportInfo(
271 TransportInfo("video",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000272 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000273 current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000274 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275 EXPECT_TRUE(current_desc->AddTransportInfo(
276 TransportInfo("data",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000277 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000278 current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000279 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000280 }
281 if (offer) {
282 desc.reset(f1_.CreateOffer(options, current_desc.get()));
283 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000284 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 offer.reset(f1_.CreateOffer(options, NULL));
286 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
287 }
288 ASSERT_TRUE(desc.get() != NULL);
289 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000290 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000291 EXPECT_TRUE(ti_audio != NULL);
292 if (has_current_desc) {
293 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
294 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
295 } else {
296 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
297 ti_audio->description.ice_ufrag.size());
298 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
299 ti_audio->description.ice_pwd.size());
300 }
301
302 } else {
303 EXPECT_TRUE(ti_audio == NULL);
304 }
305 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000306 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000307 EXPECT_TRUE(ti_video != NULL);
308 if (options.bundle_enabled) {
309 EXPECT_EQ(ti_audio->description.ice_ufrag,
310 ti_video->description.ice_ufrag);
311 EXPECT_EQ(ti_audio->description.ice_pwd,
312 ti_video->description.ice_pwd);
313 } else {
314 if (has_current_desc) {
315 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
316 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
317 } else {
318 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
319 ti_video->description.ice_ufrag.size());
320 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
321 ti_video->description.ice_pwd.size());
322 }
323 }
324 } else {
325 EXPECT_TRUE(ti_video == NULL);
326 }
327 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
328 if (options.has_data()) {
329 EXPECT_TRUE(ti_data != NULL);
330 if (options.bundle_enabled) {
331 EXPECT_EQ(ti_audio->description.ice_ufrag,
332 ti_data->description.ice_ufrag);
333 EXPECT_EQ(ti_audio->description.ice_pwd,
334 ti_data->description.ice_pwd);
335 } else {
336 if (has_current_desc) {
337 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
338 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
339 } else {
340 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
341 ti_data->description.ice_ufrag.size());
342 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
343 ti_data->description.ice_pwd.size());
344 }
345 }
346 } else {
347 EXPECT_TRUE(ti_video == NULL);
348 }
349 }
350
351 void TestCryptoWithBundle(bool offer) {
352 f1_.set_secure(SEC_ENABLED);
353 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000354 options.recv_audio = true;
355 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000357 rtc::scoped_ptr<SessionDescription> ref_desc;
358 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 if (offer) {
360 options.bundle_enabled = false;
361 ref_desc.reset(f1_.CreateOffer(options, NULL));
362 options.bundle_enabled = true;
363 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
364 } else {
365 options.bundle_enabled = true;
366 ref_desc.reset(f1_.CreateOffer(options, NULL));
367 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
368 }
369 ASSERT_TRUE(desc.get() != NULL);
370 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000371 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000372 desc.get()->GetContentDescriptionByName("audio"));
373 ASSERT_TRUE(audio_media_desc != NULL);
374 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000375 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000376 desc.get()->GetContentDescriptionByName("video"));
377 ASSERT_TRUE(video_media_desc != NULL);
378 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
379 video_media_desc->cryptos()));
380 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
381 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
382 audio_media_desc->cryptos()[0].cipher_suite);
383
384 // Verify the selected crypto is one from the reference audio
385 // media content.
386 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000387 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000388 ref_desc.get()->GetContentDescriptionByName("audio"));
389 bool found = false;
390 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
391 if (ref_audio_media_desc->cryptos()[i].Matches(
392 audio_media_desc->cryptos()[0])) {
393 found = true;
394 break;
395 }
396 }
397 EXPECT_TRUE(found);
398 }
399
400 // This test that the audio and video media direction is set to
401 // |expected_direction_in_answer| in an answer if the offer direction is set
402 // to |direction_in_offer|.
403 void TestMediaDirectionInAnswer(
404 cricket::MediaContentDirection direction_in_offer,
405 cricket::MediaContentDirection expected_direction_in_answer) {
406 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000407 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000408 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409 f1_.CreateOffer(opts, NULL));
410 ASSERT_TRUE(offer.get() != NULL);
411 ContentInfo* ac_offer= offer->GetContentByName("audio");
412 ASSERT_TRUE(ac_offer != NULL);
413 AudioContentDescription* acd_offer =
414 static_cast<AudioContentDescription*>(ac_offer->description);
415 acd_offer->set_direction(direction_in_offer);
416 ContentInfo* vc_offer= offer->GetContentByName("video");
417 ASSERT_TRUE(vc_offer != NULL);
418 VideoContentDescription* vcd_offer =
419 static_cast<VideoContentDescription*>(vc_offer->description);
420 vcd_offer->set_direction(direction_in_offer);
421
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000422 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000423 f2_.CreateAnswer(offer.get(), opts, NULL));
424 const AudioContentDescription* acd_answer =
425 GetFirstAudioContentDescription(answer.get());
426 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
427 const VideoContentDescription* vcd_answer =
428 GetFirstVideoContentDescription(answer.get());
429 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
430 }
431
432 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
433 const cricket::ContentDescription* description = content->description;
434 ASSERT(description != NULL);
435 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000436 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000437 ASSERT(audio_content_desc != NULL);
438 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
439 if (audio_content_desc->codecs()[i].name == "CN")
440 return false;
441 }
442 return true;
443 }
444
445 protected:
446 MediaSessionDescriptionFactory f1_;
447 MediaSessionDescriptionFactory f2_;
448 TransportDescriptionFactory tdf1_;
449 TransportDescriptionFactory tdf2_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000450 rtc::FakeSSLIdentity id1_;
451 rtc::FakeSSLIdentity id2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000452};
453
454// Create a typical audio offer, and ensure it matches what we expect.
455TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
456 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000457 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458 f1_.CreateOffer(MediaSessionOptions(), NULL));
459 ASSERT_TRUE(offer.get() != NULL);
460 const ContentInfo* ac = offer->GetContentByName("audio");
461 const ContentInfo* vc = offer->GetContentByName("video");
462 ASSERT_TRUE(ac != NULL);
463 ASSERT_TRUE(vc == NULL);
464 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
465 const AudioContentDescription* acd =
466 static_cast<const AudioContentDescription*>(ac->description);
467 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
468 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
469 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
470 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
471 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
472 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
473 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
474}
475
476// Create a typical video offer, and ensure it matches what we expect.
477TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
478 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000479 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000480 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000481 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000482 offer(f1_.CreateOffer(opts, NULL));
483 ASSERT_TRUE(offer.get() != NULL);
484 const ContentInfo* ac = offer->GetContentByName("audio");
485 const ContentInfo* vc = offer->GetContentByName("video");
486 ASSERT_TRUE(ac != NULL);
487 ASSERT_TRUE(vc != NULL);
488 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
489 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
490 const AudioContentDescription* acd =
491 static_cast<const AudioContentDescription*>(ac->description);
492 const VideoContentDescription* vcd =
493 static_cast<const VideoContentDescription*>(vc->description);
494 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
495 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
496 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
497 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
498 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
499 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
500 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
501 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
502 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
503 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
504 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
505 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
506 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
507 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
508}
509
510// Test creating an offer with bundle where the Codecs have the same dynamic
511// RTP playlod type. The test verifies that the offer don't contain the
512// duplicate RTP payload types.
513TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
514 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
515 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
516 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
517 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
518 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
519
520 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000521 opts.recv_audio = true;
522 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000523 opts.data_channel_type = cricket::DCT_RTP;
524 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000525 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000526 offer(f2_.CreateOffer(opts, NULL));
527 const VideoContentDescription* vcd =
528 GetFirstVideoContentDescription(offer.get());
529 const AudioContentDescription* acd =
530 GetFirstAudioContentDescription(offer.get());
531 const DataContentDescription* dcd =
532 GetFirstDataContentDescription(offer.get());
533 ASSERT_TRUE(NULL != vcd);
534 ASSERT_TRUE(NULL != acd);
535 ASSERT_TRUE(NULL != dcd);
536 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
537 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
538 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
539 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
540 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
541 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
542}
543
544// Test creating an updated offer with with bundle, audio, video and data
545// after an audio only session has been negotiated.
546TEST_F(MediaSessionDescriptionFactoryTest,
547 TestCreateUpdatedVideoOfferWithBundle) {
548 f1_.set_secure(SEC_ENABLED);
549 f2_.set_secure(SEC_ENABLED);
550 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000551 opts.recv_audio = true;
552 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000553 opts.data_channel_type = cricket::DCT_NONE;
554 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000555 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
556 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 f2_.CreateAnswer(offer.get(), opts, NULL));
558
559 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000560 updated_opts.recv_audio = true;
561 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 updated_opts.data_channel_type = cricket::DCT_RTP;
563 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000564 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000565 updated_opts, answer.get()));
566
567 const AudioContentDescription* acd =
568 GetFirstAudioContentDescription(updated_offer.get());
569 const VideoContentDescription* vcd =
570 GetFirstVideoContentDescription(updated_offer.get());
571 const DataContentDescription* dcd =
572 GetFirstDataContentDescription(updated_offer.get());
573 EXPECT_TRUE(NULL != vcd);
574 EXPECT_TRUE(NULL != acd);
575 EXPECT_TRUE(NULL != dcd);
576
577 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
578 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
579 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
580 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
581 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
582 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
583}
wu@webrtc.org78187522013-10-07 23:32:02 +0000584// Create a RTP data offer, and ensure it matches what we expect.
585TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586 MediaSessionOptions opts;
587 opts.data_channel_type = cricket::DCT_RTP;
588 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000589 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000590 offer(f1_.CreateOffer(opts, NULL));
591 ASSERT_TRUE(offer.get() != NULL);
592 const ContentInfo* ac = offer->GetContentByName("audio");
593 const ContentInfo* dc = offer->GetContentByName("data");
594 ASSERT_TRUE(ac != NULL);
595 ASSERT_TRUE(dc != NULL);
596 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
597 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
598 const AudioContentDescription* acd =
599 static_cast<const AudioContentDescription*>(ac->description);
600 const DataContentDescription* dcd =
601 static_cast<const DataContentDescription*>(dc->description);
602 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
603 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
604 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
605 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
606 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
607 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
608 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
609 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
610 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
611 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
612 EXPECT_EQ(cricket::kDataMaxBandwidth,
613 dcd->bandwidth()); // default bandwidth (auto)
614 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
615 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
616 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
617}
618
wu@webrtc.org78187522013-10-07 23:32:02 +0000619// Create an SCTP data offer with bundle without error.
620TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
621 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000622 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000623 opts.bundle_enabled = true;
624 opts.data_channel_type = cricket::DCT_SCTP;
625 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000626 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000627 EXPECT_TRUE(offer.get() != NULL);
628 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
629}
630
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631// Create an audio, video offer without legacy StreamParams.
632TEST_F(MediaSessionDescriptionFactoryTest,
633 TestCreateOfferWithoutLegacyStreams) {
634 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000635 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000637 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000638 offer(f1_.CreateOffer(opts, NULL));
639 ASSERT_TRUE(offer.get() != NULL);
640 const ContentInfo* ac = offer->GetContentByName("audio");
641 const ContentInfo* vc = offer->GetContentByName("video");
642 ASSERT_TRUE(ac != NULL);
643 ASSERT_TRUE(vc != NULL);
644 const AudioContentDescription* acd =
645 static_cast<const AudioContentDescription*>(ac->description);
646 const VideoContentDescription* vcd =
647 static_cast<const VideoContentDescription*>(vc->description);
648
649 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
650 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
651}
652
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000653// Creates an audio+video sendonly offer.
654TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
655 MediaSessionOptions options;
656 options.recv_audio = false;
657 options.recv_video = false;
658 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
659 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
660
661 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
662 ASSERT_TRUE(offer.get() != NULL);
663 EXPECT_EQ(2u, offer->contents().size());
664 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
665 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
666
667 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
668 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
669}
670
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000671// Verifies that the order of the media contents in the current
672// SessionDescription is preserved in the new SessionDescription.
673TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
674 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000675 opts.recv_audio = false;
676 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000677 opts.data_channel_type = cricket::DCT_SCTP;
678
679 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
680 ASSERT_TRUE(offer1.get() != NULL);
681 EXPECT_EQ(1u, offer1->contents().size());
682 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
683
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000684 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000685 rtc::scoped_ptr<SessionDescription> offer2(
686 f1_.CreateOffer(opts, offer1.get()));
687 ASSERT_TRUE(offer2.get() != NULL);
688 EXPECT_EQ(2u, offer2->contents().size());
689 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
690 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
691
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000692 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000693 rtc::scoped_ptr<SessionDescription> offer3(
694 f1_.CreateOffer(opts, offer2.get()));
695 ASSERT_TRUE(offer3.get() != NULL);
696 EXPECT_EQ(3u, offer3->contents().size());
697 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
698 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
699 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
700
701 // Verifies the default order is audio-video-data, so that the previous checks
702 // didn't pass by accident.
703 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
704 ASSERT_TRUE(offer4.get() != NULL);
705 EXPECT_EQ(3u, offer4->contents().size());
706 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
707 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
708 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
709}
710
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000711// Create a typical audio answer, and ensure it matches what we expect.
712TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
713 f1_.set_secure(SEC_ENABLED);
714 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000715 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000716 f1_.CreateOffer(MediaSessionOptions(), NULL));
717 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000718 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000719 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
720 const ContentInfo* ac = answer->GetContentByName("audio");
721 const ContentInfo* vc = answer->GetContentByName("video");
722 ASSERT_TRUE(ac != NULL);
723 ASSERT_TRUE(vc == NULL);
724 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
725 const AudioContentDescription* acd =
726 static_cast<const AudioContentDescription*>(ac->description);
727 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
728 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
729 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
730 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
731 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
732 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
733 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
734}
735
736// Create a typical video answer, and ensure it matches what we expect.
737TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
738 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000739 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000740 f1_.set_secure(SEC_ENABLED);
741 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000742 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000743 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000744 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000745 f2_.CreateAnswer(offer.get(), opts, NULL));
746 const ContentInfo* ac = answer->GetContentByName("audio");
747 const ContentInfo* vc = answer->GetContentByName("video");
748 ASSERT_TRUE(ac != NULL);
749 ASSERT_TRUE(vc != NULL);
750 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
751 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
752 const AudioContentDescription* acd =
753 static_cast<const AudioContentDescription*>(ac->description);
754 const VideoContentDescription* vcd =
755 static_cast<const VideoContentDescription*>(vc->description);
756 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
757 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
758 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
759 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
760 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
761 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
762 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
763 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
764 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
765 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
766 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
767 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
768}
769
770TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
771 MediaSessionOptions opts;
772 opts.data_channel_type = cricket::DCT_RTP;
773 f1_.set_secure(SEC_ENABLED);
774 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000775 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000777 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000778 f2_.CreateAnswer(offer.get(), opts, NULL));
779 const ContentInfo* ac = answer->GetContentByName("audio");
780 const ContentInfo* vc = answer->GetContentByName("data");
781 ASSERT_TRUE(ac != NULL);
782 ASSERT_TRUE(vc != NULL);
783 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
784 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
785 const AudioContentDescription* acd =
786 static_cast<const AudioContentDescription*>(ac->description);
787 const DataContentDescription* vcd =
788 static_cast<const DataContentDescription*>(vc->description);
789 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
790 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
791 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
792 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
793 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
794 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
795 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
796 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
797 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
798 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
799 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
800 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
801}
802
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000803// Verifies that the order of the media contents in the offer is preserved in
804// the answer.
805TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
806 MediaSessionOptions opts;
807
808 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000809 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000810 opts.data_channel_type = cricket::DCT_SCTP;
811 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
812 ASSERT_TRUE(offer1.get() != NULL);
813
814 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000815 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000816 rtc::scoped_ptr<SessionDescription> offer2(
817 f1_.CreateOffer(opts, offer1.get()));
818 ASSERT_TRUE(offer2.get() != NULL);
819
820 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000821 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000822 rtc::scoped_ptr<SessionDescription> offer3(
823 f1_.CreateOffer(opts, offer2.get()));
824 ASSERT_TRUE(offer3.get() != NULL);
825
826 rtc::scoped_ptr<SessionDescription> answer(
827 f2_.CreateAnswer(offer3.get(), opts, NULL));
828 ASSERT_TRUE(answer.get() != NULL);
829 EXPECT_EQ(3u, answer->contents().size());
830 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
831 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
832 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
833}
834
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835// This test that the media direction is set to send/receive in an answer if
836// the offer is send receive.
837TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
838 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
839}
840
841// This test that the media direction is set to receive only in an answer if
842// the offer is send only.
843TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
844 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
845}
846
847// This test that the media direction is set to send only in an answer if
848// the offer is recv only.
849TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
850 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
851}
852
853// This test that the media direction is set to inactive in an answer if
854// the offer is inactive.
855TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
856 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
857}
858
859// Test that a data content with an unknown protocol is rejected in an answer.
860TEST_F(MediaSessionDescriptionFactoryTest,
861 CreateDataAnswerToOfferWithUnknownProtocol) {
862 MediaSessionOptions opts;
863 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000864 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000865 f1_.set_secure(SEC_ENABLED);
866 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000867 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000868 ContentInfo* dc_offer= offer->GetContentByName("data");
869 ASSERT_TRUE(dc_offer != NULL);
870 DataContentDescription* dcd_offer =
871 static_cast<DataContentDescription*>(dc_offer->description);
872 ASSERT_TRUE(dcd_offer != NULL);
873 std::string protocol = "a weird unknown protocol";
874 dcd_offer->set_protocol(protocol);
875
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000876 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000877 f2_.CreateAnswer(offer.get(), opts, NULL));
878
879 const ContentInfo* dc_answer = answer->GetContentByName("data");
880 ASSERT_TRUE(dc_answer != NULL);
881 EXPECT_TRUE(dc_answer->rejected);
882 const DataContentDescription* dcd_answer =
883 static_cast<const DataContentDescription*>(dc_answer->description);
884 ASSERT_TRUE(dcd_answer != NULL);
885 EXPECT_EQ(protocol, dcd_answer->protocol());
886}
887
888// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
889TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
890 MediaSessionOptions opts;
891 f1_.set_secure(SEC_DISABLED);
892 f2_.set_secure(SEC_DISABLED);
893 tdf1_.set_secure(SEC_DISABLED);
894 tdf2_.set_secure(SEC_DISABLED);
895
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000896 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000897 const AudioContentDescription* offer_acd =
898 GetFirstAudioContentDescription(offer.get());
899 ASSERT_TRUE(offer_acd != NULL);
900 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
901
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000902 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000903 f2_.CreateAnswer(offer.get(), opts, NULL));
904
905 const ContentInfo* ac_answer = answer->GetContentByName("audio");
906 ASSERT_TRUE(ac_answer != NULL);
907 EXPECT_FALSE(ac_answer->rejected);
908
909 const AudioContentDescription* answer_acd =
910 GetFirstAudioContentDescription(answer.get());
911 ASSERT_TRUE(answer_acd != NULL);
912 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
913}
914
915// Create a video offer and answer and ensure the RTP header extensions
916// matches what we expect.
917TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
918 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000919 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000920
921 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
922 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
923 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
924 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
925
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000926 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000927 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000928 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000929 f2_.CreateAnswer(offer.get(), opts, NULL));
930
931 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
932 GetFirstAudioContentDescription(
933 offer.get())->rtp_header_extensions());
934 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
935 GetFirstVideoContentDescription(
936 offer.get())->rtp_header_extensions());
937 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
938 GetFirstAudioContentDescription(
939 answer.get())->rtp_header_extensions());
940 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
941 GetFirstVideoContentDescription(
942 answer.get())->rtp_header_extensions());
943}
944
945// Create an audio, video, data answer without legacy StreamParams.
946TEST_F(MediaSessionDescriptionFactoryTest,
947 TestCreateAnswerWithoutLegacyStreams) {
948 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000949 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950 opts.data_channel_type = cricket::DCT_RTP;
951 f1_.set_add_legacy_streams(false);
952 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000953 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000954 ASSERT_TRUE(offer.get() != NULL);
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 const ContentInfo* ac = answer->GetContentByName("audio");
958 const ContentInfo* vc = answer->GetContentByName("video");
959 const ContentInfo* dc = answer->GetContentByName("data");
960 ASSERT_TRUE(ac != NULL);
961 ASSERT_TRUE(vc != NULL);
962 const AudioContentDescription* acd =
963 static_cast<const AudioContentDescription*>(ac->description);
964 const VideoContentDescription* vcd =
965 static_cast<const VideoContentDescription*>(vc->description);
966 const DataContentDescription* dcd =
967 static_cast<const DataContentDescription*>(dc->description);
968
969 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
970 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
971 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
972}
973
974TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
975 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000976 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000977 opts.data_channel_type = cricket::DCT_RTP;
978 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000979 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 offer(f1_.CreateOffer(opts, NULL));
981 ASSERT_TRUE(offer.get() != NULL);
982 const ContentInfo* ac = offer->GetContentByName("audio");
983 const ContentInfo* vc = offer->GetContentByName("video");
984 const ContentInfo* dc = offer->GetContentByName("data");
985 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
986 static_cast<const AudioContentDescription*>(ac->description));
987 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
988 static_cast<const VideoContentDescription*>(vc->description));
989 DataContentDescription* dcd = const_cast<DataContentDescription*>(
990 static_cast<const DataContentDescription*>(dc->description));
991
992 EXPECT_FALSE(acd->partial()); // default is false.
993 acd->set_partial(true);
994 EXPECT_TRUE(acd->partial());
995 acd->set_partial(false);
996 EXPECT_FALSE(acd->partial());
997
998 EXPECT_FALSE(vcd->partial()); // default is false.
999 vcd->set_partial(true);
1000 EXPECT_TRUE(vcd->partial());
1001 vcd->set_partial(false);
1002 EXPECT_FALSE(vcd->partial());
1003
1004 EXPECT_FALSE(dcd->partial()); // default is false.
1005 dcd->set_partial(true);
1006 EXPECT_TRUE(dcd->partial());
1007 dcd->set_partial(false);
1008 EXPECT_FALSE(dcd->partial());
1009}
1010
1011// Create a typical video answer, and ensure it matches what we expect.
1012TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1013 MediaSessionOptions offer_opts;
1014 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001015 answer_opts.recv_video = true;
1016 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001017 answer_opts.data_channel_type = cricket::DCT_RTP;
1018 offer_opts.data_channel_type = cricket::DCT_RTP;
1019
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001020 rtc::scoped_ptr<SessionDescription> offer;
1021 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001022
1023 offer_opts.rtcp_mux_enabled = true;
1024 answer_opts.rtcp_mux_enabled = true;
1025
1026 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1027 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1028 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1029 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1030 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1031 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1032 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1033 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1034 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1035 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1036 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1037 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1038 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1039 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1040
1041 offer_opts.rtcp_mux_enabled = true;
1042 answer_opts.rtcp_mux_enabled = false;
1043
1044 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1045 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1046 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1047 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1048 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1049 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1050 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1051 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1052 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1053 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1054 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1055 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1056 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1057 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1058
1059 offer_opts.rtcp_mux_enabled = false;
1060 answer_opts.rtcp_mux_enabled = true;
1061
1062 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1063 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1064 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1065 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1066 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1067 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1068 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1069 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1070 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1071 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1072 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1073 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1074 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1075 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1076
1077 offer_opts.rtcp_mux_enabled = false;
1078 answer_opts.rtcp_mux_enabled = false;
1079
1080 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1081 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1082 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1083 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1084 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1085 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1086 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1087 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1088 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1089 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1090 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1091 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1092 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1093 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1094}
1095
1096// Create an audio-only answer to a video offer.
1097TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1098 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001099 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001100 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 offer(f1_.CreateOffer(opts, NULL));
1102 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001103 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001104 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1105 const ContentInfo* ac = answer->GetContentByName("audio");
1106 const ContentInfo* vc = answer->GetContentByName("video");
1107 ASSERT_TRUE(ac != NULL);
1108 ASSERT_TRUE(vc != NULL);
1109 ASSERT_TRUE(vc->description != NULL);
1110 EXPECT_TRUE(vc->rejected);
1111}
1112
1113// Create an audio-only answer to an offer with data.
1114TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1115 MediaSessionOptions opts;
1116 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001117 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001118 offer(f1_.CreateOffer(opts, NULL));
1119 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001120 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001121 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1122 const ContentInfo* ac = answer->GetContentByName("audio");
1123 const ContentInfo* dc = answer->GetContentByName("data");
1124 ASSERT_TRUE(ac != NULL);
1125 ASSERT_TRUE(dc != NULL);
1126 ASSERT_TRUE(dc->description != NULL);
1127 EXPECT_TRUE(dc->rejected);
1128}
1129
1130// Create an answer that rejects the contents which are rejected in the offer.
1131TEST_F(MediaSessionDescriptionFactoryTest,
1132 CreateAnswerToOfferWithRejectedMedia) {
1133 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001134 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001135 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001136 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001137 offer(f1_.CreateOffer(opts, NULL));
1138 ASSERT_TRUE(offer.get() != NULL);
1139 ContentInfo* ac = offer->GetContentByName("audio");
1140 ContentInfo* vc = offer->GetContentByName("video");
1141 ContentInfo* dc = offer->GetContentByName("data");
1142 ASSERT_TRUE(ac != NULL);
1143 ASSERT_TRUE(vc != NULL);
1144 ASSERT_TRUE(dc != NULL);
1145 ac->rejected = true;
1146 vc->rejected = true;
1147 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001148 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149 f2_.CreateAnswer(offer.get(), opts, NULL));
1150 ac = answer->GetContentByName("audio");
1151 vc = answer->GetContentByName("video");
1152 dc = answer->GetContentByName("data");
1153 ASSERT_TRUE(ac != NULL);
1154 ASSERT_TRUE(vc != NULL);
1155 ASSERT_TRUE(dc != NULL);
1156 EXPECT_TRUE(ac->rejected);
1157 EXPECT_TRUE(vc->rejected);
1158 EXPECT_TRUE(dc->rejected);
1159}
1160
1161// Create an audio and video offer with:
1162// - one video track
1163// - two audio tracks
1164// - two data tracks
1165// and ensure it matches what we expect. Also updates the initial offer by
1166// adding a new video track and replaces one of the audio tracks.
1167TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1168 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001169 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1170 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1171 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001173 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1174 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175
1176 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001177 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178
1179 ASSERT_TRUE(offer.get() != NULL);
1180 const ContentInfo* ac = offer->GetContentByName("audio");
1181 const ContentInfo* vc = offer->GetContentByName("video");
1182 const ContentInfo* dc = offer->GetContentByName("data");
1183 ASSERT_TRUE(ac != NULL);
1184 ASSERT_TRUE(vc != NULL);
1185 ASSERT_TRUE(dc != NULL);
1186 const AudioContentDescription* acd =
1187 static_cast<const AudioContentDescription*>(ac->description);
1188 const VideoContentDescription* vcd =
1189 static_cast<const VideoContentDescription*>(vc->description);
1190 const DataContentDescription* dcd =
1191 static_cast<const DataContentDescription*>(dc->description);
1192 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1193 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1194
1195 const StreamParamsVec& audio_streams = acd->streams();
1196 ASSERT_EQ(2U, audio_streams.size());
1197 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1198 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1199 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1200 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1201 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1202 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1203 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1204
1205 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1206 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1207 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1208
1209 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1210 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1211 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1212
1213 const StreamParamsVec& video_streams = vcd->streams();
1214 ASSERT_EQ(1U, video_streams.size());
1215 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1216 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1217 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1218 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1219
1220 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1221 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1222 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1223
1224 const StreamParamsVec& data_streams = dcd->streams();
1225 ASSERT_EQ(2U, data_streams.size());
1226 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1227 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1228 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1229 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1230 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1231 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1232 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1233
1234 EXPECT_EQ(cricket::kDataMaxBandwidth,
1235 dcd->bandwidth()); // default bandwidth (auto)
1236 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1237 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1238
1239
1240 // Update the offer. Add a new video track that is not synched to the
1241 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001242 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1243 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1244 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1245 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1246 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001247 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001248 updated_offer(f1_.CreateOffer(opts, offer.get()));
1249
1250 ASSERT_TRUE(updated_offer.get() != NULL);
1251 ac = updated_offer->GetContentByName("audio");
1252 vc = updated_offer->GetContentByName("video");
1253 dc = updated_offer->GetContentByName("data");
1254 ASSERT_TRUE(ac != NULL);
1255 ASSERT_TRUE(vc != NULL);
1256 ASSERT_TRUE(dc != NULL);
1257 const AudioContentDescription* updated_acd =
1258 static_cast<const AudioContentDescription*>(ac->description);
1259 const VideoContentDescription* updated_vcd =
1260 static_cast<const VideoContentDescription*>(vc->description);
1261 const DataContentDescription* updated_dcd =
1262 static_cast<const DataContentDescription*>(dc->description);
1263
1264 EXPECT_EQ(acd->type(), updated_acd->type());
1265 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1266 EXPECT_EQ(vcd->type(), updated_vcd->type());
1267 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1268 EXPECT_EQ(dcd->type(), updated_dcd->type());
1269 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1270 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1271 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1272 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1273 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1274 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1275 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1276
1277 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1278 ASSERT_EQ(2U, updated_audio_streams.size());
1279 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1280 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1281 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1282 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1283 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1284
1285 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1286 ASSERT_EQ(2U, updated_video_streams.size());
1287 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1288 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1289 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1290
1291 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1292 ASSERT_EQ(2U, updated_data_streams.size());
1293 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1294 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1295 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1296 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1297 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1298}
1299
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001300// Create an offer with simulcast video stream.
1301TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1302 MediaSessionOptions opts;
1303 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001304 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001305 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001306
1307 ASSERT_TRUE(offer.get() != NULL);
1308 const ContentInfo* vc = offer->GetContentByName("video");
1309 ASSERT_TRUE(vc != NULL);
1310 const VideoContentDescription* vcd =
1311 static_cast<const VideoContentDescription*>(vc->description);
1312
1313 const StreamParamsVec& video_streams = vcd->streams();
1314 ASSERT_EQ(1U, video_streams.size());
1315 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1316 const SsrcGroup* sim_ssrc_group =
1317 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1318 ASSERT_TRUE(sim_ssrc_group != NULL);
1319 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1320}
1321
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001322// Create an audio and video answer to a standard video offer with:
1323// - one video track
1324// - two audio tracks
1325// - two data tracks
1326// and ensure it matches what we expect. Also updates the initial answer by
1327// adding a new video track and removes one of the audio tracks.
1328TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1329 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001330 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001331 offer_opts.data_channel_type = cricket::DCT_RTP;
1332 f1_.set_secure(SEC_ENABLED);
1333 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001334 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001335 NULL));
1336
1337 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001338 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1339 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1340 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001341 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001342 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1343 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001344
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001345 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001346 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1347
1348 ASSERT_TRUE(answer.get() != NULL);
1349 const ContentInfo* ac = answer->GetContentByName("audio");
1350 const ContentInfo* vc = answer->GetContentByName("video");
1351 const ContentInfo* dc = answer->GetContentByName("data");
1352 ASSERT_TRUE(ac != NULL);
1353 ASSERT_TRUE(vc != NULL);
1354 ASSERT_TRUE(dc != NULL);
1355 const AudioContentDescription* acd =
1356 static_cast<const AudioContentDescription*>(ac->description);
1357 const VideoContentDescription* vcd =
1358 static_cast<const VideoContentDescription*>(vc->description);
1359 const DataContentDescription* dcd =
1360 static_cast<const DataContentDescription*>(dc->description);
1361 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1362 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1363 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1364
1365 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1366 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1367
1368 const StreamParamsVec& audio_streams = acd->streams();
1369 ASSERT_EQ(2U, audio_streams.size());
1370 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1371 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1372 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1373 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1374 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1375 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1376 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1377
1378 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1379 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1380
1381 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1382 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1383
1384 const StreamParamsVec& video_streams = vcd->streams();
1385 ASSERT_EQ(1U, video_streams.size());
1386 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1387 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1388 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1389 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1390
1391 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1392 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1393
1394 const StreamParamsVec& data_streams = dcd->streams();
1395 ASSERT_EQ(2U, data_streams.size());
1396 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1397 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1398 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1399 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1400 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1401 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1402 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1403
1404 EXPECT_EQ(cricket::kDataMaxBandwidth,
1405 dcd->bandwidth()); // default bandwidth (auto)
1406 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1407
1408 // Update the answer. Add a new video track that is not synched to the
1409 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001410 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1411 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1412 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001413 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001414 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1415
1416 ASSERT_TRUE(updated_answer.get() != NULL);
1417 ac = updated_answer->GetContentByName("audio");
1418 vc = updated_answer->GetContentByName("video");
1419 dc = updated_answer->GetContentByName("data");
1420 ASSERT_TRUE(ac != NULL);
1421 ASSERT_TRUE(vc != NULL);
1422 ASSERT_TRUE(dc != NULL);
1423 const AudioContentDescription* updated_acd =
1424 static_cast<const AudioContentDescription*>(ac->description);
1425 const VideoContentDescription* updated_vcd =
1426 static_cast<const VideoContentDescription*>(vc->description);
1427 const DataContentDescription* updated_dcd =
1428 static_cast<const DataContentDescription*>(dc->description);
1429
1430 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1431 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1432 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1433 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1434 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1435 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1436
1437 EXPECT_EQ(acd->type(), updated_acd->type());
1438 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1439 EXPECT_EQ(vcd->type(), updated_vcd->type());
1440 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1441 EXPECT_EQ(dcd->type(), updated_dcd->type());
1442 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1443
1444 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1445 ASSERT_EQ(1U, updated_audio_streams.size());
1446 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1447
1448 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1449 ASSERT_EQ(2U, updated_video_streams.size());
1450 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1451 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1452 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1453
1454 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1455 ASSERT_EQ(1U, updated_data_streams.size());
1456 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1457}
1458
1459
1460// Create an updated offer after creating an answer to the original offer and
1461// verify that the codecs that were part of the original answer are not changed
1462// in the updated offer.
1463TEST_F(MediaSessionDescriptionFactoryTest,
1464 RespondentCreatesOfferAfterCreatingAnswer) {
1465 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001466 opts.recv_audio = true;
1467 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001468
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001469 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1470 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001471 f2_.CreateAnswer(offer.get(), opts, NULL));
1472
1473 const AudioContentDescription* acd =
1474 GetFirstAudioContentDescription(answer.get());
1475 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1476
1477 const VideoContentDescription* vcd =
1478 GetFirstVideoContentDescription(answer.get());
1479 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1480
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001481 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001482 f2_.CreateOffer(opts, answer.get()));
1483
1484 // The expected audio codecs are the common audio codecs from the first
1485 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1486 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001487 // TODO(wu): |updated_offer| should not include the codec
1488 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001489 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001490 kAudioCodecsAnswer[0],
1491 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001492 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001493 };
1494
1495 // The expected video codecs are the common video codecs from the first
1496 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1497 // preference order.
1498 const VideoCodec kUpdatedVideoCodecOffer[] = {
1499 kVideoCodecsAnswer[0],
1500 kVideoCodecs2[1],
1501 };
1502
1503 const AudioContentDescription* updated_acd =
1504 GetFirstAudioContentDescription(updated_offer.get());
1505 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1506
1507 const VideoContentDescription* updated_vcd =
1508 GetFirstVideoContentDescription(updated_offer.get());
1509 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1510}
1511
1512// Create an updated offer after creating an answer to the original offer and
1513// verify that the codecs that were part of the original answer are not changed
1514// in the updated offer. In this test Rtx is enabled.
1515TEST_F(MediaSessionDescriptionFactoryTest,
1516 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1517 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001518 opts.recv_video = true;
1519 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1521 VideoCodec rtx_f1;
1522 rtx_f1.id = 126;
1523 rtx_f1.name = cricket::kRtxCodecName;
1524
1525 // This creates rtx for H264 with the payload type |f1_| uses.
1526 rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001527 rtc::ToString<int>(kVideoCodecs1[1].id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 f1_codecs.push_back(rtx_f1);
1529 f1_.set_video_codecs(f1_codecs);
1530
1531 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1532 VideoCodec rtx_f2;
1533 rtx_f2.id = 127;
1534 rtx_f2.name = cricket::kRtxCodecName;
1535
1536 // This creates rtx for H264 with the payload type |f2_| uses.
1537 rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001538 rtc::ToString<int>(kVideoCodecs2[0].id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 f2_codecs.push_back(rtx_f2);
1540 f2_.set_video_codecs(f2_codecs);
1541
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001542 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001543 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001544 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 f2_.CreateAnswer(offer.get(), opts, NULL));
1546
1547 const VideoContentDescription* vcd =
1548 GetFirstVideoContentDescription(answer.get());
1549
1550 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1551 expected_codecs.push_back(rtx_f1);
1552
1553 EXPECT_EQ(expected_codecs, vcd->codecs());
1554
1555 // Now, make sure we get same result, except for the preference order,
1556 // if |f2_| creates an updated offer even though the default payload types
1557 // are different from |f1_|.
1558 expected_codecs[0].preference = f1_codecs[1].preference;
1559
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001560 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561 f2_.CreateOffer(opts, answer.get()));
1562 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001563 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1565
1566 const VideoContentDescription* updated_vcd =
1567 GetFirstVideoContentDescription(updated_answer.get());
1568
1569 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1570}
1571
1572// Create an updated offer that adds video after creating an audio only answer
1573// to the original offer. This test verifies that if a video codec and the RTX
1574// codec have the same default payload type as an audio codec that is already in
1575// use, the added codecs payload types are changed.
1576TEST_F(MediaSessionDescriptionFactoryTest,
1577 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1578 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1579 VideoCodec rtx_f1;
1580 rtx_f1.id = 126;
1581 rtx_f1.name = cricket::kRtxCodecName;
1582
1583 // This creates rtx for H264 with the payload type |f1_| uses.
1584 rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001585 rtc::ToString<int>(kVideoCodecs1[1].id);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001586 f1_codecs.push_back(rtx_f1);
1587 f1_.set_video_codecs(f1_codecs);
1588
1589 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001590 opts.recv_audio = true;
1591 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001592
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001593 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1594 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001595 f2_.CreateAnswer(offer.get(), opts, NULL));
1596
1597 const AudioContentDescription* acd =
1598 GetFirstAudioContentDescription(answer.get());
1599 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1600
1601 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1602 // reference be the same as an audio codec that was negotiated in the
1603 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001604 opts.recv_audio = true;
1605 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001606
1607 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1608 int used_pl_type = acd->codecs()[0].id;
1609 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
1610 VideoCodec rtx_f2;
1611 rtx_f2.id = 127;
1612 rtx_f2.name = cricket::kRtxCodecName;
1613 rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001614 rtc::ToString<int>(used_pl_type);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001615 f2_codecs.push_back(rtx_f2);
1616 f2_.set_video_codecs(f2_codecs);
1617
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001618 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001619 f2_.CreateOffer(opts, answer.get()));
1620 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001621 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001622 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1623
1624 const AudioContentDescription* updated_acd =
1625 GetFirstAudioContentDescription(answer.get());
1626 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1627
1628 const VideoContentDescription* updated_vcd =
1629 GetFirstVideoContentDescription(updated_answer.get());
1630
1631 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001632 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001633 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1634 EXPECT_NE(used_pl_type, new_h264_pl_type);
1635 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001636 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001637 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1638 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1639}
1640
1641// Test that RTX is ignored when there is no associated payload type parameter.
1642TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1643 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001644 opts.recv_video = true;
1645 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1647 VideoCodec rtx_f1;
1648 rtx_f1.id = 126;
1649 rtx_f1.name = cricket::kRtxCodecName;
1650
1651 f1_codecs.push_back(rtx_f1);
1652 f1_.set_video_codecs(f1_codecs);
1653
1654 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1655 VideoCodec rtx_f2;
1656 rtx_f2.id = 127;
1657 rtx_f2.name = cricket::kRtxCodecName;
1658
1659 // This creates rtx for H264 with the payload type |f2_| uses.
1660 rtx_f2.SetParam(cricket::kCodecParamAssociatedPayloadType,
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001661 rtc::ToString<int>(kVideoCodecs2[0].id));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001662 f2_codecs.push_back(rtx_f2);
1663 f2_.set_video_codecs(f2_codecs);
1664
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001665 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001666 ASSERT_TRUE(offer.get() != NULL);
1667 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1668 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1669 // is possible to test that that RTX is dropped when
1670 // kCodecParamAssociatedPayloadType is missing in the offer.
1671 VideoContentDescription* desc =
1672 static_cast<cricket::VideoContentDescription*>(
1673 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1674 ASSERT_TRUE(desc != NULL);
1675 std::vector<VideoCodec> codecs = desc->codecs();
1676 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1677 iter != codecs.end(); ++iter) {
1678 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1679 iter->params.clear();
1680 }
1681 }
1682 desc->set_codecs(codecs);
1683
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001684 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001685 f2_.CreateAnswer(offer.get(), opts, NULL));
1686
1687 const VideoContentDescription* vcd =
1688 GetFirstVideoContentDescription(answer.get());
1689
1690 for (std::vector<VideoCodec>::const_iterator iter = vcd->codecs().begin();
1691 iter != vcd->codecs().end(); ++iter) {
1692 ASSERT_STRNE(iter->name.c_str(), cricket::kRtxCodecName);
1693 }
1694}
1695
1696// Create an updated offer after creating an answer to the original offer and
1697// verify that the RTP header extensions that were part of the original answer
1698// are not changed in the updated offer.
1699TEST_F(MediaSessionDescriptionFactoryTest,
1700 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1701 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001702 opts.recv_audio = true;
1703 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704
1705 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1706 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1707 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1708 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1709
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001710 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1711 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 f2_.CreateAnswer(offer.get(), opts, NULL));
1713
1714 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1715 GetFirstAudioContentDescription(
1716 answer.get())->rtp_header_extensions());
1717 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1718 GetFirstVideoContentDescription(
1719 answer.get())->rtp_header_extensions());
1720
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001721 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722 f2_.CreateOffer(opts, answer.get()));
1723
1724 // The expected RTP header extensions in the new offer are the resulting
1725 // extensions from the first offer/answer exchange plus the extensions only
1726 // |f2_| offer.
1727 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001728 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001729 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1730 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001731 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1732 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001733 };
1734
1735 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001736 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001737 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1738 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001739 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1740 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001741 };
1742
1743 const AudioContentDescription* updated_acd =
1744 GetFirstAudioContentDescription(updated_offer.get());
1745 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1746 updated_acd->rtp_header_extensions());
1747
1748 const VideoContentDescription* updated_vcd =
1749 GetFirstVideoContentDescription(updated_offer.get());
1750 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1751 updated_vcd->rtp_header_extensions());
1752}
1753
1754TEST(MediaSessionDescription, CopySessionDescription) {
1755 SessionDescription source;
1756 cricket::ContentGroup group(cricket::CN_AUDIO);
1757 source.AddGroup(group);
1758 AudioContentDescription* acd(new AudioContentDescription());
1759 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1760 acd->AddLegacyStream(1);
1761 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1762 VideoContentDescription* vcd(new VideoContentDescription());
1763 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1764 vcd->AddLegacyStream(2);
1765 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1766
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001767 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001768 ASSERT_TRUE(copy.get() != NULL);
1769 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1770 const ContentInfo* ac = copy->GetContentByName("audio");
1771 const ContentInfo* vc = copy->GetContentByName("video");
1772 ASSERT_TRUE(ac != NULL);
1773 ASSERT_TRUE(vc != NULL);
1774 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1775 const AudioContentDescription* acd_copy =
1776 static_cast<const AudioContentDescription*>(ac->description);
1777 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1778 EXPECT_EQ(1u, acd->first_ssrc());
1779
1780 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1781 const VideoContentDescription* vcd_copy =
1782 static_cast<const VideoContentDescription*>(vc->description);
1783 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1784 EXPECT_EQ(2u, vcd->first_ssrc());
1785}
1786
1787// The below TestTransportInfoXXX tests create different offers/answers, and
1788// ensure the TransportInfo in the SessionDescription matches what we expect.
1789TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1790 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001791 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001792 TestTransportInfo(true, options, false);
1793}
1794
1795TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1796 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001797 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001798 TestTransportInfo(true, options, true);
1799}
1800
1801TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1802 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001803 options.recv_audio = true;
1804 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001805 options.data_channel_type = cricket::DCT_RTP;
1806 TestTransportInfo(true, options, false);
1807}
1808
1809TEST_F(MediaSessionDescriptionFactoryTest,
1810 TestTransportInfoOfferMultimediaCurrent) {
1811 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001812 options.recv_audio = true;
1813 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001814 options.data_channel_type = cricket::DCT_RTP;
1815 TestTransportInfo(true, options, true);
1816}
1817
1818TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1819 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001820 options.recv_audio = true;
1821 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001822 options.data_channel_type = cricket::DCT_RTP;
1823 options.bundle_enabled = true;
1824 TestTransportInfo(true, options, false);
1825}
1826
1827TEST_F(MediaSessionDescriptionFactoryTest,
1828 TestTransportInfoOfferBundleCurrent) {
1829 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001830 options.recv_audio = true;
1831 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001832 options.data_channel_type = cricket::DCT_RTP;
1833 options.bundle_enabled = true;
1834 TestTransportInfo(true, options, true);
1835}
1836
1837TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
1838 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001839 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001840 TestTransportInfo(false, options, false);
1841}
1842
1843TEST_F(MediaSessionDescriptionFactoryTest,
1844 TestTransportInfoAnswerAudioCurrent) {
1845 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001846 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 TestTransportInfo(false, options, true);
1848}
1849
1850TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
1851 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001852 options.recv_audio = true;
1853 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001854 options.data_channel_type = cricket::DCT_RTP;
1855 TestTransportInfo(false, options, false);
1856}
1857
1858TEST_F(MediaSessionDescriptionFactoryTest,
1859 TestTransportInfoAnswerMultimediaCurrent) {
1860 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001861 options.recv_audio = true;
1862 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001863 options.data_channel_type = cricket::DCT_RTP;
1864 TestTransportInfo(false, options, true);
1865}
1866
1867TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
1868 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001869 options.recv_audio = true;
1870 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001871 options.data_channel_type = cricket::DCT_RTP;
1872 options.bundle_enabled = true;
1873 TestTransportInfo(false, options, false);
1874}
1875
1876TEST_F(MediaSessionDescriptionFactoryTest,
1877 TestTransportInfoAnswerBundleCurrent) {
1878 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001879 options.recv_audio = true;
1880 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001881 options.data_channel_type = cricket::DCT_RTP;
1882 options.bundle_enabled = true;
1883 TestTransportInfo(false, options, true);
1884}
1885
1886// Create an offer with bundle enabled and verify the crypto parameters are
1887// the common set of the available cryptos.
1888TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
1889 TestCryptoWithBundle(true);
1890}
1891
1892// Create an answer with bundle enabled and verify the crypto parameters are
1893// the common set of the available cryptos.
1894TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
1895 TestCryptoWithBundle(false);
1896}
1897
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001898// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
1899// DTLS is not enabled locally.
1900TEST_F(MediaSessionDescriptionFactoryTest,
1901 TestOfferDtlsSavpfWithoutDtlsFailed) {
1902 f1_.set_secure(SEC_ENABLED);
1903 f2_.set_secure(SEC_ENABLED);
1904 tdf1_.set_secure(SEC_DISABLED);
1905 tdf2_.set_secure(SEC_DISABLED);
1906
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001907 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001908 f1_.CreateOffer(MediaSessionOptions(), NULL));
1909 ASSERT_TRUE(offer.get() != NULL);
1910 ContentInfo* offer_content = offer->GetContentByName("audio");
1911 ASSERT_TRUE(offer_content != NULL);
1912 AudioContentDescription* offer_audio_desc =
1913 static_cast<AudioContentDescription*>(offer_content->description);
1914 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1915
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001916 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001917 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1918 ASSERT_TRUE(answer != NULL);
1919 ContentInfo* answer_content = answer->GetContentByName("audio");
1920 ASSERT_TRUE(answer_content != NULL);
1921
1922 ASSERT_TRUE(answer_content->rejected);
1923}
1924
1925// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
1926// UDP/TLS/RTP/SAVPF.
1927TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
1928 f1_.set_secure(SEC_ENABLED);
1929 f2_.set_secure(SEC_ENABLED);
1930 tdf1_.set_secure(SEC_ENABLED);
1931 tdf2_.set_secure(SEC_ENABLED);
1932
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001933 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001934 f1_.CreateOffer(MediaSessionOptions(), NULL));
1935 ASSERT_TRUE(offer.get() != NULL);
1936 ContentInfo* offer_content = offer->GetContentByName("audio");
1937 ASSERT_TRUE(offer_content != NULL);
1938 AudioContentDescription* offer_audio_desc =
1939 static_cast<AudioContentDescription*>(offer_content->description);
1940 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1941
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001942 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001943 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1944 ASSERT_TRUE(answer != NULL);
1945
1946 const ContentInfo* answer_content = answer->GetContentByName("audio");
1947 ASSERT_TRUE(answer_content != NULL);
1948 ASSERT_FALSE(answer_content->rejected);
1949
1950 const AudioContentDescription* answer_audio_desc =
1951 static_cast<const AudioContentDescription*>(answer_content->description);
1952 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
1953 answer_audio_desc->protocol());
1954}
1955
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001956// Test that we include both SDES and DTLS in the offer, but only include SDES
1957// in the answer if DTLS isn't negotiated.
1958TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
1959 f1_.set_secure(SEC_ENABLED);
1960 f2_.set_secure(SEC_ENABLED);
1961 tdf1_.set_secure(SEC_ENABLED);
1962 tdf2_.set_secure(SEC_DISABLED);
1963 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001964 options.recv_audio = true;
1965 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001966 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967 const cricket::MediaContentDescription* audio_media_desc;
1968 const cricket::MediaContentDescription* video_media_desc;
1969 const cricket::TransportDescription* audio_trans_desc;
1970 const cricket::TransportDescription* video_trans_desc;
1971
1972 // Generate an offer with SDES and DTLS support.
1973 offer.reset(f1_.CreateOffer(options, NULL));
1974 ASSERT_TRUE(offer.get() != NULL);
1975
1976 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1977 offer->GetContentDescriptionByName("audio"));
1978 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001979 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 offer->GetContentDescriptionByName("video"));
1981 ASSERT_TRUE(video_media_desc != NULL);
1982 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
1983 EXPECT_EQ(1u, video_media_desc->cryptos().size());
1984
1985 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
1986 ASSERT_TRUE(audio_trans_desc != NULL);
1987 video_trans_desc = offer->GetTransportDescriptionByName("video");
1988 ASSERT_TRUE(video_trans_desc != NULL);
1989 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
1990 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
1991
1992 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
1993 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1994 ASSERT_TRUE(answer.get() != NULL);
1995
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001996 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001997 answer->GetContentDescriptionByName("audio"));
1998 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00001999 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002000 answer->GetContentDescriptionByName("video"));
2001 ASSERT_TRUE(video_media_desc != NULL);
2002 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2003 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2004
2005 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2006 ASSERT_TRUE(audio_trans_desc != NULL);
2007 video_trans_desc = answer->GetTransportDescriptionByName("video");
2008 ASSERT_TRUE(video_trans_desc != NULL);
2009 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2010 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2011
2012 // Enable DTLS; the answer should now only have DTLS support.
2013 tdf2_.set_secure(SEC_ENABLED);
2014 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2015 ASSERT_TRUE(answer.get() != NULL);
2016
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002017 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002018 answer->GetContentDescriptionByName("audio"));
2019 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002020 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002021 answer->GetContentDescriptionByName("video"));
2022 ASSERT_TRUE(video_media_desc != NULL);
2023 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2024 EXPECT_TRUE(video_media_desc->cryptos().empty());
2025 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2026 audio_media_desc->protocol());
2027 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2028 video_media_desc->protocol());
2029
2030 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2031 ASSERT_TRUE(audio_trans_desc != NULL);
2032 video_trans_desc = answer->GetTransportDescriptionByName("video");
2033 ASSERT_TRUE(video_trans_desc != NULL);
2034 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2035 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002036
2037 // Try creating offer again. DTLS enabled now, crypto's should be empty
2038 // in new offer.
2039 offer.reset(f1_.CreateOffer(options, offer.get()));
2040 ASSERT_TRUE(offer.get() != NULL);
2041 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2042 offer->GetContentDescriptionByName("audio"));
2043 ASSERT_TRUE(audio_media_desc != NULL);
2044 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2045 offer->GetContentDescriptionByName("video"));
2046 ASSERT_TRUE(video_media_desc != NULL);
2047 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2048 EXPECT_TRUE(video_media_desc->cryptos().empty());
2049
2050 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2051 ASSERT_TRUE(audio_trans_desc != NULL);
2052 video_trans_desc = offer->GetTransportDescriptionByName("video");
2053 ASSERT_TRUE(video_trans_desc != NULL);
2054 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2055 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056}
2057
2058// Test that an answer can't be created if cryptos are required but the offer is
2059// unsecure.
2060TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2061 MediaSessionOptions options;
2062 f1_.set_secure(SEC_DISABLED);
2063 tdf1_.set_secure(SEC_DISABLED);
2064 f2_.set_secure(SEC_REQUIRED);
2065 tdf1_.set_secure(SEC_ENABLED);
2066
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002067 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002068 NULL));
2069 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002070 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002071 f2_.CreateAnswer(offer.get(), options, NULL));
2072 EXPECT_TRUE(answer.get() == NULL);
2073}
2074
2075// Test that we accept a DTLS offer without SDES and create an appropriate
2076// answer.
2077TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2078 f1_.set_secure(SEC_DISABLED);
2079 f2_.set_secure(SEC_ENABLED);
2080 tdf1_.set_secure(SEC_ENABLED);
2081 tdf2_.set_secure(SEC_ENABLED);
2082 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002083 options.recv_audio = true;
2084 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002085 options.data_channel_type = cricket::DCT_RTP;
2086
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002087 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002088
2089 // Generate an offer with DTLS but without SDES.
2090 offer.reset(f1_.CreateOffer(options, NULL));
2091 ASSERT_TRUE(offer.get() != NULL);
2092
2093 const AudioContentDescription* audio_offer =
2094 GetFirstAudioContentDescription(offer.get());
2095 ASSERT_TRUE(audio_offer->cryptos().empty());
2096 const VideoContentDescription* video_offer =
2097 GetFirstVideoContentDescription(offer.get());
2098 ASSERT_TRUE(video_offer->cryptos().empty());
2099 const DataContentDescription* data_offer =
2100 GetFirstDataContentDescription(offer.get());
2101 ASSERT_TRUE(data_offer->cryptos().empty());
2102
2103 const cricket::TransportDescription* audio_offer_trans_desc =
2104 offer->GetTransportDescriptionByName("audio");
2105 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2106 const cricket::TransportDescription* video_offer_trans_desc =
2107 offer->GetTransportDescriptionByName("video");
2108 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2109 const cricket::TransportDescription* data_offer_trans_desc =
2110 offer->GetTransportDescriptionByName("data");
2111 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2112
2113 // Generate an answer with DTLS.
2114 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2115 ASSERT_TRUE(answer.get() != NULL);
2116
2117 const cricket::TransportDescription* audio_answer_trans_desc =
2118 answer->GetTransportDescriptionByName("audio");
2119 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2120 const cricket::TransportDescription* video_answer_trans_desc =
2121 answer->GetTransportDescriptionByName("video");
2122 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2123 const cricket::TransportDescription* data_answer_trans_desc =
2124 answer->GetTransportDescriptionByName("data");
2125 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2126}
2127
2128// Verifies if vad_enabled option is set to false, CN codecs are not present in
2129// offer or answer.
2130TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2131 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002132 options.recv_audio = true;
2133 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002134 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135 f1_.CreateOffer(options, NULL));
2136 ASSERT_TRUE(offer.get() != NULL);
2137 const ContentInfo* audio_content = offer->GetContentByName("audio");
2138 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2139
2140 options.vad_enabled = false;
2141 offer.reset(f1_.CreateOffer(options, NULL));
2142 ASSERT_TRUE(offer.get() != NULL);
2143 audio_content = offer->GetContentByName("audio");
2144 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002145 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002146 f1_.CreateAnswer(offer.get(), options, NULL));
2147 ASSERT_TRUE(answer.get() != NULL);
2148 audio_content = answer->GetContentByName("audio");
2149 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2150}