blob: 1b2aa4eb3b40d1f9295d07b67e0fa362f43042e2 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg31022942016-03-11 14:18:21 -080011#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012#include <string>
13#include <vector>
14
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000015#include "webrtc/base/fakesslidentity.h"
16#include "webrtc/base/gunit.h"
17#include "webrtc/base/messagedigest.h"
18#include "webrtc/base/ssladapter.h"
kjellandera96e2d72016-02-04 23:52:28 -080019#include "webrtc/media/base/codec.h"
20#include "webrtc/media/base/testutils.h"
kjellanderf4752772016-03-02 05:42:30 -080021#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/p2p/base/transportdescription.h"
23#include "webrtc/p2p/base/transportinfo.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010024#include "webrtc/pc/mediasession.h"
25#include "webrtc/pc/srtpfilter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000026
27#ifdef HAVE_SRTP
28#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000029 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030 ASSERT_EQ(s, cd->cryptos().size()); \
31 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
32#else
33#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000034 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035 ASSERT_EQ(0U, cd->cryptos().size());
36#endif
37
38typedef std::vector<cricket::Candidate> Candidates;
39
40using cricket::MediaContentDescription;
41using cricket::MediaSessionDescriptionFactory;
42using cricket::MediaSessionOptions;
43using cricket::MediaType;
44using cricket::SessionDescription;
45using cricket::SsrcGroup;
46using cricket::StreamParams;
47using cricket::StreamParamsVec;
48using cricket::TransportDescription;
49using cricket::TransportDescriptionFactory;
50using cricket::TransportInfo;
51using cricket::ContentInfo;
52using cricket::CryptoParamsVec;
53using cricket::AudioContentDescription;
54using cricket::VideoContentDescription;
55using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080056using cricket::GetFirstAudioContent;
57using cricket::GetFirstVideoContent;
58using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059using cricket::GetFirstAudioContentDescription;
60using cricket::GetFirstVideoContentDescription;
61using cricket::GetFirstDataContentDescription;
62using cricket::kAutoBandwidth;
63using cricket::AudioCodec;
64using cricket::VideoCodec;
65using cricket::DataCodec;
66using cricket::NS_JINGLE_RTP;
67using cricket::MEDIA_TYPE_AUDIO;
68using cricket::MEDIA_TYPE_VIDEO;
69using cricket::MEDIA_TYPE_DATA;
70using cricket::RtpHeaderExtension;
71using cricket::SEC_DISABLED;
72using cricket::SEC_ENABLED;
73using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070074using rtc::CS_AES_CM_128_HMAC_SHA1_32;
75using rtc::CS_AES_CM_128_HMAC_SHA1_80;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076
77static const AudioCodec kAudioCodecs1[] = {
78 AudioCodec(103, "ISAC", 16000, -1, 1, 6),
79 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
80 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
81 AudioCodec(8, "PCMA", 8000, 64000, 1, 3),
82 AudioCodec(117, "red", 8000, 0, 1, 2),
83 AudioCodec(107, "CN", 48000, 0, 1, 1)
84};
85
86static const AudioCodec kAudioCodecs2[] = {
87 AudioCodec(126, "speex", 16000, 22000, 1, 3),
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +000088 AudioCodec(0, "PCMU", 8000, 64000, 1, 2),
89 AudioCodec(127, "iLBC", 8000, 13300, 1, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090};
91
92static const AudioCodec kAudioCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +000093 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
94 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095};
96
97static const VideoCodec kVideoCodecs1[] = {
98 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
99 VideoCodec(97, "H264", 320, 200, 30, 1)
100};
101
102static const VideoCodec kVideoCodecs2[] = {
103 VideoCodec(126, "H264", 320, 200, 30, 2),
104 VideoCodec(127, "H263", 320, 200, 30, 1)
105};
106
107static const VideoCodec kVideoCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000108 VideoCodec(97, "H264", 320, 200, 30, 1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109};
110
111static const DataCodec kDataCodecs1[] = {
112 DataCodec(98, "binary-data", 2),
113 DataCodec(99, "utf8-text", 1)
114};
115
116static const DataCodec kDataCodecs2[] = {
117 DataCodec(126, "binary-data", 2),
118 DataCodec(127, "utf8-text", 1)
119};
120
121static const DataCodec kDataCodecsAnswer[] = {
122 DataCodec(98, "binary-data", 2),
123 DataCodec(99, "utf8-text", 1)
124};
125
126static const RtpHeaderExtension kAudioRtpExtension1[] = {
127 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
128 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
129};
130
131static const RtpHeaderExtension kAudioRtpExtension2[] = {
132 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
133 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000134 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000135};
136
deadbeefa5b273a2015-08-20 17:30:13 -0700137static const RtpHeaderExtension kAudioRtpExtension3[] = {
138 RtpHeaderExtension("http://google.com/testing/audio_something", 2),
139 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 3),
140};
141
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000142static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
143 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
144};
145
146static const RtpHeaderExtension kVideoRtpExtension1[] = {
147 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000148 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000149};
150
151static const RtpHeaderExtension kVideoRtpExtension2[] = {
152 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
153 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000154 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155};
156
deadbeefa5b273a2015-08-20 17:30:13 -0700157static const RtpHeaderExtension kVideoRtpExtension3[] = {
158 RtpHeaderExtension("http://google.com/testing/video_something", 4),
159 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 5),
160};
161
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000162static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
163 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
164};
165
Peter Boström0c4e06b2015-10-07 12:23:21 +0200166static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
167static const uint32_t kSimSsrc[] = {10, 20, 30};
168static const uint32_t kFec1Ssrc[] = {10, 11};
169static const uint32_t kFec2Ssrc[] = {20, 21};
170static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171
172static const char kMediaStream1[] = "stream_1";
173static const char kMediaStream2[] = "stream_2";
174static const char kVideoTrack1[] = "video_1";
175static const char kVideoTrack2[] = "video_2";
176static const char kAudioTrack1[] = "audio_1";
177static const char kAudioTrack2[] = "audio_2";
178static const char kAudioTrack3[] = "audio_3";
179static const char kDataTrack1[] = "data_1";
180static const char kDataTrack2[] = "data_2";
181static const char kDataTrack3[] = "data_3";
182
zhihuangb7f425a2016-04-12 18:32:30 -0700183static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
184 "RTP/SAVPF"};
185static const char* kMediaProtocolsDtls[] = {
186 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
187 "UDP/TLS/RTP/SAVP"};
188
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000189static bool IsMediaContentOfType(const ContentInfo* content,
190 MediaType media_type) {
191 const MediaContentDescription* mdesc =
192 static_cast<const MediaContentDescription*>(content->description);
193 return mdesc && mdesc->type() == media_type;
194}
195
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000196static cricket::MediaContentDirection
197GetMediaDirection(const ContentInfo* content) {
198 cricket::MediaContentDescription* desc =
199 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
200 return desc->direction();
201}
202
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000203static void AddRtxCodec(const VideoCodec& rtx_codec,
204 std::vector<VideoCodec>* codecs) {
205 VideoCodec rtx;
206 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
207 codecs->push_back(rtx_codec);
208}
209
210template <class T>
211static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
212 std::vector<std::string> codec_names;
213 for (const auto& codec : codecs) {
214 codec_names.push_back(codec.name);
215 }
216 return codec_names;
217}
218
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000219class MediaSessionDescriptionFactoryTest : public testing::Test {
220 public:
221 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200222 : f1_(&tdf1_),
223 f2_(&tdf2_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
225 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
226 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
227 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
228 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
229 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200230 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwiberg0eb15ed2015-12-17 03:04:15 -0800231 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200232 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwiberg0eb15ed2015-12-17 03:04:15 -0800233 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000234 }
235
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000236 // Create a video StreamParamsVec object with:
237 // - one video stream with 3 simulcast streams and FEC,
238 StreamParamsVec CreateComplexVideoStreamParamsVec() {
239 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
240 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
241 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
242 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
243
244 std::vector<SsrcGroup> ssrc_groups;
245 ssrc_groups.push_back(sim_group);
246 ssrc_groups.push_back(fec_group1);
247 ssrc_groups.push_back(fec_group2);
248 ssrc_groups.push_back(fec_group3);
249
250 StreamParams simulcast_params;
251 simulcast_params.id = kVideoTrack1;
252 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
253 simulcast_params.ssrc_groups = ssrc_groups;
254 simulcast_params.cname = "Video_SIM_FEC";
255 simulcast_params.sync_label = kMediaStream1;
256
257 StreamParamsVec video_streams;
258 video_streams.push_back(simulcast_params);
259
260 return video_streams;
261 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262
263 bool CompareCryptoParams(const CryptoParamsVec& c1,
264 const CryptoParamsVec& c2) {
265 if (c1.size() != c2.size())
266 return false;
267 for (size_t i = 0; i < c1.size(); ++i)
268 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
269 c1[i].key_params != c2[i].key_params ||
270 c1[i].session_params != c2[i].session_params)
271 return false;
272 return true;
273 }
274
275 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
276 bool has_current_desc) {
277 const std::string current_audio_ufrag = "current_audio_ufrag";
278 const std::string current_audio_pwd = "current_audio_pwd";
279 const std::string current_video_ufrag = "current_video_ufrag";
280 const std::string current_video_pwd = "current_video_pwd";
281 const std::string current_data_ufrag = "current_data_ufrag";
282 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800283 std::unique_ptr<SessionDescription> current_desc;
284 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 if (has_current_desc) {
286 current_desc.reset(new SessionDescription());
287 EXPECT_TRUE(current_desc->AddTransportInfo(
288 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700289 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000290 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000291 EXPECT_TRUE(current_desc->AddTransportInfo(
292 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700293 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000294 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295 EXPECT_TRUE(current_desc->AddTransportInfo(
296 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700297 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000298 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000299 }
300 if (offer) {
301 desc.reset(f1_.CreateOffer(options, current_desc.get()));
302 } else {
kwiberg31022942016-03-11 14:18:21 -0800303 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 offer.reset(f1_.CreateOffer(options, NULL));
305 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
306 }
307 ASSERT_TRUE(desc.get() != NULL);
308 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000309 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000310 EXPECT_TRUE(ti_audio != NULL);
311 if (has_current_desc) {
312 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
313 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
314 } else {
315 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
316 ti_audio->description.ice_ufrag.size());
317 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
318 ti_audio->description.ice_pwd.size());
319 }
320
321 } else {
322 EXPECT_TRUE(ti_audio == NULL);
323 }
324 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000325 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326 EXPECT_TRUE(ti_video != NULL);
327 if (options.bundle_enabled) {
328 EXPECT_EQ(ti_audio->description.ice_ufrag,
329 ti_video->description.ice_ufrag);
330 EXPECT_EQ(ti_audio->description.ice_pwd,
331 ti_video->description.ice_pwd);
332 } else {
333 if (has_current_desc) {
334 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
335 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
336 } else {
337 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
338 ti_video->description.ice_ufrag.size());
339 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
340 ti_video->description.ice_pwd.size());
341 }
342 }
343 } else {
344 EXPECT_TRUE(ti_video == NULL);
345 }
346 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
347 if (options.has_data()) {
348 EXPECT_TRUE(ti_data != NULL);
349 if (options.bundle_enabled) {
350 EXPECT_EQ(ti_audio->description.ice_ufrag,
351 ti_data->description.ice_ufrag);
352 EXPECT_EQ(ti_audio->description.ice_pwd,
353 ti_data->description.ice_pwd);
354 } else {
355 if (has_current_desc) {
356 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
357 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
358 } else {
359 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
360 ti_data->description.ice_ufrag.size());
361 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
362 ti_data->description.ice_pwd.size());
363 }
364 }
365 } else {
366 EXPECT_TRUE(ti_video == NULL);
367 }
368 }
369
370 void TestCryptoWithBundle(bool offer) {
371 f1_.set_secure(SEC_ENABLED);
372 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000373 options.recv_audio = true;
374 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000375 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800376 std::unique_ptr<SessionDescription> ref_desc;
377 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 if (offer) {
379 options.bundle_enabled = false;
380 ref_desc.reset(f1_.CreateOffer(options, NULL));
381 options.bundle_enabled = true;
382 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
383 } else {
384 options.bundle_enabled = true;
385 ref_desc.reset(f1_.CreateOffer(options, NULL));
386 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
387 }
388 ASSERT_TRUE(desc.get() != NULL);
389 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000390 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000391 desc.get()->GetContentDescriptionByName("audio"));
392 ASSERT_TRUE(audio_media_desc != NULL);
393 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000394 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000395 desc.get()->GetContentDescriptionByName("video"));
396 ASSERT_TRUE(video_media_desc != NULL);
397 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
398 video_media_desc->cryptos()));
399 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
400 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
401 audio_media_desc->cryptos()[0].cipher_suite);
402
403 // Verify the selected crypto is one from the reference audio
404 // media content.
405 const cricket::MediaContentDescription* ref_audio_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 ref_desc.get()->GetContentDescriptionByName("audio"));
408 bool found = false;
409 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
410 if (ref_audio_media_desc->cryptos()[i].Matches(
411 audio_media_desc->cryptos()[0])) {
412 found = true;
413 break;
414 }
415 }
416 EXPECT_TRUE(found);
417 }
418
419 // This test that the audio and video media direction is set to
420 // |expected_direction_in_answer| in an answer if the offer direction is set
421 // to |direction_in_offer|.
422 void TestMediaDirectionInAnswer(
423 cricket::MediaContentDirection direction_in_offer,
424 cricket::MediaContentDirection expected_direction_in_answer) {
425 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000426 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800427 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000428 ASSERT_TRUE(offer.get() != NULL);
429 ContentInfo* ac_offer= offer->GetContentByName("audio");
430 ASSERT_TRUE(ac_offer != NULL);
431 AudioContentDescription* acd_offer =
432 static_cast<AudioContentDescription*>(ac_offer->description);
433 acd_offer->set_direction(direction_in_offer);
434 ContentInfo* vc_offer= offer->GetContentByName("video");
435 ASSERT_TRUE(vc_offer != NULL);
436 VideoContentDescription* vcd_offer =
437 static_cast<VideoContentDescription*>(vc_offer->description);
438 vcd_offer->set_direction(direction_in_offer);
439
kwiberg31022942016-03-11 14:18:21 -0800440 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000441 f2_.CreateAnswer(offer.get(), opts, NULL));
442 const AudioContentDescription* acd_answer =
443 GetFirstAudioContentDescription(answer.get());
444 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
445 const VideoContentDescription* vcd_answer =
446 GetFirstVideoContentDescription(answer.get());
447 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
448 }
449
450 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
451 const cricket::ContentDescription* description = content->description;
452 ASSERT(description != NULL);
453 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000454 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000455 ASSERT(audio_content_desc != NULL);
456 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
457 if (audio_content_desc->codecs()[i].name == "CN")
458 return false;
459 }
460 return true;
461 }
462
463 protected:
464 MediaSessionDescriptionFactory f1_;
465 MediaSessionDescriptionFactory f2_;
466 TransportDescriptionFactory tdf1_;
467 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468};
469
470// Create a typical audio offer, and ensure it matches what we expect.
471TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
472 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800473 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 f1_.CreateOffer(MediaSessionOptions(), NULL));
475 ASSERT_TRUE(offer.get() != NULL);
476 const ContentInfo* ac = offer->GetContentByName("audio");
477 const ContentInfo* vc = offer->GetContentByName("video");
478 ASSERT_TRUE(ac != NULL);
479 ASSERT_TRUE(vc == NULL);
480 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
481 const AudioContentDescription* acd =
482 static_cast<const AudioContentDescription*>(ac->description);
483 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
484 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
485 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
486 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
487 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
488 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
489 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
490}
491
492// Create a typical video offer, and ensure it matches what we expect.
493TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
494 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000495 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000496 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800497 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000498 ASSERT_TRUE(offer.get() != NULL);
499 const ContentInfo* ac = offer->GetContentByName("audio");
500 const ContentInfo* vc = offer->GetContentByName("video");
501 ASSERT_TRUE(ac != NULL);
502 ASSERT_TRUE(vc != NULL);
503 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
504 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
505 const AudioContentDescription* acd =
506 static_cast<const AudioContentDescription*>(ac->description);
507 const VideoContentDescription* vcd =
508 static_cast<const VideoContentDescription*>(vc->description);
509 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
510 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
511 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
512 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
513 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
514 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
515 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
516 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
517 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
518 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
519 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
520 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
521 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
522 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
523}
524
525// Test creating an offer with bundle where the Codecs have the same dynamic
526// RTP playlod type. The test verifies that the offer don't contain the
527// duplicate RTP payload types.
528TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
529 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
530 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
531 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
532 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
533 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
534
535 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000536 opts.recv_audio = true;
537 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000538 opts.data_channel_type = cricket::DCT_RTP;
539 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800540 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000541 const VideoContentDescription* vcd =
542 GetFirstVideoContentDescription(offer.get());
543 const AudioContentDescription* acd =
544 GetFirstAudioContentDescription(offer.get());
545 const DataContentDescription* dcd =
546 GetFirstDataContentDescription(offer.get());
547 ASSERT_TRUE(NULL != vcd);
548 ASSERT_TRUE(NULL != acd);
549 ASSERT_TRUE(NULL != dcd);
550 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
551 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
552 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
553 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
554 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
555 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
556}
557
558// Test creating an updated offer with with bundle, audio, video and data
559// after an audio only session has been negotiated.
560TEST_F(MediaSessionDescriptionFactoryTest,
561 TestCreateUpdatedVideoOfferWithBundle) {
562 f1_.set_secure(SEC_ENABLED);
563 f2_.set_secure(SEC_ENABLED);
564 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000565 opts.recv_audio = true;
566 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000567 opts.data_channel_type = cricket::DCT_NONE;
568 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800569 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
570 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000571 f2_.CreateAnswer(offer.get(), opts, NULL));
572
573 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000574 updated_opts.recv_audio = true;
575 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000576 updated_opts.data_channel_type = cricket::DCT_RTP;
577 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800578 std::unique_ptr<SessionDescription> updated_offer(
579 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580
581 const AudioContentDescription* acd =
582 GetFirstAudioContentDescription(updated_offer.get());
583 const VideoContentDescription* vcd =
584 GetFirstVideoContentDescription(updated_offer.get());
585 const DataContentDescription* dcd =
586 GetFirstDataContentDescription(updated_offer.get());
587 EXPECT_TRUE(NULL != vcd);
588 EXPECT_TRUE(NULL != acd);
589 EXPECT_TRUE(NULL != dcd);
590
591 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
592 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
593 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
594 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
595 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
596 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
597}
deadbeef44f08192015-12-15 16:20:09 -0800598
wu@webrtc.org78187522013-10-07 23:32:02 +0000599// Create a RTP data offer, and ensure it matches what we expect.
600TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000601 MediaSessionOptions opts;
602 opts.data_channel_type = cricket::DCT_RTP;
603 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800604 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000605 ASSERT_TRUE(offer.get() != NULL);
606 const ContentInfo* ac = offer->GetContentByName("audio");
607 const ContentInfo* dc = offer->GetContentByName("data");
608 ASSERT_TRUE(ac != NULL);
609 ASSERT_TRUE(dc != NULL);
610 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
611 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
612 const AudioContentDescription* acd =
613 static_cast<const AudioContentDescription*>(ac->description);
614 const DataContentDescription* dcd =
615 static_cast<const DataContentDescription*>(dc->description);
616 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
617 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
618 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
619 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
620 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
621 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
622 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
623 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
624 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
625 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
626 EXPECT_EQ(cricket::kDataMaxBandwidth,
627 dcd->bandwidth()); // default bandwidth (auto)
628 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
629 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
630 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
631}
632
wu@webrtc.org78187522013-10-07 23:32:02 +0000633// Create an SCTP data offer with bundle without error.
634TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
635 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000636 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000637 opts.bundle_enabled = true;
638 opts.data_channel_type = cricket::DCT_SCTP;
639 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800640 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000641 EXPECT_TRUE(offer.get() != NULL);
642 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
643}
644
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000645// Test creating an sctp data channel from an already generated offer.
646TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
647 MediaSessionOptions opts;
648 opts.recv_audio = false;
649 opts.bundle_enabled = true;
650 opts.data_channel_type = cricket::DCT_SCTP;
651 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800652 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000653 ASSERT_TRUE(offer1.get() != NULL);
654 const ContentInfo* data = offer1->GetContentByName("data");
655 ASSERT_TRUE(data != NULL);
656 const MediaContentDescription* mdesc =
657 static_cast<const MediaContentDescription*>(data->description);
658 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
659
660 // Now set data_channel_type to 'none' (default) and make sure that the
661 // datachannel type that gets generated from the previous offer, is of the
662 // same type.
663 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800664 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000665 f1_.CreateOffer(opts, offer1.get()));
666 data = offer2->GetContentByName("data");
667 ASSERT_TRUE(data != NULL);
668 mdesc = static_cast<const MediaContentDescription*>(data->description);
669 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
670}
671
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672// Create an audio, video offer without legacy StreamParams.
673TEST_F(MediaSessionDescriptionFactoryTest,
674 TestCreateOfferWithoutLegacyStreams) {
675 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000676 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000677 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800678 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 ASSERT_TRUE(offer.get() != NULL);
680 const ContentInfo* ac = offer->GetContentByName("audio");
681 const ContentInfo* vc = offer->GetContentByName("video");
682 ASSERT_TRUE(ac != NULL);
683 ASSERT_TRUE(vc != NULL);
684 const AudioContentDescription* acd =
685 static_cast<const AudioContentDescription*>(ac->description);
686 const VideoContentDescription* vcd =
687 static_cast<const VideoContentDescription*>(vc->description);
688
689 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
690 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
691}
692
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000693// Creates an audio+video sendonly offer.
694TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
695 MediaSessionOptions options;
696 options.recv_audio = false;
697 options.recv_video = false;
698 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
699 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
700
kwiberg31022942016-03-11 14:18:21 -0800701 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000702 ASSERT_TRUE(offer.get() != NULL);
703 EXPECT_EQ(2u, offer->contents().size());
704 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
705 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
706
707 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
708 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
709}
710
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000711// Verifies that the order of the media contents in the current
712// SessionDescription is preserved in the new SessionDescription.
713TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
714 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000715 opts.recv_audio = false;
716 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000717 opts.data_channel_type = cricket::DCT_SCTP;
718
kwiberg31022942016-03-11 14:18:21 -0800719 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000720 ASSERT_TRUE(offer1.get() != NULL);
721 EXPECT_EQ(1u, offer1->contents().size());
722 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
723
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000724 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800725 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000726 f1_.CreateOffer(opts, offer1.get()));
727 ASSERT_TRUE(offer2.get() != NULL);
728 EXPECT_EQ(2u, offer2->contents().size());
729 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
730 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
731
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000732 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800733 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000734 f1_.CreateOffer(opts, offer2.get()));
735 ASSERT_TRUE(offer3.get() != NULL);
736 EXPECT_EQ(3u, offer3->contents().size());
737 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
738 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
739 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
740
741 // Verifies the default order is audio-video-data, so that the previous checks
742 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800743 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000744 ASSERT_TRUE(offer4.get() != NULL);
745 EXPECT_EQ(3u, offer4->contents().size());
746 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
747 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
748 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
749}
750
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000751// Create a typical audio answer, and ensure it matches what we expect.
752TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
753 f1_.set_secure(SEC_ENABLED);
754 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800755 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000756 f1_.CreateOffer(MediaSessionOptions(), NULL));
757 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800758 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
760 const ContentInfo* ac = answer->GetContentByName("audio");
761 const ContentInfo* vc = answer->GetContentByName("video");
762 ASSERT_TRUE(ac != NULL);
763 ASSERT_TRUE(vc == NULL);
764 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
765 const AudioContentDescription* acd =
766 static_cast<const AudioContentDescription*>(ac->description);
767 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
768 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
769 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
770 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
771 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
772 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
773 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
774}
775
776// Create a typical video answer, and ensure it matches what we expect.
777TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
778 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000779 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000780 f1_.set_secure(SEC_ENABLED);
781 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800782 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800784 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000785 f2_.CreateAnswer(offer.get(), opts, NULL));
786 const ContentInfo* ac = answer->GetContentByName("audio");
787 const ContentInfo* vc = answer->GetContentByName("video");
788 ASSERT_TRUE(ac != NULL);
789 ASSERT_TRUE(vc != NULL);
790 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
791 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
792 const AudioContentDescription* acd =
793 static_cast<const AudioContentDescription*>(ac->description);
794 const VideoContentDescription* vcd =
795 static_cast<const VideoContentDescription*>(vc->description);
796 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
797 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
798 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
799 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
800 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
801 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
802 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
803 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
804 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
805 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
806 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
807 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
808}
809
810TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
811 MediaSessionOptions opts;
812 opts.data_channel_type = cricket::DCT_RTP;
813 f1_.set_secure(SEC_ENABLED);
814 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800815 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000816 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800817 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000818 f2_.CreateAnswer(offer.get(), opts, NULL));
819 const ContentInfo* ac = answer->GetContentByName("audio");
820 const ContentInfo* vc = answer->GetContentByName("data");
821 ASSERT_TRUE(ac != NULL);
822 ASSERT_TRUE(vc != NULL);
823 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
824 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
825 const AudioContentDescription* acd =
826 static_cast<const AudioContentDescription*>(ac->description);
827 const DataContentDescription* vcd =
828 static_cast<const DataContentDescription*>(vc->description);
829 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
830 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
831 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
832 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
833 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
834 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
835 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
836 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
837 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
838 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
839 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
840 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
841}
842
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000843// Verifies that the order of the media contents in the offer is preserved in
844// the answer.
845TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
846 MediaSessionOptions opts;
847
848 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000849 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000850 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -0800851 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000852 ASSERT_TRUE(offer1.get() != NULL);
853
854 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000855 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800856 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000857 f1_.CreateOffer(opts, offer1.get()));
858 ASSERT_TRUE(offer2.get() != NULL);
859
860 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000861 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800862 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000863 f1_.CreateOffer(opts, offer2.get()));
864 ASSERT_TRUE(offer3.get() != NULL);
865
kwiberg31022942016-03-11 14:18:21 -0800866 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000867 f2_.CreateAnswer(offer3.get(), opts, NULL));
868 ASSERT_TRUE(answer.get() != NULL);
869 EXPECT_EQ(3u, answer->contents().size());
870 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
871 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
872 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
873}
874
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000875// This test that the media direction is set to send/receive in an answer if
876// the offer is send receive.
877TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
878 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
879}
880
881// This test that the media direction is set to receive only in an answer if
882// the offer is send only.
883TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
884 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
885}
886
887// This test that the media direction is set to send only in an answer if
888// the offer is recv only.
889TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
890 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
891}
892
893// This test that the media direction is set to inactive in an answer if
894// the offer is inactive.
895TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
896 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
897}
898
899// Test that a data content with an unknown protocol is rejected in an answer.
900TEST_F(MediaSessionDescriptionFactoryTest,
901 CreateDataAnswerToOfferWithUnknownProtocol) {
902 MediaSessionOptions opts;
903 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000904 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000905 f1_.set_secure(SEC_ENABLED);
906 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800907 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000908 ContentInfo* dc_offer= offer->GetContentByName("data");
909 ASSERT_TRUE(dc_offer != NULL);
910 DataContentDescription* dcd_offer =
911 static_cast<DataContentDescription*>(dc_offer->description);
912 ASSERT_TRUE(dcd_offer != NULL);
913 std::string protocol = "a weird unknown protocol";
914 dcd_offer->set_protocol(protocol);
915
kwiberg31022942016-03-11 14:18:21 -0800916 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000917 f2_.CreateAnswer(offer.get(), opts, NULL));
918
919 const ContentInfo* dc_answer = answer->GetContentByName("data");
920 ASSERT_TRUE(dc_answer != NULL);
921 EXPECT_TRUE(dc_answer->rejected);
922 const DataContentDescription* dcd_answer =
923 static_cast<const DataContentDescription*>(dc_answer->description);
924 ASSERT_TRUE(dcd_answer != NULL);
925 EXPECT_EQ(protocol, dcd_answer->protocol());
926}
927
928// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
929TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
930 MediaSessionOptions opts;
931 f1_.set_secure(SEC_DISABLED);
932 f2_.set_secure(SEC_DISABLED);
933 tdf1_.set_secure(SEC_DISABLED);
934 tdf2_.set_secure(SEC_DISABLED);
935
kwiberg31022942016-03-11 14:18:21 -0800936 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000937 const AudioContentDescription* offer_acd =
938 GetFirstAudioContentDescription(offer.get());
939 ASSERT_TRUE(offer_acd != NULL);
940 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
941
kwiberg31022942016-03-11 14:18:21 -0800942 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000943 f2_.CreateAnswer(offer.get(), opts, NULL));
944
945 const ContentInfo* ac_answer = answer->GetContentByName("audio");
946 ASSERT_TRUE(ac_answer != NULL);
947 EXPECT_FALSE(ac_answer->rejected);
948
949 const AudioContentDescription* answer_acd =
950 GetFirstAudioContentDescription(answer.get());
951 ASSERT_TRUE(answer_acd != NULL);
952 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
953}
954
955// Create a video offer and answer and ensure the RTP header extensions
956// matches what we expect.
957TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
958 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000959 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000960
961 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
962 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
963 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
964 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
965
kwiberg31022942016-03-11 14:18:21 -0800966 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000967 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800968 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000969 f2_.CreateAnswer(offer.get(), opts, NULL));
970
971 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
972 GetFirstAudioContentDescription(
973 offer.get())->rtp_header_extensions());
974 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
975 GetFirstVideoContentDescription(
976 offer.get())->rtp_header_extensions());
977 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
978 GetFirstAudioContentDescription(
979 answer.get())->rtp_header_extensions());
980 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
981 GetFirstVideoContentDescription(
982 answer.get())->rtp_header_extensions());
983}
984
985// Create an audio, video, data answer without legacy StreamParams.
986TEST_F(MediaSessionDescriptionFactoryTest,
987 TestCreateAnswerWithoutLegacyStreams) {
988 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000989 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000990 opts.data_channel_type = cricket::DCT_RTP;
991 f1_.set_add_legacy_streams(false);
992 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800993 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000994 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800995 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000996 f2_.CreateAnswer(offer.get(), opts, NULL));
997 const ContentInfo* ac = answer->GetContentByName("audio");
998 const ContentInfo* vc = answer->GetContentByName("video");
999 const ContentInfo* dc = answer->GetContentByName("data");
1000 ASSERT_TRUE(ac != NULL);
1001 ASSERT_TRUE(vc != NULL);
1002 const AudioContentDescription* acd =
1003 static_cast<const AudioContentDescription*>(ac->description);
1004 const VideoContentDescription* vcd =
1005 static_cast<const VideoContentDescription*>(vc->description);
1006 const DataContentDescription* dcd =
1007 static_cast<const DataContentDescription*>(dc->description);
1008
1009 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1010 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1011 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1012}
1013
1014TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1015 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001016 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001017 opts.data_channel_type = cricket::DCT_RTP;
1018 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001019 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001020 ASSERT_TRUE(offer.get() != NULL);
1021 const ContentInfo* ac = offer->GetContentByName("audio");
1022 const ContentInfo* vc = offer->GetContentByName("video");
1023 const ContentInfo* dc = offer->GetContentByName("data");
1024 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1025 static_cast<const AudioContentDescription*>(ac->description));
1026 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1027 static_cast<const VideoContentDescription*>(vc->description));
1028 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1029 static_cast<const DataContentDescription*>(dc->description));
1030
1031 EXPECT_FALSE(acd->partial()); // default is false.
1032 acd->set_partial(true);
1033 EXPECT_TRUE(acd->partial());
1034 acd->set_partial(false);
1035 EXPECT_FALSE(acd->partial());
1036
1037 EXPECT_FALSE(vcd->partial()); // default is false.
1038 vcd->set_partial(true);
1039 EXPECT_TRUE(vcd->partial());
1040 vcd->set_partial(false);
1041 EXPECT_FALSE(vcd->partial());
1042
1043 EXPECT_FALSE(dcd->partial()); // default is false.
1044 dcd->set_partial(true);
1045 EXPECT_TRUE(dcd->partial());
1046 dcd->set_partial(false);
1047 EXPECT_FALSE(dcd->partial());
1048}
1049
1050// Create a typical video answer, and ensure it matches what we expect.
1051TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1052 MediaSessionOptions offer_opts;
1053 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001054 answer_opts.recv_video = true;
1055 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001056 answer_opts.data_channel_type = cricket::DCT_RTP;
1057 offer_opts.data_channel_type = cricket::DCT_RTP;
1058
kwiberg31022942016-03-11 14:18:21 -08001059 std::unique_ptr<SessionDescription> offer;
1060 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001061
1062 offer_opts.rtcp_mux_enabled = true;
1063 answer_opts.rtcp_mux_enabled = true;
1064
1065 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1066 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1067 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1068 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1069 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1070 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1071 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1072 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1073 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1074 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1075 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1076 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1077 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1078 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1079
1080 offer_opts.rtcp_mux_enabled = true;
1081 answer_opts.rtcp_mux_enabled = false;
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_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1095 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1096 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1097
1098 offer_opts.rtcp_mux_enabled = false;
1099 answer_opts.rtcp_mux_enabled = true;
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_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1110 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1111 EXPECT_FALSE(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 = false;
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
1135// Create an audio-only answer to a video offer.
1136TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1137 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001138 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001139 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001140 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001141 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001142 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1143 const ContentInfo* ac = answer->GetContentByName("audio");
1144 const ContentInfo* vc = answer->GetContentByName("video");
1145 ASSERT_TRUE(ac != NULL);
1146 ASSERT_TRUE(vc != NULL);
1147 ASSERT_TRUE(vc->description != NULL);
1148 EXPECT_TRUE(vc->rejected);
1149}
1150
1151// Create an audio-only answer to an offer with data.
1152TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1153 MediaSessionOptions opts;
1154 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001155 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001156 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001157 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001158 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1159 const ContentInfo* ac = answer->GetContentByName("audio");
1160 const ContentInfo* dc = answer->GetContentByName("data");
1161 ASSERT_TRUE(ac != NULL);
1162 ASSERT_TRUE(dc != NULL);
1163 ASSERT_TRUE(dc->description != NULL);
1164 EXPECT_TRUE(dc->rejected);
1165}
1166
1167// Create an answer that rejects the contents which are rejected in the offer.
1168TEST_F(MediaSessionDescriptionFactoryTest,
1169 CreateAnswerToOfferWithRejectedMedia) {
1170 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001171 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001172 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001173 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001174 ASSERT_TRUE(offer.get() != NULL);
1175 ContentInfo* ac = offer->GetContentByName("audio");
1176 ContentInfo* vc = offer->GetContentByName("video");
1177 ContentInfo* dc = offer->GetContentByName("data");
1178 ASSERT_TRUE(ac != NULL);
1179 ASSERT_TRUE(vc != NULL);
1180 ASSERT_TRUE(dc != NULL);
1181 ac->rejected = true;
1182 vc->rejected = true;
1183 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001184 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001185 f2_.CreateAnswer(offer.get(), opts, NULL));
1186 ac = answer->GetContentByName("audio");
1187 vc = answer->GetContentByName("video");
1188 dc = answer->GetContentByName("data");
1189 ASSERT_TRUE(ac != NULL);
1190 ASSERT_TRUE(vc != NULL);
1191 ASSERT_TRUE(dc != NULL);
1192 EXPECT_TRUE(ac->rejected);
1193 EXPECT_TRUE(vc->rejected);
1194 EXPECT_TRUE(dc->rejected);
1195}
1196
1197// Create an audio and video offer with:
1198// - one video track
1199// - two audio tracks
1200// - two data tracks
1201// and ensure it matches what we expect. Also updates the initial offer by
1202// adding a new video track and replaces one of the audio tracks.
1203TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1204 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001205 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1206 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1207 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001208 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001209 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1210 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001211
1212 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001213 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001214
1215 ASSERT_TRUE(offer.get() != NULL);
1216 const ContentInfo* ac = offer->GetContentByName("audio");
1217 const ContentInfo* vc = offer->GetContentByName("video");
1218 const ContentInfo* dc = offer->GetContentByName("data");
1219 ASSERT_TRUE(ac != NULL);
1220 ASSERT_TRUE(vc != NULL);
1221 ASSERT_TRUE(dc != NULL);
1222 const AudioContentDescription* acd =
1223 static_cast<const AudioContentDescription*>(ac->description);
1224 const VideoContentDescription* vcd =
1225 static_cast<const VideoContentDescription*>(vc->description);
1226 const DataContentDescription* dcd =
1227 static_cast<const DataContentDescription*>(dc->description);
1228 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1229 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1230
1231 const StreamParamsVec& audio_streams = acd->streams();
1232 ASSERT_EQ(2U, audio_streams.size());
1233 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1234 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1235 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1236 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1237 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1238 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1239 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1240
1241 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1242 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1243 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1244
1245 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1246 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1247 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1248
1249 const StreamParamsVec& video_streams = vcd->streams();
1250 ASSERT_EQ(1U, video_streams.size());
1251 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1252 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1253 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1254 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1255
1256 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1257 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1258 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1259
1260 const StreamParamsVec& data_streams = dcd->streams();
1261 ASSERT_EQ(2U, data_streams.size());
1262 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1263 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1264 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1265 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1266 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1267 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1268 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1269
1270 EXPECT_EQ(cricket::kDataMaxBandwidth,
1271 dcd->bandwidth()); // default bandwidth (auto)
1272 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1273 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1274
1275
1276 // Update the offer. Add a new video track that is not synched to the
1277 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001278 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1279 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1280 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1281 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1282 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001283 std::unique_ptr<SessionDescription> updated_offer(
1284 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001285
1286 ASSERT_TRUE(updated_offer.get() != NULL);
1287 ac = updated_offer->GetContentByName("audio");
1288 vc = updated_offer->GetContentByName("video");
1289 dc = updated_offer->GetContentByName("data");
1290 ASSERT_TRUE(ac != NULL);
1291 ASSERT_TRUE(vc != NULL);
1292 ASSERT_TRUE(dc != NULL);
1293 const AudioContentDescription* updated_acd =
1294 static_cast<const AudioContentDescription*>(ac->description);
1295 const VideoContentDescription* updated_vcd =
1296 static_cast<const VideoContentDescription*>(vc->description);
1297 const DataContentDescription* updated_dcd =
1298 static_cast<const DataContentDescription*>(dc->description);
1299
1300 EXPECT_EQ(acd->type(), updated_acd->type());
1301 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1302 EXPECT_EQ(vcd->type(), updated_vcd->type());
1303 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1304 EXPECT_EQ(dcd->type(), updated_dcd->type());
1305 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1306 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1307 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1308 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1309 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1310 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1311 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1312
1313 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1314 ASSERT_EQ(2U, updated_audio_streams.size());
1315 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1316 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1317 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1318 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1319 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1320
1321 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1322 ASSERT_EQ(2U, updated_video_streams.size());
1323 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1324 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1325 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1326
1327 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1328 ASSERT_EQ(2U, updated_data_streams.size());
1329 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1330 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1331 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1332 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1333 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1334}
1335
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001336// Create an offer with simulcast video stream.
1337TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1338 MediaSessionOptions opts;
1339 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001340 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001341 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001342
1343 ASSERT_TRUE(offer.get() != NULL);
1344 const ContentInfo* vc = offer->GetContentByName("video");
1345 ASSERT_TRUE(vc != NULL);
1346 const VideoContentDescription* vcd =
1347 static_cast<const VideoContentDescription*>(vc->description);
1348
1349 const StreamParamsVec& video_streams = vcd->streams();
1350 ASSERT_EQ(1U, video_streams.size());
1351 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1352 const SsrcGroup* sim_ssrc_group =
1353 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1354 ASSERT_TRUE(sim_ssrc_group != NULL);
1355 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1356}
1357
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001358// Create an audio and video answer to a standard video offer with:
1359// - one video track
1360// - two audio tracks
1361// - two data tracks
1362// and ensure it matches what we expect. Also updates the initial answer by
1363// adding a new video track and removes one of the audio tracks.
1364TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1365 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001366 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001367 offer_opts.data_channel_type = cricket::DCT_RTP;
1368 f1_.set_secure(SEC_ENABLED);
1369 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001370 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001371
1372 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001373 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1374 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1375 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001376 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001377 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1378 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001379
kwiberg31022942016-03-11 14:18:21 -08001380 std::unique_ptr<SessionDescription> answer(
1381 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001382
1383 ASSERT_TRUE(answer.get() != NULL);
1384 const ContentInfo* ac = answer->GetContentByName("audio");
1385 const ContentInfo* vc = answer->GetContentByName("video");
1386 const ContentInfo* dc = answer->GetContentByName("data");
1387 ASSERT_TRUE(ac != NULL);
1388 ASSERT_TRUE(vc != NULL);
1389 ASSERT_TRUE(dc != NULL);
1390 const AudioContentDescription* acd =
1391 static_cast<const AudioContentDescription*>(ac->description);
1392 const VideoContentDescription* vcd =
1393 static_cast<const VideoContentDescription*>(vc->description);
1394 const DataContentDescription* dcd =
1395 static_cast<const DataContentDescription*>(dc->description);
1396 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1397 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1398 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1399
1400 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1401 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1402
1403 const StreamParamsVec& audio_streams = acd->streams();
1404 ASSERT_EQ(2U, audio_streams.size());
1405 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1406 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1407 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1408 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1409 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1410 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1411 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1412
1413 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1414 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1415
1416 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1417 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1418
1419 const StreamParamsVec& video_streams = vcd->streams();
1420 ASSERT_EQ(1U, video_streams.size());
1421 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1422 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1423 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1424 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1425
1426 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1427 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1428
1429 const StreamParamsVec& data_streams = dcd->streams();
1430 ASSERT_EQ(2U, data_streams.size());
1431 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1432 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1433 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1434 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1435 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1436 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1437 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1438
1439 EXPECT_EQ(cricket::kDataMaxBandwidth,
1440 dcd->bandwidth()); // default bandwidth (auto)
1441 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1442
1443 // Update the answer. Add a new video track that is not synched to the
1444 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001445 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1446 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1447 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001448 std::unique_ptr<SessionDescription> updated_answer(
1449 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001450
1451 ASSERT_TRUE(updated_answer.get() != NULL);
1452 ac = updated_answer->GetContentByName("audio");
1453 vc = updated_answer->GetContentByName("video");
1454 dc = updated_answer->GetContentByName("data");
1455 ASSERT_TRUE(ac != NULL);
1456 ASSERT_TRUE(vc != NULL);
1457 ASSERT_TRUE(dc != NULL);
1458 const AudioContentDescription* updated_acd =
1459 static_cast<const AudioContentDescription*>(ac->description);
1460 const VideoContentDescription* updated_vcd =
1461 static_cast<const VideoContentDescription*>(vc->description);
1462 const DataContentDescription* updated_dcd =
1463 static_cast<const DataContentDescription*>(dc->description);
1464
1465 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1466 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1467 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1468 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1469 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1470 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1471
1472 EXPECT_EQ(acd->type(), updated_acd->type());
1473 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1474 EXPECT_EQ(vcd->type(), updated_vcd->type());
1475 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1476 EXPECT_EQ(dcd->type(), updated_dcd->type());
1477 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1478
1479 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1480 ASSERT_EQ(1U, updated_audio_streams.size());
1481 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1482
1483 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1484 ASSERT_EQ(2U, updated_video_streams.size());
1485 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1486 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1487 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1488
1489 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1490 ASSERT_EQ(1U, updated_data_streams.size());
1491 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1492}
1493
1494
1495// Create an updated offer after creating an answer to the original offer and
1496// verify that the codecs that were part of the original answer are not changed
1497// in the updated offer.
1498TEST_F(MediaSessionDescriptionFactoryTest,
1499 RespondentCreatesOfferAfterCreatingAnswer) {
1500 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001501 opts.recv_audio = true;
1502 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001503
kwiberg31022942016-03-11 14:18:21 -08001504 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1505 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 f2_.CreateAnswer(offer.get(), opts, NULL));
1507
1508 const AudioContentDescription* acd =
1509 GetFirstAudioContentDescription(answer.get());
1510 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1511
1512 const VideoContentDescription* vcd =
1513 GetFirstVideoContentDescription(answer.get());
1514 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1515
kwiberg31022942016-03-11 14:18:21 -08001516 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001517 f2_.CreateOffer(opts, answer.get()));
1518
1519 // The expected audio codecs are the common audio codecs from the first
1520 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1521 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001522 // TODO(wu): |updated_offer| should not include the codec
1523 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525 kAudioCodecsAnswer[0],
1526 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001527 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001528 };
1529
1530 // The expected video codecs are the common video codecs from the first
1531 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1532 // preference order.
1533 const VideoCodec kUpdatedVideoCodecOffer[] = {
1534 kVideoCodecsAnswer[0],
1535 kVideoCodecs2[1],
1536 };
1537
1538 const AudioContentDescription* updated_acd =
1539 GetFirstAudioContentDescription(updated_offer.get());
1540 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1541
1542 const VideoContentDescription* updated_vcd =
1543 GetFirstVideoContentDescription(updated_offer.get());
1544 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1545}
1546
1547// Create an updated offer after creating an answer to the original offer and
1548// verify that the codecs that were part of the original answer are not changed
1549// in the updated offer. In this test Rtx is enabled.
1550TEST_F(MediaSessionDescriptionFactoryTest,
1551 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1552 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001553 opts.recv_video = true;
1554 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001555 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001557 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558 f1_.set_video_codecs(f1_codecs);
1559
1560 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001561 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001562 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563 f2_.set_video_codecs(f2_codecs);
1564
kwiberg31022942016-03-11 14:18:21 -08001565 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001567 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001568 f2_.CreateAnswer(offer.get(), opts, NULL));
1569
1570 const VideoContentDescription* vcd =
1571 GetFirstVideoContentDescription(answer.get());
1572
1573 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001574 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1575 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576
1577 EXPECT_EQ(expected_codecs, vcd->codecs());
1578
1579 // Now, make sure we get same result, except for the preference order,
1580 // if |f2_| creates an updated offer even though the default payload types
1581 // are different from |f1_|.
1582 expected_codecs[0].preference = f1_codecs[1].preference;
1583
kwiberg31022942016-03-11 14:18:21 -08001584 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001585 f2_.CreateOffer(opts, answer.get()));
1586 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001587 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001588 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1589
1590 const VideoContentDescription* updated_vcd =
1591 GetFirstVideoContentDescription(updated_answer.get());
1592
1593 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1594}
1595
1596// Create an updated offer that adds video after creating an audio only answer
1597// to the original offer. This test verifies that if a video codec and the RTX
1598// codec have the same default payload type as an audio codec that is already in
1599// use, the added codecs payload types are changed.
1600TEST_F(MediaSessionDescriptionFactoryTest,
1601 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1602 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001603 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001604 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001605 f1_.set_video_codecs(f1_codecs);
1606
1607 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001608 opts.recv_audio = true;
1609 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001610
kwiberg31022942016-03-11 14:18:21 -08001611 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1612 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001613 f2_.CreateAnswer(offer.get(), opts, NULL));
1614
1615 const AudioContentDescription* acd =
1616 GetFirstAudioContentDescription(answer.get());
1617 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1618
1619 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1620 // reference be the same as an audio codec that was negotiated in the
1621 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001622 opts.recv_audio = true;
1623 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001624
1625 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1626 int used_pl_type = acd->codecs()[0].id;
1627 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001628 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001629 f2_.set_video_codecs(f2_codecs);
1630
kwiberg31022942016-03-11 14:18:21 -08001631 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632 f2_.CreateOffer(opts, answer.get()));
1633 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001634 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001635 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1636
1637 const AudioContentDescription* updated_acd =
1638 GetFirstAudioContentDescription(answer.get());
1639 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1640
1641 const VideoContentDescription* updated_vcd =
1642 GetFirstVideoContentDescription(updated_answer.get());
1643
1644 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001645 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001646 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1647 EXPECT_NE(used_pl_type, new_h264_pl_type);
1648 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001649 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001650 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1651 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1652}
1653
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001654// Create an updated offer with RTX after creating an answer to an offer
1655// without RTX, and with different default payload types.
1656// Verify that the added RTX codec references the correct payload type.
1657TEST_F(MediaSessionDescriptionFactoryTest,
1658 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1659 MediaSessionOptions opts;
1660 opts.recv_video = true;
1661 opts.recv_audio = true;
1662
1663 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1664 // This creates rtx for H264 with the payload type |f2_| uses.
1665 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1666 f2_.set_video_codecs(f2_codecs);
1667
kwiberg31022942016-03-11 14:18:21 -08001668 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001669 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001670 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001671 f2_.CreateAnswer(offer.get(), opts, nullptr));
1672
1673 const VideoContentDescription* vcd =
1674 GetFirstVideoContentDescription(answer.get());
1675
1676 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1677 EXPECT_EQ(expected_codecs, vcd->codecs());
1678
1679 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1680 // updated offer, even though the default payload types are different from
1681 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001682 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001683 f2_.CreateOffer(opts, answer.get()));
1684 ASSERT_TRUE(updated_offer);
1685
1686 const VideoContentDescription* updated_vcd =
1687 GetFirstVideoContentDescription(updated_offer.get());
1688
1689 // New offer should attempt to add H263, and RTX for H264.
1690 expected_codecs.push_back(kVideoCodecs2[1]);
1691 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1692 &expected_codecs);
1693 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1694}
1695
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001696// Test that RTX is ignored when there is no associated payload type parameter.
1697TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1698 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001699 opts.recv_video = true;
1700 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001701 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001702 // This creates RTX without associated payload type parameter.
1703 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001704 f1_.set_video_codecs(f1_codecs);
1705
1706 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001707 // This creates RTX for H264 with the payload type |f2_| uses.
1708 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001709 f2_.set_video_codecs(f2_codecs);
1710
kwiberg31022942016-03-11 14:18:21 -08001711 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001712 ASSERT_TRUE(offer.get() != NULL);
1713 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1714 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1715 // is possible to test that that RTX is dropped when
1716 // kCodecParamAssociatedPayloadType is missing in the offer.
1717 VideoContentDescription* desc =
1718 static_cast<cricket::VideoContentDescription*>(
1719 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1720 ASSERT_TRUE(desc != NULL);
1721 std::vector<VideoCodec> codecs = desc->codecs();
1722 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1723 iter != codecs.end(); ++iter) {
1724 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1725 iter->params.clear();
1726 }
1727 }
1728 desc->set_codecs(codecs);
1729
kwiberg31022942016-03-11 14:18:21 -08001730 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001731 f2_.CreateAnswer(offer.get(), opts, NULL));
1732
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001733 std::vector<std::string> codec_names =
1734 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1735 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1736 cricket::kRtxCodecName));
1737}
1738
1739// Test that RTX will be filtered out in the answer if its associated payload
1740// type doesn't match the local value.
1741TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1742 MediaSessionOptions opts;
1743 opts.recv_video = true;
1744 opts.recv_audio = false;
1745 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1746 // This creates RTX for H264 in sender.
1747 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1748 f1_.set_video_codecs(f1_codecs);
1749
1750 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1751 // This creates RTX for H263 in receiver.
1752 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1753 f2_.set_video_codecs(f2_codecs);
1754
kwiberg31022942016-03-11 14:18:21 -08001755 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001756 ASSERT_TRUE(offer.get() != NULL);
1757 // Associated payload type doesn't match, therefore, RTX codec is removed in
1758 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001759 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001760 f2_.CreateAnswer(offer.get(), opts, NULL));
1761
1762 std::vector<std::string> codec_names =
1763 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1764 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1765 cricket::kRtxCodecName));
1766}
1767
1768// Test that when multiple RTX codecs are offered, only the matched RTX codec
1769// is added in the answer, and the unsupported RTX codec is filtered out.
1770TEST_F(MediaSessionDescriptionFactoryTest,
1771 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1772 MediaSessionOptions opts;
1773 opts.recv_video = true;
1774 opts.recv_audio = false;
1775 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1776 // This creates RTX for H264-SVC in sender.
1777 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1778 f1_.set_video_codecs(f1_codecs);
1779
1780 // This creates RTX for H264 in sender.
1781 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1782 f1_.set_video_codecs(f1_codecs);
1783
1784 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1785 // This creates RTX for H264 in receiver.
1786 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1787 f2_.set_video_codecs(f2_codecs);
1788
1789 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1790 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001791 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001792 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001793 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001794 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001795 const VideoContentDescription* vcd =
1796 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001797 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1798 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1799 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001800
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001801 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001802}
1803
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001804// Test that after one RTX codec has been negotiated, a new offer can attempt
1805// to add another.
1806TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1807 MediaSessionOptions opts;
1808 opts.recv_video = true;
1809 opts.recv_audio = false;
1810 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1811 // This creates RTX for H264 for the offerer.
1812 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1813 f1_.set_video_codecs(f1_codecs);
1814
kwiberg31022942016-03-11 14:18:21 -08001815 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001816 ASSERT_TRUE(offer);
1817 const VideoContentDescription* vcd =
1818 GetFirstVideoContentDescription(offer.get());
1819
1820 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1821 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1822 &expected_codecs);
1823 EXPECT_EQ(expected_codecs, vcd->codecs());
1824
1825 // Now, attempt to add RTX for H264-SVC.
1826 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1827 f1_.set_video_codecs(f1_codecs);
1828
kwiberg31022942016-03-11 14:18:21 -08001829 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001830 f1_.CreateOffer(opts, offer.get()));
1831 ASSERT_TRUE(updated_offer);
1832 vcd = GetFirstVideoContentDescription(updated_offer.get());
1833
1834 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1835 &expected_codecs);
1836 EXPECT_EQ(expected_codecs, vcd->codecs());
1837}
1838
Noah Richards2e7a0982015-05-18 14:02:54 -07001839// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1840// generated for each simulcast ssrc and correctly grouped.
1841TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1842 MediaSessionOptions opts;
1843 opts.recv_video = true;
1844 opts.recv_audio = false;
1845
1846 // Add simulcast streams.
1847 opts.AddSendVideoStream("stream1", "stream1label", 3);
1848
1849 // Use a single real codec, and then add RTX for it.
1850 std::vector<VideoCodec> f1_codecs;
1851 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30, 1));
1852 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1853 f1_.set_video_codecs(f1_codecs);
1854
1855 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1856 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001857 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001858 ASSERT_TRUE(offer.get() != NULL);
1859 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1860 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1861 ASSERT_TRUE(desc != NULL);
1862 EXPECT_TRUE(desc->multistream());
1863 const StreamParamsVec& streams = desc->streams();
1864 // Single stream.
1865 ASSERT_EQ(1u, streams.size());
1866 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1867 EXPECT_EQ(6u, streams[0].ssrcs.size());
1868 // And should have a SIM group for the simulcast.
1869 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1870 // And a FID group for RTX.
1871 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02001872 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001873 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1874 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001875 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001876 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1877 EXPECT_EQ(3u, fid_ssrcs.size());
1878}
1879
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001880// Create an updated offer after creating an answer to the original offer and
1881// verify that the RTP header extensions that were part of the original answer
1882// are not changed in the updated offer.
1883TEST_F(MediaSessionDescriptionFactoryTest,
1884 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1885 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001886 opts.recv_audio = true;
1887 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001888
1889 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1890 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1891 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1892 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1893
kwiberg31022942016-03-11 14:18:21 -08001894 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1895 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001896 f2_.CreateAnswer(offer.get(), opts, NULL));
1897
1898 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1899 GetFirstAudioContentDescription(
1900 answer.get())->rtp_header_extensions());
1901 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1902 GetFirstVideoContentDescription(
1903 answer.get())->rtp_header_extensions());
1904
kwiberg31022942016-03-11 14:18:21 -08001905 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001906 f2_.CreateOffer(opts, answer.get()));
1907
1908 // The expected RTP header extensions in the new offer are the resulting
1909 // extensions from the first offer/answer exchange plus the extensions only
1910 // |f2_| offer.
1911 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001912 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001913 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1914 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001915 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1916 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001917 };
1918
1919 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001920 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001921 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1922 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001923 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1924 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001925 };
1926
1927 const AudioContentDescription* updated_acd =
1928 GetFirstAudioContentDescription(updated_offer.get());
1929 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1930 updated_acd->rtp_header_extensions());
1931
1932 const VideoContentDescription* updated_vcd =
1933 GetFirstVideoContentDescription(updated_offer.get());
1934 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1935 updated_vcd->rtp_header_extensions());
1936}
1937
deadbeefa5b273a2015-08-20 17:30:13 -07001938// Verify that if the same RTP extension URI is used for audio and video, the
1939// same ID is used. Also verify that the ID isn't changed when creating an
1940// updated offer (this was previously a bug).
1941TEST_F(MediaSessionDescriptionFactoryTest,
1942 RtpHeaderExtensionIdReused) {
1943 MediaSessionOptions opts;
1944 opts.recv_audio = true;
1945 opts.recv_video = true;
1946
1947 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1948 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1949
kwiberg31022942016-03-11 14:18:21 -08001950 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07001951
1952 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1953 // the video extensions.
1954 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1955 kVideoRtpExtension3[0],
1956 kAudioRtpExtension3[1],
1957 };
1958
1959 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1960 GetFirstAudioContentDescription(
1961 offer.get())->rtp_header_extensions());
1962 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1963 GetFirstVideoContentDescription(
1964 offer.get())->rtp_header_extensions());
1965
1966 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08001967 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07001968 f1_.CreateOffer(opts, offer.get()));
1969
1970 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1971 GetFirstAudioContentDescription(
1972 updated_offer.get())->rtp_header_extensions());
1973 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1974 GetFirstVideoContentDescription(
1975 updated_offer.get())->rtp_header_extensions());
1976}
1977
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001978TEST(MediaSessionDescription, CopySessionDescription) {
1979 SessionDescription source;
1980 cricket::ContentGroup group(cricket::CN_AUDIO);
1981 source.AddGroup(group);
1982 AudioContentDescription* acd(new AudioContentDescription());
1983 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1984 acd->AddLegacyStream(1);
1985 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1986 VideoContentDescription* vcd(new VideoContentDescription());
1987 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1988 vcd->AddLegacyStream(2);
1989 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1990
kwiberg31022942016-03-11 14:18:21 -08001991 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001992 ASSERT_TRUE(copy.get() != NULL);
1993 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1994 const ContentInfo* ac = copy->GetContentByName("audio");
1995 const ContentInfo* vc = copy->GetContentByName("video");
1996 ASSERT_TRUE(ac != NULL);
1997 ASSERT_TRUE(vc != NULL);
1998 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1999 const AudioContentDescription* acd_copy =
2000 static_cast<const AudioContentDescription*>(ac->description);
2001 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2002 EXPECT_EQ(1u, acd->first_ssrc());
2003
2004 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
2005 const VideoContentDescription* vcd_copy =
2006 static_cast<const VideoContentDescription*>(vc->description);
2007 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2008 EXPECT_EQ(2u, vcd->first_ssrc());
2009}
2010
2011// The below TestTransportInfoXXX tests create different offers/answers, and
2012// ensure the TransportInfo in the SessionDescription matches what we expect.
2013TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
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(true, options, false);
2017}
2018
2019TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2020 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002021 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002022 TestTransportInfo(true, options, true);
2023}
2024
2025TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2026 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002027 options.recv_audio = true;
2028 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002029 options.data_channel_type = cricket::DCT_RTP;
2030 TestTransportInfo(true, options, false);
2031}
2032
2033TEST_F(MediaSessionDescriptionFactoryTest,
2034 TestTransportInfoOfferMultimediaCurrent) {
2035 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002036 options.recv_audio = true;
2037 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002038 options.data_channel_type = cricket::DCT_RTP;
2039 TestTransportInfo(true, options, true);
2040}
2041
2042TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2043 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002044 options.recv_audio = true;
2045 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002046 options.data_channel_type = cricket::DCT_RTP;
2047 options.bundle_enabled = true;
2048 TestTransportInfo(true, options, false);
2049}
2050
2051TEST_F(MediaSessionDescriptionFactoryTest,
2052 TestTransportInfoOfferBundleCurrent) {
2053 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002054 options.recv_audio = true;
2055 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002056 options.data_channel_type = cricket::DCT_RTP;
2057 options.bundle_enabled = true;
2058 TestTransportInfo(true, options, true);
2059}
2060
2061TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2062 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002063 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002064 TestTransportInfo(false, options, false);
2065}
2066
2067TEST_F(MediaSessionDescriptionFactoryTest,
2068 TestTransportInfoAnswerAudioCurrent) {
2069 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002070 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002071 TestTransportInfo(false, options, true);
2072}
2073
2074TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2075 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002076 options.recv_audio = true;
2077 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002078 options.data_channel_type = cricket::DCT_RTP;
2079 TestTransportInfo(false, options, false);
2080}
2081
2082TEST_F(MediaSessionDescriptionFactoryTest,
2083 TestTransportInfoAnswerMultimediaCurrent) {
2084 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002085 options.recv_audio = true;
2086 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002087 options.data_channel_type = cricket::DCT_RTP;
2088 TestTransportInfo(false, options, true);
2089}
2090
2091TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2092 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002093 options.recv_audio = true;
2094 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002095 options.data_channel_type = cricket::DCT_RTP;
2096 options.bundle_enabled = true;
2097 TestTransportInfo(false, options, false);
2098}
2099
2100TEST_F(MediaSessionDescriptionFactoryTest,
2101 TestTransportInfoAnswerBundleCurrent) {
2102 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002103 options.recv_audio = true;
2104 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002105 options.data_channel_type = cricket::DCT_RTP;
2106 options.bundle_enabled = true;
2107 TestTransportInfo(false, options, true);
2108}
2109
2110// Create an offer with bundle enabled and verify the crypto parameters are
2111// the common set of the available cryptos.
2112TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2113 TestCryptoWithBundle(true);
2114}
2115
2116// Create an answer with bundle enabled and verify the crypto parameters are
2117// the common set of the available cryptos.
2118TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2119 TestCryptoWithBundle(false);
2120}
2121
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002122// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2123// DTLS is not enabled locally.
2124TEST_F(MediaSessionDescriptionFactoryTest,
2125 TestOfferDtlsSavpfWithoutDtlsFailed) {
2126 f1_.set_secure(SEC_ENABLED);
2127 f2_.set_secure(SEC_ENABLED);
2128 tdf1_.set_secure(SEC_DISABLED);
2129 tdf2_.set_secure(SEC_DISABLED);
2130
kwiberg31022942016-03-11 14:18:21 -08002131 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002132 f1_.CreateOffer(MediaSessionOptions(), NULL));
2133 ASSERT_TRUE(offer.get() != NULL);
2134 ContentInfo* offer_content = offer->GetContentByName("audio");
2135 ASSERT_TRUE(offer_content != NULL);
2136 AudioContentDescription* offer_audio_desc =
2137 static_cast<AudioContentDescription*>(offer_content->description);
2138 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2139
kwiberg31022942016-03-11 14:18:21 -08002140 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002141 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2142 ASSERT_TRUE(answer != NULL);
2143 ContentInfo* answer_content = answer->GetContentByName("audio");
2144 ASSERT_TRUE(answer_content != NULL);
2145
2146 ASSERT_TRUE(answer_content->rejected);
2147}
2148
2149// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2150// UDP/TLS/RTP/SAVPF.
2151TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2152 f1_.set_secure(SEC_ENABLED);
2153 f2_.set_secure(SEC_ENABLED);
2154 tdf1_.set_secure(SEC_ENABLED);
2155 tdf2_.set_secure(SEC_ENABLED);
2156
kwiberg31022942016-03-11 14:18:21 -08002157 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002158 f1_.CreateOffer(MediaSessionOptions(), NULL));
2159 ASSERT_TRUE(offer.get() != NULL);
2160 ContentInfo* offer_content = offer->GetContentByName("audio");
2161 ASSERT_TRUE(offer_content != NULL);
2162 AudioContentDescription* offer_audio_desc =
2163 static_cast<AudioContentDescription*>(offer_content->description);
2164 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2165
kwiberg31022942016-03-11 14:18:21 -08002166 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002167 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2168 ASSERT_TRUE(answer != NULL);
2169
2170 const ContentInfo* answer_content = answer->GetContentByName("audio");
2171 ASSERT_TRUE(answer_content != NULL);
2172 ASSERT_FALSE(answer_content->rejected);
2173
2174 const AudioContentDescription* answer_audio_desc =
2175 static_cast<const AudioContentDescription*>(answer_content->description);
2176 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2177 answer_audio_desc->protocol());
2178}
2179
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002180// Test that we include both SDES and DTLS in the offer, but only include SDES
2181// in the answer if DTLS isn't negotiated.
2182TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2183 f1_.set_secure(SEC_ENABLED);
2184 f2_.set_secure(SEC_ENABLED);
2185 tdf1_.set_secure(SEC_ENABLED);
2186 tdf2_.set_secure(SEC_DISABLED);
2187 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002188 options.recv_audio = true;
2189 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002190 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002191 const cricket::MediaContentDescription* audio_media_desc;
2192 const cricket::MediaContentDescription* video_media_desc;
2193 const cricket::TransportDescription* audio_trans_desc;
2194 const cricket::TransportDescription* video_trans_desc;
2195
2196 // Generate an offer with SDES and DTLS support.
2197 offer.reset(f1_.CreateOffer(options, NULL));
2198 ASSERT_TRUE(offer.get() != NULL);
2199
2200 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2201 offer->GetContentDescriptionByName("audio"));
2202 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002203 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002204 offer->GetContentDescriptionByName("video"));
2205 ASSERT_TRUE(video_media_desc != NULL);
2206 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2207 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2208
2209 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2210 ASSERT_TRUE(audio_trans_desc != NULL);
2211 video_trans_desc = offer->GetTransportDescriptionByName("video");
2212 ASSERT_TRUE(video_trans_desc != NULL);
2213 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2214 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2215
2216 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2217 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2218 ASSERT_TRUE(answer.get() != NULL);
2219
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002220 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002221 answer->GetContentDescriptionByName("audio"));
2222 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002223 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002224 answer->GetContentDescriptionByName("video"));
2225 ASSERT_TRUE(video_media_desc != NULL);
2226 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2227 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2228
2229 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2230 ASSERT_TRUE(audio_trans_desc != NULL);
2231 video_trans_desc = answer->GetTransportDescriptionByName("video");
2232 ASSERT_TRUE(video_trans_desc != NULL);
2233 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2234 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2235
2236 // Enable DTLS; the answer should now only have DTLS support.
2237 tdf2_.set_secure(SEC_ENABLED);
2238 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2239 ASSERT_TRUE(answer.get() != NULL);
2240
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002241 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002242 answer->GetContentDescriptionByName("audio"));
2243 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002244 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002245 answer->GetContentDescriptionByName("video"));
2246 ASSERT_TRUE(video_media_desc != NULL);
2247 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2248 EXPECT_TRUE(video_media_desc->cryptos().empty());
2249 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2250 audio_media_desc->protocol());
2251 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2252 video_media_desc->protocol());
2253
2254 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2255 ASSERT_TRUE(audio_trans_desc != NULL);
2256 video_trans_desc = answer->GetTransportDescriptionByName("video");
2257 ASSERT_TRUE(video_trans_desc != NULL);
2258 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2259 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002260
2261 // Try creating offer again. DTLS enabled now, crypto's should be empty
2262 // in new offer.
2263 offer.reset(f1_.CreateOffer(options, offer.get()));
2264 ASSERT_TRUE(offer.get() != NULL);
2265 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2266 offer->GetContentDescriptionByName("audio"));
2267 ASSERT_TRUE(audio_media_desc != NULL);
2268 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2269 offer->GetContentDescriptionByName("video"));
2270 ASSERT_TRUE(video_media_desc != NULL);
2271 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2272 EXPECT_TRUE(video_media_desc->cryptos().empty());
2273
2274 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2275 ASSERT_TRUE(audio_trans_desc != NULL);
2276 video_trans_desc = offer->GetTransportDescriptionByName("video");
2277 ASSERT_TRUE(video_trans_desc != NULL);
2278 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2279 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002280}
2281
2282// Test that an answer can't be created if cryptos are required but the offer is
2283// unsecure.
2284TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2285 MediaSessionOptions options;
2286 f1_.set_secure(SEC_DISABLED);
2287 tdf1_.set_secure(SEC_DISABLED);
2288 f2_.set_secure(SEC_REQUIRED);
2289 tdf1_.set_secure(SEC_ENABLED);
2290
kwiberg31022942016-03-11 14:18:21 -08002291 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002292 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002293 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002294 f2_.CreateAnswer(offer.get(), options, NULL));
2295 EXPECT_TRUE(answer.get() == NULL);
2296}
2297
2298// Test that we accept a DTLS offer without SDES and create an appropriate
2299// answer.
2300TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2301 f1_.set_secure(SEC_DISABLED);
2302 f2_.set_secure(SEC_ENABLED);
2303 tdf1_.set_secure(SEC_ENABLED);
2304 tdf2_.set_secure(SEC_ENABLED);
2305 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002306 options.recv_audio = true;
2307 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002308 options.data_channel_type = cricket::DCT_RTP;
2309
kwiberg31022942016-03-11 14:18:21 -08002310 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002311
2312 // Generate an offer with DTLS but without SDES.
2313 offer.reset(f1_.CreateOffer(options, NULL));
2314 ASSERT_TRUE(offer.get() != NULL);
2315
2316 const AudioContentDescription* audio_offer =
2317 GetFirstAudioContentDescription(offer.get());
2318 ASSERT_TRUE(audio_offer->cryptos().empty());
2319 const VideoContentDescription* video_offer =
2320 GetFirstVideoContentDescription(offer.get());
2321 ASSERT_TRUE(video_offer->cryptos().empty());
2322 const DataContentDescription* data_offer =
2323 GetFirstDataContentDescription(offer.get());
2324 ASSERT_TRUE(data_offer->cryptos().empty());
2325
2326 const cricket::TransportDescription* audio_offer_trans_desc =
2327 offer->GetTransportDescriptionByName("audio");
2328 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2329 const cricket::TransportDescription* video_offer_trans_desc =
2330 offer->GetTransportDescriptionByName("video");
2331 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2332 const cricket::TransportDescription* data_offer_trans_desc =
2333 offer->GetTransportDescriptionByName("data");
2334 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2335
2336 // Generate an answer with DTLS.
2337 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2338 ASSERT_TRUE(answer.get() != NULL);
2339
2340 const cricket::TransportDescription* audio_answer_trans_desc =
2341 answer->GetTransportDescriptionByName("audio");
2342 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2343 const cricket::TransportDescription* video_answer_trans_desc =
2344 answer->GetTransportDescriptionByName("video");
2345 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2346 const cricket::TransportDescription* data_answer_trans_desc =
2347 answer->GetTransportDescriptionByName("data");
2348 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2349}
2350
2351// Verifies if vad_enabled option is set to false, CN codecs are not present in
2352// offer or answer.
2353TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2354 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002355 options.recv_audio = true;
2356 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002357 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002358 ASSERT_TRUE(offer.get() != NULL);
2359 const ContentInfo* audio_content = offer->GetContentByName("audio");
2360 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2361
2362 options.vad_enabled = false;
2363 offer.reset(f1_.CreateOffer(options, NULL));
2364 ASSERT_TRUE(offer.get() != NULL);
2365 audio_content = offer->GetContentByName("audio");
2366 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002367 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002368 f1_.CreateAnswer(offer.get(), options, NULL));
2369 ASSERT_TRUE(answer.get() != NULL);
2370 audio_content = answer->GetContentByName("audio");
2371 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2372}
deadbeef44f08192015-12-15 16:20:09 -08002373
2374// Test that the content name ("mid" in SDP) is unchanged when creating a
2375// new offer.
2376TEST_F(MediaSessionDescriptionFactoryTest,
2377 TestContentNameNotChangedInSubsequentOffers) {
2378 MediaSessionOptions opts;
2379 opts.recv_audio = true;
2380 opts.recv_video = true;
2381 opts.data_channel_type = cricket::DCT_SCTP;
2382 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002383 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002384 for (ContentInfo& content : offer->contents()) {
2385 content.name.append("_modified");
2386 }
2387
kwiberg31022942016-03-11 14:18:21 -08002388 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002389 f1_.CreateOffer(opts, offer.get()));
2390 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2391 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2392 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2393 ASSERT_TRUE(audio_content != nullptr);
2394 ASSERT_TRUE(video_content != nullptr);
2395 ASSERT_TRUE(data_content != nullptr);
2396 EXPECT_EQ("audio_modified", audio_content->name);
2397 EXPECT_EQ("video_modified", video_content->name);
2398 EXPECT_EQ("data_modified", data_content->name);
2399}
zhihuangb7f425a2016-04-12 18:32:30 -07002400
2401class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2402 public:
2403 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
2404 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
2405 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2406 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
2407 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
2408 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2409 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2410 f1_.set_secure(SEC_ENABLED);
2411 f2_.set_secure(SEC_ENABLED);
2412 tdf1_.set_certificate(rtc::RTCCertificate::Create(
2413 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
2414 tdf2_.set_certificate(rtc::RTCCertificate::Create(
2415 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
2416 tdf1_.set_secure(SEC_ENABLED);
2417 tdf2_.set_secure(SEC_ENABLED);
2418 }
2419
2420 protected:
2421 MediaSessionDescriptionFactory f1_;
2422 MediaSessionDescriptionFactory f2_;
2423 TransportDescriptionFactory tdf1_;
2424 TransportDescriptionFactory tdf2_;
2425};
2426
2427TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2428 MediaSessionOptions opts;
2429 opts.recv_video = true;
2430 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2431 ASSERT_TRUE(offer.get() != nullptr);
2432 // Set the protocol for all the contents.
2433 for (auto content : offer.get()->contents()) {
2434 static_cast<MediaContentDescription*>(content.description)
2435 ->set_protocol(GetParam());
2436 }
2437 std::unique_ptr<SessionDescription> answer(
2438 f2_.CreateAnswer(offer.get(), opts, nullptr));
2439 const ContentInfo* ac = answer->GetContentByName("audio");
2440 const ContentInfo* vc = answer->GetContentByName("video");
2441 ASSERT_TRUE(ac != nullptr);
2442 ASSERT_TRUE(vc != nullptr);
2443 EXPECT_FALSE(ac->rejected); // the offer is accepted
2444 EXPECT_FALSE(vc->rejected);
2445 const AudioContentDescription* acd =
2446 static_cast<const AudioContentDescription*>(ac->description);
2447 const VideoContentDescription* vcd =
2448 static_cast<const VideoContentDescription*>(vc->description);
2449 EXPECT_EQ(GetParam(), acd->protocol());
2450 EXPECT_EQ(GetParam(), vcd->protocol());
2451}
2452
2453INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2454 MediaProtocolTest,
2455 ::testing::ValuesIn(kMediaProtocols));
2456INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2457 MediaProtocolTest,
2458 ::testing::ValuesIn(kMediaProtocolsDtls));