blob: abb03e7de7049f7c707f4b74cc0ff91ed8f8b27b [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <string>
29#include <vector>
30
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031#include "talk/media/base/codec.h"
32#include "talk/media/base/testutils.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033#include "webrtc/p2p/base/constants.h"
34#include "webrtc/p2p/base/transportdescription.h"
35#include "webrtc/p2p/base/transportinfo.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036#include "talk/session/media/mediasession.h"
37#include "talk/session/media/srtpfilter.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000038#include "webrtc/base/fakesslidentity.h"
39#include "webrtc/base/gunit.h"
40#include "webrtc/base/messagedigest.h"
41#include "webrtc/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042
43#ifdef HAVE_SRTP
44#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000045 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046 ASSERT_EQ(s, cd->cryptos().size()); \
47 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
48#else
49#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000050 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051 ASSERT_EQ(0U, cd->cryptos().size());
52#endif
53
54typedef std::vector<cricket::Candidate> Candidates;
55
56using cricket::MediaContentDescription;
57using cricket::MediaSessionDescriptionFactory;
58using cricket::MediaSessionOptions;
59using cricket::MediaType;
60using cricket::SessionDescription;
61using cricket::SsrcGroup;
62using cricket::StreamParams;
63using cricket::StreamParamsVec;
64using cricket::TransportDescription;
65using cricket::TransportDescriptionFactory;
66using cricket::TransportInfo;
67using cricket::ContentInfo;
68using cricket::CryptoParamsVec;
69using cricket::AudioContentDescription;
70using cricket::VideoContentDescription;
71using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080072using cricket::GetFirstAudioContent;
73using cricket::GetFirstVideoContent;
74using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075using cricket::GetFirstAudioContentDescription;
76using cricket::GetFirstVideoContentDescription;
77using cricket::GetFirstDataContentDescription;
78using cricket::kAutoBandwidth;
79using cricket::AudioCodec;
80using cricket::VideoCodec;
81using cricket::DataCodec;
82using cricket::NS_JINGLE_RTP;
83using cricket::MEDIA_TYPE_AUDIO;
84using cricket::MEDIA_TYPE_VIDEO;
85using cricket::MEDIA_TYPE_DATA;
86using cricket::RtpHeaderExtension;
87using cricket::SEC_DISABLED;
88using cricket::SEC_ENABLED;
89using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070090using rtc::CS_AES_CM_128_HMAC_SHA1_32;
91using rtc::CS_AES_CM_128_HMAC_SHA1_80;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092
93static const AudioCodec kAudioCodecs1[] = {
94 AudioCodec(103, "ISAC", 16000, -1, 1, 6),
95 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
96 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
97 AudioCodec(8, "PCMA", 8000, 64000, 1, 3),
98 AudioCodec(117, "red", 8000, 0, 1, 2),
99 AudioCodec(107, "CN", 48000, 0, 1, 1)
100};
101
102static const AudioCodec kAudioCodecs2[] = {
103 AudioCodec(126, "speex", 16000, 22000, 1, 3),
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000104 AudioCodec(0, "PCMU", 8000, 64000, 1, 2),
105 AudioCodec(127, "iLBC", 8000, 13300, 1, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106};
107
108static const AudioCodec kAudioCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000109 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
110 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000111};
112
113static const VideoCodec kVideoCodecs1[] = {
114 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
115 VideoCodec(97, "H264", 320, 200, 30, 1)
116};
117
118static const VideoCodec kVideoCodecs2[] = {
119 VideoCodec(126, "H264", 320, 200, 30, 2),
120 VideoCodec(127, "H263", 320, 200, 30, 1)
121};
122
123static const VideoCodec kVideoCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000124 VideoCodec(97, "H264", 320, 200, 30, 1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125};
126
127static const DataCodec kDataCodecs1[] = {
128 DataCodec(98, "binary-data", 2),
129 DataCodec(99, "utf8-text", 1)
130};
131
132static const DataCodec kDataCodecs2[] = {
133 DataCodec(126, "binary-data", 2),
134 DataCodec(127, "utf8-text", 1)
135};
136
137static const DataCodec kDataCodecsAnswer[] = {
138 DataCodec(98, "binary-data", 2),
139 DataCodec(99, "utf8-text", 1)
140};
141
142static const RtpHeaderExtension kAudioRtpExtension1[] = {
143 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
144 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
145};
146
147static const RtpHeaderExtension kAudioRtpExtension2[] = {
148 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
149 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000150 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000151};
152
deadbeefa5b273a2015-08-20 17:30:13 -0700153static const RtpHeaderExtension kAudioRtpExtension3[] = {
154 RtpHeaderExtension("http://google.com/testing/audio_something", 2),
155 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 3),
156};
157
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000158static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
159 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
160};
161
162static const RtpHeaderExtension kVideoRtpExtension1[] = {
163 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000164 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000165};
166
167static const RtpHeaderExtension kVideoRtpExtension2[] = {
168 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
169 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000170 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171};
172
deadbeefa5b273a2015-08-20 17:30:13 -0700173static const RtpHeaderExtension kVideoRtpExtension3[] = {
174 RtpHeaderExtension("http://google.com/testing/video_something", 4),
175 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 5),
176};
177
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
179 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
180};
181
Peter Boström0c4e06b2015-10-07 12:23:21 +0200182static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
183static const uint32_t kSimSsrc[] = {10, 20, 30};
184static const uint32_t kFec1Ssrc[] = {10, 11};
185static const uint32_t kFec2Ssrc[] = {20, 21};
186static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000187
188static const char kMediaStream1[] = "stream_1";
189static const char kMediaStream2[] = "stream_2";
190static const char kVideoTrack1[] = "video_1";
191static const char kVideoTrack2[] = "video_2";
192static const char kAudioTrack1[] = "audio_1";
193static const char kAudioTrack2[] = "audio_2";
194static const char kAudioTrack3[] = "audio_3";
195static const char kDataTrack1[] = "data_1";
196static const char kDataTrack2[] = "data_2";
197static const char kDataTrack3[] = "data_3";
198
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000199static bool IsMediaContentOfType(const ContentInfo* content,
200 MediaType media_type) {
201 const MediaContentDescription* mdesc =
202 static_cast<const MediaContentDescription*>(content->description);
203 return mdesc && mdesc->type() == media_type;
204}
205
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000206static cricket::MediaContentDirection
207GetMediaDirection(const ContentInfo* content) {
208 cricket::MediaContentDescription* desc =
209 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
210 return desc->direction();
211}
212
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000213static void AddRtxCodec(const VideoCodec& rtx_codec,
214 std::vector<VideoCodec>* codecs) {
215 VideoCodec rtx;
216 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
217 codecs->push_back(rtx_codec);
218}
219
220template <class T>
221static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
222 std::vector<std::string> codec_names;
223 for (const auto& codec : codecs) {
224 codec_names.push_back(codec.name);
225 }
226 return codec_names;
227}
228
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000229class MediaSessionDescriptionFactoryTest : public testing::Test {
230 public:
231 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200232 : f1_(&tdf1_),
233 f2_(&tdf2_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
235 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
236 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
237 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
238 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
239 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200240 tdf1_.set_certificate(rtc::RTCCertificate::Create(
241 rtc::scoped_ptr<rtc::SSLIdentity>(
242 new rtc::FakeSSLIdentity("id1")).Pass()));
243 tdf2_.set_certificate(rtc::RTCCertificate::Create(
244 rtc::scoped_ptr<rtc::SSLIdentity>(
245 new rtc::FakeSSLIdentity("id2")).Pass()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000246 }
247
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000248 // Create a video StreamParamsVec object with:
249 // - one video stream with 3 simulcast streams and FEC,
250 StreamParamsVec CreateComplexVideoStreamParamsVec() {
251 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
252 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
253 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
254 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
255
256 std::vector<SsrcGroup> ssrc_groups;
257 ssrc_groups.push_back(sim_group);
258 ssrc_groups.push_back(fec_group1);
259 ssrc_groups.push_back(fec_group2);
260 ssrc_groups.push_back(fec_group3);
261
262 StreamParams simulcast_params;
263 simulcast_params.id = kVideoTrack1;
264 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
265 simulcast_params.ssrc_groups = ssrc_groups;
266 simulcast_params.cname = "Video_SIM_FEC";
267 simulcast_params.sync_label = kMediaStream1;
268
269 StreamParamsVec video_streams;
270 video_streams.push_back(simulcast_params);
271
272 return video_streams;
273 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274
275 bool CompareCryptoParams(const CryptoParamsVec& c1,
276 const CryptoParamsVec& c2) {
277 if (c1.size() != c2.size())
278 return false;
279 for (size_t i = 0; i < c1.size(); ++i)
280 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
281 c1[i].key_params != c2[i].key_params ||
282 c1[i].session_params != c2[i].session_params)
283 return false;
284 return true;
285 }
286
287 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
288 bool has_current_desc) {
289 const std::string current_audio_ufrag = "current_audio_ufrag";
290 const std::string current_audio_pwd = "current_audio_pwd";
291 const std::string current_video_ufrag = "current_video_ufrag";
292 const std::string current_video_pwd = "current_video_pwd";
293 const std::string current_data_ufrag = "current_data_ufrag";
294 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000295 rtc::scoped_ptr<SessionDescription> current_desc;
296 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000297 if (has_current_desc) {
298 current_desc.reset(new SessionDescription());
299 EXPECT_TRUE(current_desc->AddTransportInfo(
300 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700301 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000302 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000303 EXPECT_TRUE(current_desc->AddTransportInfo(
304 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700305 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000306 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000307 EXPECT_TRUE(current_desc->AddTransportInfo(
308 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700309 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000310 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 }
312 if (offer) {
313 desc.reset(f1_.CreateOffer(options, current_desc.get()));
314 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000315 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316 offer.reset(f1_.CreateOffer(options, NULL));
317 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
318 }
319 ASSERT_TRUE(desc.get() != NULL);
320 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000321 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322 EXPECT_TRUE(ti_audio != NULL);
323 if (has_current_desc) {
324 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
325 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
326 } else {
327 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
328 ti_audio->description.ice_ufrag.size());
329 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
330 ti_audio->description.ice_pwd.size());
331 }
332
333 } else {
334 EXPECT_TRUE(ti_audio == NULL);
335 }
336 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000337 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000338 EXPECT_TRUE(ti_video != NULL);
339 if (options.bundle_enabled) {
340 EXPECT_EQ(ti_audio->description.ice_ufrag,
341 ti_video->description.ice_ufrag);
342 EXPECT_EQ(ti_audio->description.ice_pwd,
343 ti_video->description.ice_pwd);
344 } else {
345 if (has_current_desc) {
346 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
347 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
348 } else {
349 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
350 ti_video->description.ice_ufrag.size());
351 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
352 ti_video->description.ice_pwd.size());
353 }
354 }
355 } else {
356 EXPECT_TRUE(ti_video == NULL);
357 }
358 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
359 if (options.has_data()) {
360 EXPECT_TRUE(ti_data != NULL);
361 if (options.bundle_enabled) {
362 EXPECT_EQ(ti_audio->description.ice_ufrag,
363 ti_data->description.ice_ufrag);
364 EXPECT_EQ(ti_audio->description.ice_pwd,
365 ti_data->description.ice_pwd);
366 } else {
367 if (has_current_desc) {
368 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
369 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
370 } else {
371 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
372 ti_data->description.ice_ufrag.size());
373 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
374 ti_data->description.ice_pwd.size());
375 }
376 }
377 } else {
378 EXPECT_TRUE(ti_video == NULL);
379 }
380 }
381
382 void TestCryptoWithBundle(bool offer) {
383 f1_.set_secure(SEC_ENABLED);
384 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000385 options.recv_audio = true;
386 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000388 rtc::scoped_ptr<SessionDescription> ref_desc;
389 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000390 if (offer) {
391 options.bundle_enabled = false;
392 ref_desc.reset(f1_.CreateOffer(options, NULL));
393 options.bundle_enabled = true;
394 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
395 } else {
396 options.bundle_enabled = true;
397 ref_desc.reset(f1_.CreateOffer(options, NULL));
398 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
399 }
400 ASSERT_TRUE(desc.get() != NULL);
401 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000402 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000403 desc.get()->GetContentDescriptionByName("audio"));
404 ASSERT_TRUE(audio_media_desc != NULL);
405 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000406 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 desc.get()->GetContentDescriptionByName("video"));
408 ASSERT_TRUE(video_media_desc != NULL);
409 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
410 video_media_desc->cryptos()));
411 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
412 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
413 audio_media_desc->cryptos()[0].cipher_suite);
414
415 // Verify the selected crypto is one from the reference audio
416 // media content.
417 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000418 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000419 ref_desc.get()->GetContentDescriptionByName("audio"));
420 bool found = false;
421 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
422 if (ref_audio_media_desc->cryptos()[i].Matches(
423 audio_media_desc->cryptos()[0])) {
424 found = true;
425 break;
426 }
427 }
428 EXPECT_TRUE(found);
429 }
430
431 // This test that the audio and video media direction is set to
432 // |expected_direction_in_answer| in an answer if the offer direction is set
433 // to |direction_in_offer|.
434 void TestMediaDirectionInAnswer(
435 cricket::MediaContentDirection direction_in_offer,
436 cricket::MediaContentDirection expected_direction_in_answer) {
437 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000438 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000439 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 f1_.CreateOffer(opts, NULL));
441 ASSERT_TRUE(offer.get() != NULL);
442 ContentInfo* ac_offer= offer->GetContentByName("audio");
443 ASSERT_TRUE(ac_offer != NULL);
444 AudioContentDescription* acd_offer =
445 static_cast<AudioContentDescription*>(ac_offer->description);
446 acd_offer->set_direction(direction_in_offer);
447 ContentInfo* vc_offer= offer->GetContentByName("video");
448 ASSERT_TRUE(vc_offer != NULL);
449 VideoContentDescription* vcd_offer =
450 static_cast<VideoContentDescription*>(vc_offer->description);
451 vcd_offer->set_direction(direction_in_offer);
452
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000453 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000454 f2_.CreateAnswer(offer.get(), opts, NULL));
455 const AudioContentDescription* acd_answer =
456 GetFirstAudioContentDescription(answer.get());
457 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
458 const VideoContentDescription* vcd_answer =
459 GetFirstVideoContentDescription(answer.get());
460 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
461 }
462
463 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
464 const cricket::ContentDescription* description = content->description;
465 ASSERT(description != NULL);
466 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000467 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468 ASSERT(audio_content_desc != NULL);
469 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
470 if (audio_content_desc->codecs()[i].name == "CN")
471 return false;
472 }
473 return true;
474 }
475
476 protected:
477 MediaSessionDescriptionFactory f1_;
478 MediaSessionDescriptionFactory f2_;
479 TransportDescriptionFactory tdf1_;
480 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000481};
482
483// Create a typical audio offer, and ensure it matches what we expect.
484TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
485 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000486 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000487 f1_.CreateOffer(MediaSessionOptions(), NULL));
488 ASSERT_TRUE(offer.get() != NULL);
489 const ContentInfo* ac = offer->GetContentByName("audio");
490 const ContentInfo* vc = offer->GetContentByName("video");
491 ASSERT_TRUE(ac != NULL);
492 ASSERT_TRUE(vc == NULL);
493 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
494 const AudioContentDescription* acd =
495 static_cast<const AudioContentDescription*>(ac->description);
496 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
497 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
498 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
499 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
500 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
501 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
502 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
503}
504
505// Create a typical video offer, and ensure it matches what we expect.
506TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
507 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000508 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000509 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000510 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000511 offer(f1_.CreateOffer(opts, NULL));
512 ASSERT_TRUE(offer.get() != NULL);
513 const ContentInfo* ac = offer->GetContentByName("audio");
514 const ContentInfo* vc = offer->GetContentByName("video");
515 ASSERT_TRUE(ac != NULL);
516 ASSERT_TRUE(vc != NULL);
517 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
518 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
519 const AudioContentDescription* acd =
520 static_cast<const AudioContentDescription*>(ac->description);
521 const VideoContentDescription* vcd =
522 static_cast<const VideoContentDescription*>(vc->description);
523 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
524 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
525 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
526 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
527 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
528 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
529 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
530 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
531 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
532 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
533 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
534 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
535 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
536 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
537}
538
539// Test creating an offer with bundle where the Codecs have the same dynamic
540// RTP playlod type. The test verifies that the offer don't contain the
541// duplicate RTP payload types.
542TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
543 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
544 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
545 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
546 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
547 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
548
549 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000550 opts.recv_audio = true;
551 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000552 opts.data_channel_type = cricket::DCT_RTP;
553 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000554 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000555 offer(f2_.CreateOffer(opts, NULL));
556 const VideoContentDescription* vcd =
557 GetFirstVideoContentDescription(offer.get());
558 const AudioContentDescription* acd =
559 GetFirstAudioContentDescription(offer.get());
560 const DataContentDescription* dcd =
561 GetFirstDataContentDescription(offer.get());
562 ASSERT_TRUE(NULL != vcd);
563 ASSERT_TRUE(NULL != acd);
564 ASSERT_TRUE(NULL != dcd);
565 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
566 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
567 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
568 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
569 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
570 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
571}
572
573// Test creating an updated offer with with bundle, audio, video and data
574// after an audio only session has been negotiated.
575TEST_F(MediaSessionDescriptionFactoryTest,
576 TestCreateUpdatedVideoOfferWithBundle) {
577 f1_.set_secure(SEC_ENABLED);
578 f2_.set_secure(SEC_ENABLED);
579 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000580 opts.recv_audio = true;
581 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 opts.data_channel_type = cricket::DCT_NONE;
583 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000584 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
585 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000586 f2_.CreateAnswer(offer.get(), opts, NULL));
587
588 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000589 updated_opts.recv_audio = true;
590 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 updated_opts.data_channel_type = cricket::DCT_RTP;
592 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000593 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000594 updated_opts, answer.get()));
595
596 const AudioContentDescription* acd =
597 GetFirstAudioContentDescription(updated_offer.get());
598 const VideoContentDescription* vcd =
599 GetFirstVideoContentDescription(updated_offer.get());
600 const DataContentDescription* dcd =
601 GetFirstDataContentDescription(updated_offer.get());
602 EXPECT_TRUE(NULL != vcd);
603 EXPECT_TRUE(NULL != acd);
604 EXPECT_TRUE(NULL != dcd);
605
606 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
607 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
608 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
609 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
610 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
611 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
612}
deadbeef44f08192015-12-15 16:20:09 -0800613
wu@webrtc.org78187522013-10-07 23:32:02 +0000614// Create a RTP data offer, and ensure it matches what we expect.
615TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 MediaSessionOptions opts;
617 opts.data_channel_type = cricket::DCT_RTP;
618 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000619 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000620 offer(f1_.CreateOffer(opts, NULL));
621 ASSERT_TRUE(offer.get() != NULL);
622 const ContentInfo* ac = offer->GetContentByName("audio");
623 const ContentInfo* dc = offer->GetContentByName("data");
624 ASSERT_TRUE(ac != NULL);
625 ASSERT_TRUE(dc != NULL);
626 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
627 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
628 const AudioContentDescription* acd =
629 static_cast<const AudioContentDescription*>(ac->description);
630 const DataContentDescription* dcd =
631 static_cast<const DataContentDescription*>(dc->description);
632 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
633 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
634 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
635 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
636 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
637 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
638 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
639 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
640 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
641 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
642 EXPECT_EQ(cricket::kDataMaxBandwidth,
643 dcd->bandwidth()); // default bandwidth (auto)
644 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
645 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
646 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
647}
648
wu@webrtc.org78187522013-10-07 23:32:02 +0000649// Create an SCTP data offer with bundle without error.
650TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
651 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000652 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000653 opts.bundle_enabled = true;
654 opts.data_channel_type = cricket::DCT_SCTP;
655 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000656 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000657 EXPECT_TRUE(offer.get() != NULL);
658 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
659}
660
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000661// Test creating an sctp data channel from an already generated offer.
662TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
663 MediaSessionOptions opts;
664 opts.recv_audio = false;
665 opts.bundle_enabled = true;
666 opts.data_channel_type = cricket::DCT_SCTP;
667 f1_.set_secure(SEC_ENABLED);
668 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
669 ASSERT_TRUE(offer1.get() != NULL);
670 const ContentInfo* data = offer1->GetContentByName("data");
671 ASSERT_TRUE(data != NULL);
672 const MediaContentDescription* mdesc =
673 static_cast<const MediaContentDescription*>(data->description);
674 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
675
676 // Now set data_channel_type to 'none' (default) and make sure that the
677 // datachannel type that gets generated from the previous offer, is of the
678 // same type.
679 opts.data_channel_type = cricket::DCT_NONE;
680 rtc::scoped_ptr<SessionDescription> offer2(
681 f1_.CreateOffer(opts, offer1.get()));
682 data = offer2->GetContentByName("data");
683 ASSERT_TRUE(data != NULL);
684 mdesc = static_cast<const MediaContentDescription*>(data->description);
685 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
686}
687
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000688// Create an audio, video offer without legacy StreamParams.
689TEST_F(MediaSessionDescriptionFactoryTest,
690 TestCreateOfferWithoutLegacyStreams) {
691 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000692 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000693 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000694 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000695 offer(f1_.CreateOffer(opts, NULL));
696 ASSERT_TRUE(offer.get() != NULL);
697 const ContentInfo* ac = offer->GetContentByName("audio");
698 const ContentInfo* vc = offer->GetContentByName("video");
699 ASSERT_TRUE(ac != NULL);
700 ASSERT_TRUE(vc != NULL);
701 const AudioContentDescription* acd =
702 static_cast<const AudioContentDescription*>(ac->description);
703 const VideoContentDescription* vcd =
704 static_cast<const VideoContentDescription*>(vc->description);
705
706 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
707 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
708}
709
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000710// Creates an audio+video sendonly offer.
711TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
712 MediaSessionOptions options;
713 options.recv_audio = false;
714 options.recv_video = false;
715 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
716 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
717
718 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
719 ASSERT_TRUE(offer.get() != NULL);
720 EXPECT_EQ(2u, offer->contents().size());
721 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
722 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
723
724 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
725 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
726}
727
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000728// Verifies that the order of the media contents in the current
729// SessionDescription is preserved in the new SessionDescription.
730TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
731 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000732 opts.recv_audio = false;
733 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000734 opts.data_channel_type = cricket::DCT_SCTP;
735
736 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
737 ASSERT_TRUE(offer1.get() != NULL);
738 EXPECT_EQ(1u, offer1->contents().size());
739 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
740
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000741 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000742 rtc::scoped_ptr<SessionDescription> offer2(
743 f1_.CreateOffer(opts, offer1.get()));
744 ASSERT_TRUE(offer2.get() != NULL);
745 EXPECT_EQ(2u, offer2->contents().size());
746 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
747 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
748
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000749 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000750 rtc::scoped_ptr<SessionDescription> offer3(
751 f1_.CreateOffer(opts, offer2.get()));
752 ASSERT_TRUE(offer3.get() != NULL);
753 EXPECT_EQ(3u, offer3->contents().size());
754 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
755 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
756 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
757
758 // Verifies the default order is audio-video-data, so that the previous checks
759 // didn't pass by accident.
760 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
761 ASSERT_TRUE(offer4.get() != NULL);
762 EXPECT_EQ(3u, offer4->contents().size());
763 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
764 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
765 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
766}
767
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000768// Create a typical audio answer, and ensure it matches what we expect.
769TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
770 f1_.set_secure(SEC_ENABLED);
771 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000772 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 f1_.CreateOffer(MediaSessionOptions(), NULL));
774 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000775 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000776 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
777 const ContentInfo* ac = answer->GetContentByName("audio");
778 const ContentInfo* vc = answer->GetContentByName("video");
779 ASSERT_TRUE(ac != NULL);
780 ASSERT_TRUE(vc == NULL);
781 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
782 const AudioContentDescription* acd =
783 static_cast<const AudioContentDescription*>(ac->description);
784 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
785 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
786 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
787 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
788 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
789 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
790 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
791}
792
793// Create a typical video answer, and ensure it matches what we expect.
794TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
795 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000796 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000797 f1_.set_secure(SEC_ENABLED);
798 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000799 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000800 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000801 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802 f2_.CreateAnswer(offer.get(), opts, NULL));
803 const ContentInfo* ac = answer->GetContentByName("audio");
804 const ContentInfo* vc = answer->GetContentByName("video");
805 ASSERT_TRUE(ac != NULL);
806 ASSERT_TRUE(vc != NULL);
807 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
808 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
809 const AudioContentDescription* acd =
810 static_cast<const AudioContentDescription*>(ac->description);
811 const VideoContentDescription* vcd =
812 static_cast<const VideoContentDescription*>(vc->description);
813 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
814 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
815 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
816 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
817 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
818 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
819 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
820 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
821 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
822 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
823 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
824 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
825}
826
827TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
828 MediaSessionOptions opts;
829 opts.data_channel_type = cricket::DCT_RTP;
830 f1_.set_secure(SEC_ENABLED);
831 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000832 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000833 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000834 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000835 f2_.CreateAnswer(offer.get(), opts, NULL));
836 const ContentInfo* ac = answer->GetContentByName("audio");
837 const ContentInfo* vc = answer->GetContentByName("data");
838 ASSERT_TRUE(ac != NULL);
839 ASSERT_TRUE(vc != NULL);
840 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
841 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
842 const AudioContentDescription* acd =
843 static_cast<const AudioContentDescription*>(ac->description);
844 const DataContentDescription* vcd =
845 static_cast<const DataContentDescription*>(vc->description);
846 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
847 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
848 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
849 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
850 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
851 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
852 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
853 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
854 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
855 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
856 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
857 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
858}
859
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000860// Verifies that the order of the media contents in the offer is preserved in
861// the answer.
862TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
863 MediaSessionOptions opts;
864
865 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000866 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000867 opts.data_channel_type = cricket::DCT_SCTP;
868 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
869 ASSERT_TRUE(offer1.get() != NULL);
870
871 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000872 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000873 rtc::scoped_ptr<SessionDescription> offer2(
874 f1_.CreateOffer(opts, offer1.get()));
875 ASSERT_TRUE(offer2.get() != NULL);
876
877 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000878 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000879 rtc::scoped_ptr<SessionDescription> offer3(
880 f1_.CreateOffer(opts, offer2.get()));
881 ASSERT_TRUE(offer3.get() != NULL);
882
883 rtc::scoped_ptr<SessionDescription> answer(
884 f2_.CreateAnswer(offer3.get(), opts, NULL));
885 ASSERT_TRUE(answer.get() != NULL);
886 EXPECT_EQ(3u, answer->contents().size());
887 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
888 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
889 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
890}
891
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000892// This test that the media direction is set to send/receive in an answer if
893// the offer is send receive.
894TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
895 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
896}
897
898// This test that the media direction is set to receive only in an answer if
899// the offer is send only.
900TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
901 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
902}
903
904// This test that the media direction is set to send only in an answer if
905// the offer is recv only.
906TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
907 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
908}
909
910// This test that the media direction is set to inactive in an answer if
911// the offer is inactive.
912TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
913 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
914}
915
916// Test that a data content with an unknown protocol is rejected in an answer.
917TEST_F(MediaSessionDescriptionFactoryTest,
918 CreateDataAnswerToOfferWithUnknownProtocol) {
919 MediaSessionOptions opts;
920 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000921 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000922 f1_.set_secure(SEC_ENABLED);
923 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000924 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000925 ContentInfo* dc_offer= offer->GetContentByName("data");
926 ASSERT_TRUE(dc_offer != NULL);
927 DataContentDescription* dcd_offer =
928 static_cast<DataContentDescription*>(dc_offer->description);
929 ASSERT_TRUE(dcd_offer != NULL);
930 std::string protocol = "a weird unknown protocol";
931 dcd_offer->set_protocol(protocol);
932
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000933 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000934 f2_.CreateAnswer(offer.get(), opts, NULL));
935
936 const ContentInfo* dc_answer = answer->GetContentByName("data");
937 ASSERT_TRUE(dc_answer != NULL);
938 EXPECT_TRUE(dc_answer->rejected);
939 const DataContentDescription* dcd_answer =
940 static_cast<const DataContentDescription*>(dc_answer->description);
941 ASSERT_TRUE(dcd_answer != NULL);
942 EXPECT_EQ(protocol, dcd_answer->protocol());
943}
944
945// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
946TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
947 MediaSessionOptions opts;
948 f1_.set_secure(SEC_DISABLED);
949 f2_.set_secure(SEC_DISABLED);
950 tdf1_.set_secure(SEC_DISABLED);
951 tdf2_.set_secure(SEC_DISABLED);
952
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 const AudioContentDescription* offer_acd =
955 GetFirstAudioContentDescription(offer.get());
956 ASSERT_TRUE(offer_acd != NULL);
957 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
958
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000959 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960 f2_.CreateAnswer(offer.get(), opts, NULL));
961
962 const ContentInfo* ac_answer = answer->GetContentByName("audio");
963 ASSERT_TRUE(ac_answer != NULL);
964 EXPECT_FALSE(ac_answer->rejected);
965
966 const AudioContentDescription* answer_acd =
967 GetFirstAudioContentDescription(answer.get());
968 ASSERT_TRUE(answer_acd != NULL);
969 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
970}
971
972// Create a video offer and answer and ensure the RTP header extensions
973// matches what we expect.
974TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
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
978 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
979 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
980 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
981 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
982
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000983 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000985 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 f2_.CreateAnswer(offer.get(), opts, NULL));
987
988 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
989 GetFirstAudioContentDescription(
990 offer.get())->rtp_header_extensions());
991 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
992 GetFirstVideoContentDescription(
993 offer.get())->rtp_header_extensions());
994 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
995 GetFirstAudioContentDescription(
996 answer.get())->rtp_header_extensions());
997 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
998 GetFirstVideoContentDescription(
999 answer.get())->rtp_header_extensions());
1000}
1001
1002// Create an audio, video, data answer without legacy StreamParams.
1003TEST_F(MediaSessionDescriptionFactoryTest,
1004 TestCreateAnswerWithoutLegacyStreams) {
1005 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001006 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001007 opts.data_channel_type = cricket::DCT_RTP;
1008 f1_.set_add_legacy_streams(false);
1009 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001010 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001011 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001012 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001013 f2_.CreateAnswer(offer.get(), opts, NULL));
1014 const ContentInfo* ac = answer->GetContentByName("audio");
1015 const ContentInfo* vc = answer->GetContentByName("video");
1016 const ContentInfo* dc = answer->GetContentByName("data");
1017 ASSERT_TRUE(ac != NULL);
1018 ASSERT_TRUE(vc != NULL);
1019 const AudioContentDescription* acd =
1020 static_cast<const AudioContentDescription*>(ac->description);
1021 const VideoContentDescription* vcd =
1022 static_cast<const VideoContentDescription*>(vc->description);
1023 const DataContentDescription* dcd =
1024 static_cast<const DataContentDescription*>(dc->description);
1025
1026 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1027 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1028 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1029}
1030
1031TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1032 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001033 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001034 opts.data_channel_type = cricket::DCT_RTP;
1035 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001036 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037 offer(f1_.CreateOffer(opts, NULL));
1038 ASSERT_TRUE(offer.get() != NULL);
1039 const ContentInfo* ac = offer->GetContentByName("audio");
1040 const ContentInfo* vc = offer->GetContentByName("video");
1041 const ContentInfo* dc = offer->GetContentByName("data");
1042 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1043 static_cast<const AudioContentDescription*>(ac->description));
1044 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1045 static_cast<const VideoContentDescription*>(vc->description));
1046 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1047 static_cast<const DataContentDescription*>(dc->description));
1048
1049 EXPECT_FALSE(acd->partial()); // default is false.
1050 acd->set_partial(true);
1051 EXPECT_TRUE(acd->partial());
1052 acd->set_partial(false);
1053 EXPECT_FALSE(acd->partial());
1054
1055 EXPECT_FALSE(vcd->partial()); // default is false.
1056 vcd->set_partial(true);
1057 EXPECT_TRUE(vcd->partial());
1058 vcd->set_partial(false);
1059 EXPECT_FALSE(vcd->partial());
1060
1061 EXPECT_FALSE(dcd->partial()); // default is false.
1062 dcd->set_partial(true);
1063 EXPECT_TRUE(dcd->partial());
1064 dcd->set_partial(false);
1065 EXPECT_FALSE(dcd->partial());
1066}
1067
1068// Create a typical video answer, and ensure it matches what we expect.
1069TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1070 MediaSessionOptions offer_opts;
1071 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001072 answer_opts.recv_video = true;
1073 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001074 answer_opts.data_channel_type = cricket::DCT_RTP;
1075 offer_opts.data_channel_type = cricket::DCT_RTP;
1076
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001077 rtc::scoped_ptr<SessionDescription> offer;
1078 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001079
1080 offer_opts.rtcp_mux_enabled = true;
1081 answer_opts.rtcp_mux_enabled = true;
1082
1083 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1084 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1085 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1086 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1087 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1088 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1089 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1090 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1091 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1092 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1093 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1094 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1095 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1096 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1097
1098 offer_opts.rtcp_mux_enabled = true;
1099 answer_opts.rtcp_mux_enabled = false;
1100
1101 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1102 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1103 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1104 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1105 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1106 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1107 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1108 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1109 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1110 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1111 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1112 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1113 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1114 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1115
1116 offer_opts.rtcp_mux_enabled = false;
1117 answer_opts.rtcp_mux_enabled = true;
1118
1119 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1120 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1121 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1122 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1123 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1124 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1125 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1126 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1127 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1128 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1129 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1130 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1131 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1132 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1133
1134 offer_opts.rtcp_mux_enabled = false;
1135 answer_opts.rtcp_mux_enabled = false;
1136
1137 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1138 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1139 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1140 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1141 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1142 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1143 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1144 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1145 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1146 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1147 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1148 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1149 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1150 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1151}
1152
1153// Create an audio-only answer to a video offer.
1154TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1155 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001156 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001157 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158 offer(f1_.CreateOffer(opts, NULL));
1159 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001160 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1162 const ContentInfo* ac = answer->GetContentByName("audio");
1163 const ContentInfo* vc = answer->GetContentByName("video");
1164 ASSERT_TRUE(ac != NULL);
1165 ASSERT_TRUE(vc != NULL);
1166 ASSERT_TRUE(vc->description != NULL);
1167 EXPECT_TRUE(vc->rejected);
1168}
1169
1170// Create an audio-only answer to an offer with data.
1171TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1172 MediaSessionOptions opts;
1173 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001174 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 offer(f1_.CreateOffer(opts, NULL));
1176 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001177 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1179 const ContentInfo* ac = answer->GetContentByName("audio");
1180 const ContentInfo* dc = answer->GetContentByName("data");
1181 ASSERT_TRUE(ac != NULL);
1182 ASSERT_TRUE(dc != NULL);
1183 ASSERT_TRUE(dc->description != NULL);
1184 EXPECT_TRUE(dc->rejected);
1185}
1186
1187// Create an answer that rejects the contents which are rejected in the offer.
1188TEST_F(MediaSessionDescriptionFactoryTest,
1189 CreateAnswerToOfferWithRejectedMedia) {
1190 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001191 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001192 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001193 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001194 offer(f1_.CreateOffer(opts, NULL));
1195 ASSERT_TRUE(offer.get() != NULL);
1196 ContentInfo* ac = offer->GetContentByName("audio");
1197 ContentInfo* vc = offer->GetContentByName("video");
1198 ContentInfo* dc = offer->GetContentByName("data");
1199 ASSERT_TRUE(ac != NULL);
1200 ASSERT_TRUE(vc != NULL);
1201 ASSERT_TRUE(dc != NULL);
1202 ac->rejected = true;
1203 vc->rejected = true;
1204 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001205 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001206 f2_.CreateAnswer(offer.get(), opts, NULL));
1207 ac = answer->GetContentByName("audio");
1208 vc = answer->GetContentByName("video");
1209 dc = answer->GetContentByName("data");
1210 ASSERT_TRUE(ac != NULL);
1211 ASSERT_TRUE(vc != NULL);
1212 ASSERT_TRUE(dc != NULL);
1213 EXPECT_TRUE(ac->rejected);
1214 EXPECT_TRUE(vc->rejected);
1215 EXPECT_TRUE(dc->rejected);
1216}
1217
1218// Create an audio and video offer with:
1219// - one video track
1220// - two audio tracks
1221// - two data tracks
1222// and ensure it matches what we expect. Also updates the initial offer by
1223// adding a new video track and replaces one of the audio tracks.
1224TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1225 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001226 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1227 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1228 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001229 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001230 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1231 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001232
1233 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001234 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001235
1236 ASSERT_TRUE(offer.get() != NULL);
1237 const ContentInfo* ac = offer->GetContentByName("audio");
1238 const ContentInfo* vc = offer->GetContentByName("video");
1239 const ContentInfo* dc = offer->GetContentByName("data");
1240 ASSERT_TRUE(ac != NULL);
1241 ASSERT_TRUE(vc != NULL);
1242 ASSERT_TRUE(dc != NULL);
1243 const AudioContentDescription* acd =
1244 static_cast<const AudioContentDescription*>(ac->description);
1245 const VideoContentDescription* vcd =
1246 static_cast<const VideoContentDescription*>(vc->description);
1247 const DataContentDescription* dcd =
1248 static_cast<const DataContentDescription*>(dc->description);
1249 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1250 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1251
1252 const StreamParamsVec& audio_streams = acd->streams();
1253 ASSERT_EQ(2U, audio_streams.size());
1254 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1255 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1256 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1257 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1258 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1259 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1260 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1261
1262 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1263 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1264 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1265
1266 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1267 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1268 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1269
1270 const StreamParamsVec& video_streams = vcd->streams();
1271 ASSERT_EQ(1U, video_streams.size());
1272 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1273 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1274 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1275 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1276
1277 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1278 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1279 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1280
1281 const StreamParamsVec& data_streams = dcd->streams();
1282 ASSERT_EQ(2U, data_streams.size());
1283 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1284 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1285 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1286 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1287 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1288 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1289 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1290
1291 EXPECT_EQ(cricket::kDataMaxBandwidth,
1292 dcd->bandwidth()); // default bandwidth (auto)
1293 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1294 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1295
1296
1297 // Update the offer. Add a new video track that is not synched to the
1298 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001299 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1300 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1301 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1302 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1303 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001304 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001305 updated_offer(f1_.CreateOffer(opts, offer.get()));
1306
1307 ASSERT_TRUE(updated_offer.get() != NULL);
1308 ac = updated_offer->GetContentByName("audio");
1309 vc = updated_offer->GetContentByName("video");
1310 dc = updated_offer->GetContentByName("data");
1311 ASSERT_TRUE(ac != NULL);
1312 ASSERT_TRUE(vc != NULL);
1313 ASSERT_TRUE(dc != NULL);
1314 const AudioContentDescription* updated_acd =
1315 static_cast<const AudioContentDescription*>(ac->description);
1316 const VideoContentDescription* updated_vcd =
1317 static_cast<const VideoContentDescription*>(vc->description);
1318 const DataContentDescription* updated_dcd =
1319 static_cast<const DataContentDescription*>(dc->description);
1320
1321 EXPECT_EQ(acd->type(), updated_acd->type());
1322 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1323 EXPECT_EQ(vcd->type(), updated_vcd->type());
1324 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1325 EXPECT_EQ(dcd->type(), updated_dcd->type());
1326 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1327 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1328 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1329 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1330 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1331 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1332 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1333
1334 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1335 ASSERT_EQ(2U, updated_audio_streams.size());
1336 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1337 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1338 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1339 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1340 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1341
1342 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1343 ASSERT_EQ(2U, updated_video_streams.size());
1344 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1345 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1346 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1347
1348 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1349 ASSERT_EQ(2U, updated_data_streams.size());
1350 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1351 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1352 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1353 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1354 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1355}
1356
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001357// Create an offer with simulcast video stream.
1358TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1359 MediaSessionOptions opts;
1360 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001361 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001362 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001363
1364 ASSERT_TRUE(offer.get() != NULL);
1365 const ContentInfo* vc = offer->GetContentByName("video");
1366 ASSERT_TRUE(vc != NULL);
1367 const VideoContentDescription* vcd =
1368 static_cast<const VideoContentDescription*>(vc->description);
1369
1370 const StreamParamsVec& video_streams = vcd->streams();
1371 ASSERT_EQ(1U, video_streams.size());
1372 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1373 const SsrcGroup* sim_ssrc_group =
1374 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1375 ASSERT_TRUE(sim_ssrc_group != NULL);
1376 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1377}
1378
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001379// Create an audio and video answer to a standard video offer with:
1380// - one video track
1381// - two audio tracks
1382// - two data tracks
1383// and ensure it matches what we expect. Also updates the initial answer by
1384// adding a new video track and removes one of the audio tracks.
1385TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1386 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001387 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001388 offer_opts.data_channel_type = cricket::DCT_RTP;
1389 f1_.set_secure(SEC_ENABLED);
1390 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001391 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001392 NULL));
1393
1394 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001395 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1396 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1397 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001398 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001399 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1400 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001401
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001402 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001403 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1404
1405 ASSERT_TRUE(answer.get() != NULL);
1406 const ContentInfo* ac = answer->GetContentByName("audio");
1407 const ContentInfo* vc = answer->GetContentByName("video");
1408 const ContentInfo* dc = answer->GetContentByName("data");
1409 ASSERT_TRUE(ac != NULL);
1410 ASSERT_TRUE(vc != NULL);
1411 ASSERT_TRUE(dc != NULL);
1412 const AudioContentDescription* acd =
1413 static_cast<const AudioContentDescription*>(ac->description);
1414 const VideoContentDescription* vcd =
1415 static_cast<const VideoContentDescription*>(vc->description);
1416 const DataContentDescription* dcd =
1417 static_cast<const DataContentDescription*>(dc->description);
1418 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1419 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1420 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1421
1422 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1423 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1424
1425 const StreamParamsVec& audio_streams = acd->streams();
1426 ASSERT_EQ(2U, audio_streams.size());
1427 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1428 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1429 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1430 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1431 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1432 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1433 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1434
1435 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1436 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1437
1438 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1439 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1440
1441 const StreamParamsVec& video_streams = vcd->streams();
1442 ASSERT_EQ(1U, video_streams.size());
1443 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1444 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1445 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1446 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1447
1448 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1449 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1450
1451 const StreamParamsVec& data_streams = dcd->streams();
1452 ASSERT_EQ(2U, data_streams.size());
1453 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1454 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1455 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1456 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1457 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1458 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1459 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1460
1461 EXPECT_EQ(cricket::kDataMaxBandwidth,
1462 dcd->bandwidth()); // default bandwidth (auto)
1463 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1464
1465 // Update the answer. Add a new video track that is not synched to the
1466 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001467 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1468 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1469 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001470 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001471 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1472
1473 ASSERT_TRUE(updated_answer.get() != NULL);
1474 ac = updated_answer->GetContentByName("audio");
1475 vc = updated_answer->GetContentByName("video");
1476 dc = updated_answer->GetContentByName("data");
1477 ASSERT_TRUE(ac != NULL);
1478 ASSERT_TRUE(vc != NULL);
1479 ASSERT_TRUE(dc != NULL);
1480 const AudioContentDescription* updated_acd =
1481 static_cast<const AudioContentDescription*>(ac->description);
1482 const VideoContentDescription* updated_vcd =
1483 static_cast<const VideoContentDescription*>(vc->description);
1484 const DataContentDescription* updated_dcd =
1485 static_cast<const DataContentDescription*>(dc->description);
1486
1487 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1488 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1489 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1490 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1491 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1492 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1493
1494 EXPECT_EQ(acd->type(), updated_acd->type());
1495 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1496 EXPECT_EQ(vcd->type(), updated_vcd->type());
1497 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1498 EXPECT_EQ(dcd->type(), updated_dcd->type());
1499 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1500
1501 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1502 ASSERT_EQ(1U, updated_audio_streams.size());
1503 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1504
1505 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1506 ASSERT_EQ(2U, updated_video_streams.size());
1507 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1508 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1509 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1510
1511 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1512 ASSERT_EQ(1U, updated_data_streams.size());
1513 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1514}
1515
1516
1517// Create an updated offer after creating an answer to the original offer and
1518// verify that the codecs that were part of the original answer are not changed
1519// in the updated offer.
1520TEST_F(MediaSessionDescriptionFactoryTest,
1521 RespondentCreatesOfferAfterCreatingAnswer) {
1522 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001523 opts.recv_audio = true;
1524 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001526 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1527 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 f2_.CreateAnswer(offer.get(), opts, NULL));
1529
1530 const AudioContentDescription* acd =
1531 GetFirstAudioContentDescription(answer.get());
1532 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1533
1534 const VideoContentDescription* vcd =
1535 GetFirstVideoContentDescription(answer.get());
1536 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1537
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001538 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001539 f2_.CreateOffer(opts, answer.get()));
1540
1541 // The expected audio codecs are the common audio codecs from the first
1542 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1543 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001544 // TODO(wu): |updated_offer| should not include the codec
1545 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001547 kAudioCodecsAnswer[0],
1548 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001549 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001550 };
1551
1552 // The expected video codecs are the common video codecs from the first
1553 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1554 // preference order.
1555 const VideoCodec kUpdatedVideoCodecOffer[] = {
1556 kVideoCodecsAnswer[0],
1557 kVideoCodecs2[1],
1558 };
1559
1560 const AudioContentDescription* updated_acd =
1561 GetFirstAudioContentDescription(updated_offer.get());
1562 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1563
1564 const VideoContentDescription* updated_vcd =
1565 GetFirstVideoContentDescription(updated_offer.get());
1566 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1567}
1568
1569// Create an updated offer after creating an answer to the original offer and
1570// verify that the codecs that were part of the original answer are not changed
1571// in the updated offer. In this test Rtx is enabled.
1572TEST_F(MediaSessionDescriptionFactoryTest,
1573 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1574 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001575 opts.recv_video = true;
1576 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001577 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001578 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001579 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001580 f1_.set_video_codecs(f1_codecs);
1581
1582 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001583 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001584 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585 f2_.set_video_codecs(f2_codecs);
1586
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001587 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001589 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001590 f2_.CreateAnswer(offer.get(), opts, NULL));
1591
1592 const VideoContentDescription* vcd =
1593 GetFirstVideoContentDescription(answer.get());
1594
1595 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001596 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1597 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001598
1599 EXPECT_EQ(expected_codecs, vcd->codecs());
1600
1601 // Now, make sure we get same result, except for the preference order,
1602 // if |f2_| creates an updated offer even though the default payload types
1603 // are different from |f1_|.
1604 expected_codecs[0].preference = f1_codecs[1].preference;
1605
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001606 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 f2_.CreateOffer(opts, answer.get()));
1608 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001609 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1611
1612 const VideoContentDescription* updated_vcd =
1613 GetFirstVideoContentDescription(updated_answer.get());
1614
1615 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1616}
1617
1618// Create an updated offer that adds video after creating an audio only answer
1619// to the original offer. This test verifies that if a video codec and the RTX
1620// codec have the same default payload type as an audio codec that is already in
1621// use, the added codecs payload types are changed.
1622TEST_F(MediaSessionDescriptionFactoryTest,
1623 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1624 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001625 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001626 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001627 f1_.set_video_codecs(f1_codecs);
1628
1629 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001630 opts.recv_audio = true;
1631 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001633 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1634 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 f2_.CreateAnswer(offer.get(), opts, NULL));
1636
1637 const AudioContentDescription* acd =
1638 GetFirstAudioContentDescription(answer.get());
1639 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1640
1641 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1642 // reference be the same as an audio codec that was negotiated in the
1643 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001644 opts.recv_audio = true;
1645 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646
1647 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1648 int used_pl_type = acd->codecs()[0].id;
1649 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001650 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001651 f2_.set_video_codecs(f2_codecs);
1652
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001653 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654 f2_.CreateOffer(opts, answer.get()));
1655 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001656 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001657 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1658
1659 const AudioContentDescription* updated_acd =
1660 GetFirstAudioContentDescription(answer.get());
1661 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1662
1663 const VideoContentDescription* updated_vcd =
1664 GetFirstVideoContentDescription(updated_answer.get());
1665
1666 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001667 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001668 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1669 EXPECT_NE(used_pl_type, new_h264_pl_type);
1670 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001671 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001672 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1673 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1674}
1675
1676// Test that RTX is ignored when there is no associated payload type parameter.
1677TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1678 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001679 opts.recv_video = true;
1680 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001681 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001682 // This creates RTX without associated payload type parameter.
1683 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001684 f1_.set_video_codecs(f1_codecs);
1685
1686 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001687 // This creates RTX for H264 with the payload type |f2_| uses.
1688 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001689 f2_.set_video_codecs(f2_codecs);
1690
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001691 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001692 ASSERT_TRUE(offer.get() != NULL);
1693 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1694 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1695 // is possible to test that that RTX is dropped when
1696 // kCodecParamAssociatedPayloadType is missing in the offer.
1697 VideoContentDescription* desc =
1698 static_cast<cricket::VideoContentDescription*>(
1699 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1700 ASSERT_TRUE(desc != NULL);
1701 std::vector<VideoCodec> codecs = desc->codecs();
1702 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1703 iter != codecs.end(); ++iter) {
1704 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1705 iter->params.clear();
1706 }
1707 }
1708 desc->set_codecs(codecs);
1709
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001710 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001711 f2_.CreateAnswer(offer.get(), opts, NULL));
1712
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001713 std::vector<std::string> codec_names =
1714 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1715 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1716 cricket::kRtxCodecName));
1717}
1718
1719// Test that RTX will be filtered out in the answer if its associated payload
1720// type doesn't match the local value.
1721TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1722 MediaSessionOptions opts;
1723 opts.recv_video = true;
1724 opts.recv_audio = false;
1725 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1726 // This creates RTX for H264 in sender.
1727 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1728 f1_.set_video_codecs(f1_codecs);
1729
1730 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1731 // This creates RTX for H263 in receiver.
1732 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1733 f2_.set_video_codecs(f2_codecs);
1734
1735 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1736 ASSERT_TRUE(offer.get() != NULL);
1737 // Associated payload type doesn't match, therefore, RTX codec is removed in
1738 // the answer.
1739 rtc::scoped_ptr<SessionDescription> answer(
1740 f2_.CreateAnswer(offer.get(), opts, NULL));
1741
1742 std::vector<std::string> codec_names =
1743 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1744 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1745 cricket::kRtxCodecName));
1746}
1747
1748// Test that when multiple RTX codecs are offered, only the matched RTX codec
1749// is added in the answer, and the unsupported RTX codec is filtered out.
1750TEST_F(MediaSessionDescriptionFactoryTest,
1751 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1752 MediaSessionOptions opts;
1753 opts.recv_video = true;
1754 opts.recv_audio = false;
1755 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1756 // This creates RTX for H264-SVC in sender.
1757 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1758 f1_.set_video_codecs(f1_codecs);
1759
1760 // This creates RTX for H264 in sender.
1761 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1762 f1_.set_video_codecs(f1_codecs);
1763
1764 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1765 // This creates RTX for H264 in receiver.
1766 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1767 f2_.set_video_codecs(f2_codecs);
1768
1769 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1770 // for H264-SVC should also be removed.
1771 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1772 ASSERT_TRUE(offer.get() != NULL);
1773 rtc::scoped_ptr<SessionDescription> answer(
1774 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001775 const VideoContentDescription* vcd =
1776 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001777 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1778 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1779 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001780
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001781 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001782}
1783
Noah Richards2e7a0982015-05-18 14:02:54 -07001784// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1785// generated for each simulcast ssrc and correctly grouped.
1786TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1787 MediaSessionOptions opts;
1788 opts.recv_video = true;
1789 opts.recv_audio = false;
1790
1791 // Add simulcast streams.
1792 opts.AddSendVideoStream("stream1", "stream1label", 3);
1793
1794 // Use a single real codec, and then add RTX for it.
1795 std::vector<VideoCodec> f1_codecs;
1796 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30, 1));
1797 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1798 f1_.set_video_codecs(f1_codecs);
1799
1800 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1801 // is a FID ssrc + grouping for each.
1802 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1803 ASSERT_TRUE(offer.get() != NULL);
1804 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1805 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1806 ASSERT_TRUE(desc != NULL);
1807 EXPECT_TRUE(desc->multistream());
1808 const StreamParamsVec& streams = desc->streams();
1809 // Single stream.
1810 ASSERT_EQ(1u, streams.size());
1811 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1812 EXPECT_EQ(6u, streams[0].ssrcs.size());
1813 // And should have a SIM group for the simulcast.
1814 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1815 // And a FID group for RTX.
1816 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02001817 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001818 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1819 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001820 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001821 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1822 EXPECT_EQ(3u, fid_ssrcs.size());
1823}
1824
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001825// Create an updated offer after creating an answer to the original offer and
1826// verify that the RTP header extensions that were part of the original answer
1827// are not changed in the updated offer.
1828TEST_F(MediaSessionDescriptionFactoryTest,
1829 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1830 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001831 opts.recv_audio = true;
1832 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001833
1834 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1835 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1836 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1837 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1838
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001839 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1840 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841 f2_.CreateAnswer(offer.get(), opts, NULL));
1842
1843 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1844 GetFirstAudioContentDescription(
1845 answer.get())->rtp_header_extensions());
1846 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1847 GetFirstVideoContentDescription(
1848 answer.get())->rtp_header_extensions());
1849
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001850 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001851 f2_.CreateOffer(opts, answer.get()));
1852
1853 // The expected RTP header extensions in the new offer are the resulting
1854 // extensions from the first offer/answer exchange plus the extensions only
1855 // |f2_| offer.
1856 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001857 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001858 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1859 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001860 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1861 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001862 };
1863
1864 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001865 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1867 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001868 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1869 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001870 };
1871
1872 const AudioContentDescription* updated_acd =
1873 GetFirstAudioContentDescription(updated_offer.get());
1874 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1875 updated_acd->rtp_header_extensions());
1876
1877 const VideoContentDescription* updated_vcd =
1878 GetFirstVideoContentDescription(updated_offer.get());
1879 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1880 updated_vcd->rtp_header_extensions());
1881}
1882
deadbeefa5b273a2015-08-20 17:30:13 -07001883// Verify that if the same RTP extension URI is used for audio and video, the
1884// same ID is used. Also verify that the ID isn't changed when creating an
1885// updated offer (this was previously a bug).
1886TEST_F(MediaSessionDescriptionFactoryTest,
1887 RtpHeaderExtensionIdReused) {
1888 MediaSessionOptions opts;
1889 opts.recv_audio = true;
1890 opts.recv_video = true;
1891
1892 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1893 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1894
1895 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1896
1897 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1898 // the video extensions.
1899 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1900 kVideoRtpExtension3[0],
1901 kAudioRtpExtension3[1],
1902 };
1903
1904 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1905 GetFirstAudioContentDescription(
1906 offer.get())->rtp_header_extensions());
1907 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1908 GetFirstVideoContentDescription(
1909 offer.get())->rtp_header_extensions());
1910
1911 // Nothing should change when creating a new offer
1912 rtc::scoped_ptr<SessionDescription> updated_offer(
1913 f1_.CreateOffer(opts, offer.get()));
1914
1915 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1916 GetFirstAudioContentDescription(
1917 updated_offer.get())->rtp_header_extensions());
1918 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1919 GetFirstVideoContentDescription(
1920 updated_offer.get())->rtp_header_extensions());
1921}
1922
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001923TEST(MediaSessionDescription, CopySessionDescription) {
1924 SessionDescription source;
1925 cricket::ContentGroup group(cricket::CN_AUDIO);
1926 source.AddGroup(group);
1927 AudioContentDescription* acd(new AudioContentDescription());
1928 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1929 acd->AddLegacyStream(1);
1930 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1931 VideoContentDescription* vcd(new VideoContentDescription());
1932 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1933 vcd->AddLegacyStream(2);
1934 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1935
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001936 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001937 ASSERT_TRUE(copy.get() != NULL);
1938 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1939 const ContentInfo* ac = copy->GetContentByName("audio");
1940 const ContentInfo* vc = copy->GetContentByName("video");
1941 ASSERT_TRUE(ac != NULL);
1942 ASSERT_TRUE(vc != NULL);
1943 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1944 const AudioContentDescription* acd_copy =
1945 static_cast<const AudioContentDescription*>(ac->description);
1946 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1947 EXPECT_EQ(1u, acd->first_ssrc());
1948
1949 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1950 const VideoContentDescription* vcd_copy =
1951 static_cast<const VideoContentDescription*>(vc->description);
1952 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1953 EXPECT_EQ(2u, vcd->first_ssrc());
1954}
1955
1956// The below TestTransportInfoXXX tests create different offers/answers, and
1957// ensure the TransportInfo in the SessionDescription matches what we expect.
1958TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1959 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001960 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001961 TestTransportInfo(true, options, false);
1962}
1963
1964TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1965 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001966 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001967 TestTransportInfo(true, options, true);
1968}
1969
1970TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1971 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001972 options.recv_audio = true;
1973 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001974 options.data_channel_type = cricket::DCT_RTP;
1975 TestTransportInfo(true, options, false);
1976}
1977
1978TEST_F(MediaSessionDescriptionFactoryTest,
1979 TestTransportInfoOfferMultimediaCurrent) {
1980 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001981 options.recv_audio = true;
1982 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001983 options.data_channel_type = cricket::DCT_RTP;
1984 TestTransportInfo(true, options, true);
1985}
1986
1987TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1988 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001989 options.recv_audio = true;
1990 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001991 options.data_channel_type = cricket::DCT_RTP;
1992 options.bundle_enabled = true;
1993 TestTransportInfo(true, options, false);
1994}
1995
1996TEST_F(MediaSessionDescriptionFactoryTest,
1997 TestTransportInfoOfferBundleCurrent) {
1998 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001999 options.recv_audio = true;
2000 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002001 options.data_channel_type = cricket::DCT_RTP;
2002 options.bundle_enabled = true;
2003 TestTransportInfo(true, options, true);
2004}
2005
2006TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2007 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002008 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002009 TestTransportInfo(false, options, false);
2010}
2011
2012TEST_F(MediaSessionDescriptionFactoryTest,
2013 TestTransportInfoAnswerAudioCurrent) {
2014 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002015 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002016 TestTransportInfo(false, options, true);
2017}
2018
2019TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2020 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002021 options.recv_audio = true;
2022 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023 options.data_channel_type = cricket::DCT_RTP;
2024 TestTransportInfo(false, options, false);
2025}
2026
2027TEST_F(MediaSessionDescriptionFactoryTest,
2028 TestTransportInfoAnswerMultimediaCurrent) {
2029 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002030 options.recv_audio = true;
2031 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 options.data_channel_type = cricket::DCT_RTP;
2033 TestTransportInfo(false, options, true);
2034}
2035
2036TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2037 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002038 options.recv_audio = true;
2039 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040 options.data_channel_type = cricket::DCT_RTP;
2041 options.bundle_enabled = true;
2042 TestTransportInfo(false, options, false);
2043}
2044
2045TEST_F(MediaSessionDescriptionFactoryTest,
2046 TestTransportInfoAnswerBundleCurrent) {
2047 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002048 options.recv_audio = true;
2049 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050 options.data_channel_type = cricket::DCT_RTP;
2051 options.bundle_enabled = true;
2052 TestTransportInfo(false, options, true);
2053}
2054
2055// Create an offer with bundle enabled and verify the crypto parameters are
2056// the common set of the available cryptos.
2057TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2058 TestCryptoWithBundle(true);
2059}
2060
2061// Create an answer with bundle enabled and verify the crypto parameters are
2062// the common set of the available cryptos.
2063TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2064 TestCryptoWithBundle(false);
2065}
2066
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002067// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2068// DTLS is not enabled locally.
2069TEST_F(MediaSessionDescriptionFactoryTest,
2070 TestOfferDtlsSavpfWithoutDtlsFailed) {
2071 f1_.set_secure(SEC_ENABLED);
2072 f2_.set_secure(SEC_ENABLED);
2073 tdf1_.set_secure(SEC_DISABLED);
2074 tdf2_.set_secure(SEC_DISABLED);
2075
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002076 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002077 f1_.CreateOffer(MediaSessionOptions(), NULL));
2078 ASSERT_TRUE(offer.get() != NULL);
2079 ContentInfo* offer_content = offer->GetContentByName("audio");
2080 ASSERT_TRUE(offer_content != NULL);
2081 AudioContentDescription* offer_audio_desc =
2082 static_cast<AudioContentDescription*>(offer_content->description);
2083 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2084
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002085 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002086 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2087 ASSERT_TRUE(answer != NULL);
2088 ContentInfo* answer_content = answer->GetContentByName("audio");
2089 ASSERT_TRUE(answer_content != NULL);
2090
2091 ASSERT_TRUE(answer_content->rejected);
2092}
2093
2094// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2095// UDP/TLS/RTP/SAVPF.
2096TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2097 f1_.set_secure(SEC_ENABLED);
2098 f2_.set_secure(SEC_ENABLED);
2099 tdf1_.set_secure(SEC_ENABLED);
2100 tdf2_.set_secure(SEC_ENABLED);
2101
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002102 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002103 f1_.CreateOffer(MediaSessionOptions(), NULL));
2104 ASSERT_TRUE(offer.get() != NULL);
2105 ContentInfo* offer_content = offer->GetContentByName("audio");
2106 ASSERT_TRUE(offer_content != NULL);
2107 AudioContentDescription* offer_audio_desc =
2108 static_cast<AudioContentDescription*>(offer_content->description);
2109 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2110
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002111 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002112 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2113 ASSERT_TRUE(answer != NULL);
2114
2115 const ContentInfo* answer_content = answer->GetContentByName("audio");
2116 ASSERT_TRUE(answer_content != NULL);
2117 ASSERT_FALSE(answer_content->rejected);
2118
2119 const AudioContentDescription* answer_audio_desc =
2120 static_cast<const AudioContentDescription*>(answer_content->description);
2121 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2122 answer_audio_desc->protocol());
2123}
2124
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002125// Test that we include both SDES and DTLS in the offer, but only include SDES
2126// in the answer if DTLS isn't negotiated.
2127TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2128 f1_.set_secure(SEC_ENABLED);
2129 f2_.set_secure(SEC_ENABLED);
2130 tdf1_.set_secure(SEC_ENABLED);
2131 tdf2_.set_secure(SEC_DISABLED);
2132 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002133 options.recv_audio = true;
2134 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002135 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002136 const cricket::MediaContentDescription* audio_media_desc;
2137 const cricket::MediaContentDescription* video_media_desc;
2138 const cricket::TransportDescription* audio_trans_desc;
2139 const cricket::TransportDescription* video_trans_desc;
2140
2141 // Generate an offer with SDES and DTLS support.
2142 offer.reset(f1_.CreateOffer(options, NULL));
2143 ASSERT_TRUE(offer.get() != NULL);
2144
2145 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2146 offer->GetContentDescriptionByName("audio"));
2147 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002148 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002149 offer->GetContentDescriptionByName("video"));
2150 ASSERT_TRUE(video_media_desc != NULL);
2151 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2152 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2153
2154 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2155 ASSERT_TRUE(audio_trans_desc != NULL);
2156 video_trans_desc = offer->GetTransportDescriptionByName("video");
2157 ASSERT_TRUE(video_trans_desc != NULL);
2158 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2159 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2160
2161 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2162 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2163 ASSERT_TRUE(answer.get() != NULL);
2164
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002165 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002166 answer->GetContentDescriptionByName("audio"));
2167 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002168 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002169 answer->GetContentDescriptionByName("video"));
2170 ASSERT_TRUE(video_media_desc != NULL);
2171 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2172 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2173
2174 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2175 ASSERT_TRUE(audio_trans_desc != NULL);
2176 video_trans_desc = answer->GetTransportDescriptionByName("video");
2177 ASSERT_TRUE(video_trans_desc != NULL);
2178 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2179 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2180
2181 // Enable DTLS; the answer should now only have DTLS support.
2182 tdf2_.set_secure(SEC_ENABLED);
2183 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2184 ASSERT_TRUE(answer.get() != NULL);
2185
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002186 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002187 answer->GetContentDescriptionByName("audio"));
2188 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002189 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002190 answer->GetContentDescriptionByName("video"));
2191 ASSERT_TRUE(video_media_desc != NULL);
2192 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2193 EXPECT_TRUE(video_media_desc->cryptos().empty());
2194 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2195 audio_media_desc->protocol());
2196 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2197 video_media_desc->protocol());
2198
2199 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2200 ASSERT_TRUE(audio_trans_desc != NULL);
2201 video_trans_desc = answer->GetTransportDescriptionByName("video");
2202 ASSERT_TRUE(video_trans_desc != NULL);
2203 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2204 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002205
2206 // Try creating offer again. DTLS enabled now, crypto's should be empty
2207 // in new offer.
2208 offer.reset(f1_.CreateOffer(options, offer.get()));
2209 ASSERT_TRUE(offer.get() != NULL);
2210 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2211 offer->GetContentDescriptionByName("audio"));
2212 ASSERT_TRUE(audio_media_desc != NULL);
2213 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2214 offer->GetContentDescriptionByName("video"));
2215 ASSERT_TRUE(video_media_desc != NULL);
2216 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2217 EXPECT_TRUE(video_media_desc->cryptos().empty());
2218
2219 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2220 ASSERT_TRUE(audio_trans_desc != NULL);
2221 video_trans_desc = offer->GetTransportDescriptionByName("video");
2222 ASSERT_TRUE(video_trans_desc != NULL);
2223 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2224 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002225}
2226
2227// Test that an answer can't be created if cryptos are required but the offer is
2228// unsecure.
2229TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2230 MediaSessionOptions options;
2231 f1_.set_secure(SEC_DISABLED);
2232 tdf1_.set_secure(SEC_DISABLED);
2233 f2_.set_secure(SEC_REQUIRED);
2234 tdf1_.set_secure(SEC_ENABLED);
2235
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002236 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002237 NULL));
2238 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002239 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002240 f2_.CreateAnswer(offer.get(), options, NULL));
2241 EXPECT_TRUE(answer.get() == NULL);
2242}
2243
2244// Test that we accept a DTLS offer without SDES and create an appropriate
2245// answer.
2246TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2247 f1_.set_secure(SEC_DISABLED);
2248 f2_.set_secure(SEC_ENABLED);
2249 tdf1_.set_secure(SEC_ENABLED);
2250 tdf2_.set_secure(SEC_ENABLED);
2251 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002252 options.recv_audio = true;
2253 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002254 options.data_channel_type = cricket::DCT_RTP;
2255
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002256 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002257
2258 // Generate an offer with DTLS but without SDES.
2259 offer.reset(f1_.CreateOffer(options, NULL));
2260 ASSERT_TRUE(offer.get() != NULL);
2261
2262 const AudioContentDescription* audio_offer =
2263 GetFirstAudioContentDescription(offer.get());
2264 ASSERT_TRUE(audio_offer->cryptos().empty());
2265 const VideoContentDescription* video_offer =
2266 GetFirstVideoContentDescription(offer.get());
2267 ASSERT_TRUE(video_offer->cryptos().empty());
2268 const DataContentDescription* data_offer =
2269 GetFirstDataContentDescription(offer.get());
2270 ASSERT_TRUE(data_offer->cryptos().empty());
2271
2272 const cricket::TransportDescription* audio_offer_trans_desc =
2273 offer->GetTransportDescriptionByName("audio");
2274 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2275 const cricket::TransportDescription* video_offer_trans_desc =
2276 offer->GetTransportDescriptionByName("video");
2277 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2278 const cricket::TransportDescription* data_offer_trans_desc =
2279 offer->GetTransportDescriptionByName("data");
2280 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2281
2282 // Generate an answer with DTLS.
2283 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2284 ASSERT_TRUE(answer.get() != NULL);
2285
2286 const cricket::TransportDescription* audio_answer_trans_desc =
2287 answer->GetTransportDescriptionByName("audio");
2288 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2289 const cricket::TransportDescription* video_answer_trans_desc =
2290 answer->GetTransportDescriptionByName("video");
2291 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2292 const cricket::TransportDescription* data_answer_trans_desc =
2293 answer->GetTransportDescriptionByName("data");
2294 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2295}
2296
2297// Verifies if vad_enabled option is set to false, CN codecs are not present in
2298// offer or answer.
2299TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2300 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002301 options.recv_audio = true;
2302 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002303 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002304 f1_.CreateOffer(options, NULL));
2305 ASSERT_TRUE(offer.get() != NULL);
2306 const ContentInfo* audio_content = offer->GetContentByName("audio");
2307 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2308
2309 options.vad_enabled = false;
2310 offer.reset(f1_.CreateOffer(options, NULL));
2311 ASSERT_TRUE(offer.get() != NULL);
2312 audio_content = offer->GetContentByName("audio");
2313 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002314 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002315 f1_.CreateAnswer(offer.get(), options, NULL));
2316 ASSERT_TRUE(answer.get() != NULL);
2317 audio_content = answer->GetContentByName("audio");
2318 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2319}
deadbeef44f08192015-12-15 16:20:09 -08002320
2321// Test that the content name ("mid" in SDP) is unchanged when creating a
2322// new offer.
2323TEST_F(MediaSessionDescriptionFactoryTest,
2324 TestContentNameNotChangedInSubsequentOffers) {
2325 MediaSessionOptions opts;
2326 opts.recv_audio = true;
2327 opts.recv_video = true;
2328 opts.data_channel_type = cricket::DCT_SCTP;
2329 // Create offer and modify the default content names.
2330 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2331 for (ContentInfo& content : offer->contents()) {
2332 content.name.append("_modified");
2333 }
2334
2335 rtc::scoped_ptr<SessionDescription> updated_offer(
2336 f1_.CreateOffer(opts, offer.get()));
2337 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2338 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2339 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2340 ASSERT_TRUE(audio_content != nullptr);
2341 ASSERT_TRUE(video_content != nullptr);
2342 ASSERT_TRUE(data_content != nullptr);
2343 EXPECT_EQ("audio_modified", audio_content->name);
2344 EXPECT_EQ("video_modified", video_content->name);
2345 EXPECT_EQ("data_modified", data_content->name);
2346}