blob: 4c3eb4f01e71a433b52451dd2af477127759c065 [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
zhihuangb7f425a2016-04-12 18:32:30 -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(
kwiberg0eb15ed2015-12-17 03:04:15 -0800221 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200222 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwiberg0eb15ed2015-12-17 03:04:15 -0800223 rtc::scoped_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);
419 ContentInfo* ac_offer= offer->GetContentByName("audio");
420 ASSERT_TRUE(ac_offer != NULL);
421 AudioContentDescription* acd_offer =
422 static_cast<AudioContentDescription*>(ac_offer->description);
423 acd_offer->set_direction(direction_in_offer);
424 ContentInfo* vc_offer= offer->GetContentByName("video");
425 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));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000898 ContentInfo* dc_offer= offer->GetContentByName("data");
899 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);
1315 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1316
1317 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1318 ASSERT_EQ(2U, updated_data_streams.size());
1319 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1320 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1321 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1322 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1323 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1324}
1325
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001326// Create an offer with simulcast video stream.
1327TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1328 MediaSessionOptions opts;
1329 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001330 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001331 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001332
1333 ASSERT_TRUE(offer.get() != NULL);
1334 const ContentInfo* vc = offer->GetContentByName("video");
1335 ASSERT_TRUE(vc != NULL);
1336 const VideoContentDescription* vcd =
1337 static_cast<const VideoContentDescription*>(vc->description);
1338
1339 const StreamParamsVec& video_streams = vcd->streams();
1340 ASSERT_EQ(1U, video_streams.size());
1341 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1342 const SsrcGroup* sim_ssrc_group =
1343 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1344 ASSERT_TRUE(sim_ssrc_group != NULL);
1345 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1346}
1347
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348// Create an audio and video answer to a standard video offer with:
1349// - one video track
1350// - two audio tracks
1351// - two data tracks
1352// and ensure it matches what we expect. Also updates the initial answer by
1353// adding a new video track and removes one of the audio tracks.
1354TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1355 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001356 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001357 offer_opts.data_channel_type = cricket::DCT_RTP;
1358 f1_.set_secure(SEC_ENABLED);
1359 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001360 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001361
1362 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001363 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1364 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1365 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001366 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001367 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1368 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001369
kwiberg31022942016-03-11 14:18:21 -08001370 std::unique_ptr<SessionDescription> answer(
1371 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001372
1373 ASSERT_TRUE(answer.get() != NULL);
1374 const ContentInfo* ac = answer->GetContentByName("audio");
1375 const ContentInfo* vc = answer->GetContentByName("video");
1376 const ContentInfo* dc = answer->GetContentByName("data");
1377 ASSERT_TRUE(ac != NULL);
1378 ASSERT_TRUE(vc != NULL);
1379 ASSERT_TRUE(dc != NULL);
1380 const AudioContentDescription* acd =
1381 static_cast<const AudioContentDescription*>(ac->description);
1382 const VideoContentDescription* vcd =
1383 static_cast<const VideoContentDescription*>(vc->description);
1384 const DataContentDescription* dcd =
1385 static_cast<const DataContentDescription*>(dc->description);
1386 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1387 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1388 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1389
1390 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1391 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1392
1393 const StreamParamsVec& audio_streams = acd->streams();
1394 ASSERT_EQ(2U, audio_streams.size());
1395 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1396 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1397 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1398 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1399 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1400 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1401 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1402
1403 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1404 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1405
1406 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1407 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1408
1409 const StreamParamsVec& video_streams = vcd->streams();
1410 ASSERT_EQ(1U, video_streams.size());
1411 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1412 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1413 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1414 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1415
1416 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1417 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1418
1419 const StreamParamsVec& data_streams = dcd->streams();
1420 ASSERT_EQ(2U, data_streams.size());
1421 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1422 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1423 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1424 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1425 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1426 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1427 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1428
1429 EXPECT_EQ(cricket::kDataMaxBandwidth,
1430 dcd->bandwidth()); // default bandwidth (auto)
1431 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1432
1433 // Update the answer. Add a new video track that is not synched to the
1434 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001435 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1436 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1437 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001438 std::unique_ptr<SessionDescription> updated_answer(
1439 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001440
1441 ASSERT_TRUE(updated_answer.get() != NULL);
1442 ac = updated_answer->GetContentByName("audio");
1443 vc = updated_answer->GetContentByName("video");
1444 dc = updated_answer->GetContentByName("data");
1445 ASSERT_TRUE(ac != NULL);
1446 ASSERT_TRUE(vc != NULL);
1447 ASSERT_TRUE(dc != NULL);
1448 const AudioContentDescription* updated_acd =
1449 static_cast<const AudioContentDescription*>(ac->description);
1450 const VideoContentDescription* updated_vcd =
1451 static_cast<const VideoContentDescription*>(vc->description);
1452 const DataContentDescription* updated_dcd =
1453 static_cast<const DataContentDescription*>(dc->description);
1454
1455 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1456 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1457 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1458 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1459 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1460 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1461
1462 EXPECT_EQ(acd->type(), updated_acd->type());
1463 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1464 EXPECT_EQ(vcd->type(), updated_vcd->type());
1465 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1466 EXPECT_EQ(dcd->type(), updated_dcd->type());
1467 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1468
1469 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1470 ASSERT_EQ(1U, updated_audio_streams.size());
1471 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1472
1473 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1474 ASSERT_EQ(2U, updated_video_streams.size());
1475 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1476 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1477 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1478
1479 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1480 ASSERT_EQ(1U, updated_data_streams.size());
1481 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1482}
1483
1484
1485// Create an updated offer after creating an answer to the original offer and
1486// verify that the codecs that were part of the original answer are not changed
1487// in the updated offer.
1488TEST_F(MediaSessionDescriptionFactoryTest,
1489 RespondentCreatesOfferAfterCreatingAnswer) {
1490 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001491 opts.recv_audio = true;
1492 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001493
kwiberg31022942016-03-11 14:18:21 -08001494 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1495 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001496 f2_.CreateAnswer(offer.get(), opts, NULL));
1497
1498 const AudioContentDescription* acd =
1499 GetFirstAudioContentDescription(answer.get());
1500 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1501
1502 const VideoContentDescription* vcd =
1503 GetFirstVideoContentDescription(answer.get());
1504 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1505
kwiberg31022942016-03-11 14:18:21 -08001506 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001507 f2_.CreateOffer(opts, answer.get()));
1508
1509 // The expected audio codecs are the common audio codecs from the first
1510 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1511 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001512 // TODO(wu): |updated_offer| should not include the codec
1513 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001514 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001515 kAudioCodecsAnswer[0],
1516 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001517 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518 };
1519
1520 // The expected video codecs are the common video codecs from the first
1521 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1522 // preference order.
1523 const VideoCodec kUpdatedVideoCodecOffer[] = {
1524 kVideoCodecsAnswer[0],
1525 kVideoCodecs2[1],
1526 };
1527
1528 const AudioContentDescription* updated_acd =
1529 GetFirstAudioContentDescription(updated_offer.get());
1530 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1531
1532 const VideoContentDescription* updated_vcd =
1533 GetFirstVideoContentDescription(updated_offer.get());
1534 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1535}
1536
1537// Create an updated offer after creating an answer to the original offer and
1538// verify that the codecs that were part of the original answer are not changed
1539// in the updated offer. In this test Rtx is enabled.
1540TEST_F(MediaSessionDescriptionFactoryTest,
1541 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1542 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001543 opts.recv_video = true;
1544 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001545 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001546 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001547 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001548 f1_.set_video_codecs(f1_codecs);
1549
1550 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001551 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001552 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001553 f2_.set_video_codecs(f2_codecs);
1554
kwiberg31022942016-03-11 14:18:21 -08001555 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001556 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001557 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001558 f2_.CreateAnswer(offer.get(), opts, NULL));
1559
1560 const VideoContentDescription* vcd =
1561 GetFirstVideoContentDescription(answer.get());
1562
1563 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001564 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1565 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566
1567 EXPECT_EQ(expected_codecs, vcd->codecs());
1568
deadbeef67cf2c12016-04-13 10:07:16 -07001569 // Now, make sure we get same result (except for the order) if |f2_| creates
1570 // an updated offer even though the default payload types between |f1_| and
1571 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001572 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001573 f2_.CreateOffer(opts, answer.get()));
1574 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001575 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1577
1578 const VideoContentDescription* updated_vcd =
1579 GetFirstVideoContentDescription(updated_answer.get());
1580
1581 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1582}
1583
1584// Create an updated offer that adds video after creating an audio only answer
1585// to the original offer. This test verifies that if a video codec and the RTX
1586// codec have the same default payload type as an audio codec that is already in
1587// use, the added codecs payload types are changed.
1588TEST_F(MediaSessionDescriptionFactoryTest,
1589 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1590 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001591 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001592 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001593 f1_.set_video_codecs(f1_codecs);
1594
1595 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001596 opts.recv_audio = true;
1597 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001598
kwiberg31022942016-03-11 14:18:21 -08001599 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1600 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001601 f2_.CreateAnswer(offer.get(), opts, NULL));
1602
1603 const AudioContentDescription* acd =
1604 GetFirstAudioContentDescription(answer.get());
1605 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1606
1607 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1608 // reference be the same as an audio codec that was negotiated in the
1609 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001610 opts.recv_audio = true;
1611 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001612
1613 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1614 int used_pl_type = acd->codecs()[0].id;
1615 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001616 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001617 f2_.set_video_codecs(f2_codecs);
1618
kwiberg31022942016-03-11 14:18:21 -08001619 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001620 f2_.CreateOffer(opts, answer.get()));
1621 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001622 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001623 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1624
1625 const AudioContentDescription* updated_acd =
1626 GetFirstAudioContentDescription(answer.get());
1627 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1628
1629 const VideoContentDescription* updated_vcd =
1630 GetFirstVideoContentDescription(updated_answer.get());
1631
1632 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001633 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1635 EXPECT_NE(used_pl_type, new_h264_pl_type);
1636 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001637 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001638 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1639 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1640}
1641
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001642// Create an updated offer with RTX after creating an answer to an offer
1643// without RTX, and with different default payload types.
1644// Verify that the added RTX codec references the correct payload type.
1645TEST_F(MediaSessionDescriptionFactoryTest,
1646 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1647 MediaSessionOptions opts;
1648 opts.recv_video = true;
1649 opts.recv_audio = true;
1650
1651 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1652 // This creates rtx for H264 with the payload type |f2_| uses.
1653 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1654 f2_.set_video_codecs(f2_codecs);
1655
kwiberg31022942016-03-11 14:18:21 -08001656 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001657 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001658 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001659 f2_.CreateAnswer(offer.get(), opts, nullptr));
1660
1661 const VideoContentDescription* vcd =
1662 GetFirstVideoContentDescription(answer.get());
1663
1664 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1665 EXPECT_EQ(expected_codecs, vcd->codecs());
1666
1667 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1668 // updated offer, even though the default payload types are different from
1669 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001670 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001671 f2_.CreateOffer(opts, answer.get()));
1672 ASSERT_TRUE(updated_offer);
1673
1674 const VideoContentDescription* updated_vcd =
1675 GetFirstVideoContentDescription(updated_offer.get());
1676
1677 // New offer should attempt to add H263, and RTX for H264.
1678 expected_codecs.push_back(kVideoCodecs2[1]);
1679 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1680 &expected_codecs);
1681 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1682}
1683
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001684// Test that RTX is ignored when there is no associated payload type parameter.
1685TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1686 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001687 opts.recv_video = true;
1688 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001689 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001690 // This creates RTX without associated payload type parameter.
deadbeef67cf2c12016-04-13 10:07:16 -07001691 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001692 f1_.set_video_codecs(f1_codecs);
1693
1694 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001695 // This creates RTX for H264 with the payload type |f2_| uses.
1696 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697 f2_.set_video_codecs(f2_codecs);
1698
kwiberg31022942016-03-11 14:18:21 -08001699 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001700 ASSERT_TRUE(offer.get() != NULL);
1701 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1702 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1703 // is possible to test that that RTX is dropped when
1704 // kCodecParamAssociatedPayloadType is missing in the offer.
1705 VideoContentDescription* desc =
1706 static_cast<cricket::VideoContentDescription*>(
1707 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1708 ASSERT_TRUE(desc != NULL);
1709 std::vector<VideoCodec> codecs = desc->codecs();
1710 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1711 iter != codecs.end(); ++iter) {
1712 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1713 iter->params.clear();
1714 }
1715 }
1716 desc->set_codecs(codecs);
1717
kwiberg31022942016-03-11 14:18:21 -08001718 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001719 f2_.CreateAnswer(offer.get(), opts, NULL));
1720
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001721 std::vector<std::string> codec_names =
1722 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1723 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1724 cricket::kRtxCodecName));
1725}
1726
1727// Test that RTX will be filtered out in the answer if its associated payload
1728// type doesn't match the local value.
1729TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1730 MediaSessionOptions opts;
1731 opts.recv_video = true;
1732 opts.recv_audio = false;
1733 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1734 // This creates RTX for H264 in sender.
1735 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1736 f1_.set_video_codecs(f1_codecs);
1737
1738 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1739 // This creates RTX for H263 in receiver.
1740 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1741 f2_.set_video_codecs(f2_codecs);
1742
kwiberg31022942016-03-11 14:18:21 -08001743 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001744 ASSERT_TRUE(offer.get() != NULL);
1745 // Associated payload type doesn't match, therefore, RTX codec is removed in
1746 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001747 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001748 f2_.CreateAnswer(offer.get(), opts, NULL));
1749
1750 std::vector<std::string> codec_names =
1751 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1752 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1753 cricket::kRtxCodecName));
1754}
1755
1756// Test that when multiple RTX codecs are offered, only the matched RTX codec
1757// is added in the answer, and the unsupported RTX codec is filtered out.
1758TEST_F(MediaSessionDescriptionFactoryTest,
1759 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1760 MediaSessionOptions opts;
1761 opts.recv_video = true;
1762 opts.recv_audio = false;
1763 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1764 // This creates RTX for H264-SVC in sender.
1765 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1766 f1_.set_video_codecs(f1_codecs);
1767
1768 // This creates RTX for H264 in sender.
1769 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1770 f1_.set_video_codecs(f1_codecs);
1771
1772 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1773 // This creates RTX for H264 in receiver.
1774 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1775 f2_.set_video_codecs(f2_codecs);
1776
1777 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1778 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001779 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001780 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001781 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001782 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783 const VideoContentDescription* vcd =
1784 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001785 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1786 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1787 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001788
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001789 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001790}
1791
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001792// Test that after one RTX codec has been negotiated, a new offer can attempt
1793// to add another.
1794TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1795 MediaSessionOptions opts;
1796 opts.recv_video = true;
1797 opts.recv_audio = false;
1798 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1799 // This creates RTX for H264 for the offerer.
1800 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1801 f1_.set_video_codecs(f1_codecs);
1802
kwiberg31022942016-03-11 14:18:21 -08001803 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001804 ASSERT_TRUE(offer);
1805 const VideoContentDescription* vcd =
1806 GetFirstVideoContentDescription(offer.get());
1807
1808 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1809 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1810 &expected_codecs);
1811 EXPECT_EQ(expected_codecs, vcd->codecs());
1812
1813 // Now, attempt to add RTX for H264-SVC.
1814 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1815 f1_.set_video_codecs(f1_codecs);
1816
kwiberg31022942016-03-11 14:18:21 -08001817 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001818 f1_.CreateOffer(opts, offer.get()));
1819 ASSERT_TRUE(updated_offer);
1820 vcd = GetFirstVideoContentDescription(updated_offer.get());
1821
1822 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1823 &expected_codecs);
1824 EXPECT_EQ(expected_codecs, vcd->codecs());
1825}
1826
Noah Richards2e7a0982015-05-18 14:02:54 -07001827// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1828// generated for each simulcast ssrc and correctly grouped.
1829TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1830 MediaSessionOptions opts;
1831 opts.recv_video = true;
1832 opts.recv_audio = false;
1833
1834 // Add simulcast streams.
1835 opts.AddSendVideoStream("stream1", "stream1label", 3);
1836
1837 // Use a single real codec, and then add RTX for it.
1838 std::vector<VideoCodec> f1_codecs;
deadbeef67cf2c12016-04-13 10:07:16 -07001839 f1_codecs.push_back(VideoCodec(97, "H264", 320, 200, 30));
Noah Richards2e7a0982015-05-18 14:02:54 -07001840 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1841 f1_.set_video_codecs(f1_codecs);
1842
1843 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1844 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001845 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001846 ASSERT_TRUE(offer.get() != NULL);
1847 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1848 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1849 ASSERT_TRUE(desc != NULL);
1850 EXPECT_TRUE(desc->multistream());
1851 const StreamParamsVec& streams = desc->streams();
1852 // Single stream.
1853 ASSERT_EQ(1u, streams.size());
1854 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
1855 EXPECT_EQ(6u, streams[0].ssrcs.size());
1856 // And should have a SIM group for the simulcast.
1857 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
1858 // And a FID group for RTX.
1859 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02001860 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001861 streams[0].GetPrimarySsrcs(&primary_ssrcs);
1862 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02001863 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07001864 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
1865 EXPECT_EQ(3u, fid_ssrcs.size());
1866}
1867
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868// Create an updated offer after creating an answer to the original offer and
1869// verify that the RTP header extensions that were part of the original answer
1870// are not changed in the updated offer.
1871TEST_F(MediaSessionDescriptionFactoryTest,
1872 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1873 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001874 opts.recv_audio = true;
1875 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001876
1877 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1878 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1879 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1880 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1881
kwiberg31022942016-03-11 14:18:21 -08001882 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1883 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001884 f2_.CreateAnswer(offer.get(), opts, NULL));
1885
1886 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1887 GetFirstAudioContentDescription(
1888 answer.get())->rtp_header_extensions());
1889 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1890 GetFirstVideoContentDescription(
1891 answer.get())->rtp_header_extensions());
1892
kwiberg31022942016-03-11 14:18:21 -08001893 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001894 f2_.CreateOffer(opts, answer.get()));
1895
1896 // The expected RTP header extensions in the new offer are the resulting
1897 // extensions from the first offer/answer exchange plus the extensions only
1898 // |f2_| offer.
1899 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001900 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001901 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1902 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001903 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1904 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001905 };
1906
1907 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001908 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001909 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1910 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001911 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1912 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001913 };
1914
1915 const AudioContentDescription* updated_acd =
1916 GetFirstAudioContentDescription(updated_offer.get());
1917 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1918 updated_acd->rtp_header_extensions());
1919
1920 const VideoContentDescription* updated_vcd =
1921 GetFirstVideoContentDescription(updated_offer.get());
1922 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1923 updated_vcd->rtp_header_extensions());
1924}
1925
deadbeefa5b273a2015-08-20 17:30:13 -07001926// Verify that if the same RTP extension URI is used for audio and video, the
1927// same ID is used. Also verify that the ID isn't changed when creating an
1928// updated offer (this was previously a bug).
1929TEST_F(MediaSessionDescriptionFactoryTest,
1930 RtpHeaderExtensionIdReused) {
1931 MediaSessionOptions opts;
1932 opts.recv_audio = true;
1933 opts.recv_video = true;
1934
1935 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
1936 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
1937
kwiberg31022942016-03-11 14:18:21 -08001938 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07001939
1940 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
1941 // the video extensions.
1942 const RtpHeaderExtension kExpectedVideoRtpExtension[] = {
1943 kVideoRtpExtension3[0],
1944 kAudioRtpExtension3[1],
1945 };
1946
1947 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1948 GetFirstAudioContentDescription(
1949 offer.get())->rtp_header_extensions());
1950 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1951 GetFirstVideoContentDescription(
1952 offer.get())->rtp_header_extensions());
1953
1954 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08001955 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07001956 f1_.CreateOffer(opts, offer.get()));
1957
1958 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
1959 GetFirstAudioContentDescription(
1960 updated_offer.get())->rtp_header_extensions());
1961 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
1962 GetFirstVideoContentDescription(
1963 updated_offer.get())->rtp_header_extensions());
1964}
1965
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001966TEST(MediaSessionDescription, CopySessionDescription) {
1967 SessionDescription source;
1968 cricket::ContentGroup group(cricket::CN_AUDIO);
1969 source.AddGroup(group);
1970 AudioContentDescription* acd(new AudioContentDescription());
1971 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1972 acd->AddLegacyStream(1);
1973 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1974 VideoContentDescription* vcd(new VideoContentDescription());
1975 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1976 vcd->AddLegacyStream(2);
1977 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1978
kwiberg31022942016-03-11 14:18:21 -08001979 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001980 ASSERT_TRUE(copy.get() != NULL);
1981 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1982 const ContentInfo* ac = copy->GetContentByName("audio");
1983 const ContentInfo* vc = copy->GetContentByName("video");
1984 ASSERT_TRUE(ac != NULL);
1985 ASSERT_TRUE(vc != NULL);
1986 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1987 const AudioContentDescription* acd_copy =
1988 static_cast<const AudioContentDescription*>(ac->description);
1989 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1990 EXPECT_EQ(1u, acd->first_ssrc());
1991
1992 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1993 const VideoContentDescription* vcd_copy =
1994 static_cast<const VideoContentDescription*>(vc->description);
1995 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1996 EXPECT_EQ(2u, vcd->first_ssrc());
1997}
1998
1999// The below TestTransportInfoXXX tests create different offers/answers, and
2000// ensure the TransportInfo in the SessionDescription matches what we expect.
2001TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2002 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002003 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002004 TestTransportInfo(true, options, false);
2005}
2006
2007TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
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, true);
2011}
2012
2013TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2014 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002015 options.recv_audio = true;
2016 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002017 options.data_channel_type = cricket::DCT_RTP;
2018 TestTransportInfo(true, options, false);
2019}
2020
2021TEST_F(MediaSessionDescriptionFactoryTest,
2022 TestTransportInfoOfferMultimediaCurrent) {
2023 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002024 options.recv_audio = true;
2025 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002026 options.data_channel_type = cricket::DCT_RTP;
2027 TestTransportInfo(true, options, true);
2028}
2029
2030TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2031 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002032 options.recv_audio = true;
2033 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002034 options.data_channel_type = cricket::DCT_RTP;
2035 options.bundle_enabled = true;
2036 TestTransportInfo(true, options, false);
2037}
2038
2039TEST_F(MediaSessionDescriptionFactoryTest,
2040 TestTransportInfoOfferBundleCurrent) {
2041 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002042 options.recv_audio = true;
2043 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002044 options.data_channel_type = cricket::DCT_RTP;
2045 options.bundle_enabled = true;
2046 TestTransportInfo(true, options, true);
2047}
2048
2049TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2050 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002051 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002052 TestTransportInfo(false, options, false);
2053}
2054
2055TEST_F(MediaSessionDescriptionFactoryTest,
2056 TestTransportInfoAnswerAudioCurrent) {
2057 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002058 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002059 TestTransportInfo(false, options, true);
2060}
2061
2062TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2063 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002064 options.recv_audio = true;
2065 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002066 options.data_channel_type = cricket::DCT_RTP;
2067 TestTransportInfo(false, options, false);
2068}
2069
2070TEST_F(MediaSessionDescriptionFactoryTest,
2071 TestTransportInfoAnswerMultimediaCurrent) {
2072 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002073 options.recv_audio = true;
2074 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002075 options.data_channel_type = cricket::DCT_RTP;
2076 TestTransportInfo(false, options, true);
2077}
2078
2079TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2080 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002081 options.recv_audio = true;
2082 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002083 options.data_channel_type = cricket::DCT_RTP;
2084 options.bundle_enabled = true;
2085 TestTransportInfo(false, options, false);
2086}
2087
2088TEST_F(MediaSessionDescriptionFactoryTest,
2089 TestTransportInfoAnswerBundleCurrent) {
2090 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002091 options.recv_audio = true;
2092 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002093 options.data_channel_type = cricket::DCT_RTP;
2094 options.bundle_enabled = true;
2095 TestTransportInfo(false, options, true);
2096}
2097
2098// Create an offer with bundle enabled and verify the crypto parameters are
2099// the common set of the available cryptos.
2100TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2101 TestCryptoWithBundle(true);
2102}
2103
2104// Create an answer with bundle enabled and verify the crypto parameters are
2105// the common set of the available cryptos.
2106TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2107 TestCryptoWithBundle(false);
2108}
2109
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002110// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2111// DTLS is not enabled locally.
2112TEST_F(MediaSessionDescriptionFactoryTest,
2113 TestOfferDtlsSavpfWithoutDtlsFailed) {
2114 f1_.set_secure(SEC_ENABLED);
2115 f2_.set_secure(SEC_ENABLED);
2116 tdf1_.set_secure(SEC_DISABLED);
2117 tdf2_.set_secure(SEC_DISABLED);
2118
kwiberg31022942016-03-11 14:18:21 -08002119 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002120 f1_.CreateOffer(MediaSessionOptions(), NULL));
2121 ASSERT_TRUE(offer.get() != NULL);
2122 ContentInfo* offer_content = offer->GetContentByName("audio");
2123 ASSERT_TRUE(offer_content != NULL);
2124 AudioContentDescription* offer_audio_desc =
2125 static_cast<AudioContentDescription*>(offer_content->description);
2126 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2127
kwiberg31022942016-03-11 14:18:21 -08002128 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002129 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2130 ASSERT_TRUE(answer != NULL);
2131 ContentInfo* answer_content = answer->GetContentByName("audio");
2132 ASSERT_TRUE(answer_content != NULL);
2133
2134 ASSERT_TRUE(answer_content->rejected);
2135}
2136
2137// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2138// UDP/TLS/RTP/SAVPF.
2139TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2140 f1_.set_secure(SEC_ENABLED);
2141 f2_.set_secure(SEC_ENABLED);
2142 tdf1_.set_secure(SEC_ENABLED);
2143 tdf2_.set_secure(SEC_ENABLED);
2144
kwiberg31022942016-03-11 14:18:21 -08002145 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002146 f1_.CreateOffer(MediaSessionOptions(), NULL));
2147 ASSERT_TRUE(offer.get() != NULL);
2148 ContentInfo* offer_content = offer->GetContentByName("audio");
2149 ASSERT_TRUE(offer_content != NULL);
2150 AudioContentDescription* offer_audio_desc =
2151 static_cast<AudioContentDescription*>(offer_content->description);
2152 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2153
kwiberg31022942016-03-11 14:18:21 -08002154 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002155 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2156 ASSERT_TRUE(answer != NULL);
2157
2158 const ContentInfo* answer_content = answer->GetContentByName("audio");
2159 ASSERT_TRUE(answer_content != NULL);
2160 ASSERT_FALSE(answer_content->rejected);
2161
2162 const AudioContentDescription* answer_audio_desc =
2163 static_cast<const AudioContentDescription*>(answer_content->description);
2164 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2165 answer_audio_desc->protocol());
2166}
2167
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002168// Test that we include both SDES and DTLS in the offer, but only include SDES
2169// in the answer if DTLS isn't negotiated.
2170TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2171 f1_.set_secure(SEC_ENABLED);
2172 f2_.set_secure(SEC_ENABLED);
2173 tdf1_.set_secure(SEC_ENABLED);
2174 tdf2_.set_secure(SEC_DISABLED);
2175 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002176 options.recv_audio = true;
2177 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002178 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002179 const cricket::MediaContentDescription* audio_media_desc;
2180 const cricket::MediaContentDescription* video_media_desc;
2181 const cricket::TransportDescription* audio_trans_desc;
2182 const cricket::TransportDescription* video_trans_desc;
2183
2184 // Generate an offer with SDES and DTLS support.
2185 offer.reset(f1_.CreateOffer(options, NULL));
2186 ASSERT_TRUE(offer.get() != NULL);
2187
2188 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2189 offer->GetContentDescriptionByName("audio"));
2190 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002191 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002192 offer->GetContentDescriptionByName("video"));
2193 ASSERT_TRUE(video_media_desc != NULL);
2194 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2195 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2196
2197 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2198 ASSERT_TRUE(audio_trans_desc != NULL);
2199 video_trans_desc = offer->GetTransportDescriptionByName("video");
2200 ASSERT_TRUE(video_trans_desc != NULL);
2201 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2202 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2203
2204 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2205 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2206 ASSERT_TRUE(answer.get() != NULL);
2207
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002208 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002209 answer->GetContentDescriptionByName("audio"));
2210 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002211 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002212 answer->GetContentDescriptionByName("video"));
2213 ASSERT_TRUE(video_media_desc != NULL);
2214 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2215 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2216
2217 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2218 ASSERT_TRUE(audio_trans_desc != NULL);
2219 video_trans_desc = answer->GetTransportDescriptionByName("video");
2220 ASSERT_TRUE(video_trans_desc != NULL);
2221 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2222 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2223
2224 // Enable DTLS; the answer should now only have DTLS support.
2225 tdf2_.set_secure(SEC_ENABLED);
2226 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2227 ASSERT_TRUE(answer.get() != NULL);
2228
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002229 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002230 answer->GetContentDescriptionByName("audio"));
2231 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002232 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002233 answer->GetContentDescriptionByName("video"));
2234 ASSERT_TRUE(video_media_desc != NULL);
2235 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2236 EXPECT_TRUE(video_media_desc->cryptos().empty());
2237 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2238 audio_media_desc->protocol());
2239 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2240 video_media_desc->protocol());
2241
2242 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2243 ASSERT_TRUE(audio_trans_desc != NULL);
2244 video_trans_desc = answer->GetTransportDescriptionByName("video");
2245 ASSERT_TRUE(video_trans_desc != NULL);
2246 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2247 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002248
2249 // Try creating offer again. DTLS enabled now, crypto's should be empty
2250 // in new offer.
2251 offer.reset(f1_.CreateOffer(options, offer.get()));
2252 ASSERT_TRUE(offer.get() != NULL);
2253 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2254 offer->GetContentDescriptionByName("audio"));
2255 ASSERT_TRUE(audio_media_desc != NULL);
2256 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2257 offer->GetContentDescriptionByName("video"));
2258 ASSERT_TRUE(video_media_desc != NULL);
2259 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2260 EXPECT_TRUE(video_media_desc->cryptos().empty());
2261
2262 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2263 ASSERT_TRUE(audio_trans_desc != NULL);
2264 video_trans_desc = offer->GetTransportDescriptionByName("video");
2265 ASSERT_TRUE(video_trans_desc != NULL);
2266 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2267 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002268}
2269
2270// Test that an answer can't be created if cryptos are required but the offer is
2271// unsecure.
2272TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2273 MediaSessionOptions options;
2274 f1_.set_secure(SEC_DISABLED);
2275 tdf1_.set_secure(SEC_DISABLED);
2276 f2_.set_secure(SEC_REQUIRED);
2277 tdf1_.set_secure(SEC_ENABLED);
2278
kwiberg31022942016-03-11 14:18:21 -08002279 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002280 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002281 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002282 f2_.CreateAnswer(offer.get(), options, NULL));
2283 EXPECT_TRUE(answer.get() == NULL);
2284}
2285
2286// Test that we accept a DTLS offer without SDES and create an appropriate
2287// answer.
2288TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2289 f1_.set_secure(SEC_DISABLED);
2290 f2_.set_secure(SEC_ENABLED);
2291 tdf1_.set_secure(SEC_ENABLED);
2292 tdf2_.set_secure(SEC_ENABLED);
2293 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002294 options.recv_audio = true;
2295 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002296 options.data_channel_type = cricket::DCT_RTP;
2297
kwiberg31022942016-03-11 14:18:21 -08002298 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002299
2300 // Generate an offer with DTLS but without SDES.
2301 offer.reset(f1_.CreateOffer(options, NULL));
2302 ASSERT_TRUE(offer.get() != NULL);
2303
2304 const AudioContentDescription* audio_offer =
2305 GetFirstAudioContentDescription(offer.get());
2306 ASSERT_TRUE(audio_offer->cryptos().empty());
2307 const VideoContentDescription* video_offer =
2308 GetFirstVideoContentDescription(offer.get());
2309 ASSERT_TRUE(video_offer->cryptos().empty());
2310 const DataContentDescription* data_offer =
2311 GetFirstDataContentDescription(offer.get());
2312 ASSERT_TRUE(data_offer->cryptos().empty());
2313
2314 const cricket::TransportDescription* audio_offer_trans_desc =
2315 offer->GetTransportDescriptionByName("audio");
2316 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2317 const cricket::TransportDescription* video_offer_trans_desc =
2318 offer->GetTransportDescriptionByName("video");
2319 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2320 const cricket::TransportDescription* data_offer_trans_desc =
2321 offer->GetTransportDescriptionByName("data");
2322 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2323
2324 // Generate an answer with DTLS.
2325 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2326 ASSERT_TRUE(answer.get() != NULL);
2327
2328 const cricket::TransportDescription* audio_answer_trans_desc =
2329 answer->GetTransportDescriptionByName("audio");
2330 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2331 const cricket::TransportDescription* video_answer_trans_desc =
2332 answer->GetTransportDescriptionByName("video");
2333 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2334 const cricket::TransportDescription* data_answer_trans_desc =
2335 answer->GetTransportDescriptionByName("data");
2336 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2337}
2338
2339// Verifies if vad_enabled option is set to false, CN codecs are not present in
2340// offer or answer.
2341TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2342 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002343 options.recv_audio = true;
2344 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002345 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002346 ASSERT_TRUE(offer.get() != NULL);
2347 const ContentInfo* audio_content = offer->GetContentByName("audio");
2348 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2349
2350 options.vad_enabled = false;
2351 offer.reset(f1_.CreateOffer(options, NULL));
2352 ASSERT_TRUE(offer.get() != NULL);
2353 audio_content = offer->GetContentByName("audio");
2354 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002355 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002356 f1_.CreateAnswer(offer.get(), options, NULL));
2357 ASSERT_TRUE(answer.get() != NULL);
2358 audio_content = answer->GetContentByName("audio");
2359 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2360}
deadbeef44f08192015-12-15 16:20:09 -08002361
2362// Test that the content name ("mid" in SDP) is unchanged when creating a
2363// new offer.
2364TEST_F(MediaSessionDescriptionFactoryTest,
2365 TestContentNameNotChangedInSubsequentOffers) {
2366 MediaSessionOptions opts;
2367 opts.recv_audio = true;
2368 opts.recv_video = true;
2369 opts.data_channel_type = cricket::DCT_SCTP;
2370 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002371 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002372 for (ContentInfo& content : offer->contents()) {
2373 content.name.append("_modified");
2374 }
2375
kwiberg31022942016-03-11 14:18:21 -08002376 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002377 f1_.CreateOffer(opts, offer.get()));
2378 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2379 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2380 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2381 ASSERT_TRUE(audio_content != nullptr);
2382 ASSERT_TRUE(video_content != nullptr);
2383 ASSERT_TRUE(data_content != nullptr);
2384 EXPECT_EQ("audio_modified", audio_content->name);
2385 EXPECT_EQ("video_modified", video_content->name);
2386 EXPECT_EQ("data_modified", data_content->name);
2387}
zhihuangb7f425a2016-04-12 18:32:30 -07002388
2389class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2390 public:
2391 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
2392 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
2393 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2394 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
2395 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
2396 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2397 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2398 f1_.set_secure(SEC_ENABLED);
2399 f2_.set_secure(SEC_ENABLED);
2400 tdf1_.set_certificate(rtc::RTCCertificate::Create(
2401 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
2402 tdf2_.set_certificate(rtc::RTCCertificate::Create(
2403 rtc::scoped_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
2404 tdf1_.set_secure(SEC_ENABLED);
2405 tdf2_.set_secure(SEC_ENABLED);
2406 }
2407
2408 protected:
2409 MediaSessionDescriptionFactory f1_;
2410 MediaSessionDescriptionFactory f2_;
2411 TransportDescriptionFactory tdf1_;
2412 TransportDescriptionFactory tdf2_;
2413};
2414
2415TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2416 MediaSessionOptions opts;
2417 opts.recv_video = true;
2418 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2419 ASSERT_TRUE(offer.get() != nullptr);
2420 // Set the protocol for all the contents.
2421 for (auto content : offer.get()->contents()) {
2422 static_cast<MediaContentDescription*>(content.description)
2423 ->set_protocol(GetParam());
2424 }
2425 std::unique_ptr<SessionDescription> answer(
2426 f2_.CreateAnswer(offer.get(), opts, nullptr));
2427 const ContentInfo* ac = answer->GetContentByName("audio");
2428 const ContentInfo* vc = answer->GetContentByName("video");
2429 ASSERT_TRUE(ac != nullptr);
2430 ASSERT_TRUE(vc != nullptr);
2431 EXPECT_FALSE(ac->rejected); // the offer is accepted
2432 EXPECT_FALSE(vc->rejected);
2433 const AudioContentDescription* acd =
2434 static_cast<const AudioContentDescription*>(ac->description);
2435 const VideoContentDescription* vcd =
2436 static_cast<const VideoContentDescription*>(vc->description);
2437 EXPECT_EQ(GetParam(), acd->protocol());
2438 EXPECT_EQ(GetParam(), vcd->protocol());
2439}
2440
2441INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2442 MediaProtocolTest,
2443 ::testing::ValuesIn(kMediaProtocols));
2444INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2445 MediaProtocolTest,
2446 ::testing::ValuesIn(kMediaProtocolsDtls));