blob: 6676240b0c4e8b258e5098b1e996d4b5a1559ac9 [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
nissec8ee8822017-01-18 07:20:55 -080015#include "webrtc/base/checks.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000016#include "webrtc/base/fakesslidentity.h"
17#include "webrtc/base/gunit.h"
18#include "webrtc/base/messagedigest.h"
19#include "webrtc/base/ssladapter.h"
kjellandera96e2d72016-02-04 23:52:28 -080020#include "webrtc/media/base/codec.h"
21#include "webrtc/media/base/testutils.h"
kjellanderf4752772016-03-02 05:42:30 -080022#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080023#include "webrtc/p2p/base/transportdescription.h"
24#include "webrtc/p2p/base/transportinfo.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010025#include "webrtc/pc/mediasession.h"
26#include "webrtc/pc/srtpfilter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
28#ifdef HAVE_SRTP
29#define ASSERT_CRYPTO(cd, s, cs) \
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
deadbeef7af91dd2016-12-13 11:29:11 -080033#define ASSERT_CRYPTO(cd, s, cs) ASSERT_EQ(0, cd->cryptos().size());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034#endif
35
36typedef std::vector<cricket::Candidate> Candidates;
37
38using cricket::MediaContentDescription;
39using cricket::MediaSessionDescriptionFactory;
ossu075af922016-06-14 03:29:38 -070040using cricket::MediaContentDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000041using cricket::MediaSessionOptions;
42using cricket::MediaType;
43using cricket::SessionDescription;
44using cricket::SsrcGroup;
45using cricket::StreamParams;
46using cricket::StreamParamsVec;
47using cricket::TransportDescription;
48using cricket::TransportDescriptionFactory;
49using cricket::TransportInfo;
50using cricket::ContentInfo;
51using cricket::CryptoParamsVec;
52using cricket::AudioContentDescription;
53using cricket::VideoContentDescription;
54using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080055using cricket::GetFirstAudioContent;
56using cricket::GetFirstVideoContent;
57using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058using cricket::GetFirstAudioContentDescription;
59using cricket::GetFirstVideoContentDescription;
60using cricket::GetFirstDataContentDescription;
61using cricket::kAutoBandwidth;
62using cricket::AudioCodec;
63using cricket::VideoCodec;
64using cricket::DataCodec;
65using cricket::NS_JINGLE_RTP;
66using cricket::MEDIA_TYPE_AUDIO;
67using cricket::MEDIA_TYPE_VIDEO;
68using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000069using cricket::SEC_DISABLED;
70using cricket::SEC_ENABLED;
71using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070072using rtc::CS_AES_CM_128_HMAC_SHA1_32;
73using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070074using rtc::CS_AEAD_AES_128_GCM;
75using rtc::CS_AEAD_AES_256_GCM;
isheriff6f8d6862016-05-26 11:24:55 -070076using webrtc::RtpExtension;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000077
78static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070079 AudioCodec(103, "ISAC", 16000, -1, 1),
80 AudioCodec(102, "iLBC", 8000, 13300, 1),
81 AudioCodec(0, "PCMU", 8000, 64000, 1),
82 AudioCodec(8, "PCMA", 8000, 64000, 1),
83 AudioCodec(117, "red", 8000, 0, 1),
84 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085
86static const AudioCodec kAudioCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070087 AudioCodec(126, "speex", 16000, 22000, 1),
88 AudioCodec(0, "PCMU", 8000, 64000, 1),
89 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090};
91
92static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070093 AudioCodec(102, "iLBC", 8000, 13300, 1),
94 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095};
96
perkj26752742016-10-24 01:21:16 -070097static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
98 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000099
perkj26752742016-10-24 01:21:16 -0700100static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
101 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102
perkj26752742016-10-24 01:21:16 -0700103static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104
deadbeef67cf2c12016-04-13 10:07:16 -0700105static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
106 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000107
deadbeef67cf2c12016-04-13 10:07:16 -0700108static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
109 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110
deadbeef67cf2c12016-04-13 10:07:16 -0700111static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
112 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113
isheriff6f8d6862016-05-26 11:24:55 -0700114static const RtpExtension kAudioRtpExtension1[] = {
115 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
116 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117};
118
isheriff6f8d6862016-05-26 11:24:55 -0700119static const RtpExtension kAudioRtpExtension2[] = {
120 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
121 RtpExtension("http://google.com/testing/audio_something_else", 8),
122 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000123};
124
isheriff6f8d6862016-05-26 11:24:55 -0700125static const RtpExtension kAudioRtpExtension3[] = {
126 RtpExtension("http://google.com/testing/audio_something", 2),
127 RtpExtension("http://google.com/testing/both_audio_and_video", 3),
deadbeefa5b273a2015-08-20 17:30:13 -0700128};
129
isheriff6f8d6862016-05-26 11:24:55 -0700130static const RtpExtension kAudioRtpExtensionAnswer[] = {
131 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000132};
133
isheriff6f8d6862016-05-26 11:24:55 -0700134static const RtpExtension kVideoRtpExtension1[] = {
135 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
136 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137};
138
isheriff6f8d6862016-05-26 11:24:55 -0700139static const RtpExtension kVideoRtpExtension2[] = {
140 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
141 RtpExtension("http://google.com/testing/video_something_else", 14),
142 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000143};
144
isheriff6f8d6862016-05-26 11:24:55 -0700145static const RtpExtension kVideoRtpExtension3[] = {
146 RtpExtension("http://google.com/testing/video_something", 4),
147 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700148};
149
isheriff6f8d6862016-05-26 11:24:55 -0700150static const RtpExtension kVideoRtpExtensionAnswer[] = {
151 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152};
153
Peter Boström0c4e06b2015-10-07 12:23:21 +0200154static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
155static const uint32_t kSimSsrc[] = {10, 20, 30};
156static const uint32_t kFec1Ssrc[] = {10, 11};
157static const uint32_t kFec2Ssrc[] = {20, 21};
158static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159
160static const char kMediaStream1[] = "stream_1";
161static const char kMediaStream2[] = "stream_2";
162static const char kVideoTrack1[] = "video_1";
163static const char kVideoTrack2[] = "video_2";
164static const char kAudioTrack1[] = "audio_1";
165static const char kAudioTrack2[] = "audio_2";
166static const char kAudioTrack3[] = "audio_3";
167static const char kDataTrack1[] = "data_1";
168static const char kDataTrack2[] = "data_2";
169static const char kDataTrack3[] = "data_3";
170
zhihuangcf5b37c2016-05-05 11:44:35 -0700171static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
172 "RTP/SAVPF"};
173static const char* kMediaProtocolsDtls[] = {
174 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
175 "UDP/TLS/RTP/SAVP"};
176
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000177static bool IsMediaContentOfType(const ContentInfo* content,
178 MediaType media_type) {
179 const MediaContentDescription* mdesc =
180 static_cast<const MediaContentDescription*>(content->description);
181 return mdesc && mdesc->type() == media_type;
182}
183
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000184static cricket::MediaContentDirection
185GetMediaDirection(const ContentInfo* content) {
186 cricket::MediaContentDescription* desc =
187 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
188 return desc->direction();
189}
190
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000191static void AddRtxCodec(const VideoCodec& rtx_codec,
192 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800193 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000194 codecs->push_back(rtx_codec);
195}
196
197template <class T>
198static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
199 std::vector<std::string> codec_names;
200 for (const auto& codec : codecs) {
201 codec_names.push_back(codec.name);
202 }
203 return codec_names;
204}
205
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000206class MediaSessionDescriptionFactoryTest : public testing::Test {
207 public:
208 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200209 : f1_(&tdf1_),
210 f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700211 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
212 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000213 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
214 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700215 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
216 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000217 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
218 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200219 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700220 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200221 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700222 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000223 }
224
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000225 // Create a video StreamParamsVec object with:
226 // - one video stream with 3 simulcast streams and FEC,
227 StreamParamsVec CreateComplexVideoStreamParamsVec() {
228 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
229 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
230 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
231 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
232
233 std::vector<SsrcGroup> ssrc_groups;
234 ssrc_groups.push_back(sim_group);
235 ssrc_groups.push_back(fec_group1);
236 ssrc_groups.push_back(fec_group2);
237 ssrc_groups.push_back(fec_group3);
238
239 StreamParams simulcast_params;
240 simulcast_params.id = kVideoTrack1;
241 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
242 simulcast_params.ssrc_groups = ssrc_groups;
243 simulcast_params.cname = "Video_SIM_FEC";
244 simulcast_params.sync_label = kMediaStream1;
245
246 StreamParamsVec video_streams;
247 video_streams.push_back(simulcast_params);
248
249 return video_streams;
250 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000251
252 bool CompareCryptoParams(const CryptoParamsVec& c1,
253 const CryptoParamsVec& c2) {
254 if (c1.size() != c2.size())
255 return false;
256 for (size_t i = 0; i < c1.size(); ++i)
257 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
258 c1[i].key_params != c2[i].key_params ||
259 c1[i].session_params != c2[i].session_params)
260 return false;
261 return true;
262 }
263
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700264 // Returns true if the transport info contains "renomination" as an
265 // ICE option.
266 bool GetIceRenomination(const TransportInfo* transport_info) {
267 const std::vector<std::string>& ice_options =
268 transport_info->description.transport_options;
269 auto iter = std::find(ice_options.begin(), ice_options.end(),
270 cricket::ICE_RENOMINATION_STR);
271 return iter != ice_options.end();
272 }
273
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000274 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
275 bool has_current_desc) {
276 const std::string current_audio_ufrag = "current_audio_ufrag";
277 const std::string current_audio_pwd = "current_audio_pwd";
278 const std::string current_video_ufrag = "current_video_ufrag";
279 const std::string current_video_pwd = "current_video_pwd";
280 const std::string current_data_ufrag = "current_data_ufrag";
281 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800282 std::unique_ptr<SessionDescription> current_desc;
283 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 if (has_current_desc) {
285 current_desc.reset(new SessionDescription());
286 EXPECT_TRUE(current_desc->AddTransportInfo(
287 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700288 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000289 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 EXPECT_TRUE(current_desc->AddTransportInfo(
291 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700292 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000293 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 EXPECT_TRUE(current_desc->AddTransportInfo(
295 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700296 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000297 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000298 }
299 if (offer) {
300 desc.reset(f1_.CreateOffer(options, current_desc.get()));
301 } else {
kwiberg31022942016-03-11 14:18:21 -0800302 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000303 offer.reset(f1_.CreateOffer(options, NULL));
304 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
305 }
306 ASSERT_TRUE(desc.get() != NULL);
307 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000308 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000309 EXPECT_TRUE(ti_audio != NULL);
310 if (has_current_desc) {
311 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
312 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
313 } else {
314 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
315 ti_audio->description.ice_ufrag.size());
316 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
317 ti_audio->description.ice_pwd.size());
318 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700319 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000320
321 } else {
322 EXPECT_TRUE(ti_audio == NULL);
323 }
324 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000325 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000326 EXPECT_TRUE(ti_video != NULL);
327 if (options.bundle_enabled) {
328 EXPECT_EQ(ti_audio->description.ice_ufrag,
329 ti_video->description.ice_ufrag);
330 EXPECT_EQ(ti_audio->description.ice_pwd,
331 ti_video->description.ice_pwd);
332 } else {
333 if (has_current_desc) {
334 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
335 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
336 } else {
337 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
338 ti_video->description.ice_ufrag.size());
339 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
340 ti_video->description.ice_pwd.size());
341 }
342 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700343 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000344 } else {
345 EXPECT_TRUE(ti_video == NULL);
346 }
347 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
348 if (options.has_data()) {
349 EXPECT_TRUE(ti_data != NULL);
350 if (options.bundle_enabled) {
351 EXPECT_EQ(ti_audio->description.ice_ufrag,
352 ti_data->description.ice_ufrag);
353 EXPECT_EQ(ti_audio->description.ice_pwd,
354 ti_data->description.ice_pwd);
355 } else {
356 if (has_current_desc) {
357 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
358 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
359 } else {
360 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
361 ti_data->description.ice_ufrag.size());
362 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
363 ti_data->description.ice_pwd.size());
364 }
365 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700366 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_data));
367
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368 } else {
369 EXPECT_TRUE(ti_video == NULL);
370 }
371 }
372
373 void TestCryptoWithBundle(bool offer) {
374 f1_.set_secure(SEC_ENABLED);
375 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000376 options.recv_audio = true;
377 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000378 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800379 std::unique_ptr<SessionDescription> ref_desc;
380 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000381 if (offer) {
382 options.bundle_enabled = false;
383 ref_desc.reset(f1_.CreateOffer(options, NULL));
384 options.bundle_enabled = true;
385 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
386 } else {
387 options.bundle_enabled = true;
388 ref_desc.reset(f1_.CreateOffer(options, NULL));
389 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
390 }
391 ASSERT_TRUE(desc.get() != NULL);
392 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000393 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000394 desc.get()->GetContentDescriptionByName("audio"));
395 ASSERT_TRUE(audio_media_desc != NULL);
396 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000397 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000398 desc.get()->GetContentDescriptionByName("video"));
399 ASSERT_TRUE(video_media_desc != NULL);
400 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
401 video_media_desc->cryptos()));
402 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
403 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
404 audio_media_desc->cryptos()[0].cipher_suite);
405
406 // Verify the selected crypto is one from the reference audio
407 // media content.
408 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000409 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000410 ref_desc.get()->GetContentDescriptionByName("audio"));
411 bool found = false;
412 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
413 if (ref_audio_media_desc->cryptos()[i].Matches(
414 audio_media_desc->cryptos()[0])) {
415 found = true;
416 break;
417 }
418 }
419 EXPECT_TRUE(found);
420 }
421
422 // This test that the audio and video media direction is set to
423 // |expected_direction_in_answer| in an answer if the offer direction is set
424 // to |direction_in_offer|.
425 void TestMediaDirectionInAnswer(
426 cricket::MediaContentDirection direction_in_offer,
427 cricket::MediaContentDirection expected_direction_in_answer) {
428 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000429 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800430 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000431 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700432 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433 ASSERT_TRUE(ac_offer != NULL);
434 AudioContentDescription* acd_offer =
435 static_cast<AudioContentDescription*>(ac_offer->description);
436 acd_offer->set_direction(direction_in_offer);
terelius8c011e52016-04-26 05:28:11 -0700437 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 ASSERT_TRUE(vc_offer != NULL);
439 VideoContentDescription* vcd_offer =
440 static_cast<VideoContentDescription*>(vc_offer->description);
441 vcd_offer->set_direction(direction_in_offer);
442
kwiberg31022942016-03-11 14:18:21 -0800443 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000444 f2_.CreateAnswer(offer.get(), opts, NULL));
445 const AudioContentDescription* acd_answer =
446 GetFirstAudioContentDescription(answer.get());
447 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
448 const VideoContentDescription* vcd_answer =
449 GetFirstVideoContentDescription(answer.get());
450 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
451 }
452
453 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
454 const cricket::ContentDescription* description = content->description;
nissec8ee8822017-01-18 07:20:55 -0800455 RTC_CHECK(description != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000456 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000457 static_cast<const cricket::AudioContentDescription*>(description);
nissec8ee8822017-01-18 07:20:55 -0800458 RTC_CHECK(audio_content_desc != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000459 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
460 if (audio_content_desc->codecs()[i].name == "CN")
461 return false;
462 }
463 return true;
464 }
465
jbauchcb560652016-08-04 05:20:32 -0700466 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
467 MediaSessionOptions offer_opts;
468 offer_opts.recv_video = true;
469 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
470 MediaSessionOptions answer_opts;
471 answer_opts.recv_video = true;
472 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
473 f1_.set_secure(SEC_ENABLED);
474 f2_.set_secure(SEC_ENABLED);
475 std::unique_ptr<SessionDescription> offer(
476 f1_.CreateOffer(offer_opts, NULL));
477 ASSERT_TRUE(offer.get() != NULL);
478 std::unique_ptr<SessionDescription> answer(
479 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
480 const ContentInfo* ac = answer->GetContentByName("audio");
481 const ContentInfo* vc = answer->GetContentByName("video");
482 ASSERT_TRUE(ac != NULL);
483 ASSERT_TRUE(vc != NULL);
484 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
485 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
486 const AudioContentDescription* acd =
487 static_cast<const AudioContentDescription*>(ac->description);
488 const VideoContentDescription* vcd =
489 static_cast<const VideoContentDescription*>(vc->description);
490 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
491 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
492 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
493 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
494 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
495 if (gcm_offer && gcm_answer) {
496 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
497 } else {
498 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
499 }
500 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
501 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
502 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
503 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
504 if (gcm_offer && gcm_answer) {
505 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
506 } else {
507 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
508 }
509 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
510 }
511
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 protected:
513 MediaSessionDescriptionFactory f1_;
514 MediaSessionDescriptionFactory f2_;
515 TransportDescriptionFactory tdf1_;
516 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000517};
518
519// Create a typical audio offer, and ensure it matches what we expect.
520TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
521 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800522 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000523 f1_.CreateOffer(MediaSessionOptions(), NULL));
524 ASSERT_TRUE(offer.get() != NULL);
525 const ContentInfo* ac = offer->GetContentByName("audio");
526 const ContentInfo* vc = offer->GetContentByName("video");
527 ASSERT_TRUE(ac != NULL);
528 ASSERT_TRUE(vc == NULL);
529 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
530 const AudioContentDescription* acd =
531 static_cast<const AudioContentDescription*>(ac->description);
532 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700533 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000534 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
535 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
536 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
537 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
538 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
539}
540
541// Create a typical video offer, and ensure it matches what we expect.
542TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
543 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000544 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000545 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800546 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 ASSERT_TRUE(offer.get() != NULL);
548 const ContentInfo* ac = offer->GetContentByName("audio");
549 const ContentInfo* vc = offer->GetContentByName("video");
550 ASSERT_TRUE(ac != NULL);
551 ASSERT_TRUE(vc != NULL);
552 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
553 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
554 const AudioContentDescription* acd =
555 static_cast<const AudioContentDescription*>(ac->description);
556 const VideoContentDescription* vcd =
557 static_cast<const VideoContentDescription*>(vc->description);
558 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700559 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000560 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
561 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
562 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
563 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
564 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
565 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
566 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
567 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
568 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
569 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
570 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
571 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
572}
573
574// Test creating an offer with bundle where the Codecs have the same dynamic
575// RTP playlod type. The test verifies that the offer don't contain the
576// duplicate RTP payload types.
577TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
578 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700579 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000580 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
581 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
582 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
583
584 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000585 opts.recv_audio = true;
586 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000587 opts.data_channel_type = cricket::DCT_RTP;
588 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800589 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000590 const VideoContentDescription* vcd =
591 GetFirstVideoContentDescription(offer.get());
592 const AudioContentDescription* acd =
593 GetFirstAudioContentDescription(offer.get());
594 const DataContentDescription* dcd =
595 GetFirstDataContentDescription(offer.get());
596 ASSERT_TRUE(NULL != vcd);
597 ASSERT_TRUE(NULL != acd);
598 ASSERT_TRUE(NULL != dcd);
599 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
600 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
601 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
602 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
603 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
604 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
605}
606
607// Test creating an updated offer with with bundle, audio, video and data
608// after an audio only session has been negotiated.
609TEST_F(MediaSessionDescriptionFactoryTest,
610 TestCreateUpdatedVideoOfferWithBundle) {
611 f1_.set_secure(SEC_ENABLED);
612 f2_.set_secure(SEC_ENABLED);
613 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000614 opts.recv_audio = true;
615 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 opts.data_channel_type = cricket::DCT_NONE;
617 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800618 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
619 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000620 f2_.CreateAnswer(offer.get(), opts, NULL));
621
622 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000623 updated_opts.recv_audio = true;
624 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000625 updated_opts.data_channel_type = cricket::DCT_RTP;
626 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800627 std::unique_ptr<SessionDescription> updated_offer(
628 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000629
630 const AudioContentDescription* acd =
631 GetFirstAudioContentDescription(updated_offer.get());
632 const VideoContentDescription* vcd =
633 GetFirstVideoContentDescription(updated_offer.get());
634 const DataContentDescription* dcd =
635 GetFirstDataContentDescription(updated_offer.get());
636 EXPECT_TRUE(NULL != vcd);
637 EXPECT_TRUE(NULL != acd);
638 EXPECT_TRUE(NULL != dcd);
639
640 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
641 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
642 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
643 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
644 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
645 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
646}
deadbeef44f08192015-12-15 16:20:09 -0800647
wu@webrtc.org78187522013-10-07 23:32:02 +0000648// Create a RTP data offer, and ensure it matches what we expect.
649TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000650 MediaSessionOptions opts;
651 opts.data_channel_type = cricket::DCT_RTP;
652 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800653 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000654 ASSERT_TRUE(offer.get() != NULL);
655 const ContentInfo* ac = offer->GetContentByName("audio");
656 const ContentInfo* dc = offer->GetContentByName("data");
657 ASSERT_TRUE(ac != NULL);
658 ASSERT_TRUE(dc != NULL);
659 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
660 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
661 const AudioContentDescription* acd =
662 static_cast<const AudioContentDescription*>(ac->description);
663 const DataContentDescription* dcd =
664 static_cast<const DataContentDescription*>(dc->description);
665 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700666 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000667 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
668 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
669 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
670 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
671 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
672 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
673 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
674 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
675 EXPECT_EQ(cricket::kDataMaxBandwidth,
676 dcd->bandwidth()); // default bandwidth (auto)
677 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
678 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
679 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
680}
681
wu@webrtc.org78187522013-10-07 23:32:02 +0000682// Create an SCTP data offer with bundle without error.
683TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
684 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000685 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000686 opts.bundle_enabled = true;
687 opts.data_channel_type = cricket::DCT_SCTP;
688 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800689 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000690 EXPECT_TRUE(offer.get() != NULL);
691 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
692}
693
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000694// Test creating an sctp data channel from an already generated offer.
695TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
696 MediaSessionOptions opts;
697 opts.recv_audio = false;
698 opts.bundle_enabled = true;
699 opts.data_channel_type = cricket::DCT_SCTP;
700 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800701 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000702 ASSERT_TRUE(offer1.get() != NULL);
703 const ContentInfo* data = offer1->GetContentByName("data");
704 ASSERT_TRUE(data != NULL);
705 const MediaContentDescription* mdesc =
706 static_cast<const MediaContentDescription*>(data->description);
707 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
708
709 // Now set data_channel_type to 'none' (default) and make sure that the
710 // datachannel type that gets generated from the previous offer, is of the
711 // same type.
712 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800713 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000714 f1_.CreateOffer(opts, offer1.get()));
715 data = offer2->GetContentByName("data");
716 ASSERT_TRUE(data != NULL);
717 mdesc = static_cast<const MediaContentDescription*>(data->description);
718 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
719}
720
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000721// Create an audio, video offer without legacy StreamParams.
722TEST_F(MediaSessionDescriptionFactoryTest,
723 TestCreateOfferWithoutLegacyStreams) {
724 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000725 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000726 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800727 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 ASSERT_TRUE(offer.get() != NULL);
729 const ContentInfo* ac = offer->GetContentByName("audio");
730 const ContentInfo* vc = offer->GetContentByName("video");
731 ASSERT_TRUE(ac != NULL);
732 ASSERT_TRUE(vc != NULL);
733 const AudioContentDescription* acd =
734 static_cast<const AudioContentDescription*>(ac->description);
735 const VideoContentDescription* vcd =
736 static_cast<const VideoContentDescription*>(vc->description);
737
738 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
739 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
740}
741
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000742// Creates an audio+video sendonly offer.
743TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
744 MediaSessionOptions options;
745 options.recv_audio = false;
746 options.recv_video = false;
747 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
748 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
749
kwiberg31022942016-03-11 14:18:21 -0800750 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000751 ASSERT_TRUE(offer.get() != NULL);
752 EXPECT_EQ(2u, offer->contents().size());
753 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
754 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
755
756 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
757 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
758}
759
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000760// Verifies that the order of the media contents in the current
761// SessionDescription is preserved in the new SessionDescription.
762TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
763 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000764 opts.recv_audio = false;
765 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000766 opts.data_channel_type = cricket::DCT_SCTP;
767
kwiberg31022942016-03-11 14:18:21 -0800768 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000769 ASSERT_TRUE(offer1.get() != NULL);
770 EXPECT_EQ(1u, offer1->contents().size());
771 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
772
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000773 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800774 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000775 f1_.CreateOffer(opts, offer1.get()));
776 ASSERT_TRUE(offer2.get() != NULL);
777 EXPECT_EQ(2u, offer2->contents().size());
778 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
779 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
780
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000781 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800782 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000783 f1_.CreateOffer(opts, offer2.get()));
784 ASSERT_TRUE(offer3.get() != NULL);
785 EXPECT_EQ(3u, offer3->contents().size());
786 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
787 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
788 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
789
790 // Verifies the default order is audio-video-data, so that the previous checks
791 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800792 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000793 ASSERT_TRUE(offer4.get() != NULL);
794 EXPECT_EQ(3u, offer4->contents().size());
795 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
796 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
797 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
798}
799
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000800// Create a typical audio answer, and ensure it matches what we expect.
801TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
802 f1_.set_secure(SEC_ENABLED);
803 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800804 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000805 f1_.CreateOffer(MediaSessionOptions(), NULL));
806 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(), MediaSessionOptions(), NULL));
809 const ContentInfo* ac = answer->GetContentByName("audio");
810 const ContentInfo* vc = answer->GetContentByName("video");
811 ASSERT_TRUE(ac != NULL);
812 ASSERT_TRUE(vc == NULL);
813 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
814 const AudioContentDescription* acd =
815 static_cast<const AudioContentDescription*>(ac->description);
816 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
817 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
818 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
819 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
820 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
821 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
822 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
823}
824
jbauchcb560652016-08-04 05:20:32 -0700825// Create a typical audio answer with GCM ciphers enabled, and ensure it
826// matches what we expect.
827TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
828 f1_.set_secure(SEC_ENABLED);
829 f2_.set_secure(SEC_ENABLED);
830 MediaSessionOptions options;
831 options.crypto_options.enable_gcm_crypto_suites = true;
832 std::unique_ptr<SessionDescription> offer(
833 f1_.CreateOffer(options, NULL));
834 ASSERT_TRUE(offer.get() != NULL);
835 std::unique_ptr<SessionDescription> answer(
836 f2_.CreateAnswer(offer.get(), options, NULL));
837 const ContentInfo* ac = answer->GetContentByName("audio");
838 const ContentInfo* vc = answer->GetContentByName("video");
839 ASSERT_TRUE(ac != NULL);
840 ASSERT_TRUE(vc == NULL);
841 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
842 const AudioContentDescription* acd =
843 static_cast<const AudioContentDescription*>(ac->description);
844 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
845 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
846 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
847 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
848 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
849 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
850 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
851}
852
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000853// Create a typical video answer, and ensure it matches what we expect.
854TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
855 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000856 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000857 f1_.set_secure(SEC_ENABLED);
858 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800859 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000860 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800861 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 f2_.CreateAnswer(offer.get(), opts, NULL));
863 const ContentInfo* ac = answer->GetContentByName("audio");
864 const ContentInfo* vc = answer->GetContentByName("video");
865 ASSERT_TRUE(ac != NULL);
866 ASSERT_TRUE(vc != NULL);
867 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
868 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
869 const AudioContentDescription* acd =
870 static_cast<const AudioContentDescription*>(ac->description);
871 const VideoContentDescription* vcd =
872 static_cast<const VideoContentDescription*>(vc->description);
873 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
874 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
875 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
876 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
877 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
878 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
879 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
880 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
881 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
882 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
883 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
884 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
885}
886
jbauchcb560652016-08-04 05:20:32 -0700887// Create a typical video answer with GCM ciphers enabled, and ensure it
888// matches what we expect.
889TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
890 TestVideoGcmCipher(true, true);
891}
892
893// Create a typical video answer with GCM ciphers enabled for the offer only,
894// and ensure it matches what we expect.
895TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
896 TestVideoGcmCipher(true, false);
897}
898
899// Create a typical video answer with GCM ciphers enabled for the answer only,
900// and ensure it matches what we expect.
901TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
902 TestVideoGcmCipher(false, true);
903}
904
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000905TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
906 MediaSessionOptions opts;
907 opts.data_channel_type = cricket::DCT_RTP;
908 f1_.set_secure(SEC_ENABLED);
909 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800910 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800912 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000913 f2_.CreateAnswer(offer.get(), opts, NULL));
914 const ContentInfo* ac = answer->GetContentByName("audio");
915 const ContentInfo* vc = answer->GetContentByName("data");
916 ASSERT_TRUE(ac != NULL);
917 ASSERT_TRUE(vc != NULL);
918 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
919 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
920 const AudioContentDescription* acd =
921 static_cast<const AudioContentDescription*>(ac->description);
922 const DataContentDescription* vcd =
923 static_cast<const DataContentDescription*>(vc->description);
924 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
925 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
926 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
927 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
928 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
929 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
930 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
931 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
932 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
933 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
934 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
935 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
936}
937
jbauchcb560652016-08-04 05:20:32 -0700938TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
939 MediaSessionOptions opts;
940 opts.data_channel_type = cricket::DCT_RTP;
941 opts.crypto_options.enable_gcm_crypto_suites = true;
942 f1_.set_secure(SEC_ENABLED);
943 f2_.set_secure(SEC_ENABLED);
944 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
945 ASSERT_TRUE(offer.get() != NULL);
946 std::unique_ptr<SessionDescription> answer(
947 f2_.CreateAnswer(offer.get(), opts, NULL));
948 const ContentInfo* ac = answer->GetContentByName("audio");
949 const ContentInfo* vc = answer->GetContentByName("data");
950 ASSERT_TRUE(ac != NULL);
951 ASSERT_TRUE(vc != NULL);
952 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
953 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
954 const AudioContentDescription* acd =
955 static_cast<const AudioContentDescription*>(ac->description);
956 const DataContentDescription* vcd =
957 static_cast<const DataContentDescription*>(vc->description);
958 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
959 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
960 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
961 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
962 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
963 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
964 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
965 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
966 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
967 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
968 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
969 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
970}
971
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000972// Verifies that the order of the media contents in the offer is preserved in
973// the answer.
974TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
975 MediaSessionOptions opts;
976
977 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000978 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000979 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -0800980 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000981 ASSERT_TRUE(offer1.get() != NULL);
982
983 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000984 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800985 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000986 f1_.CreateOffer(opts, offer1.get()));
987 ASSERT_TRUE(offer2.get() != NULL);
988
989 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000990 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800991 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000992 f1_.CreateOffer(opts, offer2.get()));
993 ASSERT_TRUE(offer3.get() != NULL);
994
kwiberg31022942016-03-11 14:18:21 -0800995 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000996 f2_.CreateAnswer(offer3.get(), opts, NULL));
997 ASSERT_TRUE(answer.get() != NULL);
998 EXPECT_EQ(3u, answer->contents().size());
999 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1000 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1001 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1002}
1003
ossu075af922016-06-14 03:29:38 -07001004// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1005// answerer settings.
1006
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001007// This test that the media direction is set to send/receive in an answer if
1008// the offer is send receive.
1009TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
1010 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
1011}
1012
1013// This test that the media direction is set to receive only in an answer if
1014// the offer is send only.
1015TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
1016 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
1017}
1018
1019// This test that the media direction is set to send only in an answer if
1020// the offer is recv only.
1021TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
1022 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
1023}
1024
1025// This test that the media direction is set to inactive in an answer if
1026// the offer is inactive.
1027TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
1028 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
1029}
1030
1031// Test that a data content with an unknown protocol is rejected in an answer.
1032TEST_F(MediaSessionDescriptionFactoryTest,
1033 CreateDataAnswerToOfferWithUnknownProtocol) {
1034 MediaSessionOptions opts;
1035 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001036 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001037 f1_.set_secure(SEC_ENABLED);
1038 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001039 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001040 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001041 ASSERT_TRUE(dc_offer != NULL);
1042 DataContentDescription* dcd_offer =
1043 static_cast<DataContentDescription*>(dc_offer->description);
1044 ASSERT_TRUE(dcd_offer != NULL);
1045 std::string protocol = "a weird unknown protocol";
1046 dcd_offer->set_protocol(protocol);
1047
kwiberg31022942016-03-11 14:18:21 -08001048 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001049 f2_.CreateAnswer(offer.get(), opts, NULL));
1050
1051 const ContentInfo* dc_answer = answer->GetContentByName("data");
1052 ASSERT_TRUE(dc_answer != NULL);
1053 EXPECT_TRUE(dc_answer->rejected);
1054 const DataContentDescription* dcd_answer =
1055 static_cast<const DataContentDescription*>(dc_answer->description);
1056 ASSERT_TRUE(dcd_answer != NULL);
1057 EXPECT_EQ(protocol, dcd_answer->protocol());
1058}
1059
1060// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1061TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
1062 MediaSessionOptions opts;
1063 f1_.set_secure(SEC_DISABLED);
1064 f2_.set_secure(SEC_DISABLED);
1065 tdf1_.set_secure(SEC_DISABLED);
1066 tdf2_.set_secure(SEC_DISABLED);
1067
kwiberg31022942016-03-11 14:18:21 -08001068 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001069 const AudioContentDescription* offer_acd =
1070 GetFirstAudioContentDescription(offer.get());
1071 ASSERT_TRUE(offer_acd != NULL);
1072 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1073
kwiberg31022942016-03-11 14:18:21 -08001074 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001075 f2_.CreateAnswer(offer.get(), opts, NULL));
1076
1077 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1078 ASSERT_TRUE(ac_answer != NULL);
1079 EXPECT_FALSE(ac_answer->rejected);
1080
1081 const AudioContentDescription* answer_acd =
1082 GetFirstAudioContentDescription(answer.get());
1083 ASSERT_TRUE(answer_acd != NULL);
1084 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1085}
1086
1087// Create a video offer and answer and ensure the RTP header extensions
1088// matches what we expect.
1089TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1090 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001091 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001092
1093 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1094 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1095 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1096 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1097
kwiberg31022942016-03-11 14:18:21 -08001098 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001099 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001100 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 f2_.CreateAnswer(offer.get(), opts, NULL));
1102
1103 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1104 GetFirstAudioContentDescription(
1105 offer.get())->rtp_header_extensions());
1106 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1107 GetFirstVideoContentDescription(
1108 offer.get())->rtp_header_extensions());
1109 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1110 GetFirstAudioContentDescription(
1111 answer.get())->rtp_header_extensions());
1112 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1113 GetFirstVideoContentDescription(
1114 answer.get())->rtp_header_extensions());
1115}
1116
1117// Create an audio, video, data answer without legacy StreamParams.
1118TEST_F(MediaSessionDescriptionFactoryTest,
1119 TestCreateAnswerWithoutLegacyStreams) {
1120 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001121 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001122 opts.data_channel_type = cricket::DCT_RTP;
1123 f1_.set_add_legacy_streams(false);
1124 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -08001125 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001126 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001127 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001128 f2_.CreateAnswer(offer.get(), opts, NULL));
1129 const ContentInfo* ac = answer->GetContentByName("audio");
1130 const ContentInfo* vc = answer->GetContentByName("video");
1131 const ContentInfo* dc = answer->GetContentByName("data");
1132 ASSERT_TRUE(ac != NULL);
1133 ASSERT_TRUE(vc != NULL);
1134 const AudioContentDescription* acd =
1135 static_cast<const AudioContentDescription*>(ac->description);
1136 const VideoContentDescription* vcd =
1137 static_cast<const VideoContentDescription*>(vc->description);
1138 const DataContentDescription* dcd =
1139 static_cast<const DataContentDescription*>(dc->description);
1140
1141 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1142 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1143 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1144}
1145
1146TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1147 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001148 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001149 opts.data_channel_type = cricket::DCT_RTP;
1150 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001151 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001152 ASSERT_TRUE(offer.get() != NULL);
1153 const ContentInfo* ac = offer->GetContentByName("audio");
1154 const ContentInfo* vc = offer->GetContentByName("video");
1155 const ContentInfo* dc = offer->GetContentByName("data");
1156 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1157 static_cast<const AudioContentDescription*>(ac->description));
1158 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1159 static_cast<const VideoContentDescription*>(vc->description));
1160 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1161 static_cast<const DataContentDescription*>(dc->description));
1162
1163 EXPECT_FALSE(acd->partial()); // default is false.
1164 acd->set_partial(true);
1165 EXPECT_TRUE(acd->partial());
1166 acd->set_partial(false);
1167 EXPECT_FALSE(acd->partial());
1168
1169 EXPECT_FALSE(vcd->partial()); // default is false.
1170 vcd->set_partial(true);
1171 EXPECT_TRUE(vcd->partial());
1172 vcd->set_partial(false);
1173 EXPECT_FALSE(vcd->partial());
1174
1175 EXPECT_FALSE(dcd->partial()); // default is false.
1176 dcd->set_partial(true);
1177 EXPECT_TRUE(dcd->partial());
1178 dcd->set_partial(false);
1179 EXPECT_FALSE(dcd->partial());
1180}
1181
1182// Create a typical video answer, and ensure it matches what we expect.
1183TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1184 MediaSessionOptions offer_opts;
1185 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001186 answer_opts.recv_video = true;
1187 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001188 answer_opts.data_channel_type = cricket::DCT_RTP;
1189 offer_opts.data_channel_type = cricket::DCT_RTP;
1190
kwiberg31022942016-03-11 14:18:21 -08001191 std::unique_ptr<SessionDescription> offer;
1192 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001193
1194 offer_opts.rtcp_mux_enabled = true;
1195 answer_opts.rtcp_mux_enabled = true;
1196
1197 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1198 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1199 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1200 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1201 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1202 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1203 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1204 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1205 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1206 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1207 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1208 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1209 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1210 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1211
1212 offer_opts.rtcp_mux_enabled = true;
1213 answer_opts.rtcp_mux_enabled = false;
1214
1215 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1216 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1217 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1218 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1219 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1220 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1221 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1222 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1223 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1224 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1225 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1226 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1227 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1228 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1229
1230 offer_opts.rtcp_mux_enabled = false;
1231 answer_opts.rtcp_mux_enabled = true;
1232
1233 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1234 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1235 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1236 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1237 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1238 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1239 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1240 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1241 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1242 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1243 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1244 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1245 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1246 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1247
1248 offer_opts.rtcp_mux_enabled = false;
1249 answer_opts.rtcp_mux_enabled = false;
1250
1251 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1252 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1253 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1254 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1255 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1256 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1257 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1258 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1259 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1260 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1261 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1262 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1263 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1264 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1265}
1266
1267// Create an audio-only answer to a video offer.
1268TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1269 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001270 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001271 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001272 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001273 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001274 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1275 const ContentInfo* ac = answer->GetContentByName("audio");
1276 const ContentInfo* vc = answer->GetContentByName("video");
1277 ASSERT_TRUE(ac != NULL);
1278 ASSERT_TRUE(vc != NULL);
1279 ASSERT_TRUE(vc->description != NULL);
1280 EXPECT_TRUE(vc->rejected);
1281}
1282
1283// Create an audio-only answer to an offer with data.
1284TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1285 MediaSessionOptions opts;
1286 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001287 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001288 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001289 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1291 const ContentInfo* ac = answer->GetContentByName("audio");
1292 const ContentInfo* dc = answer->GetContentByName("data");
1293 ASSERT_TRUE(ac != NULL);
1294 ASSERT_TRUE(dc != NULL);
1295 ASSERT_TRUE(dc->description != NULL);
1296 EXPECT_TRUE(dc->rejected);
1297}
1298
1299// Create an answer that rejects the contents which are rejected in the offer.
1300TEST_F(MediaSessionDescriptionFactoryTest,
1301 CreateAnswerToOfferWithRejectedMedia) {
1302 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001303 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001304 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001305 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 ASSERT_TRUE(offer.get() != NULL);
1307 ContentInfo* ac = offer->GetContentByName("audio");
1308 ContentInfo* vc = offer->GetContentByName("video");
1309 ContentInfo* dc = offer->GetContentByName("data");
1310 ASSERT_TRUE(ac != NULL);
1311 ASSERT_TRUE(vc != NULL);
1312 ASSERT_TRUE(dc != NULL);
1313 ac->rejected = true;
1314 vc->rejected = true;
1315 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001316 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001317 f2_.CreateAnswer(offer.get(), opts, NULL));
1318 ac = answer->GetContentByName("audio");
1319 vc = answer->GetContentByName("video");
1320 dc = answer->GetContentByName("data");
1321 ASSERT_TRUE(ac != NULL);
1322 ASSERT_TRUE(vc != NULL);
1323 ASSERT_TRUE(dc != NULL);
1324 EXPECT_TRUE(ac->rejected);
1325 EXPECT_TRUE(vc->rejected);
1326 EXPECT_TRUE(dc->rejected);
1327}
1328
1329// Create an audio and video offer with:
1330// - one video track
1331// - two audio tracks
1332// - two data tracks
1333// and ensure it matches what we expect. Also updates the initial offer by
1334// adding a new video track and replaces one of the audio tracks.
1335TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1336 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001337 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1338 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1339 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001340 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001341 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1342 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001343
1344 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001345 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001346
1347 ASSERT_TRUE(offer.get() != NULL);
1348 const ContentInfo* ac = offer->GetContentByName("audio");
1349 const ContentInfo* vc = offer->GetContentByName("video");
1350 const ContentInfo* dc = offer->GetContentByName("data");
1351 ASSERT_TRUE(ac != NULL);
1352 ASSERT_TRUE(vc != NULL);
1353 ASSERT_TRUE(dc != NULL);
1354 const AudioContentDescription* acd =
1355 static_cast<const AudioContentDescription*>(ac->description);
1356 const VideoContentDescription* vcd =
1357 static_cast<const VideoContentDescription*>(vc->description);
1358 const DataContentDescription* dcd =
1359 static_cast<const DataContentDescription*>(dc->description);
1360 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001361 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001362
1363 const StreamParamsVec& audio_streams = acd->streams();
1364 ASSERT_EQ(2U, audio_streams.size());
1365 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1366 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1367 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1368 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1369 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1370 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1371 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1372
1373 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1374 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1375 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1376
1377 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1378 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1379 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1380
1381 const StreamParamsVec& video_streams = vcd->streams();
1382 ASSERT_EQ(1U, video_streams.size());
1383 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1384 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1385 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1386 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1387
1388 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1389 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1390 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1391
1392 const StreamParamsVec& data_streams = dcd->streams();
1393 ASSERT_EQ(2U, data_streams.size());
1394 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1395 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1396 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1397 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1398 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1399 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1400 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1401
1402 EXPECT_EQ(cricket::kDataMaxBandwidth,
1403 dcd->bandwidth()); // default bandwidth (auto)
1404 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1405 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1406
1407
1408 // Update the offer. Add a new video track that is not synched to the
1409 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001410 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1411 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1412 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1413 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1414 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001415 std::unique_ptr<SessionDescription> updated_offer(
1416 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001417
1418 ASSERT_TRUE(updated_offer.get() != NULL);
1419 ac = updated_offer->GetContentByName("audio");
1420 vc = updated_offer->GetContentByName("video");
1421 dc = updated_offer->GetContentByName("data");
1422 ASSERT_TRUE(ac != NULL);
1423 ASSERT_TRUE(vc != NULL);
1424 ASSERT_TRUE(dc != NULL);
1425 const AudioContentDescription* updated_acd =
1426 static_cast<const AudioContentDescription*>(ac->description);
1427 const VideoContentDescription* updated_vcd =
1428 static_cast<const VideoContentDescription*>(vc->description);
1429 const DataContentDescription* updated_dcd =
1430 static_cast<const DataContentDescription*>(dc->description);
1431
1432 EXPECT_EQ(acd->type(), updated_acd->type());
1433 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1434 EXPECT_EQ(vcd->type(), updated_vcd->type());
1435 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1436 EXPECT_EQ(dcd->type(), updated_dcd->type());
1437 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1438 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1439 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1440 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1441 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1442 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1443 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1444
1445 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1446 ASSERT_EQ(2U, updated_audio_streams.size());
1447 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1448 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1449 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1450 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1451 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1452
1453 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1454 ASSERT_EQ(2U, updated_video_streams.size());
1455 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1456 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001457 // All the media streams in one PeerConnection share one RTCP CNAME.
1458 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001459
1460 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1461 ASSERT_EQ(2U, updated_data_streams.size());
1462 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1463 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1464 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1465 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1466 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001467 // The stream correctly got the CNAME from the MediaSessionOptions.
1468 // The Expected RTCP CNAME is the default one as we are using the default
1469 // MediaSessionOptions.
1470 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001471}
1472
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001473// Create an offer with simulcast video stream.
1474TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1475 MediaSessionOptions opts;
1476 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001477 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001478 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001479
1480 ASSERT_TRUE(offer.get() != NULL);
1481 const ContentInfo* vc = offer->GetContentByName("video");
1482 ASSERT_TRUE(vc != NULL);
1483 const VideoContentDescription* vcd =
1484 static_cast<const VideoContentDescription*>(vc->description);
1485
1486 const StreamParamsVec& video_streams = vcd->streams();
1487 ASSERT_EQ(1U, video_streams.size());
1488 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1489 const SsrcGroup* sim_ssrc_group =
1490 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1491 ASSERT_TRUE(sim_ssrc_group != NULL);
1492 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1493}
1494
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001495// Create an audio and video answer to a standard video offer with:
1496// - one video track
1497// - two audio tracks
1498// - two data tracks
1499// and ensure it matches what we expect. Also updates the initial answer by
1500// adding a new video track and removes one of the audio tracks.
1501TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1502 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001503 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001504 offer_opts.data_channel_type = cricket::DCT_RTP;
1505 f1_.set_secure(SEC_ENABLED);
1506 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001507 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001508
1509 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001510 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1511 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1512 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001513 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001514 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1515 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001516
kwiberg31022942016-03-11 14:18:21 -08001517 std::unique_ptr<SessionDescription> answer(
1518 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001519
1520 ASSERT_TRUE(answer.get() != NULL);
1521 const ContentInfo* ac = answer->GetContentByName("audio");
1522 const ContentInfo* vc = answer->GetContentByName("video");
1523 const ContentInfo* dc = answer->GetContentByName("data");
1524 ASSERT_TRUE(ac != NULL);
1525 ASSERT_TRUE(vc != NULL);
1526 ASSERT_TRUE(dc != NULL);
1527 const AudioContentDescription* acd =
1528 static_cast<const AudioContentDescription*>(ac->description);
1529 const VideoContentDescription* vcd =
1530 static_cast<const VideoContentDescription*>(vc->description);
1531 const DataContentDescription* dcd =
1532 static_cast<const DataContentDescription*>(dc->description);
1533 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1534 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1535 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1536
1537 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1538 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1539
1540 const StreamParamsVec& audio_streams = acd->streams();
1541 ASSERT_EQ(2U, audio_streams.size());
1542 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1543 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1544 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1545 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1546 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1547 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1548 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1549
1550 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1551 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1552
1553 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1554 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1555
1556 const StreamParamsVec& video_streams = vcd->streams();
1557 ASSERT_EQ(1U, video_streams.size());
1558 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1559 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1560 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1561 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1562
1563 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1564 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1565
1566 const StreamParamsVec& data_streams = dcd->streams();
1567 ASSERT_EQ(2U, data_streams.size());
1568 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1569 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1570 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1571 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1572 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1573 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1574 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1575
1576 EXPECT_EQ(cricket::kDataMaxBandwidth,
1577 dcd->bandwidth()); // default bandwidth (auto)
1578 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1579
1580 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001581 // other tracks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001582 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1583 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1584 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001585 std::unique_ptr<SessionDescription> updated_answer(
1586 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001587
1588 ASSERT_TRUE(updated_answer.get() != NULL);
1589 ac = updated_answer->GetContentByName("audio");
1590 vc = updated_answer->GetContentByName("video");
1591 dc = updated_answer->GetContentByName("data");
1592 ASSERT_TRUE(ac != NULL);
1593 ASSERT_TRUE(vc != NULL);
1594 ASSERT_TRUE(dc != NULL);
1595 const AudioContentDescription* updated_acd =
1596 static_cast<const AudioContentDescription*>(ac->description);
1597 const VideoContentDescription* updated_vcd =
1598 static_cast<const VideoContentDescription*>(vc->description);
1599 const DataContentDescription* updated_dcd =
1600 static_cast<const DataContentDescription*>(dc->description);
1601
1602 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1603 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1604 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1605 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1606 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1607 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1608
1609 EXPECT_EQ(acd->type(), updated_acd->type());
1610 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1611 EXPECT_EQ(vcd->type(), updated_vcd->type());
1612 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1613 EXPECT_EQ(dcd->type(), updated_dcd->type());
1614 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1615
1616 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1617 ASSERT_EQ(1U, updated_audio_streams.size());
1618 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1619
1620 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1621 ASSERT_EQ(2U, updated_video_streams.size());
1622 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1623 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001624 // All media streams in one PeerConnection share one CNAME.
1625 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001626
1627 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1628 ASSERT_EQ(1U, updated_data_streams.size());
1629 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1630}
1631
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632// Create an updated offer after creating an answer to the original offer and
1633// verify that the codecs that were part of the original answer are not changed
1634// in the updated offer.
1635TEST_F(MediaSessionDescriptionFactoryTest,
1636 RespondentCreatesOfferAfterCreatingAnswer) {
1637 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001638 opts.recv_audio = true;
1639 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640
kwiberg31022942016-03-11 14:18:21 -08001641 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1642 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001643 f2_.CreateAnswer(offer.get(), opts, NULL));
1644
1645 const AudioContentDescription* acd =
1646 GetFirstAudioContentDescription(answer.get());
1647 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1648
1649 const VideoContentDescription* vcd =
1650 GetFirstVideoContentDescription(answer.get());
1651 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1652
kwiberg31022942016-03-11 14:18:21 -08001653 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654 f2_.CreateOffer(opts, answer.get()));
1655
1656 // The expected audio codecs are the common audio codecs from the first
1657 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1658 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001659 // TODO(wu): |updated_offer| should not include the codec
1660 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001661 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001662 kAudioCodecsAnswer[0],
1663 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001664 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001665 };
1666
1667 // The expected video codecs are the common video codecs from the first
1668 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1669 // preference order.
1670 const VideoCodec kUpdatedVideoCodecOffer[] = {
1671 kVideoCodecsAnswer[0],
1672 kVideoCodecs2[1],
1673 };
1674
1675 const AudioContentDescription* updated_acd =
1676 GetFirstAudioContentDescription(updated_offer.get());
1677 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1678
1679 const VideoContentDescription* updated_vcd =
1680 GetFirstVideoContentDescription(updated_offer.get());
1681 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1682}
1683
1684// Create an updated offer after creating an answer to the original offer and
1685// verify that the codecs that were part of the original answer are not changed
1686// in the updated offer. In this test Rtx is enabled.
1687TEST_F(MediaSessionDescriptionFactoryTest,
1688 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1689 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001690 opts.recv_video = true;
1691 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001692 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001693 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001694 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 f1_.set_video_codecs(f1_codecs);
1696
1697 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001698 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001699 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001700 f2_.set_video_codecs(f2_codecs);
1701
kwiberg31022942016-03-11 14:18:21 -08001702 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001703 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001704 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 f2_.CreateAnswer(offer.get(), opts, NULL));
1706
1707 const VideoContentDescription* vcd =
1708 GetFirstVideoContentDescription(answer.get());
1709
1710 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001711 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1712 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001713
1714 EXPECT_EQ(expected_codecs, vcd->codecs());
1715
deadbeef67cf2c12016-04-13 10:07:16 -07001716 // Now, make sure we get same result (except for the order) if |f2_| creates
1717 // an updated offer even though the default payload types between |f1_| and
1718 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001719 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001720 f2_.CreateOffer(opts, answer.get()));
1721 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001722 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001723 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1724
1725 const VideoContentDescription* updated_vcd =
1726 GetFirstVideoContentDescription(updated_answer.get());
1727
1728 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1729}
1730
1731// Create an updated offer that adds video after creating an audio only answer
1732// to the original offer. This test verifies that if a video codec and the RTX
1733// codec have the same default payload type as an audio codec that is already in
1734// use, the added codecs payload types are changed.
1735TEST_F(MediaSessionDescriptionFactoryTest,
1736 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1737 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001738 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001739 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001740 f1_.set_video_codecs(f1_codecs);
1741
1742 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001743 opts.recv_audio = true;
1744 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001745
kwiberg31022942016-03-11 14:18:21 -08001746 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1747 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001748 f2_.CreateAnswer(offer.get(), opts, NULL));
1749
1750 const AudioContentDescription* acd =
1751 GetFirstAudioContentDescription(answer.get());
1752 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1753
1754 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1755 // reference be the same as an audio codec that was negotiated in the
1756 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001757 opts.recv_audio = true;
1758 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001759
1760 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1761 int used_pl_type = acd->codecs()[0].id;
1762 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001763 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001764 f2_.set_video_codecs(f2_codecs);
1765
kwiberg31022942016-03-11 14:18:21 -08001766 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001767 f2_.CreateOffer(opts, answer.get()));
1768 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001769 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001770 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1771
1772 const AudioContentDescription* updated_acd =
1773 GetFirstAudioContentDescription(answer.get());
1774 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1775
1776 const VideoContentDescription* updated_vcd =
1777 GetFirstVideoContentDescription(updated_answer.get());
1778
1779 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001780 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001781 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1782 EXPECT_NE(used_pl_type, new_h264_pl_type);
1783 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001784 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001785 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1786 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1787}
1788
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001789// Create an updated offer with RTX after creating an answer to an offer
1790// without RTX, and with different default payload types.
1791// Verify that the added RTX codec references the correct payload type.
1792TEST_F(MediaSessionDescriptionFactoryTest,
1793 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1794 MediaSessionOptions opts;
1795 opts.recv_video = true;
1796 opts.recv_audio = true;
1797
1798 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1799 // This creates rtx for H264 with the payload type |f2_| uses.
1800 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1801 f2_.set_video_codecs(f2_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.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001805 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001806 f2_.CreateAnswer(offer.get(), opts, nullptr));
1807
1808 const VideoContentDescription* vcd =
1809 GetFirstVideoContentDescription(answer.get());
1810
1811 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1812 EXPECT_EQ(expected_codecs, vcd->codecs());
1813
1814 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1815 // updated offer, even though the default payload types are different from
1816 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001817 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001818 f2_.CreateOffer(opts, answer.get()));
1819 ASSERT_TRUE(updated_offer);
1820
1821 const VideoContentDescription* updated_vcd =
1822 GetFirstVideoContentDescription(updated_offer.get());
1823
1824 // New offer should attempt to add H263, and RTX for H264.
1825 expected_codecs.push_back(kVideoCodecs2[1]);
1826 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1827 &expected_codecs);
1828 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1829}
1830
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001831// Test that RTX is ignored when there is no associated payload type parameter.
1832TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1833 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001834 opts.recv_video = true;
1835 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001836 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001837 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07001838 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001839 f1_.set_video_codecs(f1_codecs);
1840
1841 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001842 // This creates RTX for H264 with the payload type |f2_| uses.
1843 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001844 f2_.set_video_codecs(f2_codecs);
1845
kwiberg31022942016-03-11 14:18:21 -08001846 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001847 ASSERT_TRUE(offer.get() != NULL);
1848 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1849 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1850 // is possible to test that that RTX is dropped when
1851 // kCodecParamAssociatedPayloadType is missing in the offer.
1852 VideoContentDescription* desc =
1853 static_cast<cricket::VideoContentDescription*>(
1854 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1855 ASSERT_TRUE(desc != NULL);
1856 std::vector<VideoCodec> codecs = desc->codecs();
1857 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1858 iter != codecs.end(); ++iter) {
1859 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1860 iter->params.clear();
1861 }
1862 }
1863 desc->set_codecs(codecs);
1864
kwiberg31022942016-03-11 14:18:21 -08001865 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866 f2_.CreateAnswer(offer.get(), opts, NULL));
1867
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001868 std::vector<std::string> codec_names =
1869 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1870 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1871 cricket::kRtxCodecName));
1872}
1873
1874// Test that RTX will be filtered out in the answer if its associated payload
1875// type doesn't match the local value.
1876TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1877 MediaSessionOptions opts;
1878 opts.recv_video = true;
1879 opts.recv_audio = false;
1880 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1881 // This creates RTX for H264 in sender.
1882 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1883 f1_.set_video_codecs(f1_codecs);
1884
1885 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1886 // This creates RTX for H263 in receiver.
1887 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1888 f2_.set_video_codecs(f2_codecs);
1889
kwiberg31022942016-03-11 14:18:21 -08001890 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001891 ASSERT_TRUE(offer.get() != NULL);
1892 // Associated payload type doesn't match, therefore, RTX codec is removed in
1893 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001894 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001895 f2_.CreateAnswer(offer.get(), opts, NULL));
1896
1897 std::vector<std::string> codec_names =
1898 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1899 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1900 cricket::kRtxCodecName));
1901}
1902
1903// Test that when multiple RTX codecs are offered, only the matched RTX codec
1904// is added in the answer, and the unsupported RTX codec is filtered out.
1905TEST_F(MediaSessionDescriptionFactoryTest,
1906 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1907 MediaSessionOptions opts;
1908 opts.recv_video = true;
1909 opts.recv_audio = false;
1910 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1911 // This creates RTX for H264-SVC in sender.
1912 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1913 f1_.set_video_codecs(f1_codecs);
1914
1915 // This creates RTX for H264 in sender.
1916 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1917 f1_.set_video_codecs(f1_codecs);
1918
1919 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1920 // This creates RTX for H264 in receiver.
1921 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1922 f2_.set_video_codecs(f2_codecs);
1923
1924 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1925 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001926 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001927 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001928 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001929 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001930 const VideoContentDescription* vcd =
1931 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001932 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1933 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1934 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001935
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001936 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001937}
1938
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001939// Test that after one RTX codec has been negotiated, a new offer can attempt
1940// to add another.
1941TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1942 MediaSessionOptions opts;
1943 opts.recv_video = true;
1944 opts.recv_audio = false;
1945 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1946 // This creates RTX for H264 for the offerer.
1947 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1948 f1_.set_video_codecs(f1_codecs);
1949
kwiberg31022942016-03-11 14:18:21 -08001950 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001951 ASSERT_TRUE(offer);
1952 const VideoContentDescription* vcd =
1953 GetFirstVideoContentDescription(offer.get());
1954
1955 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1956 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1957 &expected_codecs);
1958 EXPECT_EQ(expected_codecs, vcd->codecs());
1959
1960 // Now, attempt to add RTX for H264-SVC.
1961 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1962 f1_.set_video_codecs(f1_codecs);
1963
kwiberg31022942016-03-11 14:18:21 -08001964 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001965 f1_.CreateOffer(opts, offer.get()));
1966 ASSERT_TRUE(updated_offer);
1967 vcd = GetFirstVideoContentDescription(updated_offer.get());
1968
1969 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1970 &expected_codecs);
1971 EXPECT_EQ(expected_codecs, vcd->codecs());
1972}
1973
Noah Richards2e7a0982015-05-18 14:02:54 -07001974// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1975// generated for each simulcast ssrc and correctly grouped.
1976TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1977 MediaSessionOptions opts;
1978 opts.recv_video = true;
1979 opts.recv_audio = false;
1980
1981 // Add simulcast streams.
1982 opts.AddSendVideoStream("stream1", "stream1label", 3);
1983
1984 // Use a single real codec, and then add RTX for it.
1985 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07001986 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07001987 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1988 f1_.set_video_codecs(f1_codecs);
1989
1990 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1991 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001992 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001993 ASSERT_TRUE(offer.get() != NULL);
1994 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1995 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1996 ASSERT_TRUE(desc != NULL);
1997 EXPECT_TRUE(desc->multistream());
1998 const StreamParamsVec& streams = desc->streams();
1999 // Single stream.
2000 ASSERT_EQ(1u, streams.size());
2001 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2002 EXPECT_EQ(6u, streams[0].ssrcs.size());
2003 // And should have a SIM group for the simulcast.
2004 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2005 // And a FID group for RTX.
2006 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002007 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002008 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2009 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002010 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002011 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2012 EXPECT_EQ(3u, fid_ssrcs.size());
2013}
2014
brandtr03d5fb12016-11-22 03:37:59 -08002015// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2016// together with a FEC-FR grouping.
2017TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2018 MediaSessionOptions opts;
2019 opts.recv_video = true;
2020 opts.recv_audio = false;
2021
2022 // Add single stream.
2023 opts.AddSendVideoStream("stream1", "stream1label", 1);
2024
2025 // Use a single real codec, and then add FlexFEC for it.
2026 std::vector<VideoCodec> f1_codecs;
2027 f1_codecs.push_back(VideoCodec(97, "H264"));
2028 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2029 f1_.set_video_codecs(f1_codecs);
2030
2031 // Ensure that the offer has a single FlexFEC ssrc and that
2032 // there is no FEC-FR ssrc + grouping for each.
2033 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2034 ASSERT_TRUE(offer.get() != nullptr);
2035 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2036 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2037 ASSERT_TRUE(desc != nullptr);
2038 EXPECT_TRUE(desc->multistream());
2039 const StreamParamsVec& streams = desc->streams();
2040 // Single stream.
2041 ASSERT_EQ(1u, streams.size());
2042 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2043 EXPECT_EQ(2u, streams[0].ssrcs.size());
2044 // And should have a FEC-FR group for FlexFEC.
2045 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2046 std::vector<uint32_t> primary_ssrcs;
2047 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2048 ASSERT_EQ(1u, primary_ssrcs.size());
2049 uint32_t flexfec_ssrc;
2050 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2051 EXPECT_NE(flexfec_ssrc, 0u);
2052}
2053
2054// Test that FlexFEC is disabled for simulcast.
2055// TODO(brandtr): Remove this test when we support simulcast, either through
2056// multiple FlexfecSenders, or through multistream protection.
2057TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2058 MediaSessionOptions opts;
2059 opts.recv_video = true;
2060 opts.recv_audio = false;
2061
2062 // Add simulcast streams.
2063 opts.AddSendVideoStream("stream1", "stream1label", 3);
2064
2065 // Use a single real codec, and then add FlexFEC for it.
2066 std::vector<VideoCodec> f1_codecs;
2067 f1_codecs.push_back(VideoCodec(97, "H264"));
2068 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2069 f1_.set_video_codecs(f1_codecs);
2070
2071 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2072 // there is no FEC-FR ssrc + grouping for each.
2073 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2074 ASSERT_TRUE(offer.get() != nullptr);
2075 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2076 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2077 ASSERT_TRUE(desc != nullptr);
2078 EXPECT_FALSE(desc->multistream());
2079 const StreamParamsVec& streams = desc->streams();
2080 // Single stream.
2081 ASSERT_EQ(1u, streams.size());
2082 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2083 EXPECT_EQ(3u, streams[0].ssrcs.size());
2084 // And should have a SIM group for the simulcast.
2085 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2086 // And not a FEC-FR group for FlexFEC.
2087 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2088 std::vector<uint32_t> primary_ssrcs;
2089 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2090 EXPECT_EQ(3u, primary_ssrcs.size());
2091 for (uint32_t primary_ssrc : primary_ssrcs) {
2092 uint32_t flexfec_ssrc;
2093 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2094 }
2095}
2096
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002097// Create an updated offer after creating an answer to the original offer and
2098// verify that the RTP header extensions that were part of the original answer
2099// are not changed in the updated offer.
2100TEST_F(MediaSessionDescriptionFactoryTest,
2101 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2102 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002103 opts.recv_audio = true;
2104 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002105
2106 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2107 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2108 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2109 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2110
kwiberg31022942016-03-11 14:18:21 -08002111 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2112 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002113 f2_.CreateAnswer(offer.get(), opts, NULL));
2114
2115 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
2116 GetFirstAudioContentDescription(
2117 answer.get())->rtp_header_extensions());
2118 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
2119 GetFirstVideoContentDescription(
2120 answer.get())->rtp_header_extensions());
2121
kwiberg31022942016-03-11 14:18:21 -08002122 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002123 f2_.CreateOffer(opts, answer.get()));
2124
2125 // The expected RTP header extensions in the new offer are the resulting
2126 // extensions from the first offer/answer exchange plus the extensions only
2127 // |f2_| offer.
2128 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002129 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002130 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2131 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2132 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002133 };
2134
2135 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002136 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002137 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2138 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2139 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002140 };
2141
2142 const AudioContentDescription* updated_acd =
2143 GetFirstAudioContentDescription(updated_offer.get());
2144 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2145 updated_acd->rtp_header_extensions());
2146
2147 const VideoContentDescription* updated_vcd =
2148 GetFirstVideoContentDescription(updated_offer.get());
2149 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2150 updated_vcd->rtp_header_extensions());
2151}
2152
deadbeefa5b273a2015-08-20 17:30:13 -07002153// Verify that if the same RTP extension URI is used for audio and video, the
2154// same ID is used. Also verify that the ID isn't changed when creating an
2155// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002156TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002157 MediaSessionOptions opts;
2158 opts.recv_audio = true;
2159 opts.recv_video = true;
2160
2161 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2162 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2163
kwiberg31022942016-03-11 14:18:21 -08002164 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002165
2166 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2167 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002168 const RtpExtension kExpectedVideoRtpExtension[] = {
2169 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002170 };
2171
2172 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2173 GetFirstAudioContentDescription(
2174 offer.get())->rtp_header_extensions());
2175 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2176 GetFirstVideoContentDescription(
2177 offer.get())->rtp_header_extensions());
2178
2179 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002180 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002181 f1_.CreateOffer(opts, offer.get()));
2182
2183 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2184 GetFirstAudioContentDescription(
2185 updated_offer.get())->rtp_header_extensions());
2186 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2187 GetFirstVideoContentDescription(
2188 updated_offer.get())->rtp_header_extensions());
2189}
2190
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002191TEST(MediaSessionDescription, CopySessionDescription) {
2192 SessionDescription source;
2193 cricket::ContentGroup group(cricket::CN_AUDIO);
2194 source.AddGroup(group);
2195 AudioContentDescription* acd(new AudioContentDescription());
2196 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2197 acd->AddLegacyStream(1);
2198 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
2199 VideoContentDescription* vcd(new VideoContentDescription());
2200 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2201 vcd->AddLegacyStream(2);
2202 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
2203
kwiberg31022942016-03-11 14:18:21 -08002204 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002205 ASSERT_TRUE(copy.get() != NULL);
2206 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2207 const ContentInfo* ac = copy->GetContentByName("audio");
2208 const ContentInfo* vc = copy->GetContentByName("video");
2209 ASSERT_TRUE(ac != NULL);
2210 ASSERT_TRUE(vc != NULL);
2211 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
2212 const AudioContentDescription* acd_copy =
2213 static_cast<const AudioContentDescription*>(ac->description);
2214 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2215 EXPECT_EQ(1u, acd->first_ssrc());
2216
2217 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
2218 const VideoContentDescription* vcd_copy =
2219 static_cast<const VideoContentDescription*>(vc->description);
2220 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2221 EXPECT_EQ(2u, vcd->first_ssrc());
2222}
2223
2224// The below TestTransportInfoXXX tests create different offers/answers, and
2225// ensure the TransportInfo in the SessionDescription matches what we expect.
2226TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2227 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002228 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002229 TestTransportInfo(true, options, false);
2230}
2231
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002232TEST_F(MediaSessionDescriptionFactoryTest,
2233 TestTransportInfoOfferIceRenomination) {
2234 MediaSessionOptions options;
2235 options.enable_ice_renomination = true;
2236 TestTransportInfo(true, options, false);
2237}
2238
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002239TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2240 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002241 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002242 TestTransportInfo(true, options, true);
2243}
2244
2245TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2246 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002247 options.recv_audio = true;
2248 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002249 options.data_channel_type = cricket::DCT_RTP;
2250 TestTransportInfo(true, options, false);
2251}
2252
2253TEST_F(MediaSessionDescriptionFactoryTest,
2254 TestTransportInfoOfferMultimediaCurrent) {
2255 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002256 options.recv_audio = true;
2257 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002258 options.data_channel_type = cricket::DCT_RTP;
2259 TestTransportInfo(true, options, true);
2260}
2261
2262TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2263 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002264 options.recv_audio = true;
2265 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002266 options.data_channel_type = cricket::DCT_RTP;
2267 options.bundle_enabled = true;
2268 TestTransportInfo(true, options, false);
2269}
2270
2271TEST_F(MediaSessionDescriptionFactoryTest,
2272 TestTransportInfoOfferBundleCurrent) {
2273 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002274 options.recv_audio = true;
2275 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002276 options.data_channel_type = cricket::DCT_RTP;
2277 options.bundle_enabled = true;
2278 TestTransportInfo(true, options, true);
2279}
2280
2281TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2282 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002283 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002284 TestTransportInfo(false, options, false);
2285}
2286
2287TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002288 TestTransportInfoAnswerIceRenomination) {
2289 MediaSessionOptions options;
2290 options.enable_ice_renomination = true;
2291 TestTransportInfo(false, options, false);
2292}
2293
2294TEST_F(MediaSessionDescriptionFactoryTest,
2295 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002296 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002297 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002298 TestTransportInfo(false, options, true);
2299}
2300
2301TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2302 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002303 options.recv_audio = true;
2304 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002305 options.data_channel_type = cricket::DCT_RTP;
2306 TestTransportInfo(false, options, false);
2307}
2308
2309TEST_F(MediaSessionDescriptionFactoryTest,
2310 TestTransportInfoAnswerMultimediaCurrent) {
2311 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002312 options.recv_audio = true;
2313 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002314 options.data_channel_type = cricket::DCT_RTP;
2315 TestTransportInfo(false, options, true);
2316}
2317
2318TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2319 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002320 options.recv_audio = true;
2321 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002322 options.data_channel_type = cricket::DCT_RTP;
2323 options.bundle_enabled = true;
2324 TestTransportInfo(false, options, false);
2325}
2326
2327TEST_F(MediaSessionDescriptionFactoryTest,
2328 TestTransportInfoAnswerBundleCurrent) {
2329 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002330 options.recv_audio = true;
2331 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002332 options.data_channel_type = cricket::DCT_RTP;
2333 options.bundle_enabled = true;
2334 TestTransportInfo(false, options, true);
2335}
2336
2337// Create an offer with bundle enabled and verify the crypto parameters are
2338// the common set of the available cryptos.
2339TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2340 TestCryptoWithBundle(true);
2341}
2342
2343// Create an answer with bundle enabled and verify the crypto parameters are
2344// the common set of the available cryptos.
2345TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2346 TestCryptoWithBundle(false);
2347}
2348
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002349// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2350// DTLS is not enabled locally.
2351TEST_F(MediaSessionDescriptionFactoryTest,
2352 TestOfferDtlsSavpfWithoutDtlsFailed) {
2353 f1_.set_secure(SEC_ENABLED);
2354 f2_.set_secure(SEC_ENABLED);
2355 tdf1_.set_secure(SEC_DISABLED);
2356 tdf2_.set_secure(SEC_DISABLED);
2357
kwiberg31022942016-03-11 14:18:21 -08002358 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002359 f1_.CreateOffer(MediaSessionOptions(), NULL));
2360 ASSERT_TRUE(offer.get() != NULL);
2361 ContentInfo* offer_content = offer->GetContentByName("audio");
2362 ASSERT_TRUE(offer_content != NULL);
2363 AudioContentDescription* offer_audio_desc =
2364 static_cast<AudioContentDescription*>(offer_content->description);
2365 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2366
kwiberg31022942016-03-11 14:18:21 -08002367 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002368 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2369 ASSERT_TRUE(answer != NULL);
2370 ContentInfo* answer_content = answer->GetContentByName("audio");
2371 ASSERT_TRUE(answer_content != NULL);
2372
2373 ASSERT_TRUE(answer_content->rejected);
2374}
2375
2376// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2377// UDP/TLS/RTP/SAVPF.
2378TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2379 f1_.set_secure(SEC_ENABLED);
2380 f2_.set_secure(SEC_ENABLED);
2381 tdf1_.set_secure(SEC_ENABLED);
2382 tdf2_.set_secure(SEC_ENABLED);
2383
kwiberg31022942016-03-11 14:18:21 -08002384 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002385 f1_.CreateOffer(MediaSessionOptions(), NULL));
2386 ASSERT_TRUE(offer.get() != NULL);
2387 ContentInfo* offer_content = offer->GetContentByName("audio");
2388 ASSERT_TRUE(offer_content != NULL);
2389 AudioContentDescription* offer_audio_desc =
2390 static_cast<AudioContentDescription*>(offer_content->description);
2391 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2392
kwiberg31022942016-03-11 14:18:21 -08002393 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002394 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2395 ASSERT_TRUE(answer != NULL);
2396
2397 const ContentInfo* answer_content = answer->GetContentByName("audio");
2398 ASSERT_TRUE(answer_content != NULL);
2399 ASSERT_FALSE(answer_content->rejected);
2400
2401 const AudioContentDescription* answer_audio_desc =
2402 static_cast<const AudioContentDescription*>(answer_content->description);
2403 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2404 answer_audio_desc->protocol());
2405}
2406
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002407// Test that we include both SDES and DTLS in the offer, but only include SDES
2408// in the answer if DTLS isn't negotiated.
2409TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2410 f1_.set_secure(SEC_ENABLED);
2411 f2_.set_secure(SEC_ENABLED);
2412 tdf1_.set_secure(SEC_ENABLED);
2413 tdf2_.set_secure(SEC_DISABLED);
2414 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002415 options.recv_audio = true;
2416 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002417 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002418 const cricket::MediaContentDescription* audio_media_desc;
2419 const cricket::MediaContentDescription* video_media_desc;
2420 const cricket::TransportDescription* audio_trans_desc;
2421 const cricket::TransportDescription* video_trans_desc;
2422
2423 // Generate an offer with SDES and DTLS support.
2424 offer.reset(f1_.CreateOffer(options, NULL));
2425 ASSERT_TRUE(offer.get() != NULL);
2426
2427 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2428 offer->GetContentDescriptionByName("audio"));
2429 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002430 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002431 offer->GetContentDescriptionByName("video"));
2432 ASSERT_TRUE(video_media_desc != NULL);
2433 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2434 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2435
2436 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2437 ASSERT_TRUE(audio_trans_desc != NULL);
2438 video_trans_desc = offer->GetTransportDescriptionByName("video");
2439 ASSERT_TRUE(video_trans_desc != NULL);
2440 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2441 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2442
2443 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2444 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2445 ASSERT_TRUE(answer.get() != NULL);
2446
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002447 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002448 answer->GetContentDescriptionByName("audio"));
2449 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002450 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002451 answer->GetContentDescriptionByName("video"));
2452 ASSERT_TRUE(video_media_desc != NULL);
2453 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2454 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2455
2456 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2457 ASSERT_TRUE(audio_trans_desc != NULL);
2458 video_trans_desc = answer->GetTransportDescriptionByName("video");
2459 ASSERT_TRUE(video_trans_desc != NULL);
2460 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2461 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2462
2463 // Enable DTLS; the answer should now only have DTLS support.
2464 tdf2_.set_secure(SEC_ENABLED);
2465 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2466 ASSERT_TRUE(answer.get() != NULL);
2467
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002468 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002469 answer->GetContentDescriptionByName("audio"));
2470 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002471 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002472 answer->GetContentDescriptionByName("video"));
2473 ASSERT_TRUE(video_media_desc != NULL);
2474 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2475 EXPECT_TRUE(video_media_desc->cryptos().empty());
2476 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2477 audio_media_desc->protocol());
2478 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2479 video_media_desc->protocol());
2480
2481 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2482 ASSERT_TRUE(audio_trans_desc != NULL);
2483 video_trans_desc = answer->GetTransportDescriptionByName("video");
2484 ASSERT_TRUE(video_trans_desc != NULL);
2485 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2486 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002487
2488 // Try creating offer again. DTLS enabled now, crypto's should be empty
2489 // in new offer.
2490 offer.reset(f1_.CreateOffer(options, offer.get()));
2491 ASSERT_TRUE(offer.get() != NULL);
2492 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2493 offer->GetContentDescriptionByName("audio"));
2494 ASSERT_TRUE(audio_media_desc != NULL);
2495 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2496 offer->GetContentDescriptionByName("video"));
2497 ASSERT_TRUE(video_media_desc != NULL);
2498 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2499 EXPECT_TRUE(video_media_desc->cryptos().empty());
2500
2501 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2502 ASSERT_TRUE(audio_trans_desc != NULL);
2503 video_trans_desc = offer->GetTransportDescriptionByName("video");
2504 ASSERT_TRUE(video_trans_desc != NULL);
2505 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2506 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002507}
2508
2509// Test that an answer can't be created if cryptos are required but the offer is
2510// unsecure.
2511TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2512 MediaSessionOptions options;
2513 f1_.set_secure(SEC_DISABLED);
2514 tdf1_.set_secure(SEC_DISABLED);
2515 f2_.set_secure(SEC_REQUIRED);
2516 tdf1_.set_secure(SEC_ENABLED);
2517
kwiberg31022942016-03-11 14:18:21 -08002518 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002519 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002520 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002521 f2_.CreateAnswer(offer.get(), options, NULL));
2522 EXPECT_TRUE(answer.get() == NULL);
2523}
2524
2525// Test that we accept a DTLS offer without SDES and create an appropriate
2526// answer.
2527TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2528 f1_.set_secure(SEC_DISABLED);
2529 f2_.set_secure(SEC_ENABLED);
2530 tdf1_.set_secure(SEC_ENABLED);
2531 tdf2_.set_secure(SEC_ENABLED);
2532 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002533 options.recv_audio = true;
2534 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002535 options.data_channel_type = cricket::DCT_RTP;
2536
kwiberg31022942016-03-11 14:18:21 -08002537 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002538
2539 // Generate an offer with DTLS but without SDES.
2540 offer.reset(f1_.CreateOffer(options, NULL));
2541 ASSERT_TRUE(offer.get() != NULL);
2542
2543 const AudioContentDescription* audio_offer =
2544 GetFirstAudioContentDescription(offer.get());
2545 ASSERT_TRUE(audio_offer->cryptos().empty());
2546 const VideoContentDescription* video_offer =
2547 GetFirstVideoContentDescription(offer.get());
2548 ASSERT_TRUE(video_offer->cryptos().empty());
2549 const DataContentDescription* data_offer =
2550 GetFirstDataContentDescription(offer.get());
2551 ASSERT_TRUE(data_offer->cryptos().empty());
2552
2553 const cricket::TransportDescription* audio_offer_trans_desc =
2554 offer->GetTransportDescriptionByName("audio");
2555 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2556 const cricket::TransportDescription* video_offer_trans_desc =
2557 offer->GetTransportDescriptionByName("video");
2558 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2559 const cricket::TransportDescription* data_offer_trans_desc =
2560 offer->GetTransportDescriptionByName("data");
2561 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2562
2563 // Generate an answer with DTLS.
2564 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2565 ASSERT_TRUE(answer.get() != NULL);
2566
2567 const cricket::TransportDescription* audio_answer_trans_desc =
2568 answer->GetTransportDescriptionByName("audio");
2569 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2570 const cricket::TransportDescription* video_answer_trans_desc =
2571 answer->GetTransportDescriptionByName("video");
2572 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2573 const cricket::TransportDescription* data_answer_trans_desc =
2574 answer->GetTransportDescriptionByName("data");
2575 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2576}
2577
2578// Verifies if vad_enabled option is set to false, CN codecs are not present in
2579// offer or answer.
2580TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2581 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002582 options.recv_audio = true;
2583 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002584 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002585 ASSERT_TRUE(offer.get() != NULL);
2586 const ContentInfo* audio_content = offer->GetContentByName("audio");
2587 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2588
2589 options.vad_enabled = false;
2590 offer.reset(f1_.CreateOffer(options, NULL));
2591 ASSERT_TRUE(offer.get() != NULL);
2592 audio_content = offer->GetContentByName("audio");
2593 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002594 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002595 f1_.CreateAnswer(offer.get(), options, NULL));
2596 ASSERT_TRUE(answer.get() != NULL);
2597 audio_content = answer->GetContentByName("audio");
2598 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2599}
deadbeef44f08192015-12-15 16:20:09 -08002600
2601// Test that the content name ("mid" in SDP) is unchanged when creating a
2602// new offer.
2603TEST_F(MediaSessionDescriptionFactoryTest,
2604 TestContentNameNotChangedInSubsequentOffers) {
2605 MediaSessionOptions opts;
2606 opts.recv_audio = true;
2607 opts.recv_video = true;
2608 opts.data_channel_type = cricket::DCT_SCTP;
2609 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002610 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002611 for (ContentInfo& content : offer->contents()) {
2612 content.name.append("_modified");
2613 }
2614
kwiberg31022942016-03-11 14:18:21 -08002615 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002616 f1_.CreateOffer(opts, offer.get()));
2617 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2618 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2619 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2620 ASSERT_TRUE(audio_content != nullptr);
2621 ASSERT_TRUE(video_content != nullptr);
2622 ASSERT_TRUE(data_content != nullptr);
2623 EXPECT_EQ("audio_modified", audio_content->name);
2624 EXPECT_EQ("video_modified", video_content->name);
2625 EXPECT_EQ("data_modified", data_content->name);
2626}
zhihuangcf5b37c2016-05-05 11:44:35 -07002627
2628class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2629 public:
2630 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07002631 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
2632 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07002633 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2634 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07002635 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
2636 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07002637 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2638 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2639 f1_.set_secure(SEC_ENABLED);
2640 f2_.set_secure(SEC_ENABLED);
2641 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002642 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002643 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002644 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002645 tdf1_.set_secure(SEC_ENABLED);
2646 tdf2_.set_secure(SEC_ENABLED);
2647 }
2648
2649 protected:
2650 MediaSessionDescriptionFactory f1_;
2651 MediaSessionDescriptionFactory f2_;
2652 TransportDescriptionFactory tdf1_;
2653 TransportDescriptionFactory tdf2_;
2654};
2655
2656TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2657 MediaSessionOptions opts;
2658 opts.recv_video = true;
2659 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2660 ASSERT_TRUE(offer.get() != nullptr);
2661 // Set the protocol for all the contents.
2662 for (auto content : offer.get()->contents()) {
2663 static_cast<MediaContentDescription*>(content.description)
2664 ->set_protocol(GetParam());
2665 }
2666 std::unique_ptr<SessionDescription> answer(
2667 f2_.CreateAnswer(offer.get(), opts, nullptr));
2668 const ContentInfo* ac = answer->GetContentByName("audio");
2669 const ContentInfo* vc = answer->GetContentByName("video");
2670 ASSERT_TRUE(ac != nullptr);
2671 ASSERT_TRUE(vc != nullptr);
2672 EXPECT_FALSE(ac->rejected); // the offer is accepted
2673 EXPECT_FALSE(vc->rejected);
2674 const AudioContentDescription* acd =
2675 static_cast<const AudioContentDescription*>(ac->description);
2676 const VideoContentDescription* vcd =
2677 static_cast<const VideoContentDescription*>(vc->description);
2678 EXPECT_EQ(GetParam(), acd->protocol());
2679 EXPECT_EQ(GetParam(), vcd->protocol());
2680}
2681
2682INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2683 MediaProtocolTest,
2684 ::testing::ValuesIn(kMediaProtocols));
2685INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2686 MediaProtocolTest,
2687 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07002688
2689TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
2690 TransportDescriptionFactory tdf;
2691 MediaSessionDescriptionFactory sf(&tdf);
2692 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2693 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2694
2695 // The merged list of codecs should contain any send codecs that are also
2696 // nominally in the recieve codecs list. Payload types should be picked from
2697 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
2698 // (set to 1). This equals what happens when the send codecs are used in an
2699 // offer and the receive codecs are used in the following answer.
2700 const std::vector<AudioCodec> sendrecv_codecs =
2701 MAKE_VECTOR(kAudioCodecsAnswer);
2702 const std::vector<AudioCodec> no_codecs;
2703
2704 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
2705 << "Please don't change shared test data!";
2706 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
2707 << "Please don't change shared test data!";
2708 // Alter iLBC send codec to have zero channels, to test that that is handled
2709 // properly.
2710 send_codecs[1].channels = 0;
2711
2712 // Alther iLBC receive codec to be lowercase, to test that case conversions
2713 // are handled properly.
2714 recv_codecs[2].name = "ilbc";
2715
2716 // Test proper merge
2717 sf.set_audio_codecs(send_codecs, recv_codecs);
2718 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2719 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002720 EXPECT_TRUE(sf.audio_sendrecv_codecs() == sendrecv_codecs);
ossu075af922016-06-14 03:29:38 -07002721
2722 // Test empty send codecs list
2723 sf.set_audio_codecs(no_codecs, recv_codecs);
2724 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2725 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002726 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002727
2728 // Test empty recv codecs list
2729 sf.set_audio_codecs(send_codecs, no_codecs);
2730 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2731 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002732 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002733
2734 // Test all empty codec lists
2735 sf.set_audio_codecs(no_codecs, no_codecs);
2736 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2737 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002738 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002739}
2740
2741namespace {
2742void TestAudioCodecsOffer(MediaContentDirection direction,
2743 bool add_legacy_stream) {
2744 TransportDescriptionFactory tdf;
2745 MediaSessionDescriptionFactory sf(&tdf);
2746 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2747 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2748 const std::vector<AudioCodec> sendrecv_codecs =
2749 MAKE_VECTOR(kAudioCodecsAnswer);
2750 sf.set_audio_codecs(send_codecs, recv_codecs);
2751 sf.set_add_legacy_streams(add_legacy_stream);
2752
2753 MediaSessionOptions opts;
2754 opts.recv_audio = (direction == cricket::MD_RECVONLY ||
2755 direction == cricket::MD_SENDRECV);
2756 opts.recv_video = false;
2757 if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV)
2758 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2759
2760 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
2761 ASSERT_TRUE(offer.get() != NULL);
2762 const ContentInfo* ac = offer->GetContentByName("audio");
2763
2764 // If the factory didn't add any audio content to the offer, we cannot check
2765 // that the codecs put in are right. This happens when we neither want to send
2766 // nor receive audio. The checks are still in place if at some point we'd
2767 // instead create an inactive stream.
2768 if (ac) {
2769 AudioContentDescription* acd =
2770 static_cast<AudioContentDescription*>(ac->description);
2771 // sendrecv and inactive should both present lists as if the channel was to
2772 // be used for sending and receiving. Inactive essentially means it might
2773 // eventually be used anything, but we don't know more at this moment.
2774 if (acd->direction() == cricket::MD_SENDONLY) {
2775 EXPECT_TRUE(acd->codecs() == send_codecs);
2776 } else if (acd->direction() == cricket::MD_RECVONLY) {
2777 EXPECT_TRUE(acd->codecs() == recv_codecs);
2778 } else {
2779 EXPECT_TRUE(acd->codecs() == sendrecv_codecs);
2780 }
2781 }
2782}
2783
2784static const AudioCodec kOfferAnswerCodecs[] = {
2785 AudioCodec(0, "codec0", 16000, -1, 1),
2786 AudioCodec(1, "codec1", 8000, 13300, 1),
2787 AudioCodec(2, "codec2", 8000, 64000, 1),
2788 AudioCodec(3, "codec3", 8000, 64000, 1),
2789 AudioCodec(4, "codec4", 8000, 0, 2),
2790 AudioCodec(5, "codec5", 32000, 0, 1),
2791 AudioCodec(6, "codec6", 48000, 0, 1)
2792};
2793
2794
2795/* The codecs groups below are chosen as per the matrix below. The objective is
2796 * to have different sets of codecs in the inputs, to get unique sets of codecs
2797 * after negotiation, depending on offer and answer communication directions.
2798 * One-way directions in the offer should either result in the opposite
2799 * direction in the answer, or an inactive answer. Regardless, the choice of
2800 * codecs should be as if the answer contained the opposite direction.
2801 * Inactive offers should be treated as sendrecv/sendrecv.
2802 *
2803 * | Offer | Answer | Result
2804 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
2805 * 0 | x - - | - x - | x - - - -
2806 * 1 | x x x | - x - | x - - x -
2807 * 2 | - x - | x - - | - x - - -
2808 * 3 | x x x | x - - | - x x - -
2809 * 4 | - x - | x x x | - x - - -
2810 * 5 | x - - | x x x | x - - - -
2811 * 6 | x x x | x x x | x x x x x
2812 */
2813// Codecs used by offerer in the AudioCodecsAnswerTest
2814static const int kOfferSendCodecs[] = { 0, 1, 3, 5, 6 };
2815static const int kOfferRecvCodecs[] = { 1, 2, 3, 4, 6 };
2816// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
2817// jumbled to catch the answer not following the order in the offer.
2818static const int kAnswerSendCodecs[] = { 6, 5, 2, 3, 4 };
2819static const int kAnswerRecvCodecs[] = { 6, 5, 4, 1, 0 };
2820// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
2821static const int kResultSend_RecvCodecs[] = { 0, 1, 5, 6 };
2822static const int kResultRecv_SendCodecs[] = { 2, 3, 4, 6 };
2823static const int kResultSendrecv_SendCodecs[] = { 3, 6 };
2824static const int kResultSendrecv_RecvCodecs[] = { 1, 6 };
2825static const int kResultSendrecv_SendrecvCodecs[] = { 6 };
2826
2827template <typename T, int IDXS>
2828std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
2829 std::vector<T> out;
2830 out.reserve(IDXS);
2831 for (int idx : indices)
2832 out.push_back(array[idx]);
2833
2834 return out;
2835}
2836
2837void TestAudioCodecsAnswer(MediaContentDirection offer_direction,
2838 MediaContentDirection answer_direction,
2839 bool add_legacy_stream) {
2840 TransportDescriptionFactory offer_tdf;
2841 TransportDescriptionFactory answer_tdf;
2842 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
2843 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
2844 offer_factory.set_audio_codecs(
2845 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
2846 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
2847 answer_factory.set_audio_codecs(
2848 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
2849 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
2850
2851 // Never add a legacy stream to offer - we want to control the offer
2852 // parameters exactly.
2853 offer_factory.set_add_legacy_streams(false);
2854 answer_factory.set_add_legacy_streams(add_legacy_stream);
2855 MediaSessionOptions offer_opts;
2856 offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY ||
2857 offer_direction == cricket::MD_SENDRECV);
2858 offer_opts.recv_video = false;
2859 if (offer_direction == cricket::MD_SENDONLY ||
2860 offer_direction == cricket::MD_SENDRECV) {
2861 offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2862 }
2863
2864 std::unique_ptr<SessionDescription> offer(
2865 offer_factory.CreateOffer(offer_opts, NULL));
2866 ASSERT_TRUE(offer.get() != NULL);
2867
2868 MediaSessionOptions answer_opts;
2869 answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY ||
2870 answer_direction == cricket::MD_SENDRECV);
2871 answer_opts.recv_video = false;
2872 if (answer_direction == cricket::MD_SENDONLY ||
2873 answer_direction == cricket::MD_SENDRECV) {
2874 answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2875 }
2876 std::unique_ptr<SessionDescription> answer(
2877 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
2878 const ContentInfo* ac = answer->GetContentByName("audio");
2879
2880 // If the factory didn't add any audio content to the answer, we cannot check
2881 // that the codecs put in are right. This happens when we neither want to send
2882 // nor receive audio. The checks are still in place if at some point we'd
2883 // instead create an inactive stream.
2884 if (ac) {
2885 const AudioContentDescription* acd =
2886 static_cast<const AudioContentDescription*>(ac->description);
2887 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
2888
2889
2890 std::vector<AudioCodec> target_codecs;
2891 // For offers with sendrecv or inactive, we should never reply with more
2892 // codecs than offered, with these codec sets.
2893 switch (offer_direction) {
2894 case cricket::MD_INACTIVE:
2895 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2896 kResultSendrecv_SendrecvCodecs);
2897 break;
2898 case cricket::MD_SENDONLY:
2899 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2900 kResultSend_RecvCodecs);
2901 break;
2902 case cricket::MD_RECVONLY:
2903 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2904 kResultRecv_SendCodecs);
2905 break;
2906 case cricket::MD_SENDRECV:
2907 if (acd->direction() == cricket::MD_SENDONLY) {
2908 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2909 kResultSendrecv_SendCodecs);
2910 } else if (acd->direction() == cricket::MD_RECVONLY) {
2911 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2912 kResultSendrecv_RecvCodecs);
2913 } else {
2914 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2915 kResultSendrecv_SendrecvCodecs);
2916 }
2917 break;
2918 }
2919
2920 auto format_codecs = [] (const std::vector<AudioCodec>& codecs) {
2921 std::stringstream os;
2922 bool first = true;
2923 os << "{";
2924 for (const auto& c : codecs) {
2925 os << (first ? " " : ", ") << c.id;
2926 first = false;
2927 }
2928 os << " }";
2929 return os.str();
2930 };
2931
2932 EXPECT_TRUE(acd->codecs() == target_codecs)
2933 << "Expected: " << format_codecs(target_codecs)
2934 << ", got: " << format_codecs(acd->codecs())
2935 << "; Offered: " << MediaContentDirectionToString(offer_direction)
2936 << ", answerer wants: "
2937 << MediaContentDirectionToString(answer_direction)
2938 << "; got: " << MediaContentDirectionToString(acd->direction());
2939 } else {
2940 EXPECT_EQ(offer_direction, cricket::MD_INACTIVE)
2941 << "Only inactive offers are allowed to not generate any audio content";
2942 }
2943}
brandtr03d5fb12016-11-22 03:37:59 -08002944
2945} // namespace
ossu075af922016-06-14 03:29:38 -07002946
2947class AudioCodecsOfferTest
ehmaldonadoabcef5d2017-02-08 04:07:11 -08002948 : public ::testing::TestWithParam<::testing::tuple<MediaContentDirection,
2949 bool>> {
ossu075af922016-06-14 03:29:38 -07002950};
2951
2952TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08002953 TestAudioCodecsOffer(::testing::get<0>(GetParam()),
2954 ::testing::get<1>(GetParam()));
ossu075af922016-06-14 03:29:38 -07002955}
2956
2957INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
2958 AudioCodecsOfferTest,
2959 ::testing::Combine(
2960 ::testing::Values(cricket::MD_SENDONLY,
2961 cricket::MD_RECVONLY,
2962 cricket::MD_SENDRECV,
2963 cricket::MD_INACTIVE),
2964 ::testing::Bool()));
2965
2966class AudioCodecsAnswerTest
ehmaldonadoabcef5d2017-02-08 04:07:11 -08002967 : public ::testing::TestWithParam<::testing::tuple<MediaContentDirection,
2968 MediaContentDirection,
2969 bool>> {
ossu075af922016-06-14 03:29:38 -07002970};
2971
2972TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
ehmaldonadoabcef5d2017-02-08 04:07:11 -08002973 TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
2974 ::testing::get<1>(GetParam()),
2975 ::testing::get<2>(GetParam()));
ossu075af922016-06-14 03:29:38 -07002976}
2977
2978INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
2979 AudioCodecsAnswerTest,
2980 ::testing::Combine(
2981 ::testing::Values(cricket::MD_SENDONLY,
2982 cricket::MD_RECVONLY,
2983 cricket::MD_SENDRECV,
2984 cricket::MD_INACTIVE),
2985 ::testing::Values(cricket::MD_SENDONLY,
2986 cricket::MD_RECVONLY,
2987 cricket::MD_SENDRECV,
2988 cricket::MD_INACTIVE),
2989 ::testing::Bool()));