blob: b14bd801cbe0dca29fc071100f6ef405ccf29a2c [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[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070078 AudioCodec(103, "ISAC", 16000, -1, 1),
79 AudioCodec(102, "iLBC", 8000, 13300, 1),
80 AudioCodec(0, "PCMU", 8000, 64000, 1),
81 AudioCodec(8, "PCMA", 8000, 64000, 1),
82 AudioCodec(117, "red", 8000, 0, 1),
83 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
85static const AudioCodec kAudioCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070086 AudioCodec(126, "speex", 16000, 22000, 1),
87 AudioCodec(0, "PCMU", 8000, 64000, 1),
88 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089};
90
91static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070092 AudioCodec(102, "iLBC", 8000, 13300, 1),
93 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000094};
95
96static const VideoCodec kVideoCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070097 VideoCodec(96, "H264-SVC", 320, 200, 30),
98 VideoCodec(97, "H264", 320, 200, 30)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099
100static const VideoCodec kVideoCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -0700101 VideoCodec(126, "H264", 320, 200, 30),
102 VideoCodec(127, "H263", 320, 200, 30)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103
104static const VideoCodec kVideoCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -0700105 VideoCodec(97, "H264", 320, 200, 30)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106
deadbeef67cf2c12016-04-13 10:07:16 -0700107static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
108 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109
deadbeef67cf2c12016-04-13 10:07:16 -0700110static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
111 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112
deadbeef67cf2c12016-04-13 10:07:16 -0700113static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
114 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115
116static const RtpHeaderExtension kAudioRtpExtension1[] = {
117 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
118 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
119};
120
121static const RtpHeaderExtension kAudioRtpExtension2[] = {
122 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
123 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000124 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125};
126
deadbeefa5b273a2015-08-20 17:30:13 -0700127static const RtpHeaderExtension kAudioRtpExtension3[] = {
128 RtpHeaderExtension("http://google.com/testing/audio_something", 2),
129 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 3),
130};
131
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000132static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
133 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
134};
135
136static const RtpHeaderExtension kVideoRtpExtension1[] = {
137 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000138 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000139};
140
141static const RtpHeaderExtension kVideoRtpExtension2[] = {
142 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
143 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000144 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145};
146
deadbeefa5b273a2015-08-20 17:30:13 -0700147static const RtpHeaderExtension kVideoRtpExtension3[] = {
148 RtpHeaderExtension("http://google.com/testing/video_something", 4),
149 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 5),
150};
151
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
153 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
154};
155
Peter Boström0c4e06b2015-10-07 12:23:21 +0200156static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
157static const uint32_t kSimSsrc[] = {10, 20, 30};
158static const uint32_t kFec1Ssrc[] = {10, 11};
159static const uint32_t kFec2Ssrc[] = {20, 21};
160static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161
162static const char kMediaStream1[] = "stream_1";
163static const char kMediaStream2[] = "stream_2";
164static const char kVideoTrack1[] = "video_1";
165static const char kVideoTrack2[] = "video_2";
166static const char kAudioTrack1[] = "audio_1";
167static const char kAudioTrack2[] = "audio_2";
168static const char kAudioTrack3[] = "audio_3";
169static const char kDataTrack1[] = "data_1";
170static const char kDataTrack2[] = "data_2";
171static const char kDataTrack3[] = "data_3";
172
zhihuangcf5b37c2016-05-05 11:44:35 -0700173static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
174 "RTP/SAVPF"};
175static const char* kMediaProtocolsDtls[] = {
176 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
177 "UDP/TLS/RTP/SAVP"};
178
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000179static bool IsMediaContentOfType(const ContentInfo* content,
180 MediaType media_type) {
181 const MediaContentDescription* mdesc =
182 static_cast<const MediaContentDescription*>(content->description);
183 return mdesc && mdesc->type() == media_type;
184}
185
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000186static cricket::MediaContentDirection
187GetMediaDirection(const ContentInfo* content) {
188 cricket::MediaContentDescription* desc =
189 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
190 return desc->direction();
191}
192
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000193static void AddRtxCodec(const VideoCodec& rtx_codec,
194 std::vector<VideoCodec>* codecs) {
195 VideoCodec rtx;
196 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
197 codecs->push_back(rtx_codec);
198}
199
200template <class T>
201static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
202 std::vector<std::string> codec_names;
203 for (const auto& codec : codecs) {
204 codec_names.push_back(codec.name);
205 }
206 return codec_names;
207}
208
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000209class MediaSessionDescriptionFactoryTest : public testing::Test {
210 public:
211 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200212 : f1_(&tdf1_),
213 f2_(&tdf2_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000214 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
215 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
216 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
217 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
218 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
219 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200220 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700221 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200222 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700223 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000224 }
225
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000226 // Create a video StreamParamsVec object with:
227 // - one video stream with 3 simulcast streams and FEC,
228 StreamParamsVec CreateComplexVideoStreamParamsVec() {
229 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
230 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
231 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
232 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
233
234 std::vector<SsrcGroup> ssrc_groups;
235 ssrc_groups.push_back(sim_group);
236 ssrc_groups.push_back(fec_group1);
237 ssrc_groups.push_back(fec_group2);
238 ssrc_groups.push_back(fec_group3);
239
240 StreamParams simulcast_params;
241 simulcast_params.id = kVideoTrack1;
242 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
243 simulcast_params.ssrc_groups = ssrc_groups;
244 simulcast_params.cname = "Video_SIM_FEC";
245 simulcast_params.sync_label = kMediaStream1;
246
247 StreamParamsVec video_streams;
248 video_streams.push_back(simulcast_params);
249
250 return video_streams;
251 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000252
253 bool CompareCryptoParams(const CryptoParamsVec& c1,
254 const CryptoParamsVec& c2) {
255 if (c1.size() != c2.size())
256 return false;
257 for (size_t i = 0; i < c1.size(); ++i)
258 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
259 c1[i].key_params != c2[i].key_params ||
260 c1[i].session_params != c2[i].session_params)
261 return false;
262 return true;
263 }
264
265 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
266 bool has_current_desc) {
267 const std::string current_audio_ufrag = "current_audio_ufrag";
268 const std::string current_audio_pwd = "current_audio_pwd";
269 const std::string current_video_ufrag = "current_video_ufrag";
270 const std::string current_video_pwd = "current_video_pwd";
271 const std::string current_data_ufrag = "current_data_ufrag";
272 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800273 std::unique_ptr<SessionDescription> current_desc;
274 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000275 if (has_current_desc) {
276 current_desc.reset(new SessionDescription());
277 EXPECT_TRUE(current_desc->AddTransportInfo(
278 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700279 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000280 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 EXPECT_TRUE(current_desc->AddTransportInfo(
282 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700283 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000284 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 EXPECT_TRUE(current_desc->AddTransportInfo(
286 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700287 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000288 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 }
290 if (offer) {
291 desc.reset(f1_.CreateOffer(options, current_desc.get()));
292 } else {
kwiberg31022942016-03-11 14:18:21 -0800293 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 offer.reset(f1_.CreateOffer(options, NULL));
295 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
296 }
297 ASSERT_TRUE(desc.get() != NULL);
298 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000299 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000300 EXPECT_TRUE(ti_audio != NULL);
301 if (has_current_desc) {
302 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
303 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
304 } else {
305 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
306 ti_audio->description.ice_ufrag.size());
307 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
308 ti_audio->description.ice_pwd.size());
309 }
310
311 } else {
312 EXPECT_TRUE(ti_audio == NULL);
313 }
314 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000315 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316 EXPECT_TRUE(ti_video != NULL);
317 if (options.bundle_enabled) {
318 EXPECT_EQ(ti_audio->description.ice_ufrag,
319 ti_video->description.ice_ufrag);
320 EXPECT_EQ(ti_audio->description.ice_pwd,
321 ti_video->description.ice_pwd);
322 } else {
323 if (has_current_desc) {
324 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
325 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
326 } else {
327 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
328 ti_video->description.ice_ufrag.size());
329 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
330 ti_video->description.ice_pwd.size());
331 }
332 }
333 } else {
334 EXPECT_TRUE(ti_video == NULL);
335 }
336 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
337 if (options.has_data()) {
338 EXPECT_TRUE(ti_data != NULL);
339 if (options.bundle_enabled) {
340 EXPECT_EQ(ti_audio->description.ice_ufrag,
341 ti_data->description.ice_ufrag);
342 EXPECT_EQ(ti_audio->description.ice_pwd,
343 ti_data->description.ice_pwd);
344 } else {
345 if (has_current_desc) {
346 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
347 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
348 } else {
349 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
350 ti_data->description.ice_ufrag.size());
351 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
352 ti_data->description.ice_pwd.size());
353 }
354 }
355 } else {
356 EXPECT_TRUE(ti_video == NULL);
357 }
358 }
359
360 void TestCryptoWithBundle(bool offer) {
361 f1_.set_secure(SEC_ENABLED);
362 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000363 options.recv_audio = true;
364 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800366 std::unique_ptr<SessionDescription> ref_desc;
367 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 if (offer) {
369 options.bundle_enabled = false;
370 ref_desc.reset(f1_.CreateOffer(options, NULL));
371 options.bundle_enabled = true;
372 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
373 } else {
374 options.bundle_enabled = true;
375 ref_desc.reset(f1_.CreateOffer(options, NULL));
376 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
377 }
378 ASSERT_TRUE(desc.get() != NULL);
379 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000380 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000381 desc.get()->GetContentDescriptionByName("audio"));
382 ASSERT_TRUE(audio_media_desc != NULL);
383 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000384 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000385 desc.get()->GetContentDescriptionByName("video"));
386 ASSERT_TRUE(video_media_desc != NULL);
387 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
388 video_media_desc->cryptos()));
389 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
390 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
391 audio_media_desc->cryptos()[0].cipher_suite);
392
393 // Verify the selected crypto is one from the reference audio
394 // media content.
395 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000396 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000397 ref_desc.get()->GetContentDescriptionByName("audio"));
398 bool found = false;
399 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
400 if (ref_audio_media_desc->cryptos()[i].Matches(
401 audio_media_desc->cryptos()[0])) {
402 found = true;
403 break;
404 }
405 }
406 EXPECT_TRUE(found);
407 }
408
409 // This test that the audio and video media direction is set to
410 // |expected_direction_in_answer| in an answer if the offer direction is set
411 // to |direction_in_offer|.
412 void TestMediaDirectionInAnswer(
413 cricket::MediaContentDirection direction_in_offer,
414 cricket::MediaContentDirection expected_direction_in_answer) {
415 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000416 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800417 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700419 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000420 ASSERT_TRUE(ac_offer != NULL);
421 AudioContentDescription* acd_offer =
422 static_cast<AudioContentDescription*>(ac_offer->description);
423 acd_offer->set_direction(direction_in_offer);
terelius8c011e52016-04-26 05:28:11 -0700424 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 ASSERT_TRUE(vc_offer != NULL);
426 VideoContentDescription* vcd_offer =
427 static_cast<VideoContentDescription*>(vc_offer->description);
428 vcd_offer->set_direction(direction_in_offer);
429
kwiberg31022942016-03-11 14:18:21 -0800430 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431 f2_.CreateAnswer(offer.get(), opts, NULL));
432 const AudioContentDescription* acd_answer =
433 GetFirstAudioContentDescription(answer.get());
434 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
435 const VideoContentDescription* vcd_answer =
436 GetFirstVideoContentDescription(answer.get());
437 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
438 }
439
440 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
441 const cricket::ContentDescription* description = content->description;
442 ASSERT(description != NULL);
443 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000444 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000445 ASSERT(audio_content_desc != NULL);
446 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
447 if (audio_content_desc->codecs()[i].name == "CN")
448 return false;
449 }
450 return true;
451 }
452
453 protected:
454 MediaSessionDescriptionFactory f1_;
455 MediaSessionDescriptionFactory f2_;
456 TransportDescriptionFactory tdf1_;
457 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000458};
459
460// Create a typical audio offer, and ensure it matches what we expect.
461TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
462 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800463 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000464 f1_.CreateOffer(MediaSessionOptions(), NULL));
465 ASSERT_TRUE(offer.get() != NULL);
466 const ContentInfo* ac = offer->GetContentByName("audio");
467 const ContentInfo* vc = offer->GetContentByName("video");
468 ASSERT_TRUE(ac != NULL);
469 ASSERT_TRUE(vc == NULL);
470 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
471 const AudioContentDescription* acd =
472 static_cast<const AudioContentDescription*>(ac->description);
473 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
474 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
475 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
476 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
477 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
478 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
479 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
480}
481
482// Create a typical video offer, and ensure it matches what we expect.
483TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
484 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000485 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000486 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800487 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488 ASSERT_TRUE(offer.get() != NULL);
489 const ContentInfo* ac = offer->GetContentByName("audio");
490 const ContentInfo* vc = offer->GetContentByName("video");
491 ASSERT_TRUE(ac != NULL);
492 ASSERT_TRUE(vc != NULL);
493 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
494 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
495 const AudioContentDescription* acd =
496 static_cast<const AudioContentDescription*>(ac->description);
497 const VideoContentDescription* vcd =
498 static_cast<const VideoContentDescription*>(vc->description);
499 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
500 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
501 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
502 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
503 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
504 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
505 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
506 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
507 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
508 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
509 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
510 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
511 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
512 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
513}
514
515// Test creating an offer with bundle where the Codecs have the same dynamic
516// RTP playlod type. The test verifies that the offer don't contain the
517// duplicate RTP payload types.
518TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
519 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
520 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
521 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
522 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
523 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
524
525 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000526 opts.recv_audio = true;
527 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528 opts.data_channel_type = cricket::DCT_RTP;
529 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800530 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000531 const VideoContentDescription* vcd =
532 GetFirstVideoContentDescription(offer.get());
533 const AudioContentDescription* acd =
534 GetFirstAudioContentDescription(offer.get());
535 const DataContentDescription* dcd =
536 GetFirstDataContentDescription(offer.get());
537 ASSERT_TRUE(NULL != vcd);
538 ASSERT_TRUE(NULL != acd);
539 ASSERT_TRUE(NULL != dcd);
540 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
541 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
542 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
543 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
544 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
545 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
546}
547
548// Test creating an updated offer with with bundle, audio, video and data
549// after an audio only session has been negotiated.
550TEST_F(MediaSessionDescriptionFactoryTest,
551 TestCreateUpdatedVideoOfferWithBundle) {
552 f1_.set_secure(SEC_ENABLED);
553 f2_.set_secure(SEC_ENABLED);
554 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000555 opts.recv_audio = true;
556 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000557 opts.data_channel_type = cricket::DCT_NONE;
558 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800559 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
560 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000561 f2_.CreateAnswer(offer.get(), opts, NULL));
562
563 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000564 updated_opts.recv_audio = true;
565 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000566 updated_opts.data_channel_type = cricket::DCT_RTP;
567 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800568 std::unique_ptr<SessionDescription> updated_offer(
569 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000570
571 const AudioContentDescription* acd =
572 GetFirstAudioContentDescription(updated_offer.get());
573 const VideoContentDescription* vcd =
574 GetFirstVideoContentDescription(updated_offer.get());
575 const DataContentDescription* dcd =
576 GetFirstDataContentDescription(updated_offer.get());
577 EXPECT_TRUE(NULL != vcd);
578 EXPECT_TRUE(NULL != acd);
579 EXPECT_TRUE(NULL != dcd);
580
581 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
582 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
583 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
584 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
585 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
586 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
587}
deadbeef44f08192015-12-15 16:20:09 -0800588
wu@webrtc.org78187522013-10-07 23:32:02 +0000589// Create a RTP data offer, and ensure it matches what we expect.
590TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000591 MediaSessionOptions opts;
592 opts.data_channel_type = cricket::DCT_RTP;
593 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800594 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000595 ASSERT_TRUE(offer.get() != NULL);
596 const ContentInfo* ac = offer->GetContentByName("audio");
597 const ContentInfo* dc = offer->GetContentByName("data");
598 ASSERT_TRUE(ac != NULL);
599 ASSERT_TRUE(dc != NULL);
600 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
601 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
602 const AudioContentDescription* acd =
603 static_cast<const AudioContentDescription*>(ac->description);
604 const DataContentDescription* dcd =
605 static_cast<const DataContentDescription*>(dc->description);
606 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
607 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
608 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
609 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
610 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
611 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
612 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
613 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
614 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
615 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
616 EXPECT_EQ(cricket::kDataMaxBandwidth,
617 dcd->bandwidth()); // default bandwidth (auto)
618 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
619 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
620 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
621}
622
wu@webrtc.org78187522013-10-07 23:32:02 +0000623// Create an SCTP data offer with bundle without error.
624TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
625 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000626 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000627 opts.bundle_enabled = true;
628 opts.data_channel_type = cricket::DCT_SCTP;
629 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800630 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000631 EXPECT_TRUE(offer.get() != NULL);
632 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
633}
634
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000635// Test creating an sctp data channel from an already generated offer.
636TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
637 MediaSessionOptions opts;
638 opts.recv_audio = false;
639 opts.bundle_enabled = true;
640 opts.data_channel_type = cricket::DCT_SCTP;
641 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800642 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000643 ASSERT_TRUE(offer1.get() != NULL);
644 const ContentInfo* data = offer1->GetContentByName("data");
645 ASSERT_TRUE(data != NULL);
646 const MediaContentDescription* mdesc =
647 static_cast<const MediaContentDescription*>(data->description);
648 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
649
650 // Now set data_channel_type to 'none' (default) and make sure that the
651 // datachannel type that gets generated from the previous offer, is of the
652 // same type.
653 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800654 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000655 f1_.CreateOffer(opts, offer1.get()));
656 data = offer2->GetContentByName("data");
657 ASSERT_TRUE(data != NULL);
658 mdesc = static_cast<const MediaContentDescription*>(data->description);
659 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
660}
661
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000662// Create an audio, video offer without legacy StreamParams.
663TEST_F(MediaSessionDescriptionFactoryTest,
664 TestCreateOfferWithoutLegacyStreams) {
665 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000666 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800668 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 ASSERT_TRUE(offer.get() != NULL);
670 const ContentInfo* ac = offer->GetContentByName("audio");
671 const ContentInfo* vc = offer->GetContentByName("video");
672 ASSERT_TRUE(ac != NULL);
673 ASSERT_TRUE(vc != NULL);
674 const AudioContentDescription* acd =
675 static_cast<const AudioContentDescription*>(ac->description);
676 const VideoContentDescription* vcd =
677 static_cast<const VideoContentDescription*>(vc->description);
678
679 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
680 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
681}
682
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000683// Creates an audio+video sendonly offer.
684TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
685 MediaSessionOptions options;
686 options.recv_audio = false;
687 options.recv_video = false;
688 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
689 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
690
kwiberg31022942016-03-11 14:18:21 -0800691 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000692 ASSERT_TRUE(offer.get() != NULL);
693 EXPECT_EQ(2u, offer->contents().size());
694 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
695 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
696
697 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
698 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
699}
700
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000701// Verifies that the order of the media contents in the current
702// SessionDescription is preserved in the new SessionDescription.
703TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
704 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000705 opts.recv_audio = false;
706 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000707 opts.data_channel_type = cricket::DCT_SCTP;
708
kwiberg31022942016-03-11 14:18:21 -0800709 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000710 ASSERT_TRUE(offer1.get() != NULL);
711 EXPECT_EQ(1u, offer1->contents().size());
712 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
713
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000714 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800715 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000716 f1_.CreateOffer(opts, offer1.get()));
717 ASSERT_TRUE(offer2.get() != NULL);
718 EXPECT_EQ(2u, offer2->contents().size());
719 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
720 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
721
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000722 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800723 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000724 f1_.CreateOffer(opts, offer2.get()));
725 ASSERT_TRUE(offer3.get() != NULL);
726 EXPECT_EQ(3u, offer3->contents().size());
727 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
728 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
729 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
730
731 // Verifies the default order is audio-video-data, so that the previous checks
732 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800733 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000734 ASSERT_TRUE(offer4.get() != NULL);
735 EXPECT_EQ(3u, offer4->contents().size());
736 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
737 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
738 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
739}
740
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000741// Create a typical audio answer, and ensure it matches what we expect.
742TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
743 f1_.set_secure(SEC_ENABLED);
744 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800745 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000746 f1_.CreateOffer(MediaSessionOptions(), NULL));
747 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800748 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000749 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
750 const ContentInfo* ac = answer->GetContentByName("audio");
751 const ContentInfo* vc = answer->GetContentByName("video");
752 ASSERT_TRUE(ac != NULL);
753 ASSERT_TRUE(vc == NULL);
754 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
755 const AudioContentDescription* acd =
756 static_cast<const AudioContentDescription*>(ac->description);
757 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
758 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
759 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
760 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
761 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
762 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
763 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
764}
765
766// Create a typical video answer, and ensure it matches what we expect.
767TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
768 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000769 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000770 f1_.set_secure(SEC_ENABLED);
771 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800772 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000773 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800774 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000775 f2_.CreateAnswer(offer.get(), opts, NULL));
776 const ContentInfo* ac = answer->GetContentByName("audio");
777 const ContentInfo* vc = answer->GetContentByName("video");
778 ASSERT_TRUE(ac != NULL);
779 ASSERT_TRUE(vc != NULL);
780 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
781 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
782 const AudioContentDescription* acd =
783 static_cast<const AudioContentDescription*>(ac->description);
784 const VideoContentDescription* vcd =
785 static_cast<const VideoContentDescription*>(vc->description);
786 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
787 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
788 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
789 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
790 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
791 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
792 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
793 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
794 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
795 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
796 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
797 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
798}
799
800TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
801 MediaSessionOptions opts;
802 opts.data_channel_type = cricket::DCT_RTP;
803 f1_.set_secure(SEC_ENABLED);
804 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800805 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000806 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800807 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000808 f2_.CreateAnswer(offer.get(), opts, NULL));
809 const ContentInfo* ac = answer->GetContentByName("audio");
810 const ContentInfo* vc = answer->GetContentByName("data");
811 ASSERT_TRUE(ac != NULL);
812 ASSERT_TRUE(vc != NULL);
813 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
814 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
815 const AudioContentDescription* acd =
816 static_cast<const AudioContentDescription*>(ac->description);
817 const DataContentDescription* vcd =
818 static_cast<const DataContentDescription*>(vc->description);
819 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
820 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
821 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
822 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
823 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
824 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
825 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
826 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
827 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
828 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
829 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
830 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
831}
832
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000833// Verifies that the order of the media contents in the offer is preserved in
834// the answer.
835TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
836 MediaSessionOptions opts;
837
838 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000839 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000840 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -0800841 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000842 ASSERT_TRUE(offer1.get() != NULL);
843
844 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000845 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800846 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000847 f1_.CreateOffer(opts, offer1.get()));
848 ASSERT_TRUE(offer2.get() != NULL);
849
850 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000851 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800852 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000853 f1_.CreateOffer(opts, offer2.get()));
854 ASSERT_TRUE(offer3.get() != NULL);
855
kwiberg31022942016-03-11 14:18:21 -0800856 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000857 f2_.CreateAnswer(offer3.get(), opts, NULL));
858 ASSERT_TRUE(answer.get() != NULL);
859 EXPECT_EQ(3u, answer->contents().size());
860 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
861 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
862 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
863}
864
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000865// This test that the media direction is set to send/receive in an answer if
866// the offer is send receive.
867TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
868 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
869}
870
871// This test that the media direction is set to receive only in an answer if
872// the offer is send only.
873TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
874 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
875}
876
877// This test that the media direction is set to send only in an answer if
878// the offer is recv only.
879TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
880 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
881}
882
883// This test that the media direction is set to inactive in an answer if
884// the offer is inactive.
885TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
886 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
887}
888
889// Test that a data content with an unknown protocol is rejected in an answer.
890TEST_F(MediaSessionDescriptionFactoryTest,
891 CreateDataAnswerToOfferWithUnknownProtocol) {
892 MediaSessionOptions opts;
893 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000894 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000895 f1_.set_secure(SEC_ENABLED);
896 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800897 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -0700898 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000899 ASSERT_TRUE(dc_offer != NULL);
900 DataContentDescription* dcd_offer =
901 static_cast<DataContentDescription*>(dc_offer->description);
902 ASSERT_TRUE(dcd_offer != NULL);
903 std::string protocol = "a weird unknown protocol";
904 dcd_offer->set_protocol(protocol);
905
kwiberg31022942016-03-11 14:18:21 -0800906 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907 f2_.CreateAnswer(offer.get(), opts, NULL));
908
909 const ContentInfo* dc_answer = answer->GetContentByName("data");
910 ASSERT_TRUE(dc_answer != NULL);
911 EXPECT_TRUE(dc_answer->rejected);
912 const DataContentDescription* dcd_answer =
913 static_cast<const DataContentDescription*>(dc_answer->description);
914 ASSERT_TRUE(dcd_answer != NULL);
915 EXPECT_EQ(protocol, dcd_answer->protocol());
916}
917
918// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
919TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
920 MediaSessionOptions opts;
921 f1_.set_secure(SEC_DISABLED);
922 f2_.set_secure(SEC_DISABLED);
923 tdf1_.set_secure(SEC_DISABLED);
924 tdf2_.set_secure(SEC_DISABLED);
925
kwiberg31022942016-03-11 14:18:21 -0800926 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000927 const AudioContentDescription* offer_acd =
928 GetFirstAudioContentDescription(offer.get());
929 ASSERT_TRUE(offer_acd != NULL);
930 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
931
kwiberg31022942016-03-11 14:18:21 -0800932 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000933 f2_.CreateAnswer(offer.get(), opts, NULL));
934
935 const ContentInfo* ac_answer = answer->GetContentByName("audio");
936 ASSERT_TRUE(ac_answer != NULL);
937 EXPECT_FALSE(ac_answer->rejected);
938
939 const AudioContentDescription* answer_acd =
940 GetFirstAudioContentDescription(answer.get());
941 ASSERT_TRUE(answer_acd != NULL);
942 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
943}
944
945// Create a video offer and answer and ensure the RTP header extensions
946// matches what we expect.
947TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
948 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000949 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000950
951 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
952 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
953 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
954 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
955
kwiberg31022942016-03-11 14:18:21 -0800956 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000957 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800958 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000959 f2_.CreateAnswer(offer.get(), opts, NULL));
960
961 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
962 GetFirstAudioContentDescription(
963 offer.get())->rtp_header_extensions());
964 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
965 GetFirstVideoContentDescription(
966 offer.get())->rtp_header_extensions());
967 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
968 GetFirstAudioContentDescription(
969 answer.get())->rtp_header_extensions());
970 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
971 GetFirstVideoContentDescription(
972 answer.get())->rtp_header_extensions());
973}
974
975// Create an audio, video, data answer without legacy StreamParams.
976TEST_F(MediaSessionDescriptionFactoryTest,
977 TestCreateAnswerWithoutLegacyStreams) {
978 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000979 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000980 opts.data_channel_type = cricket::DCT_RTP;
981 f1_.set_add_legacy_streams(false);
982 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800983 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000984 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800985 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000986 f2_.CreateAnswer(offer.get(), opts, NULL));
987 const ContentInfo* ac = answer->GetContentByName("audio");
988 const ContentInfo* vc = answer->GetContentByName("video");
989 const ContentInfo* dc = answer->GetContentByName("data");
990 ASSERT_TRUE(ac != NULL);
991 ASSERT_TRUE(vc != NULL);
992 const AudioContentDescription* acd =
993 static_cast<const AudioContentDescription*>(ac->description);
994 const VideoContentDescription* vcd =
995 static_cast<const VideoContentDescription*>(vc->description);
996 const DataContentDescription* dcd =
997 static_cast<const DataContentDescription*>(dc->description);
998
999 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1000 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1001 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1002}
1003
1004TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1005 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001006 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001007 opts.data_channel_type = cricket::DCT_RTP;
1008 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001009 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001010 ASSERT_TRUE(offer.get() != NULL);
1011 const ContentInfo* ac = offer->GetContentByName("audio");
1012 const ContentInfo* vc = offer->GetContentByName("video");
1013 const ContentInfo* dc = offer->GetContentByName("data");
1014 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1015 static_cast<const AudioContentDescription*>(ac->description));
1016 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1017 static_cast<const VideoContentDescription*>(vc->description));
1018 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1019 static_cast<const DataContentDescription*>(dc->description));
1020
1021 EXPECT_FALSE(acd->partial()); // default is false.
1022 acd->set_partial(true);
1023 EXPECT_TRUE(acd->partial());
1024 acd->set_partial(false);
1025 EXPECT_FALSE(acd->partial());
1026
1027 EXPECT_FALSE(vcd->partial()); // default is false.
1028 vcd->set_partial(true);
1029 EXPECT_TRUE(vcd->partial());
1030 vcd->set_partial(false);
1031 EXPECT_FALSE(vcd->partial());
1032
1033 EXPECT_FALSE(dcd->partial()); // default is false.
1034 dcd->set_partial(true);
1035 EXPECT_TRUE(dcd->partial());
1036 dcd->set_partial(false);
1037 EXPECT_FALSE(dcd->partial());
1038}
1039
1040// Create a typical video answer, and ensure it matches what we expect.
1041TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1042 MediaSessionOptions offer_opts;
1043 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001044 answer_opts.recv_video = true;
1045 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001046 answer_opts.data_channel_type = cricket::DCT_RTP;
1047 offer_opts.data_channel_type = cricket::DCT_RTP;
1048
kwiberg31022942016-03-11 14:18:21 -08001049 std::unique_ptr<SessionDescription> offer;
1050 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051
1052 offer_opts.rtcp_mux_enabled = true;
1053 answer_opts.rtcp_mux_enabled = true;
1054
1055 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1056 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1057 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1058 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1059 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1060 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1061 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1062 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1063 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1064 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1065 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1066 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1067 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1068 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1069
1070 offer_opts.rtcp_mux_enabled = true;
1071 answer_opts.rtcp_mux_enabled = false;
1072
1073 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1074 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1075 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1076 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1077 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1078 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1079 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1080 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1081 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1082 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1083 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1084 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1085 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1086 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1087
1088 offer_opts.rtcp_mux_enabled = false;
1089 answer_opts.rtcp_mux_enabled = true;
1090
1091 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1092 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1093 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1094 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1095 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1096 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1097 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1098 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1099 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1100 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1101 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1102 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1103 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1104 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1105
1106 offer_opts.rtcp_mux_enabled = false;
1107 answer_opts.rtcp_mux_enabled = false;
1108
1109 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1110 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1111 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1112 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1113 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1114 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1115 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1116 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1117 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1118 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1119 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1120 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1121 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1122 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1123}
1124
1125// Create an audio-only answer to a video offer.
1126TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1127 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001128 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001129 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001130 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001131 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001132 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1133 const ContentInfo* ac = answer->GetContentByName("audio");
1134 const ContentInfo* vc = answer->GetContentByName("video");
1135 ASSERT_TRUE(ac != NULL);
1136 ASSERT_TRUE(vc != NULL);
1137 ASSERT_TRUE(vc->description != NULL);
1138 EXPECT_TRUE(vc->rejected);
1139}
1140
1141// Create an audio-only answer to an offer with data.
1142TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1143 MediaSessionOptions opts;
1144 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001145 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001146 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001147 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001148 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1149 const ContentInfo* ac = answer->GetContentByName("audio");
1150 const ContentInfo* dc = answer->GetContentByName("data");
1151 ASSERT_TRUE(ac != NULL);
1152 ASSERT_TRUE(dc != NULL);
1153 ASSERT_TRUE(dc->description != NULL);
1154 EXPECT_TRUE(dc->rejected);
1155}
1156
1157// Create an answer that rejects the contents which are rejected in the offer.
1158TEST_F(MediaSessionDescriptionFactoryTest,
1159 CreateAnswerToOfferWithRejectedMedia) {
1160 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001161 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001162 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001163 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 ASSERT_TRUE(offer.get() != NULL);
1165 ContentInfo* ac = offer->GetContentByName("audio");
1166 ContentInfo* vc = offer->GetContentByName("video");
1167 ContentInfo* dc = offer->GetContentByName("data");
1168 ASSERT_TRUE(ac != NULL);
1169 ASSERT_TRUE(vc != NULL);
1170 ASSERT_TRUE(dc != NULL);
1171 ac->rejected = true;
1172 vc->rejected = true;
1173 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001174 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001175 f2_.CreateAnswer(offer.get(), opts, NULL));
1176 ac = answer->GetContentByName("audio");
1177 vc = answer->GetContentByName("video");
1178 dc = answer->GetContentByName("data");
1179 ASSERT_TRUE(ac != NULL);
1180 ASSERT_TRUE(vc != NULL);
1181 ASSERT_TRUE(dc != NULL);
1182 EXPECT_TRUE(ac->rejected);
1183 EXPECT_TRUE(vc->rejected);
1184 EXPECT_TRUE(dc->rejected);
1185}
1186
1187// Create an audio and video offer with:
1188// - one video track
1189// - two audio tracks
1190// - two data tracks
1191// and ensure it matches what we expect. Also updates the initial offer by
1192// adding a new video track and replaces one of the audio tracks.
1193TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1194 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001195 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1196 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1197 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001198 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001199 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1200 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001201
1202 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001203 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001204
1205 ASSERT_TRUE(offer.get() != NULL);
1206 const ContentInfo* ac = offer->GetContentByName("audio");
1207 const ContentInfo* vc = offer->GetContentByName("video");
1208 const ContentInfo* dc = offer->GetContentByName("data");
1209 ASSERT_TRUE(ac != NULL);
1210 ASSERT_TRUE(vc != NULL);
1211 ASSERT_TRUE(dc != NULL);
1212 const AudioContentDescription* acd =
1213 static_cast<const AudioContentDescription*>(ac->description);
1214 const VideoContentDescription* vcd =
1215 static_cast<const VideoContentDescription*>(vc->description);
1216 const DataContentDescription* dcd =
1217 static_cast<const DataContentDescription*>(dc->description);
1218 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1219 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1220
1221 const StreamParamsVec& audio_streams = acd->streams();
1222 ASSERT_EQ(2U, audio_streams.size());
1223 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1224 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1225 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1226 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1227 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1228 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1229 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1230
1231 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1232 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1233 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1234
1235 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1236 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1237 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1238
1239 const StreamParamsVec& video_streams = vcd->streams();
1240 ASSERT_EQ(1U, video_streams.size());
1241 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1242 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1243 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1244 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1245
1246 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1247 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1248 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1249
1250 const StreamParamsVec& data_streams = dcd->streams();
1251 ASSERT_EQ(2U, data_streams.size());
1252 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1253 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1254 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1255 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1256 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1257 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1258 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1259
1260 EXPECT_EQ(cricket::kDataMaxBandwidth,
1261 dcd->bandwidth()); // default bandwidth (auto)
1262 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1263 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1264
1265
1266 // Update the offer. Add a new video track that is not synched to the
1267 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001268 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1269 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1270 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1271 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1272 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001273 std::unique_ptr<SessionDescription> updated_offer(
1274 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001275
1276 ASSERT_TRUE(updated_offer.get() != NULL);
1277 ac = updated_offer->GetContentByName("audio");
1278 vc = updated_offer->GetContentByName("video");
1279 dc = updated_offer->GetContentByName("data");
1280 ASSERT_TRUE(ac != NULL);
1281 ASSERT_TRUE(vc != NULL);
1282 ASSERT_TRUE(dc != NULL);
1283 const AudioContentDescription* updated_acd =
1284 static_cast<const AudioContentDescription*>(ac->description);
1285 const VideoContentDescription* updated_vcd =
1286 static_cast<const VideoContentDescription*>(vc->description);
1287 const DataContentDescription* updated_dcd =
1288 static_cast<const DataContentDescription*>(dc->description);
1289
1290 EXPECT_EQ(acd->type(), updated_acd->type());
1291 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1292 EXPECT_EQ(vcd->type(), updated_vcd->type());
1293 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1294 EXPECT_EQ(dcd->type(), updated_dcd->type());
1295 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1296 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1297 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1298 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1299 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1300 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1301 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1302
1303 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1304 ASSERT_EQ(2U, updated_audio_streams.size());
1305 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1306 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1307 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1308 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1309 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1310
1311 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1312 ASSERT_EQ(2U, updated_video_streams.size());
1313 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1314 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001315 // All the media streams in one PeerConnection share one RTCP CNAME.
1316 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001317
1318 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1319 ASSERT_EQ(2U, updated_data_streams.size());
1320 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1321 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1322 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1323 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1324 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001325 // The stream correctly got the CNAME from the MediaSessionOptions.
1326 // The Expected RTCP CNAME is the default one as we are using the default
1327 // MediaSessionOptions.
1328 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001329}
1330
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001331// Create an offer with simulcast video stream.
1332TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1333 MediaSessionOptions opts;
1334 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001335 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001336 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001337
1338 ASSERT_TRUE(offer.get() != NULL);
1339 const ContentInfo* vc = offer->GetContentByName("video");
1340 ASSERT_TRUE(vc != NULL);
1341 const VideoContentDescription* vcd =
1342 static_cast<const VideoContentDescription*>(vc->description);
1343
1344 const StreamParamsVec& video_streams = vcd->streams();
1345 ASSERT_EQ(1U, video_streams.size());
1346 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1347 const SsrcGroup* sim_ssrc_group =
1348 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1349 ASSERT_TRUE(sim_ssrc_group != NULL);
1350 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1351}
1352
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001353// Create an audio and video answer to a standard video offer with:
1354// - one video track
1355// - two audio tracks
1356// - two data tracks
1357// and ensure it matches what we expect. Also updates the initial answer by
1358// adding a new video track and removes one of the audio tracks.
1359TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1360 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001361 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001362 offer_opts.data_channel_type = cricket::DCT_RTP;
1363 f1_.set_secure(SEC_ENABLED);
1364 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001365 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366
1367 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001368 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1369 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1370 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001371 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001372 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1373 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001374
kwiberg31022942016-03-11 14:18:21 -08001375 std::unique_ptr<SessionDescription> answer(
1376 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001377
1378 ASSERT_TRUE(answer.get() != NULL);
1379 const ContentInfo* ac = answer->GetContentByName("audio");
1380 const ContentInfo* vc = answer->GetContentByName("video");
1381 const ContentInfo* dc = answer->GetContentByName("data");
1382 ASSERT_TRUE(ac != NULL);
1383 ASSERT_TRUE(vc != NULL);
1384 ASSERT_TRUE(dc != NULL);
1385 const AudioContentDescription* acd =
1386 static_cast<const AudioContentDescription*>(ac->description);
1387 const VideoContentDescription* vcd =
1388 static_cast<const VideoContentDescription*>(vc->description);
1389 const DataContentDescription* dcd =
1390 static_cast<const DataContentDescription*>(dc->description);
1391 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1392 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1393 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1394
1395 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1396 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1397
1398 const StreamParamsVec& audio_streams = acd->streams();
1399 ASSERT_EQ(2U, audio_streams.size());
1400 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1401 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1402 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1403 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1404 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1405 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1406 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1407
1408 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1409 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1410
1411 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1412 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1413
1414 const StreamParamsVec& video_streams = vcd->streams();
1415 ASSERT_EQ(1U, video_streams.size());
1416 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1417 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1418 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1419 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1420
1421 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1422 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1423
1424 const StreamParamsVec& data_streams = dcd->streams();
1425 ASSERT_EQ(2U, data_streams.size());
1426 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1427 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1428 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1429 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1430 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1431 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1432 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1433
1434 EXPECT_EQ(cricket::kDataMaxBandwidth,
1435 dcd->bandwidth()); // default bandwidth (auto)
1436 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1437
1438 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001439 // other tracks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001440 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1441 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1442 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001443 std::unique_ptr<SessionDescription> updated_answer(
1444 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001445
1446 ASSERT_TRUE(updated_answer.get() != NULL);
1447 ac = updated_answer->GetContentByName("audio");
1448 vc = updated_answer->GetContentByName("video");
1449 dc = updated_answer->GetContentByName("data");
1450 ASSERT_TRUE(ac != NULL);
1451 ASSERT_TRUE(vc != NULL);
1452 ASSERT_TRUE(dc != NULL);
1453 const AudioContentDescription* updated_acd =
1454 static_cast<const AudioContentDescription*>(ac->description);
1455 const VideoContentDescription* updated_vcd =
1456 static_cast<const VideoContentDescription*>(vc->description);
1457 const DataContentDescription* updated_dcd =
1458 static_cast<const DataContentDescription*>(dc->description);
1459
1460 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1461 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1462 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1463 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1464 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1465 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1466
1467 EXPECT_EQ(acd->type(), updated_acd->type());
1468 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1469 EXPECT_EQ(vcd->type(), updated_vcd->type());
1470 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1471 EXPECT_EQ(dcd->type(), updated_dcd->type());
1472 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1473
1474 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1475 ASSERT_EQ(1U, updated_audio_streams.size());
1476 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1477
1478 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1479 ASSERT_EQ(2U, updated_video_streams.size());
1480 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1481 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001482 // All media streams in one PeerConnection share one CNAME.
1483 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001484
1485 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1486 ASSERT_EQ(1U, updated_data_streams.size());
1487 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1488}
1489
1490
1491// Create an updated offer after creating an answer to the original offer and
1492// verify that the codecs that were part of the original answer are not changed
1493// in the updated offer.
1494TEST_F(MediaSessionDescriptionFactoryTest,
1495 RespondentCreatesOfferAfterCreatingAnswer) {
1496 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001497 opts.recv_audio = true;
1498 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001499
kwiberg31022942016-03-11 14:18:21 -08001500 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1501 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001502 f2_.CreateAnswer(offer.get(), opts, NULL));
1503
1504 const AudioContentDescription* acd =
1505 GetFirstAudioContentDescription(answer.get());
1506 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1507
1508 const VideoContentDescription* vcd =
1509 GetFirstVideoContentDescription(answer.get());
1510 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1511
kwiberg31022942016-03-11 14:18:21 -08001512 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513 f2_.CreateOffer(opts, answer.get()));
1514
1515 // The expected audio codecs are the common audio codecs from the first
1516 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1517 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001518 // TODO(wu): |updated_offer| should not include the codec
1519 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001520 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521 kAudioCodecsAnswer[0],
1522 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001523 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001524 };
1525
1526 // The expected video codecs are the common video codecs from the first
1527 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1528 // preference order.
1529 const VideoCodec kUpdatedVideoCodecOffer[] = {
1530 kVideoCodecsAnswer[0],
1531 kVideoCodecs2[1],
1532 };
1533
1534 const AudioContentDescription* updated_acd =
1535 GetFirstAudioContentDescription(updated_offer.get());
1536 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1537
1538 const VideoContentDescription* updated_vcd =
1539 GetFirstVideoContentDescription(updated_offer.get());
1540 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1541}
1542
1543// Create an updated offer after creating an answer to the original offer and
1544// verify that the codecs that were part of the original answer are not changed
1545// in the updated offer. In this test Rtx is enabled.
1546TEST_F(MediaSessionDescriptionFactoryTest,
1547 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1548 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001549 opts.recv_video = true;
1550 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001551 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001552 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001553 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001554 f1_.set_video_codecs(f1_codecs);
1555
1556 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001557 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001558 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001559 f2_.set_video_codecs(f2_codecs);
1560
kwiberg31022942016-03-11 14:18:21 -08001561 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001562 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001563 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 f2_.CreateAnswer(offer.get(), opts, NULL));
1565
1566 const VideoContentDescription* vcd =
1567 GetFirstVideoContentDescription(answer.get());
1568
1569 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001570 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1571 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001572
1573 EXPECT_EQ(expected_codecs, vcd->codecs());
1574
deadbeef67cf2c12016-04-13 10:07:16 -07001575 // Now, make sure we get same result (except for the order) if |f2_| creates
1576 // an updated offer even though the default payload types between |f1_| and
1577 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001578 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001579 f2_.CreateOffer(opts, answer.get()));
1580 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001581 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001582 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1583
1584 const VideoContentDescription* updated_vcd =
1585 GetFirstVideoContentDescription(updated_answer.get());
1586
1587 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1588}
1589
1590// Create an updated offer that adds video after creating an audio only answer
1591// to the original offer. This test verifies that if a video codec and the RTX
1592// codec have the same default payload type as an audio codec that is already in
1593// use, the added codecs payload types are changed.
1594TEST_F(MediaSessionDescriptionFactoryTest,
1595 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1596 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001597 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001598 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001599 f1_.set_video_codecs(f1_codecs);
1600
1601 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001602 opts.recv_audio = true;
1603 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001604
kwiberg31022942016-03-11 14:18:21 -08001605 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1606 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001607 f2_.CreateAnswer(offer.get(), opts, NULL));
1608
1609 const AudioContentDescription* acd =
1610 GetFirstAudioContentDescription(answer.get());
1611 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1612
1613 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1614 // reference be the same as an audio codec that was negotiated in the
1615 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001616 opts.recv_audio = true;
1617 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001618
1619 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1620 int used_pl_type = acd->codecs()[0].id;
1621 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001622 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001623 f2_.set_video_codecs(f2_codecs);
1624
kwiberg31022942016-03-11 14:18:21 -08001625 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626 f2_.CreateOffer(opts, answer.get()));
1627 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001628 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001629 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1630
1631 const AudioContentDescription* updated_acd =
1632 GetFirstAudioContentDescription(answer.get());
1633 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1634
1635 const VideoContentDescription* updated_vcd =
1636 GetFirstVideoContentDescription(updated_answer.get());
1637
1638 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001639 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1641 EXPECT_NE(used_pl_type, new_h264_pl_type);
1642 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001643 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001644 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1645 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1646}
1647
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001648// Create an updated offer with RTX after creating an answer to an offer
1649// without RTX, and with different default payload types.
1650// Verify that the added RTX codec references the correct payload type.
1651TEST_F(MediaSessionDescriptionFactoryTest,
1652 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1653 MediaSessionOptions opts;
1654 opts.recv_video = true;
1655 opts.recv_audio = true;
1656
1657 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1658 // This creates rtx for H264 with the payload type |f2_| uses.
1659 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1660 f2_.set_video_codecs(f2_codecs);
1661
kwiberg31022942016-03-11 14:18:21 -08001662 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001663 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001664 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001665 f2_.CreateAnswer(offer.get(), opts, nullptr));
1666
1667 const VideoContentDescription* vcd =
1668 GetFirstVideoContentDescription(answer.get());
1669
1670 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1671 EXPECT_EQ(expected_codecs, vcd->codecs());
1672
1673 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1674 // updated offer, even though the default payload types are different from
1675 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001676 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001677 f2_.CreateOffer(opts, answer.get()));
1678 ASSERT_TRUE(updated_offer);
1679
1680 const VideoContentDescription* updated_vcd =
1681 GetFirstVideoContentDescription(updated_offer.get());
1682
1683 // New offer should attempt to add H263, and RTX for H264.
1684 expected_codecs.push_back(kVideoCodecs2[1]);
1685 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1686 &expected_codecs);
1687 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1688}
1689
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001690// Test that RTX is ignored when there is no associated payload type parameter.
1691TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1692 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001693 opts.recv_video = true;
1694 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001696 // This creates RTX without associated payload type parameter.
deadbeef67cf2c12016-04-13 10:07:16 -07001697 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001698 f1_.set_video_codecs(f1_codecs);
1699
1700 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001701 // This creates RTX for H264 with the payload type |f2_| uses.
1702 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703 f2_.set_video_codecs(f2_codecs);
1704
kwiberg31022942016-03-11 14:18:21 -08001705 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001706 ASSERT_TRUE(offer.get() != NULL);
1707 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1708 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1709 // is possible to test that that RTX is dropped when
1710 // kCodecParamAssociatedPayloadType is missing in the offer.
1711 VideoContentDescription* desc =
1712 static_cast<cricket::VideoContentDescription*>(
1713 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1714 ASSERT_TRUE(desc != NULL);
1715 std::vector<VideoCodec> codecs = desc->codecs();
1716 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1717 iter != codecs.end(); ++iter) {
1718 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1719 iter->params.clear();
1720 }
1721 }
1722 desc->set_codecs(codecs);
1723
kwiberg31022942016-03-11 14:18:21 -08001724 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001725 f2_.CreateAnswer(offer.get(), opts, NULL));
1726
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001727 std::vector<std::string> codec_names =
1728 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1729 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1730 cricket::kRtxCodecName));
1731}
1732
1733// Test that RTX will be filtered out in the answer if its associated payload
1734// type doesn't match the local value.
1735TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1736 MediaSessionOptions opts;
1737 opts.recv_video = true;
1738 opts.recv_audio = false;
1739 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1740 // This creates RTX for H264 in sender.
1741 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1742 f1_.set_video_codecs(f1_codecs);
1743
1744 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1745 // This creates RTX for H263 in receiver.
1746 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1747 f2_.set_video_codecs(f2_codecs);
1748
kwiberg31022942016-03-11 14:18:21 -08001749 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001750 ASSERT_TRUE(offer.get() != NULL);
1751 // Associated payload type doesn't match, therefore, RTX codec is removed in
1752 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001753 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001754 f2_.CreateAnswer(offer.get(), opts, NULL));
1755
1756 std::vector<std::string> codec_names =
1757 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1758 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1759 cricket::kRtxCodecName));
1760}
1761
1762// Test that when multiple RTX codecs are offered, only the matched RTX codec
1763// is added in the answer, and the unsupported RTX codec is filtered out.
1764TEST_F(MediaSessionDescriptionFactoryTest,
1765 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1766 MediaSessionOptions opts;
1767 opts.recv_video = true;
1768 opts.recv_audio = false;
1769 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1770 // This creates RTX for H264-SVC in sender.
1771 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1772 f1_.set_video_codecs(f1_codecs);
1773
1774 // This creates RTX for H264 in sender.
1775 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1776 f1_.set_video_codecs(f1_codecs);
1777
1778 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1779 // This creates RTX for H264 in receiver.
1780 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1781 f2_.set_video_codecs(f2_codecs);
1782
1783 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1784 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001785 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001786 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001787 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001788 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001789 const VideoContentDescription* vcd =
1790 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001791 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1792 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1793 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001794
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001795 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796}
1797
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001798// Test that after one RTX codec has been negotiated, a new offer can attempt
1799// to add another.
1800TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1801 MediaSessionOptions opts;
1802 opts.recv_video = true;
1803 opts.recv_audio = false;
1804 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1805 // This creates RTX for H264 for the offerer.
1806 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1807 f1_.set_video_codecs(f1_codecs);
1808
kwiberg31022942016-03-11 14:18:21 -08001809 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001810 ASSERT_TRUE(offer);
1811 const VideoContentDescription* vcd =
1812 GetFirstVideoContentDescription(offer.get());
1813
1814 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1815 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1816 &expected_codecs);
1817 EXPECT_EQ(expected_codecs, vcd->codecs());
1818
1819 // Now, attempt to add RTX for H264-SVC.
1820 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1821 f1_.set_video_codecs(f1_codecs);
1822
kwiberg31022942016-03-11 14:18:21 -08001823 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001824 f1_.CreateOffer(opts, offer.get()));
1825 ASSERT_TRUE(updated_offer);
1826 vcd = GetFirstVideoContentDescription(updated_offer.get());
1827
1828 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1829 &expected_codecs);
1830 EXPECT_EQ(expected_codecs, vcd->codecs());
1831}
1832
Noah Richards2e7a0982015-05-18 14:02:54 -07001833// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1834// generated for each simulcast ssrc and correctly grouped.
1835TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1836 MediaSessionOptions opts;
1837 opts.recv_video = true;
1838 opts.recv_audio = false;
1839
1840 // Add simulcast streams.
1841 opts.AddSendVideoStream("stream1", "stream1label", 3);
1842
1843 // Use a single real codec, and then add RTX for it.
1844 std::vector<VideoCodec> f1_codecs;
deadbeef67cf2c12016-04-13 10:07:16 -07001845 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30));
Noah Richards2e7a0982015-05-18 14:02:54 -07001846 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1847 f1_.set_video_codecs(f1_codecs);
1848
1849 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1850 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001851 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001852 ASSERT_TRUE(offer.get() != NULL);
1853 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1854 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1855 ASSERT_TRUE(desc != NULL);
1856 EXPECT_TRUE(desc->multistream());
1857 const StreamParamsVec& streams = desc->streams();
1858 // Single stream.
1859 ASSERT_EQ(1u, streams.size());
1860 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1861 EXPECT_EQ(6u, streams[0].ssrcs.size());
1862 // And should have a SIM group for the simulcast.
1863 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1864 // And a FID group for RTX.
1865 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02001866 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001867 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1868 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001869 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001870 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1871 EXPECT_EQ(3u, fid_ssrcs.size());
1872}
1873
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001874// Create an updated offer after creating an answer to the original offer and
1875// verify that the RTP header extensions that were part of the original answer
1876// are not changed in the updated offer.
1877TEST_F(MediaSessionDescriptionFactoryTest,
1878 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1879 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001880 opts.recv_audio = true;
1881 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001882
1883 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1884 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1885 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1886 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1887
kwiberg31022942016-03-11 14:18:21 -08001888 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1889 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001890 f2_.CreateAnswer(offer.get(), opts, NULL));
1891
1892 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1893 GetFirstAudioContentDescription(
1894 answer.get())->rtp_header_extensions());
1895 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1896 GetFirstVideoContentDescription(
1897 answer.get())->rtp_header_extensions());
1898
kwiberg31022942016-03-11 14:18:21 -08001899 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001900 f2_.CreateOffer(opts, answer.get()));
1901
1902 // The expected RTP header extensions in the new offer are the resulting
1903 // extensions from the first offer/answer exchange plus the extensions only
1904 // |f2_| offer.
1905 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001906 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001907 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1908 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001909 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1910 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001911 };
1912
1913 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001914 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001915 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1916 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001917 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1918 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001919 };
1920
1921 const AudioContentDescription* updated_acd =
1922 GetFirstAudioContentDescription(updated_offer.get());
1923 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1924 updated_acd->rtp_header_extensions());
1925
1926 const VideoContentDescription* updated_vcd =
1927 GetFirstVideoContentDescription(updated_offer.get());
1928 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1929 updated_vcd->rtp_header_extensions());
1930}
1931
deadbeefa5b273a2015-08-20 17:30:13 -07001932// Verify that if the same RTP extension URI is used for audio and video, the
1933// same ID is used. Also verify that the ID isn't changed when creating an
1934// updated offer (this was previously a bug).
1935TEST_F(MediaSessionDescriptionFactoryTest,
1936 RtpHeaderExtensionIdReused) {
1937 MediaSessionOptions opts;
1938 opts.recv_audio = true;
1939 opts.recv_video = true;
1940
1941 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1942 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1943
kwiberg31022942016-03-11 14:18:21 -08001944 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07001945
1946 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1947 // the video extensions.
1948 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1949 kVideoRtpExtension3[0],
1950 kAudioRtpExtension3[1],
1951 };
1952
1953 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1954 GetFirstAudioContentDescription(
1955 offer.get())->rtp_header_extensions());
1956 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1957 GetFirstVideoContentDescription(
1958 offer.get())->rtp_header_extensions());
1959
1960 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08001961 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07001962 f1_.CreateOffer(opts, offer.get()));
1963
1964 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1965 GetFirstAudioContentDescription(
1966 updated_offer.get())->rtp_header_extensions());
1967 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1968 GetFirstVideoContentDescription(
1969 updated_offer.get())->rtp_header_extensions());
1970}
1971
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001972TEST(MediaSessionDescription, CopySessionDescription) {
1973 SessionDescription source;
1974 cricket::ContentGroup group(cricket::CN_AUDIO);
1975 source.AddGroup(group);
1976 AudioContentDescription* acd(new AudioContentDescription());
1977 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1978 acd->AddLegacyStream(1);
1979 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1980 VideoContentDescription* vcd(new VideoContentDescription());
1981 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1982 vcd->AddLegacyStream(2);
1983 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1984
kwiberg31022942016-03-11 14:18:21 -08001985 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001986 ASSERT_TRUE(copy.get() != NULL);
1987 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1988 const ContentInfo* ac = copy->GetContentByName("audio");
1989 const ContentInfo* vc = copy->GetContentByName("video");
1990 ASSERT_TRUE(ac != NULL);
1991 ASSERT_TRUE(vc != NULL);
1992 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1993 const AudioContentDescription* acd_copy =
1994 static_cast<const AudioContentDescription*>(ac->description);
1995 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1996 EXPECT_EQ(1u, acd->first_ssrc());
1997
1998 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1999 const VideoContentDescription* vcd_copy =
2000 static_cast<const VideoContentDescription*>(vc->description);
2001 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2002 EXPECT_EQ(2u, vcd->first_ssrc());
2003}
2004
2005// The below TestTransportInfoXXX tests create different offers/answers, and
2006// ensure the TransportInfo in the SessionDescription matches what we expect.
2007TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2008 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002009 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002010 TestTransportInfo(true, options, false);
2011}
2012
2013TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
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, true);
2017}
2018
2019TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2020 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002021 options.recv_audio = true;
2022 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002023 options.data_channel_type = cricket::DCT_RTP;
2024 TestTransportInfo(true, options, false);
2025}
2026
2027TEST_F(MediaSessionDescriptionFactoryTest,
2028 TestTransportInfoOfferMultimediaCurrent) {
2029 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002030 options.recv_audio = true;
2031 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002032 options.data_channel_type = cricket::DCT_RTP;
2033 TestTransportInfo(true, options, true);
2034}
2035
2036TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2037 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002038 options.recv_audio = true;
2039 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002040 options.data_channel_type = cricket::DCT_RTP;
2041 options.bundle_enabled = true;
2042 TestTransportInfo(true, options, false);
2043}
2044
2045TEST_F(MediaSessionDescriptionFactoryTest,
2046 TestTransportInfoOfferBundleCurrent) {
2047 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002048 options.recv_audio = true;
2049 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002050 options.data_channel_type = cricket::DCT_RTP;
2051 options.bundle_enabled = true;
2052 TestTransportInfo(true, options, true);
2053}
2054
2055TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2056 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002057 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002058 TestTransportInfo(false, options, false);
2059}
2060
2061TEST_F(MediaSessionDescriptionFactoryTest,
2062 TestTransportInfoAnswerAudioCurrent) {
2063 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002064 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002065 TestTransportInfo(false, options, true);
2066}
2067
2068TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2069 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002070 options.recv_audio = true;
2071 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002072 options.data_channel_type = cricket::DCT_RTP;
2073 TestTransportInfo(false, options, false);
2074}
2075
2076TEST_F(MediaSessionDescriptionFactoryTest,
2077 TestTransportInfoAnswerMultimediaCurrent) {
2078 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002079 options.recv_audio = true;
2080 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002081 options.data_channel_type = cricket::DCT_RTP;
2082 TestTransportInfo(false, options, true);
2083}
2084
2085TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2086 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002087 options.recv_audio = true;
2088 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002089 options.data_channel_type = cricket::DCT_RTP;
2090 options.bundle_enabled = true;
2091 TestTransportInfo(false, options, false);
2092}
2093
2094TEST_F(MediaSessionDescriptionFactoryTest,
2095 TestTransportInfoAnswerBundleCurrent) {
2096 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002097 options.recv_audio = true;
2098 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099 options.data_channel_type = cricket::DCT_RTP;
2100 options.bundle_enabled = true;
2101 TestTransportInfo(false, options, true);
2102}
2103
2104// Create an offer with bundle enabled and verify the crypto parameters are
2105// the common set of the available cryptos.
2106TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2107 TestCryptoWithBundle(true);
2108}
2109
2110// Create an answer with bundle enabled and verify the crypto parameters are
2111// the common set of the available cryptos.
2112TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2113 TestCryptoWithBundle(false);
2114}
2115
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002116// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2117// DTLS is not enabled locally.
2118TEST_F(MediaSessionDescriptionFactoryTest,
2119 TestOfferDtlsSavpfWithoutDtlsFailed) {
2120 f1_.set_secure(SEC_ENABLED);
2121 f2_.set_secure(SEC_ENABLED);
2122 tdf1_.set_secure(SEC_DISABLED);
2123 tdf2_.set_secure(SEC_DISABLED);
2124
kwiberg31022942016-03-11 14:18:21 -08002125 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002126 f1_.CreateOffer(MediaSessionOptions(), NULL));
2127 ASSERT_TRUE(offer.get() != NULL);
2128 ContentInfo* offer_content = offer->GetContentByName("audio");
2129 ASSERT_TRUE(offer_content != NULL);
2130 AudioContentDescription* offer_audio_desc =
2131 static_cast<AudioContentDescription*>(offer_content->description);
2132 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2133
kwiberg31022942016-03-11 14:18:21 -08002134 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002135 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2136 ASSERT_TRUE(answer != NULL);
2137 ContentInfo* answer_content = answer->GetContentByName("audio");
2138 ASSERT_TRUE(answer_content != NULL);
2139
2140 ASSERT_TRUE(answer_content->rejected);
2141}
2142
2143// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2144// UDP/TLS/RTP/SAVPF.
2145TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2146 f1_.set_secure(SEC_ENABLED);
2147 f2_.set_secure(SEC_ENABLED);
2148 tdf1_.set_secure(SEC_ENABLED);
2149 tdf2_.set_secure(SEC_ENABLED);
2150
kwiberg31022942016-03-11 14:18:21 -08002151 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002152 f1_.CreateOffer(MediaSessionOptions(), NULL));
2153 ASSERT_TRUE(offer.get() != NULL);
2154 ContentInfo* offer_content = offer->GetContentByName("audio");
2155 ASSERT_TRUE(offer_content != NULL);
2156 AudioContentDescription* offer_audio_desc =
2157 static_cast<AudioContentDescription*>(offer_content->description);
2158 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2159
kwiberg31022942016-03-11 14:18:21 -08002160 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002161 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2162 ASSERT_TRUE(answer != NULL);
2163
2164 const ContentInfo* answer_content = answer->GetContentByName("audio");
2165 ASSERT_TRUE(answer_content != NULL);
2166 ASSERT_FALSE(answer_content->rejected);
2167
2168 const AudioContentDescription* answer_audio_desc =
2169 static_cast<const AudioContentDescription*>(answer_content->description);
2170 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2171 answer_audio_desc->protocol());
2172}
2173
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002174// Test that we include both SDES and DTLS in the offer, but only include SDES
2175// in the answer if DTLS isn't negotiated.
2176TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2177 f1_.set_secure(SEC_ENABLED);
2178 f2_.set_secure(SEC_ENABLED);
2179 tdf1_.set_secure(SEC_ENABLED);
2180 tdf2_.set_secure(SEC_DISABLED);
2181 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002182 options.recv_audio = true;
2183 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002184 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002185 const cricket::MediaContentDescription* audio_media_desc;
2186 const cricket::MediaContentDescription* video_media_desc;
2187 const cricket::TransportDescription* audio_trans_desc;
2188 const cricket::TransportDescription* video_trans_desc;
2189
2190 // Generate an offer with SDES and DTLS support.
2191 offer.reset(f1_.CreateOffer(options, NULL));
2192 ASSERT_TRUE(offer.get() != NULL);
2193
2194 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2195 offer->GetContentDescriptionByName("audio"));
2196 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002197 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002198 offer->GetContentDescriptionByName("video"));
2199 ASSERT_TRUE(video_media_desc != NULL);
2200 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2201 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2202
2203 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2204 ASSERT_TRUE(audio_trans_desc != NULL);
2205 video_trans_desc = offer->GetTransportDescriptionByName("video");
2206 ASSERT_TRUE(video_trans_desc != NULL);
2207 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2208 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2209
2210 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2211 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2212 ASSERT_TRUE(answer.get() != NULL);
2213
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002214 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002215 answer->GetContentDescriptionByName("audio"));
2216 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002217 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002218 answer->GetContentDescriptionByName("video"));
2219 ASSERT_TRUE(video_media_desc != NULL);
2220 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2221 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2222
2223 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2224 ASSERT_TRUE(audio_trans_desc != NULL);
2225 video_trans_desc = answer->GetTransportDescriptionByName("video");
2226 ASSERT_TRUE(video_trans_desc != NULL);
2227 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2228 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2229
2230 // Enable DTLS; the answer should now only have DTLS support.
2231 tdf2_.set_secure(SEC_ENABLED);
2232 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2233 ASSERT_TRUE(answer.get() != NULL);
2234
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002235 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002236 answer->GetContentDescriptionByName("audio"));
2237 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002238 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239 answer->GetContentDescriptionByName("video"));
2240 ASSERT_TRUE(video_media_desc != NULL);
2241 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2242 EXPECT_TRUE(video_media_desc->cryptos().empty());
2243 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2244 audio_media_desc->protocol());
2245 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2246 video_media_desc->protocol());
2247
2248 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2249 ASSERT_TRUE(audio_trans_desc != NULL);
2250 video_trans_desc = answer->GetTransportDescriptionByName("video");
2251 ASSERT_TRUE(video_trans_desc != NULL);
2252 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2253 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002254
2255 // Try creating offer again. DTLS enabled now, crypto's should be empty
2256 // in new offer.
2257 offer.reset(f1_.CreateOffer(options, offer.get()));
2258 ASSERT_TRUE(offer.get() != NULL);
2259 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2260 offer->GetContentDescriptionByName("audio"));
2261 ASSERT_TRUE(audio_media_desc != NULL);
2262 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2263 offer->GetContentDescriptionByName("video"));
2264 ASSERT_TRUE(video_media_desc != NULL);
2265 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2266 EXPECT_TRUE(video_media_desc->cryptos().empty());
2267
2268 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2269 ASSERT_TRUE(audio_trans_desc != NULL);
2270 video_trans_desc = offer->GetTransportDescriptionByName("video");
2271 ASSERT_TRUE(video_trans_desc != NULL);
2272 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2273 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002274}
2275
2276// Test that an answer can't be created if cryptos are required but the offer is
2277// unsecure.
2278TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2279 MediaSessionOptions options;
2280 f1_.set_secure(SEC_DISABLED);
2281 tdf1_.set_secure(SEC_DISABLED);
2282 f2_.set_secure(SEC_REQUIRED);
2283 tdf1_.set_secure(SEC_ENABLED);
2284
kwiberg31022942016-03-11 14:18:21 -08002285 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002286 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002287 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002288 f2_.CreateAnswer(offer.get(), options, NULL));
2289 EXPECT_TRUE(answer.get() == NULL);
2290}
2291
2292// Test that we accept a DTLS offer without SDES and create an appropriate
2293// answer.
2294TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2295 f1_.set_secure(SEC_DISABLED);
2296 f2_.set_secure(SEC_ENABLED);
2297 tdf1_.set_secure(SEC_ENABLED);
2298 tdf2_.set_secure(SEC_ENABLED);
2299 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002300 options.recv_audio = true;
2301 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002302 options.data_channel_type = cricket::DCT_RTP;
2303
kwiberg31022942016-03-11 14:18:21 -08002304 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002305
2306 // Generate an offer with DTLS but without SDES.
2307 offer.reset(f1_.CreateOffer(options, NULL));
2308 ASSERT_TRUE(offer.get() != NULL);
2309
2310 const AudioContentDescription* audio_offer =
2311 GetFirstAudioContentDescription(offer.get());
2312 ASSERT_TRUE(audio_offer->cryptos().empty());
2313 const VideoContentDescription* video_offer =
2314 GetFirstVideoContentDescription(offer.get());
2315 ASSERT_TRUE(video_offer->cryptos().empty());
2316 const DataContentDescription* data_offer =
2317 GetFirstDataContentDescription(offer.get());
2318 ASSERT_TRUE(data_offer->cryptos().empty());
2319
2320 const cricket::TransportDescription* audio_offer_trans_desc =
2321 offer->GetTransportDescriptionByName("audio");
2322 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2323 const cricket::TransportDescription* video_offer_trans_desc =
2324 offer->GetTransportDescriptionByName("video");
2325 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2326 const cricket::TransportDescription* data_offer_trans_desc =
2327 offer->GetTransportDescriptionByName("data");
2328 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2329
2330 // Generate an answer with DTLS.
2331 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2332 ASSERT_TRUE(answer.get() != NULL);
2333
2334 const cricket::TransportDescription* audio_answer_trans_desc =
2335 answer->GetTransportDescriptionByName("audio");
2336 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2337 const cricket::TransportDescription* video_answer_trans_desc =
2338 answer->GetTransportDescriptionByName("video");
2339 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2340 const cricket::TransportDescription* data_answer_trans_desc =
2341 answer->GetTransportDescriptionByName("data");
2342 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2343}
2344
2345// Verifies if vad_enabled option is set to false, CN codecs are not present in
2346// offer or answer.
2347TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2348 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002349 options.recv_audio = true;
2350 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002351 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002352 ASSERT_TRUE(offer.get() != NULL);
2353 const ContentInfo* audio_content = offer->GetContentByName("audio");
2354 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2355
2356 options.vad_enabled = false;
2357 offer.reset(f1_.CreateOffer(options, NULL));
2358 ASSERT_TRUE(offer.get() != NULL);
2359 audio_content = offer->GetContentByName("audio");
2360 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002361 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002362 f1_.CreateAnswer(offer.get(), options, NULL));
2363 ASSERT_TRUE(answer.get() != NULL);
2364 audio_content = answer->GetContentByName("audio");
2365 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2366}
deadbeef44f08192015-12-15 16:20:09 -08002367
2368// Test that the content name ("mid" in SDP) is unchanged when creating a
2369// new offer.
2370TEST_F(MediaSessionDescriptionFactoryTest,
2371 TestContentNameNotChangedInSubsequentOffers) {
2372 MediaSessionOptions opts;
2373 opts.recv_audio = true;
2374 opts.recv_video = true;
2375 opts.data_channel_type = cricket::DCT_SCTP;
2376 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002377 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002378 for (ContentInfo& content : offer->contents()) {
2379 content.name.append("_modified");
2380 }
2381
kwiberg31022942016-03-11 14:18:21 -08002382 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002383 f1_.CreateOffer(opts, offer.get()));
2384 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2385 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2386 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2387 ASSERT_TRUE(audio_content != nullptr);
2388 ASSERT_TRUE(video_content != nullptr);
2389 ASSERT_TRUE(data_content != nullptr);
2390 EXPECT_EQ("audio_modified", audio_content->name);
2391 EXPECT_EQ("video_modified", video_content->name);
2392 EXPECT_EQ("data_modified", data_content->name);
2393}
zhihuangcf5b37c2016-05-05 11:44:35 -07002394
2395class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2396 public:
2397 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
2398 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
2399 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2400 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
2401 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
2402 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2403 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2404 f1_.set_secure(SEC_ENABLED);
2405 f2_.set_secure(SEC_ENABLED);
2406 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002407 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002408 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002409 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002410 tdf1_.set_secure(SEC_ENABLED);
2411 tdf2_.set_secure(SEC_ENABLED);
2412 }
2413
2414 protected:
2415 MediaSessionDescriptionFactory f1_;
2416 MediaSessionDescriptionFactory f2_;
2417 TransportDescriptionFactory tdf1_;
2418 TransportDescriptionFactory tdf2_;
2419};
2420
2421TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2422 MediaSessionOptions opts;
2423 opts.recv_video = true;
2424 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2425 ASSERT_TRUE(offer.get() != nullptr);
2426 // Set the protocol for all the contents.
2427 for (auto content : offer.get()->contents()) {
2428 static_cast<MediaContentDescription*>(content.description)
2429 ->set_protocol(GetParam());
2430 }
2431 std::unique_ptr<SessionDescription> answer(
2432 f2_.CreateAnswer(offer.get(), opts, nullptr));
2433 const ContentInfo* ac = answer->GetContentByName("audio");
2434 const ContentInfo* vc = answer->GetContentByName("video");
2435 ASSERT_TRUE(ac != nullptr);
2436 ASSERT_TRUE(vc != nullptr);
2437 EXPECT_FALSE(ac->rejected); // the offer is accepted
2438 EXPECT_FALSE(vc->rejected);
2439 const AudioContentDescription* acd =
2440 static_cast<const AudioContentDescription*>(ac->description);
2441 const VideoContentDescription* vcd =
2442 static_cast<const VideoContentDescription*>(vc->description);
2443 EXPECT_EQ(GetParam(), acd->protocol());
2444 EXPECT_EQ(GetParam(), vcd->protocol());
2445}
2446
2447INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2448 MediaProtocolTest,
2449 ::testing::ValuesIn(kMediaProtocols));
2450INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2451 MediaProtocolTest,
2452 ::testing::ValuesIn(kMediaProtocolsDtls));