blob: 4d6418159a76f6dcb93f802c33dd2c09be0f71f0 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander65c7f672016-02-12 00:05:01 -08002 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander65c7f672016-02-12 00:05:01 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
kwiberg31022942016-03-11 14:18:21 -080011#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012#include <string>
13#include <vector>
14
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000015#include "webrtc/base/fakesslidentity.h"
16#include "webrtc/base/gunit.h"
17#include "webrtc/base/messagedigest.h"
18#include "webrtc/base/ssladapter.h"
kjellandera96e2d72016-02-04 23:52:28 -080019#include "webrtc/media/base/codec.h"
20#include "webrtc/media/base/testutils.h"
kjellanderf4752772016-03-02 05:42:30 -080021#include "webrtc/p2p/base/p2pconstants.h"
kjellandera96e2d72016-02-04 23:52:28 -080022#include "webrtc/p2p/base/transportdescription.h"
23#include "webrtc/p2p/base/transportinfo.h"
kjellander@webrtc.org9b8df252016-02-12 06:47:59 +010024#include "webrtc/pc/mediasession.h"
25#include "webrtc/pc/srtpfilter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000026
27#ifdef HAVE_SRTP
28#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000029 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030 ASSERT_EQ(s, cd->cryptos().size()); \
31 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
32#else
33#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000034 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035 ASSERT_EQ(0U, cd->cryptos().size());
36#endif
37
38typedef std::vector<cricket::Candidate> Candidates;
39
40using cricket::MediaContentDescription;
41using cricket::MediaSessionDescriptionFactory;
ossu075af922016-06-14 03:29:38 -070042using cricket::MediaContentDirection;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000043using cricket::MediaSessionOptions;
44using cricket::MediaType;
45using cricket::SessionDescription;
46using cricket::SsrcGroup;
47using cricket::StreamParams;
48using cricket::StreamParamsVec;
49using cricket::TransportDescription;
50using cricket::TransportDescriptionFactory;
51using cricket::TransportInfo;
52using cricket::ContentInfo;
53using cricket::CryptoParamsVec;
54using cricket::AudioContentDescription;
55using cricket::VideoContentDescription;
56using cricket::DataContentDescription;
deadbeef44f08192015-12-15 16:20:09 -080057using cricket::GetFirstAudioContent;
58using cricket::GetFirstVideoContent;
59using cricket::GetFirstDataContent;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060using cricket::GetFirstAudioContentDescription;
61using cricket::GetFirstVideoContentDescription;
62using cricket::GetFirstDataContentDescription;
63using cricket::kAutoBandwidth;
64using cricket::AudioCodec;
65using cricket::VideoCodec;
66using cricket::DataCodec;
67using cricket::NS_JINGLE_RTP;
68using cricket::MEDIA_TYPE_AUDIO;
69using cricket::MEDIA_TYPE_VIDEO;
70using cricket::MEDIA_TYPE_DATA;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071using cricket::SEC_DISABLED;
72using cricket::SEC_ENABLED;
73using cricket::SEC_REQUIRED;
Guo-wei Shieh456696a2015-09-30 21:48:54 -070074using rtc::CS_AES_CM_128_HMAC_SHA1_32;
75using rtc::CS_AES_CM_128_HMAC_SHA1_80;
jbauchcb560652016-08-04 05:20:32 -070076using rtc::CS_AEAD_AES_128_GCM;
77using rtc::CS_AEAD_AES_256_GCM;
isheriff6f8d6862016-05-26 11:24:55 -070078using webrtc::RtpExtension;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079
80static const AudioCodec kAudioCodecs1[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070081 AudioCodec(103, "ISAC", 16000, -1, 1),
82 AudioCodec(102, "iLBC", 8000, 13300, 1),
83 AudioCodec(0, "PCMU", 8000, 64000, 1),
84 AudioCodec(8, "PCMA", 8000, 64000, 1),
85 AudioCodec(117, "red", 8000, 0, 1),
86 AudioCodec(107, "CN", 48000, 0, 1)};
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087
88static const AudioCodec kAudioCodecs2[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070089 AudioCodec(126, "speex", 16000, 22000, 1),
90 AudioCodec(0, "PCMU", 8000, 64000, 1),
91 AudioCodec(127, "iLBC", 8000, 13300, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000092};
93
94static const AudioCodec kAudioCodecsAnswer[] = {
deadbeef67cf2c12016-04-13 10:07:16 -070095 AudioCodec(102, "iLBC", 8000, 13300, 1),
96 AudioCodec(0, "PCMU", 8000, 64000, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +000097};
98
perkj26752742016-10-24 01:21:16 -070099static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
100 VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000101
perkj26752742016-10-24 01:21:16 -0700102static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
103 VideoCodec(127, "H263")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000104
perkj26752742016-10-24 01:21:16 -0700105static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000106
deadbeef67cf2c12016-04-13 10:07:16 -0700107static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
108 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000109
deadbeef67cf2c12016-04-13 10:07:16 -0700110static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
111 DataCodec(127, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112
deadbeef67cf2c12016-04-13 10:07:16 -0700113static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
114 DataCodec(99, "utf8-text")};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000115
isheriff6f8d6862016-05-26 11:24:55 -0700116static const RtpExtension kAudioRtpExtension1[] = {
117 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
118 RtpExtension("http://google.com/testing/audio_something", 10),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000119};
120
isheriff6f8d6862016-05-26 11:24:55 -0700121static const RtpExtension kAudioRtpExtension2[] = {
122 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
123 RtpExtension("http://google.com/testing/audio_something_else", 8),
124 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125};
126
isheriff6f8d6862016-05-26 11:24:55 -0700127static const RtpExtension kAudioRtpExtension3[] = {
128 RtpExtension("http://google.com/testing/audio_something", 2),
129 RtpExtension("http://google.com/testing/both_audio_and_video", 3),
deadbeefa5b273a2015-08-20 17:30:13 -0700130};
131
isheriff6f8d6862016-05-26 11:24:55 -0700132static const RtpExtension kAudioRtpExtensionAnswer[] = {
133 RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000134};
135
isheriff6f8d6862016-05-26 11:24:55 -0700136static const RtpExtension kVideoRtpExtension1[] = {
137 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
138 RtpExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000139};
140
isheriff6f8d6862016-05-26 11:24:55 -0700141static const RtpExtension kVideoRtpExtension2[] = {
142 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
143 RtpExtension("http://google.com/testing/video_something_else", 14),
144 RtpExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000145};
146
isheriff6f8d6862016-05-26 11:24:55 -0700147static const RtpExtension kVideoRtpExtension3[] = {
148 RtpExtension("http://google.com/testing/video_something", 4),
149 RtpExtension("http://google.com/testing/both_audio_and_video", 5),
deadbeefa5b273a2015-08-20 17:30:13 -0700150};
151
isheriff6f8d6862016-05-26 11:24:55 -0700152static const RtpExtension kVideoRtpExtensionAnswer[] = {
153 RtpExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000154};
155
Peter Boström0c4e06b2015-10-07 12:23:21 +0200156static const uint32_t kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
157static const uint32_t kSimSsrc[] = {10, 20, 30};
158static const uint32_t kFec1Ssrc[] = {10, 11};
159static const uint32_t kFec2Ssrc[] = {20, 21};
160static const uint32_t kFec3Ssrc[] = {30, 31};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000161
162static const char kMediaStream1[] = "stream_1";
163static const char kMediaStream2[] = "stream_2";
164static const char kVideoTrack1[] = "video_1";
165static const char kVideoTrack2[] = "video_2";
166static const char kAudioTrack1[] = "audio_1";
167static const char kAudioTrack2[] = "audio_2";
168static const char kAudioTrack3[] = "audio_3";
169static const char kDataTrack1[] = "data_1";
170static const char kDataTrack2[] = "data_2";
171static const char kDataTrack3[] = "data_3";
172
zhihuangcf5b37c2016-05-05 11:44:35 -0700173static const char* kMediaProtocols[] = {"RTP/AVP", "RTP/SAVP", "RTP/AVPF",
174 "RTP/SAVPF"};
175static const char* kMediaProtocolsDtls[] = {
176 "TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
177 "UDP/TLS/RTP/SAVP"};
178
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000179static bool IsMediaContentOfType(const ContentInfo* content,
180 MediaType media_type) {
181 const MediaContentDescription* mdesc =
182 static_cast<const MediaContentDescription*>(content->description);
183 return mdesc && mdesc->type() == media_type;
184}
185
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000186static cricket::MediaContentDirection
187GetMediaDirection(const ContentInfo* content) {
188 cricket::MediaContentDescription* desc =
189 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
190 return desc->direction();
191}
192
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000193static void AddRtxCodec(const VideoCodec& rtx_codec,
194 std::vector<VideoCodec>* codecs) {
magjedb05fa242016-11-11 04:00:16 -0800195 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000196 codecs->push_back(rtx_codec);
197}
198
199template <class T>
200static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
201 std::vector<std::string> codec_names;
202 for (const auto& codec : codecs) {
203 codec_names.push_back(codec.name);
204 }
205 return codec_names;
206}
207
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000208class MediaSessionDescriptionFactoryTest : public testing::Test {
209 public:
210 MediaSessionDescriptionFactoryTest()
Henrik Boström3a14bf32015-08-31 09:27:58 +0200211 : f1_(&tdf1_),
212 f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -0700213 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
214 MAKE_VECTOR(kAudioCodecs1));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
216 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -0700217 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
218 MAKE_VECTOR(kAudioCodecs2));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000219 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
220 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200221 tdf1_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700222 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
Henrik Boström3a14bf32015-08-31 09:27:58 +0200223 tdf2_.set_certificate(rtc::RTCCertificate::Create(
jbauch555604a2016-04-26 03:13:22 -0700224 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000225 }
226
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000227 // Create a video StreamParamsVec object with:
228 // - one video stream with 3 simulcast streams and FEC,
229 StreamParamsVec CreateComplexVideoStreamParamsVec() {
230 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
231 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
232 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
233 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
234
235 std::vector<SsrcGroup> ssrc_groups;
236 ssrc_groups.push_back(sim_group);
237 ssrc_groups.push_back(fec_group1);
238 ssrc_groups.push_back(fec_group2);
239 ssrc_groups.push_back(fec_group3);
240
241 StreamParams simulcast_params;
242 simulcast_params.id = kVideoTrack1;
243 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
244 simulcast_params.ssrc_groups = ssrc_groups;
245 simulcast_params.cname = "Video_SIM_FEC";
246 simulcast_params.sync_label = kMediaStream1;
247
248 StreamParamsVec video_streams;
249 video_streams.push_back(simulcast_params);
250
251 return video_streams;
252 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000253
254 bool CompareCryptoParams(const CryptoParamsVec& c1,
255 const CryptoParamsVec& c2) {
256 if (c1.size() != c2.size())
257 return false;
258 for (size_t i = 0; i < c1.size(); ++i)
259 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
260 c1[i].key_params != c2[i].key_params ||
261 c1[i].session_params != c2[i].session_params)
262 return false;
263 return true;
264 }
265
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700266 // Returns true if the transport info contains "renomination" as an
267 // ICE option.
268 bool GetIceRenomination(const TransportInfo* transport_info) {
269 const std::vector<std::string>& ice_options =
270 transport_info->description.transport_options;
271 auto iter = std::find(ice_options.begin(), ice_options.end(),
272 cricket::ICE_RENOMINATION_STR);
273 return iter != ice_options.end();
274 }
275
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000276 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
277 bool has_current_desc) {
278 const std::string current_audio_ufrag = "current_audio_ufrag";
279 const std::string current_audio_pwd = "current_audio_pwd";
280 const std::string current_video_ufrag = "current_video_ufrag";
281 const std::string current_video_pwd = "current_video_pwd";
282 const std::string current_data_ufrag = "current_data_ufrag";
283 const std::string current_data_pwd = "current_data_pwd";
kwiberg31022942016-03-11 14:18:21 -0800284 std::unique_ptr<SessionDescription> current_desc;
285 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 if (has_current_desc) {
287 current_desc.reset(new SessionDescription());
288 EXPECT_TRUE(current_desc->AddTransportInfo(
289 TransportInfo("audio",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700290 TransportDescription(current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000291 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000292 EXPECT_TRUE(current_desc->AddTransportInfo(
293 TransportInfo("video",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700294 TransportDescription(current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000295 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 EXPECT_TRUE(current_desc->AddTransportInfo(
297 TransportInfo("data",
Peter Thatcher7cbd1882015-09-17 18:54:52 -0700298 TransportDescription(current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000299 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000300 }
301 if (offer) {
302 desc.reset(f1_.CreateOffer(options, current_desc.get()));
303 } else {
kwiberg31022942016-03-11 14:18:21 -0800304 std::unique_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000305 offer.reset(f1_.CreateOffer(options, NULL));
306 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
307 }
308 ASSERT_TRUE(desc.get() != NULL);
309 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000310 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000311 EXPECT_TRUE(ti_audio != NULL);
312 if (has_current_desc) {
313 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
314 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
315 } else {
316 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
317 ti_audio->description.ice_ufrag.size());
318 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
319 ti_audio->description.ice_pwd.size());
320 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700321 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_audio));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322
323 } else {
324 EXPECT_TRUE(ti_audio == NULL);
325 }
326 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000327 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 EXPECT_TRUE(ti_video != NULL);
329 if (options.bundle_enabled) {
330 EXPECT_EQ(ti_audio->description.ice_ufrag,
331 ti_video->description.ice_ufrag);
332 EXPECT_EQ(ti_audio->description.ice_pwd,
333 ti_video->description.ice_pwd);
334 } else {
335 if (has_current_desc) {
336 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
337 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
338 } else {
339 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
340 ti_video->description.ice_ufrag.size());
341 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
342 ti_video->description.ice_pwd.size());
343 }
344 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700345 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_video));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 } else {
347 EXPECT_TRUE(ti_video == NULL);
348 }
349 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
350 if (options.has_data()) {
351 EXPECT_TRUE(ti_data != NULL);
352 if (options.bundle_enabled) {
353 EXPECT_EQ(ti_audio->description.ice_ufrag,
354 ti_data->description.ice_ufrag);
355 EXPECT_EQ(ti_audio->description.ice_pwd,
356 ti_data->description.ice_pwd);
357 } else {
358 if (has_current_desc) {
359 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
360 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
361 } else {
362 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
363 ti_data->description.ice_ufrag.size());
364 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
365 ti_data->description.ice_pwd.size());
366 }
367 }
Honghai Zhang4cedf2b2016-08-31 08:18:11 -0700368 EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_data));
369
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000370 } else {
371 EXPECT_TRUE(ti_video == NULL);
372 }
373 }
374
375 void TestCryptoWithBundle(bool offer) {
376 f1_.set_secure(SEC_ENABLED);
377 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000378 options.recv_audio = true;
379 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380 options.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -0800381 std::unique_ptr<SessionDescription> ref_desc;
382 std::unique_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000383 if (offer) {
384 options.bundle_enabled = false;
385 ref_desc.reset(f1_.CreateOffer(options, NULL));
386 options.bundle_enabled = true;
387 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
388 } else {
389 options.bundle_enabled = true;
390 ref_desc.reset(f1_.CreateOffer(options, NULL));
391 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
392 }
393 ASSERT_TRUE(desc.get() != NULL);
394 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000395 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000396 desc.get()->GetContentDescriptionByName("audio"));
397 ASSERT_TRUE(audio_media_desc != NULL);
398 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000399 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000400 desc.get()->GetContentDescriptionByName("video"));
401 ASSERT_TRUE(video_media_desc != NULL);
402 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
403 video_media_desc->cryptos()));
404 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
405 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
406 audio_media_desc->cryptos()[0].cipher_suite);
407
408 // Verify the selected crypto is one from the reference audio
409 // media content.
410 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000411 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 ref_desc.get()->GetContentDescriptionByName("audio"));
413 bool found = false;
414 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
415 if (ref_audio_media_desc->cryptos()[i].Matches(
416 audio_media_desc->cryptos()[0])) {
417 found = true;
418 break;
419 }
420 }
421 EXPECT_TRUE(found);
422 }
423
424 // This test that the audio and video media direction is set to
425 // |expected_direction_in_answer| in an answer if the offer direction is set
426 // to |direction_in_offer|.
427 void TestMediaDirectionInAnswer(
428 cricket::MediaContentDirection direction_in_offer,
429 cricket::MediaContentDirection expected_direction_in_answer) {
430 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000431 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800432 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000433 ASSERT_TRUE(offer.get() != NULL);
terelius8c011e52016-04-26 05:28:11 -0700434 ContentInfo* ac_offer = offer->GetContentByName("audio");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000435 ASSERT_TRUE(ac_offer != NULL);
436 AudioContentDescription* acd_offer =
437 static_cast<AudioContentDescription*>(ac_offer->description);
438 acd_offer->set_direction(direction_in_offer);
terelius8c011e52016-04-26 05:28:11 -0700439 ContentInfo* vc_offer = offer->GetContentByName("video");
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440 ASSERT_TRUE(vc_offer != NULL);
441 VideoContentDescription* vcd_offer =
442 static_cast<VideoContentDescription*>(vc_offer->description);
443 vcd_offer->set_direction(direction_in_offer);
444
kwiberg31022942016-03-11 14:18:21 -0800445 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000446 f2_.CreateAnswer(offer.get(), opts, NULL));
447 const AudioContentDescription* acd_answer =
448 GetFirstAudioContentDescription(answer.get());
449 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
450 const VideoContentDescription* vcd_answer =
451 GetFirstVideoContentDescription(answer.get());
452 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
453 }
454
455 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
456 const cricket::ContentDescription* description = content->description;
457 ASSERT(description != NULL);
458 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000459 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000460 ASSERT(audio_content_desc != NULL);
461 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
462 if (audio_content_desc->codecs()[i].name == "CN")
463 return false;
464 }
465 return true;
466 }
467
jbauchcb560652016-08-04 05:20:32 -0700468 void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
469 MediaSessionOptions offer_opts;
470 offer_opts.recv_video = true;
471 offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
472 MediaSessionOptions answer_opts;
473 answer_opts.recv_video = true;
474 answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
475 f1_.set_secure(SEC_ENABLED);
476 f2_.set_secure(SEC_ENABLED);
477 std::unique_ptr<SessionDescription> offer(
478 f1_.CreateOffer(offer_opts, NULL));
479 ASSERT_TRUE(offer.get() != NULL);
480 std::unique_ptr<SessionDescription> answer(
481 f2_.CreateAnswer(offer.get(), answer_opts, NULL));
482 const ContentInfo* ac = answer->GetContentByName("audio");
483 const ContentInfo* vc = answer->GetContentByName("video");
484 ASSERT_TRUE(ac != NULL);
485 ASSERT_TRUE(vc != NULL);
486 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
487 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
488 const AudioContentDescription* acd =
489 static_cast<const AudioContentDescription*>(ac->description);
490 const VideoContentDescription* vcd =
491 static_cast<const VideoContentDescription*>(vc->description);
492 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
493 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
494 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
495 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
496 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
497 if (gcm_offer && gcm_answer) {
498 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
499 } else {
500 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
501 }
502 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
503 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
504 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
505 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
506 if (gcm_offer && gcm_answer) {
507 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
508 } else {
509 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
510 }
511 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
512 }
513
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000514 protected:
515 MediaSessionDescriptionFactory f1_;
516 MediaSessionDescriptionFactory f2_;
517 TransportDescriptionFactory tdf1_;
518 TransportDescriptionFactory tdf2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000519};
520
521// Create a typical audio offer, and ensure it matches what we expect.
522TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
523 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800524 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000525 f1_.CreateOffer(MediaSessionOptions(), NULL));
526 ASSERT_TRUE(offer.get() != NULL);
527 const ContentInfo* ac = offer->GetContentByName("audio");
528 const ContentInfo* vc = offer->GetContentByName("video");
529 ASSERT_TRUE(ac != NULL);
530 ASSERT_TRUE(vc == NULL);
531 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
532 const AudioContentDescription* acd =
533 static_cast<const AudioContentDescription*>(ac->description);
534 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700535 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000536 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
537 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
538 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
539 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
540 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
541}
542
543// Create a typical video offer, and ensure it matches what we expect.
544TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
545 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000546 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000547 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800548 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000549 ASSERT_TRUE(offer.get() != NULL);
550 const ContentInfo* ac = offer->GetContentByName("audio");
551 const ContentInfo* vc = offer->GetContentByName("video");
552 ASSERT_TRUE(ac != NULL);
553 ASSERT_TRUE(vc != NULL);
554 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
555 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
556 const AudioContentDescription* acd =
557 static_cast<const AudioContentDescription*>(ac->description);
558 const VideoContentDescription* vcd =
559 static_cast<const VideoContentDescription*>(vc->description);
560 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700561 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000562 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
563 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
564 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
565 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
566 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
567 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
568 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
569 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
570 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
571 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
572 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
573 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
574}
575
576// Test creating an offer with bundle where the Codecs have the same dynamic
577// RTP playlod type. The test verifies that the offer don't contain the
578// duplicate RTP payload types.
579TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
580 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
ossudedfd282016-06-14 07:12:39 -0700581 const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
583 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
584 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
585
586 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000587 opts.recv_audio = true;
588 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000589 opts.data_channel_type = cricket::DCT_RTP;
590 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800591 std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000592 const VideoContentDescription* vcd =
593 GetFirstVideoContentDescription(offer.get());
594 const AudioContentDescription* acd =
595 GetFirstAudioContentDescription(offer.get());
596 const DataContentDescription* dcd =
597 GetFirstDataContentDescription(offer.get());
598 ASSERT_TRUE(NULL != vcd);
599 ASSERT_TRUE(NULL != acd);
600 ASSERT_TRUE(NULL != dcd);
601 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
602 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
603 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
604 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
605 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
606 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
607}
608
609// Test creating an updated offer with with bundle, audio, video and data
610// after an audio only session has been negotiated.
611TEST_F(MediaSessionDescriptionFactoryTest,
612 TestCreateUpdatedVideoOfferWithBundle) {
613 f1_.set_secure(SEC_ENABLED);
614 f2_.set_secure(SEC_ENABLED);
615 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000616 opts.recv_audio = true;
617 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000618 opts.data_channel_type = cricket::DCT_NONE;
619 opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800620 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
621 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000622 f2_.CreateAnswer(offer.get(), opts, NULL));
623
624 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000625 updated_opts.recv_audio = true;
626 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000627 updated_opts.data_channel_type = cricket::DCT_RTP;
628 updated_opts.bundle_enabled = true;
kwiberg31022942016-03-11 14:18:21 -0800629 std::unique_ptr<SessionDescription> updated_offer(
630 f1_.CreateOffer(updated_opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000631
632 const AudioContentDescription* acd =
633 GetFirstAudioContentDescription(updated_offer.get());
634 const VideoContentDescription* vcd =
635 GetFirstVideoContentDescription(updated_offer.get());
636 const DataContentDescription* dcd =
637 GetFirstDataContentDescription(updated_offer.get());
638 EXPECT_TRUE(NULL != vcd);
639 EXPECT_TRUE(NULL != acd);
640 EXPECT_TRUE(NULL != dcd);
641
642 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
643 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
644 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
645 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
646 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
647 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
648}
deadbeef44f08192015-12-15 16:20:09 -0800649
wu@webrtc.org78187522013-10-07 23:32:02 +0000650// Create a RTP data offer, and ensure it matches what we expect.
651TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652 MediaSessionOptions opts;
653 opts.data_channel_type = cricket::DCT_RTP;
654 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800655 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000656 ASSERT_TRUE(offer.get() != NULL);
657 const ContentInfo* ac = offer->GetContentByName("audio");
658 const ContentInfo* dc = offer->GetContentByName("data");
659 ASSERT_TRUE(ac != NULL);
660 ASSERT_TRUE(dc != NULL);
661 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
662 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
663 const AudioContentDescription* acd =
664 static_cast<const AudioContentDescription*>(ac->description);
665 const DataContentDescription* dcd =
666 static_cast<const DataContentDescription*>(dc->description);
667 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -0700668 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000669 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
670 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
671 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
672 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
673 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
674 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
675 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
676 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
677 EXPECT_EQ(cricket::kDataMaxBandwidth,
678 dcd->bandwidth()); // default bandwidth (auto)
679 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
680 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
681 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
682}
683
wu@webrtc.org78187522013-10-07 23:32:02 +0000684// Create an SCTP data offer with bundle without error.
685TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
686 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000687 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000688 opts.bundle_enabled = true;
689 opts.data_channel_type = cricket::DCT_SCTP;
690 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800691 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000692 EXPECT_TRUE(offer.get() != NULL);
693 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
694}
695
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000696// Test creating an sctp data channel from an already generated offer.
697TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
698 MediaSessionOptions opts;
699 opts.recv_audio = false;
700 opts.bundle_enabled = true;
701 opts.data_channel_type = cricket::DCT_SCTP;
702 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800703 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000704 ASSERT_TRUE(offer1.get() != NULL);
705 const ContentInfo* data = offer1->GetContentByName("data");
706 ASSERT_TRUE(data != NULL);
707 const MediaContentDescription* mdesc =
708 static_cast<const MediaContentDescription*>(data->description);
709 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
710
711 // Now set data_channel_type to 'none' (default) and make sure that the
712 // datachannel type that gets generated from the previous offer, is of the
713 // same type.
714 opts.data_channel_type = cricket::DCT_NONE;
kwiberg31022942016-03-11 14:18:21 -0800715 std::unique_ptr<SessionDescription> offer2(
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000716 f1_.CreateOffer(opts, offer1.get()));
717 data = offer2->GetContentByName("data");
718 ASSERT_TRUE(data != NULL);
719 mdesc = static_cast<const MediaContentDescription*>(data->description);
720 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
721}
722
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000723// Create an audio, video offer without legacy StreamParams.
724TEST_F(MediaSessionDescriptionFactoryTest,
725 TestCreateOfferWithoutLegacyStreams) {
726 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000727 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000728 f1_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -0800729 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000730 ASSERT_TRUE(offer.get() != NULL);
731 const ContentInfo* ac = offer->GetContentByName("audio");
732 const ContentInfo* vc = offer->GetContentByName("video");
733 ASSERT_TRUE(ac != NULL);
734 ASSERT_TRUE(vc != NULL);
735 const AudioContentDescription* acd =
736 static_cast<const AudioContentDescription*>(ac->description);
737 const VideoContentDescription* vcd =
738 static_cast<const VideoContentDescription*>(vc->description);
739
740 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
741 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
742}
743
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000744// Creates an audio+video sendonly offer.
745TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
746 MediaSessionOptions options;
747 options.recv_audio = false;
748 options.recv_video = false;
749 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
750 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
751
kwiberg31022942016-03-11 14:18:21 -0800752 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000753 ASSERT_TRUE(offer.get() != NULL);
754 EXPECT_EQ(2u, offer->contents().size());
755 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
756 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
757
758 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
759 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
760}
761
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000762// Verifies that the order of the media contents in the current
763// SessionDescription is preserved in the new SessionDescription.
764TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
765 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000766 opts.recv_audio = false;
767 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000768 opts.data_channel_type = cricket::DCT_SCTP;
769
kwiberg31022942016-03-11 14:18:21 -0800770 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000771 ASSERT_TRUE(offer1.get() != NULL);
772 EXPECT_EQ(1u, offer1->contents().size());
773 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
774
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000775 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800776 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000777 f1_.CreateOffer(opts, offer1.get()));
778 ASSERT_TRUE(offer2.get() != NULL);
779 EXPECT_EQ(2u, offer2->contents().size());
780 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
781 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
782
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000783 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800784 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000785 f1_.CreateOffer(opts, offer2.get()));
786 ASSERT_TRUE(offer3.get() != NULL);
787 EXPECT_EQ(3u, offer3->contents().size());
788 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
789 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
790 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
791
792 // Verifies the default order is audio-video-data, so that the previous checks
793 // didn't pass by accident.
kwiberg31022942016-03-11 14:18:21 -0800794 std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000795 ASSERT_TRUE(offer4.get() != NULL);
796 EXPECT_EQ(3u, offer4->contents().size());
797 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
798 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
799 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
800}
801
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000802// Create a typical audio answer, and ensure it matches what we expect.
803TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
804 f1_.set_secure(SEC_ENABLED);
805 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800806 std::unique_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000807 f1_.CreateOffer(MediaSessionOptions(), NULL));
808 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800809 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000810 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
811 const ContentInfo* ac = answer->GetContentByName("audio");
812 const ContentInfo* vc = answer->GetContentByName("video");
813 ASSERT_TRUE(ac != NULL);
814 ASSERT_TRUE(vc == NULL);
815 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
816 const AudioContentDescription* acd =
817 static_cast<const AudioContentDescription*>(ac->description);
818 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
819 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
820 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
821 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
822 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
823 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
824 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
825}
826
jbauchcb560652016-08-04 05:20:32 -0700827// Create a typical audio answer with GCM ciphers enabled, and ensure it
828// matches what we expect.
829TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
830 f1_.set_secure(SEC_ENABLED);
831 f2_.set_secure(SEC_ENABLED);
832 MediaSessionOptions options;
833 options.crypto_options.enable_gcm_crypto_suites = true;
834 std::unique_ptr<SessionDescription> offer(
835 f1_.CreateOffer(options, NULL));
836 ASSERT_TRUE(offer.get() != NULL);
837 std::unique_ptr<SessionDescription> answer(
838 f2_.CreateAnswer(offer.get(), options, NULL));
839 const ContentInfo* ac = answer->GetContentByName("audio");
840 const ContentInfo* vc = answer->GetContentByName("video");
841 ASSERT_TRUE(ac != NULL);
842 ASSERT_TRUE(vc == NULL);
843 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
844 const AudioContentDescription* acd =
845 static_cast<const AudioContentDescription*>(ac->description);
846 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
847 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
848 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
849 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
850 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
851 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
852 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
853}
854
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000855// Create a typical video answer, and ensure it matches what we expect.
856TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
857 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000858 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000859 f1_.set_secure(SEC_ENABLED);
860 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800861 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000862 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800863 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000864 f2_.CreateAnswer(offer.get(), opts, NULL));
865 const ContentInfo* ac = answer->GetContentByName("audio");
866 const ContentInfo* vc = answer->GetContentByName("video");
867 ASSERT_TRUE(ac != NULL);
868 ASSERT_TRUE(vc != NULL);
869 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
870 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
871 const AudioContentDescription* acd =
872 static_cast<const AudioContentDescription*>(ac->description);
873 const VideoContentDescription* vcd =
874 static_cast<const VideoContentDescription*>(vc->description);
875 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
876 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
877 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
878 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
879 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
880 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
881 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
882 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
883 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
884 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
885 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
886 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
887}
888
jbauchcb560652016-08-04 05:20:32 -0700889// Create a typical video answer with GCM ciphers enabled, and ensure it
890// matches what we expect.
891TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
892 TestVideoGcmCipher(true, true);
893}
894
895// Create a typical video answer with GCM ciphers enabled for the offer only,
896// and ensure it matches what we expect.
897TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
898 TestVideoGcmCipher(true, false);
899}
900
901// Create a typical video answer with GCM ciphers enabled for the answer only,
902// and ensure it matches what we expect.
903TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
904 TestVideoGcmCipher(false, true);
905}
906
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000907TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
908 MediaSessionOptions opts;
909 opts.data_channel_type = cricket::DCT_RTP;
910 f1_.set_secure(SEC_ENABLED);
911 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -0800912 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000913 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -0800914 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000915 f2_.CreateAnswer(offer.get(), opts, NULL));
916 const ContentInfo* ac = answer->GetContentByName("audio");
917 const ContentInfo* vc = answer->GetContentByName("data");
918 ASSERT_TRUE(ac != NULL);
919 ASSERT_TRUE(vc != NULL);
920 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
921 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
922 const AudioContentDescription* acd =
923 static_cast<const AudioContentDescription*>(ac->description);
924 const DataContentDescription* vcd =
925 static_cast<const DataContentDescription*>(vc->description);
926 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
927 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
928 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
929 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
930 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
931 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
932 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
933 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
934 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
935 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
936 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
937 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
938}
939
jbauchcb560652016-08-04 05:20:32 -0700940TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
941 MediaSessionOptions opts;
942 opts.data_channel_type = cricket::DCT_RTP;
943 opts.crypto_options.enable_gcm_crypto_suites = true;
944 f1_.set_secure(SEC_ENABLED);
945 f2_.set_secure(SEC_ENABLED);
946 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
947 ASSERT_TRUE(offer.get() != NULL);
948 std::unique_ptr<SessionDescription> answer(
949 f2_.CreateAnswer(offer.get(), opts, NULL));
950 const ContentInfo* ac = answer->GetContentByName("audio");
951 const ContentInfo* vc = answer->GetContentByName("data");
952 ASSERT_TRUE(ac != NULL);
953 ASSERT_TRUE(vc != NULL);
954 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
955 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
956 const AudioContentDescription* acd =
957 static_cast<const AudioContentDescription*>(ac->description);
958 const DataContentDescription* vcd =
959 static_cast<const DataContentDescription*>(vc->description);
960 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
961 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
962 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
963 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
964 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
965 ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
966 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
967 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
968 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
969 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
970 ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
971 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
972}
973
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000974// Verifies that the order of the media contents in the offer is preserved in
975// the answer.
976TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
977 MediaSessionOptions opts;
978
979 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000980 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000981 opts.data_channel_type = cricket::DCT_SCTP;
kwiberg31022942016-03-11 14:18:21 -0800982 std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000983 ASSERT_TRUE(offer1.get() != NULL);
984
985 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000986 opts.recv_audio = true;
kwiberg31022942016-03-11 14:18:21 -0800987 std::unique_ptr<SessionDescription> offer2(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000988 f1_.CreateOffer(opts, offer1.get()));
989 ASSERT_TRUE(offer2.get() != NULL);
990
991 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000992 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -0800993 std::unique_ptr<SessionDescription> offer3(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000994 f1_.CreateOffer(opts, offer2.get()));
995 ASSERT_TRUE(offer3.get() != NULL);
996
kwiberg31022942016-03-11 14:18:21 -0800997 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000998 f2_.CreateAnswer(offer3.get(), opts, NULL));
999 ASSERT_TRUE(answer.get() != NULL);
1000 EXPECT_EQ(3u, answer->contents().size());
1001 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
1002 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
1003 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
1004}
1005
ossu075af922016-06-14 03:29:38 -07001006// TODO(deadbeef): Extend these tests to ensure the correct direction with other
1007// answerer settings.
1008
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001009// This test that the media direction is set to send/receive in an answer if
1010// the offer is send receive.
1011TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
1012 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
1013}
1014
1015// This test that the media direction is set to receive only in an answer if
1016// the offer is send only.
1017TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
1018 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
1019}
1020
1021// This test that the media direction is set to send only in an answer if
1022// the offer is recv only.
1023TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
1024 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
1025}
1026
1027// This test that the media direction is set to inactive in an answer if
1028// the offer is inactive.
1029TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
1030 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
1031}
1032
1033// Test that a data content with an unknown protocol is rejected in an answer.
1034TEST_F(MediaSessionDescriptionFactoryTest,
1035 CreateDataAnswerToOfferWithUnknownProtocol) {
1036 MediaSessionOptions opts;
1037 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001038 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001039 f1_.set_secure(SEC_ENABLED);
1040 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001041 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
terelius8c011e52016-04-26 05:28:11 -07001042 ContentInfo* dc_offer = offer->GetContentByName("data");
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001043 ASSERT_TRUE(dc_offer != NULL);
1044 DataContentDescription* dcd_offer =
1045 static_cast<DataContentDescription*>(dc_offer->description);
1046 ASSERT_TRUE(dcd_offer != NULL);
1047 std::string protocol = "a weird unknown protocol";
1048 dcd_offer->set_protocol(protocol);
1049
kwiberg31022942016-03-11 14:18:21 -08001050 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001051 f2_.CreateAnswer(offer.get(), opts, NULL));
1052
1053 const ContentInfo* dc_answer = answer->GetContentByName("data");
1054 ASSERT_TRUE(dc_answer != NULL);
1055 EXPECT_TRUE(dc_answer->rejected);
1056 const DataContentDescription* dcd_answer =
1057 static_cast<const DataContentDescription*>(dc_answer->description);
1058 ASSERT_TRUE(dcd_answer != NULL);
1059 EXPECT_EQ(protocol, dcd_answer->protocol());
1060}
1061
1062// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
1063TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
1064 MediaSessionOptions opts;
1065 f1_.set_secure(SEC_DISABLED);
1066 f2_.set_secure(SEC_DISABLED);
1067 tdf1_.set_secure(SEC_DISABLED);
1068 tdf2_.set_secure(SEC_DISABLED);
1069
kwiberg31022942016-03-11 14:18:21 -08001070 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001071 const AudioContentDescription* offer_acd =
1072 GetFirstAudioContentDescription(offer.get());
1073 ASSERT_TRUE(offer_acd != NULL);
1074 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
1075
kwiberg31022942016-03-11 14:18:21 -08001076 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001077 f2_.CreateAnswer(offer.get(), opts, NULL));
1078
1079 const ContentInfo* ac_answer = answer->GetContentByName("audio");
1080 ASSERT_TRUE(ac_answer != NULL);
1081 EXPECT_FALSE(ac_answer->rejected);
1082
1083 const AudioContentDescription* answer_acd =
1084 GetFirstAudioContentDescription(answer.get());
1085 ASSERT_TRUE(answer_acd != NULL);
1086 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
1087}
1088
1089// Create a video offer and answer and ensure the RTP header extensions
1090// matches what we expect.
1091TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
1092 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001093 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001094
1095 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1096 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1097 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1098 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1099
kwiberg31022942016-03-11 14:18:21 -08001100 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001101 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001102 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001103 f2_.CreateAnswer(offer.get(), opts, NULL));
1104
1105 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
1106 GetFirstAudioContentDescription(
1107 offer.get())->rtp_header_extensions());
1108 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
1109 GetFirstVideoContentDescription(
1110 offer.get())->rtp_header_extensions());
1111 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1112 GetFirstAudioContentDescription(
1113 answer.get())->rtp_header_extensions());
1114 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1115 GetFirstVideoContentDescription(
1116 answer.get())->rtp_header_extensions());
1117}
1118
1119// Create an audio, video, data answer without legacy StreamParams.
1120TEST_F(MediaSessionDescriptionFactoryTest,
1121 TestCreateAnswerWithoutLegacyStreams) {
1122 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001123 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001124 opts.data_channel_type = cricket::DCT_RTP;
1125 f1_.set_add_legacy_streams(false);
1126 f2_.set_add_legacy_streams(false);
kwiberg31022942016-03-11 14:18:21 -08001127 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001128 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001129 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001130 f2_.CreateAnswer(offer.get(), opts, NULL));
1131 const ContentInfo* ac = answer->GetContentByName("audio");
1132 const ContentInfo* vc = answer->GetContentByName("video");
1133 const ContentInfo* dc = answer->GetContentByName("data");
1134 ASSERT_TRUE(ac != NULL);
1135 ASSERT_TRUE(vc != NULL);
1136 const AudioContentDescription* acd =
1137 static_cast<const AudioContentDescription*>(ac->description);
1138 const VideoContentDescription* vcd =
1139 static_cast<const VideoContentDescription*>(vc->description);
1140 const DataContentDescription* dcd =
1141 static_cast<const DataContentDescription*>(dc->description);
1142
1143 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1144 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1145 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1146}
1147
1148TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1149 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001150 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001151 opts.data_channel_type = cricket::DCT_RTP;
1152 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001153 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001154 ASSERT_TRUE(offer.get() != NULL);
1155 const ContentInfo* ac = offer->GetContentByName("audio");
1156 const ContentInfo* vc = offer->GetContentByName("video");
1157 const ContentInfo* dc = offer->GetContentByName("data");
1158 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1159 static_cast<const AudioContentDescription*>(ac->description));
1160 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1161 static_cast<const VideoContentDescription*>(vc->description));
1162 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1163 static_cast<const DataContentDescription*>(dc->description));
1164
1165 EXPECT_FALSE(acd->partial()); // default is false.
1166 acd->set_partial(true);
1167 EXPECT_TRUE(acd->partial());
1168 acd->set_partial(false);
1169 EXPECT_FALSE(acd->partial());
1170
1171 EXPECT_FALSE(vcd->partial()); // default is false.
1172 vcd->set_partial(true);
1173 EXPECT_TRUE(vcd->partial());
1174 vcd->set_partial(false);
1175 EXPECT_FALSE(vcd->partial());
1176
1177 EXPECT_FALSE(dcd->partial()); // default is false.
1178 dcd->set_partial(true);
1179 EXPECT_TRUE(dcd->partial());
1180 dcd->set_partial(false);
1181 EXPECT_FALSE(dcd->partial());
1182}
1183
1184// Create a typical video answer, and ensure it matches what we expect.
1185TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1186 MediaSessionOptions offer_opts;
1187 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001188 answer_opts.recv_video = true;
1189 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001190 answer_opts.data_channel_type = cricket::DCT_RTP;
1191 offer_opts.data_channel_type = cricket::DCT_RTP;
1192
kwiberg31022942016-03-11 14:18:21 -08001193 std::unique_ptr<SessionDescription> offer;
1194 std::unique_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001195
1196 offer_opts.rtcp_mux_enabled = true;
1197 answer_opts.rtcp_mux_enabled = true;
1198
1199 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1200 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1201 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1202 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1203 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1204 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1205 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1206 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1207 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1208 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1209 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1210 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1211 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1212 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1213
1214 offer_opts.rtcp_mux_enabled = true;
1215 answer_opts.rtcp_mux_enabled = false;
1216
1217 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1218 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1219 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1220 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1221 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1222 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1223 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1224 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1225 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1226 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1227 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1228 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1229 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1230 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1231
1232 offer_opts.rtcp_mux_enabled = false;
1233 answer_opts.rtcp_mux_enabled = true;
1234
1235 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1236 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1237 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1238 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1239 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1240 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1241 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1242 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1243 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1244 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1245 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1246 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1247 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1248 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1249
1250 offer_opts.rtcp_mux_enabled = false;
1251 answer_opts.rtcp_mux_enabled = false;
1252
1253 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1254 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1255 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1256 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1257 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1258 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1259 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1260 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1261 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1262 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1263 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1264 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1265 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1266 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1267}
1268
1269// Create an audio-only answer to a video offer.
1270TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1271 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001272 opts.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08001273 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001274 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001275 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001276 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1277 const ContentInfo* ac = answer->GetContentByName("audio");
1278 const ContentInfo* vc = answer->GetContentByName("video");
1279 ASSERT_TRUE(ac != NULL);
1280 ASSERT_TRUE(vc != NULL);
1281 ASSERT_TRUE(vc->description != NULL);
1282 EXPECT_TRUE(vc->rejected);
1283}
1284
1285// Create an audio-only answer to an offer with data.
1286TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1287 MediaSessionOptions opts;
1288 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001289 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001290 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001291 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001292 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1293 const ContentInfo* ac = answer->GetContentByName("audio");
1294 const ContentInfo* dc = answer->GetContentByName("data");
1295 ASSERT_TRUE(ac != NULL);
1296 ASSERT_TRUE(dc != NULL);
1297 ASSERT_TRUE(dc->description != NULL);
1298 EXPECT_TRUE(dc->rejected);
1299}
1300
1301// Create an answer that rejects the contents which are rejected in the offer.
1302TEST_F(MediaSessionDescriptionFactoryTest,
1303 CreateAnswerToOfferWithRejectedMedia) {
1304 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001305 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001306 opts.data_channel_type = cricket::DCT_RTP;
kwiberg31022942016-03-11 14:18:21 -08001307 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001308 ASSERT_TRUE(offer.get() != NULL);
1309 ContentInfo* ac = offer->GetContentByName("audio");
1310 ContentInfo* vc = offer->GetContentByName("video");
1311 ContentInfo* dc = offer->GetContentByName("data");
1312 ASSERT_TRUE(ac != NULL);
1313 ASSERT_TRUE(vc != NULL);
1314 ASSERT_TRUE(dc != NULL);
1315 ac->rejected = true;
1316 vc->rejected = true;
1317 dc->rejected = true;
kwiberg31022942016-03-11 14:18:21 -08001318 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001319 f2_.CreateAnswer(offer.get(), opts, NULL));
1320 ac = answer->GetContentByName("audio");
1321 vc = answer->GetContentByName("video");
1322 dc = answer->GetContentByName("data");
1323 ASSERT_TRUE(ac != NULL);
1324 ASSERT_TRUE(vc != NULL);
1325 ASSERT_TRUE(dc != NULL);
1326 EXPECT_TRUE(ac->rejected);
1327 EXPECT_TRUE(vc->rejected);
1328 EXPECT_TRUE(dc->rejected);
1329}
1330
1331// Create an audio and video offer with:
1332// - one video track
1333// - two audio tracks
1334// - two data tracks
1335// and ensure it matches what we expect. Also updates the initial offer by
1336// adding a new video track and replaces one of the audio tracks.
1337TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1338 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001339 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1340 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1341 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001342 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001343 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1344 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001345
1346 f1_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001347 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001348
1349 ASSERT_TRUE(offer.get() != NULL);
1350 const ContentInfo* ac = offer->GetContentByName("audio");
1351 const ContentInfo* vc = offer->GetContentByName("video");
1352 const ContentInfo* dc = offer->GetContentByName("data");
1353 ASSERT_TRUE(ac != NULL);
1354 ASSERT_TRUE(vc != NULL);
1355 ASSERT_TRUE(dc != NULL);
1356 const AudioContentDescription* acd =
1357 static_cast<const AudioContentDescription*>(ac->description);
1358 const VideoContentDescription* vcd =
1359 static_cast<const VideoContentDescription*>(vc->description);
1360 const DataContentDescription* dcd =
1361 static_cast<const DataContentDescription*>(dc->description);
1362 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
ossudedfd282016-06-14 07:12:39 -07001363 EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001364
1365 const StreamParamsVec& audio_streams = acd->streams();
1366 ASSERT_EQ(2U, audio_streams.size());
1367 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1368 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1369 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1370 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1371 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1372 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1373 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1374
1375 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1376 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1377 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1378
1379 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1380 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1381 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1382
1383 const StreamParamsVec& video_streams = vcd->streams();
1384 ASSERT_EQ(1U, video_streams.size());
1385 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1386 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1387 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1388 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1389
1390 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1391 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1392 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1393
1394 const StreamParamsVec& data_streams = dcd->streams();
1395 ASSERT_EQ(2U, data_streams.size());
1396 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1397 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1398 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1399 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1400 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1401 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1402 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1403
1404 EXPECT_EQ(cricket::kDataMaxBandwidth,
1405 dcd->bandwidth()); // default bandwidth (auto)
1406 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1407 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1408
1409
1410 // Update the offer. Add a new video track that is not synched to the
1411 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001412 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1413 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1414 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1415 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1416 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
kwiberg31022942016-03-11 14:18:21 -08001417 std::unique_ptr<SessionDescription> updated_offer(
1418 f1_.CreateOffer(opts, offer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001419
1420 ASSERT_TRUE(updated_offer.get() != NULL);
1421 ac = updated_offer->GetContentByName("audio");
1422 vc = updated_offer->GetContentByName("video");
1423 dc = updated_offer->GetContentByName("data");
1424 ASSERT_TRUE(ac != NULL);
1425 ASSERT_TRUE(vc != NULL);
1426 ASSERT_TRUE(dc != NULL);
1427 const AudioContentDescription* updated_acd =
1428 static_cast<const AudioContentDescription*>(ac->description);
1429 const VideoContentDescription* updated_vcd =
1430 static_cast<const VideoContentDescription*>(vc->description);
1431 const DataContentDescription* updated_dcd =
1432 static_cast<const DataContentDescription*>(dc->description);
1433
1434 EXPECT_EQ(acd->type(), updated_acd->type());
1435 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1436 EXPECT_EQ(vcd->type(), updated_vcd->type());
1437 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1438 EXPECT_EQ(dcd->type(), updated_dcd->type());
1439 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1440 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1441 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1442 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1443 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1444 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1445 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1446
1447 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1448 ASSERT_EQ(2U, updated_audio_streams.size());
1449 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1450 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1451 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1452 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1453 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1454
1455 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1456 ASSERT_EQ(2U, updated_video_streams.size());
1457 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1458 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001459 // All the media streams in one PeerConnection share one RTCP CNAME.
1460 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001461
1462 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1463 ASSERT_EQ(2U, updated_data_streams.size());
1464 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1465 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1466 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1467 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1468 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
zhihuang8f65cdf2016-05-06 18:40:30 -07001469 // The stream correctly got the CNAME from the MediaSessionOptions.
1470 // The Expected RTCP CNAME is the default one as we are using the default
1471 // MediaSessionOptions.
1472 EXPECT_EQ(updated_data_streams[0].cname, cricket::kDefaultRtcpCname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001473}
1474
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001475// Create an offer with simulcast video stream.
1476TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1477 MediaSessionOptions opts;
1478 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001479 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
kwiberg31022942016-03-11 14:18:21 -08001480 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001481
1482 ASSERT_TRUE(offer.get() != NULL);
1483 const ContentInfo* vc = offer->GetContentByName("video");
1484 ASSERT_TRUE(vc != NULL);
1485 const VideoContentDescription* vcd =
1486 static_cast<const VideoContentDescription*>(vc->description);
1487
1488 const StreamParamsVec& video_streams = vcd->streams();
1489 ASSERT_EQ(1U, video_streams.size());
1490 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1491 const SsrcGroup* sim_ssrc_group =
1492 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1493 ASSERT_TRUE(sim_ssrc_group != NULL);
1494 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1495}
1496
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001497// Create an audio and video answer to a standard video offer with:
1498// - one video track
1499// - two audio tracks
1500// - two data tracks
1501// and ensure it matches what we expect. Also updates the initial answer by
1502// adding a new video track and removes one of the audio tracks.
1503TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1504 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001505 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001506 offer_opts.data_channel_type = cricket::DCT_RTP;
1507 f1_.set_secure(SEC_ENABLED);
1508 f2_.set_secure(SEC_ENABLED);
kwiberg31022942016-03-11 14:18:21 -08001509 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001510
1511 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001512 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1513 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1514 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001515 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001516 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1517 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001518
kwiberg31022942016-03-11 14:18:21 -08001519 std::unique_ptr<SessionDescription> answer(
1520 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001521
1522 ASSERT_TRUE(answer.get() != NULL);
1523 const ContentInfo* ac = answer->GetContentByName("audio");
1524 const ContentInfo* vc = answer->GetContentByName("video");
1525 const ContentInfo* dc = answer->GetContentByName("data");
1526 ASSERT_TRUE(ac != NULL);
1527 ASSERT_TRUE(vc != NULL);
1528 ASSERT_TRUE(dc != NULL);
1529 const AudioContentDescription* acd =
1530 static_cast<const AudioContentDescription*>(ac->description);
1531 const VideoContentDescription* vcd =
1532 static_cast<const VideoContentDescription*>(vc->description);
1533 const DataContentDescription* dcd =
1534 static_cast<const DataContentDescription*>(dc->description);
1535 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1536 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1537 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1538
1539 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1540 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1541
1542 const StreamParamsVec& audio_streams = acd->streams();
1543 ASSERT_EQ(2U, audio_streams.size());
1544 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1545 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1546 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1547 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1548 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1549 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1550 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1551
1552 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1553 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1554
1555 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1556 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1557
1558 const StreamParamsVec& video_streams = vcd->streams();
1559 ASSERT_EQ(1U, video_streams.size());
1560 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1561 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1562 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1563 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1564
1565 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1566 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1567
1568 const StreamParamsVec& data_streams = dcd->streams();
1569 ASSERT_EQ(2U, data_streams.size());
1570 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1571 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1572 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1573 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1574 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1575 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1576 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1577
1578 EXPECT_EQ(cricket::kDataMaxBandwidth,
1579 dcd->bandwidth()); // default bandwidth (auto)
1580 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1581
1582 // Update the answer. Add a new video track that is not synched to the
zhihuang8f65cdf2016-05-06 18:40:30 -07001583 // other tracks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001584 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1585 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1586 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
kwiberg31022942016-03-11 14:18:21 -08001587 std::unique_ptr<SessionDescription> updated_answer(
1588 f2_.CreateAnswer(offer.get(), opts, answer.get()));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001589
1590 ASSERT_TRUE(updated_answer.get() != NULL);
1591 ac = updated_answer->GetContentByName("audio");
1592 vc = updated_answer->GetContentByName("video");
1593 dc = updated_answer->GetContentByName("data");
1594 ASSERT_TRUE(ac != NULL);
1595 ASSERT_TRUE(vc != NULL);
1596 ASSERT_TRUE(dc != NULL);
1597 const AudioContentDescription* updated_acd =
1598 static_cast<const AudioContentDescription*>(ac->description);
1599 const VideoContentDescription* updated_vcd =
1600 static_cast<const VideoContentDescription*>(vc->description);
1601 const DataContentDescription* updated_dcd =
1602 static_cast<const DataContentDescription*>(dc->description);
1603
1604 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1605 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1606 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1607 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1608 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1609 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1610
1611 EXPECT_EQ(acd->type(), updated_acd->type());
1612 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1613 EXPECT_EQ(vcd->type(), updated_vcd->type());
1614 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1615 EXPECT_EQ(dcd->type(), updated_dcd->type());
1616 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1617
1618 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1619 ASSERT_EQ(1U, updated_audio_streams.size());
1620 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1621
1622 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1623 ASSERT_EQ(2U, updated_video_streams.size());
1624 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1625 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
zhihuang8f65cdf2016-05-06 18:40:30 -07001626 // All media streams in one PeerConnection share one CNAME.
1627 EXPECT_EQ(updated_video_streams[1].cname, updated_video_streams[0].cname);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001628
1629 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1630 ASSERT_EQ(1U, updated_data_streams.size());
1631 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1632}
1633
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001634// Create an updated offer after creating an answer to the original offer and
1635// verify that the codecs that were part of the original answer are not changed
1636// in the updated offer.
1637TEST_F(MediaSessionDescriptionFactoryTest,
1638 RespondentCreatesOfferAfterCreatingAnswer) {
1639 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001640 opts.recv_audio = true;
1641 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001642
kwiberg31022942016-03-11 14:18:21 -08001643 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1644 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001645 f2_.CreateAnswer(offer.get(), opts, NULL));
1646
1647 const AudioContentDescription* acd =
1648 GetFirstAudioContentDescription(answer.get());
1649 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1650
1651 const VideoContentDescription* vcd =
1652 GetFirstVideoContentDescription(answer.get());
1653 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1654
kwiberg31022942016-03-11 14:18:21 -08001655 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001656 f2_.CreateOffer(opts, answer.get()));
1657
1658 // The expected audio codecs are the common audio codecs from the first
1659 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1660 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001661 // TODO(wu): |updated_offer| should not include the codec
1662 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001663 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001664 kAudioCodecsAnswer[0],
1665 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001666 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001667 };
1668
1669 // The expected video codecs are the common video codecs from the first
1670 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1671 // preference order.
1672 const VideoCodec kUpdatedVideoCodecOffer[] = {
1673 kVideoCodecsAnswer[0],
1674 kVideoCodecs2[1],
1675 };
1676
1677 const AudioContentDescription* updated_acd =
1678 GetFirstAudioContentDescription(updated_offer.get());
1679 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1680
1681 const VideoContentDescription* updated_vcd =
1682 GetFirstVideoContentDescription(updated_offer.get());
1683 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1684}
1685
1686// Create an updated offer after creating an answer to the original offer and
1687// verify that the codecs that were part of the original answer are not changed
1688// in the updated offer. In this test Rtx is enabled.
1689TEST_F(MediaSessionDescriptionFactoryTest,
1690 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1691 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001692 opts.recv_video = true;
1693 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001694 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001695 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001696 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697 f1_.set_video_codecs(f1_codecs);
1698
1699 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001700 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001701 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001702 f2_.set_video_codecs(f2_codecs);
1703
kwiberg31022942016-03-11 14:18:21 -08001704 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001705 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001706 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001707 f2_.CreateAnswer(offer.get(), opts, NULL));
1708
1709 const VideoContentDescription* vcd =
1710 GetFirstVideoContentDescription(answer.get());
1711
1712 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001713 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1714 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001715
1716 EXPECT_EQ(expected_codecs, vcd->codecs());
1717
deadbeef67cf2c12016-04-13 10:07:16 -07001718 // Now, make sure we get same result (except for the order) if |f2_| creates
1719 // an updated offer even though the default payload types between |f1_| and
1720 // |f2_| are different.
kwiberg31022942016-03-11 14:18:21 -08001721 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001722 f2_.CreateOffer(opts, answer.get()));
1723 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001724 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001725 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1726
1727 const VideoContentDescription* updated_vcd =
1728 GetFirstVideoContentDescription(updated_answer.get());
1729
1730 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1731}
1732
1733// Create an updated offer that adds video after creating an audio only answer
1734// to the original offer. This test verifies that if a video codec and the RTX
1735// codec have the same default payload type as an audio codec that is already in
1736// use, the added codecs payload types are changed.
1737TEST_F(MediaSessionDescriptionFactoryTest,
1738 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1739 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001740 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001741 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001742 f1_.set_video_codecs(f1_codecs);
1743
1744 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001745 opts.recv_audio = true;
1746 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001747
kwiberg31022942016-03-11 14:18:21 -08001748 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1749 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001750 f2_.CreateAnswer(offer.get(), opts, NULL));
1751
1752 const AudioContentDescription* acd =
1753 GetFirstAudioContentDescription(answer.get());
1754 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1755
1756 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1757 // reference be the same as an audio codec that was negotiated in the
1758 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001759 opts.recv_audio = true;
1760 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001761
1762 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1763 int used_pl_type = acd->codecs()[0].id;
1764 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001765 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766 f2_.set_video_codecs(f2_codecs);
1767
kwiberg31022942016-03-11 14:18:21 -08001768 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001769 f2_.CreateOffer(opts, answer.get()));
1770 ASSERT_TRUE(updated_offer);
kwiberg31022942016-03-11 14:18:21 -08001771 std::unique_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001772 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1773
1774 const AudioContentDescription* updated_acd =
1775 GetFirstAudioContentDescription(answer.get());
1776 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1777
1778 const VideoContentDescription* updated_vcd =
1779 GetFirstVideoContentDescription(updated_answer.get());
1780
1781 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001782 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001783 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1784 EXPECT_NE(used_pl_type, new_h264_pl_type);
1785 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001786 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001787 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1788 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1789}
1790
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001791// Create an updated offer with RTX after creating an answer to an offer
1792// without RTX, and with different default payload types.
1793// Verify that the added RTX codec references the correct payload type.
1794TEST_F(MediaSessionDescriptionFactoryTest,
1795 RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
1796 MediaSessionOptions opts;
1797 opts.recv_video = true;
1798 opts.recv_audio = true;
1799
1800 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1801 // This creates rtx for H264 with the payload type |f2_| uses.
1802 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
1803 f2_.set_video_codecs(f2_codecs);
1804
kwiberg31022942016-03-11 14:18:21 -08001805 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001806 ASSERT_TRUE(offer.get() != nullptr);
kwiberg31022942016-03-11 14:18:21 -08001807 std::unique_ptr<SessionDescription> answer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001808 f2_.CreateAnswer(offer.get(), opts, nullptr));
1809
1810 const VideoContentDescription* vcd =
1811 GetFirstVideoContentDescription(answer.get());
1812
1813 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1814 EXPECT_EQ(expected_codecs, vcd->codecs());
1815
1816 // Now, ensure that the RTX codec is created correctly when |f2_| creates an
1817 // updated offer, even though the default payload types are different from
1818 // those of |f1_|.
kwiberg31022942016-03-11 14:18:21 -08001819 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001820 f2_.CreateOffer(opts, answer.get()));
1821 ASSERT_TRUE(updated_offer);
1822
1823 const VideoContentDescription* updated_vcd =
1824 GetFirstVideoContentDescription(updated_offer.get());
1825
1826 // New offer should attempt to add H263, and RTX for H264.
1827 expected_codecs.push_back(kVideoCodecs2[1]);
1828 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[1].id),
1829 &expected_codecs);
1830 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1831}
1832
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001833// Test that RTX is ignored when there is no associated payload type parameter.
1834TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1835 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001836 opts.recv_video = true;
1837 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001838 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001839 // This creates RTX without associated payload type parameter.
perkj26752742016-10-24 01:21:16 -07001840 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001841 f1_.set_video_codecs(f1_codecs);
1842
1843 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001844 // This creates RTX for H264 with the payload type |f2_| uses.
1845 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001846 f2_.set_video_codecs(f2_codecs);
1847
kwiberg31022942016-03-11 14:18:21 -08001848 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001849 ASSERT_TRUE(offer.get() != NULL);
1850 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1851 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1852 // is possible to test that that RTX is dropped when
1853 // kCodecParamAssociatedPayloadType is missing in the offer.
1854 VideoContentDescription* desc =
1855 static_cast<cricket::VideoContentDescription*>(
1856 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1857 ASSERT_TRUE(desc != NULL);
1858 std::vector<VideoCodec> codecs = desc->codecs();
1859 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1860 iter != codecs.end(); ++iter) {
1861 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1862 iter->params.clear();
1863 }
1864 }
1865 desc->set_codecs(codecs);
1866
kwiberg31022942016-03-11 14:18:21 -08001867 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001868 f2_.CreateAnswer(offer.get(), opts, NULL));
1869
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001870 std::vector<std::string> codec_names =
1871 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1872 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1873 cricket::kRtxCodecName));
1874}
1875
1876// Test that RTX will be filtered out in the answer if its associated payload
1877// type doesn't match the local value.
1878TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1879 MediaSessionOptions opts;
1880 opts.recv_video = true;
1881 opts.recv_audio = false;
1882 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1883 // This creates RTX for H264 in sender.
1884 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1885 f1_.set_video_codecs(f1_codecs);
1886
1887 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1888 // This creates RTX for H263 in receiver.
1889 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1890 f2_.set_video_codecs(f2_codecs);
1891
kwiberg31022942016-03-11 14:18:21 -08001892 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001893 ASSERT_TRUE(offer.get() != NULL);
1894 // Associated payload type doesn't match, therefore, RTX codec is removed in
1895 // the answer.
kwiberg31022942016-03-11 14:18:21 -08001896 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001897 f2_.CreateAnswer(offer.get(), opts, NULL));
1898
1899 std::vector<std::string> codec_names =
1900 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1901 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1902 cricket::kRtxCodecName));
1903}
1904
1905// Test that when multiple RTX codecs are offered, only the matched RTX codec
1906// is added in the answer, and the unsupported RTX codec is filtered out.
1907TEST_F(MediaSessionDescriptionFactoryTest,
1908 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1909 MediaSessionOptions opts;
1910 opts.recv_video = true;
1911 opts.recv_audio = false;
1912 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1913 // This creates RTX for H264-SVC in sender.
1914 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1915 f1_.set_video_codecs(f1_codecs);
1916
1917 // This creates RTX for H264 in sender.
1918 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1919 f1_.set_video_codecs(f1_codecs);
1920
1921 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1922 // This creates RTX for H264 in receiver.
1923 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1924 f2_.set_video_codecs(f2_codecs);
1925
1926 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1927 // for H264-SVC should also be removed.
kwiberg31022942016-03-11 14:18:21 -08001928 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001929 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08001930 std::unique_ptr<SessionDescription> answer(
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001931 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001932 const VideoContentDescription* vcd =
1933 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001934 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1935 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1936 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001937
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001938 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001939}
1940
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001941// Test that after one RTX codec has been negotiated, a new offer can attempt
1942// to add another.
1943TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
1944 MediaSessionOptions opts;
1945 opts.recv_video = true;
1946 opts.recv_audio = false;
1947 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1948 // This creates RTX for H264 for the offerer.
1949 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1950 f1_.set_video_codecs(f1_codecs);
1951
kwiberg31022942016-03-11 14:18:21 -08001952 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001953 ASSERT_TRUE(offer);
1954 const VideoContentDescription* vcd =
1955 GetFirstVideoContentDescription(offer.get());
1956
1957 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecs1);
1958 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1959 &expected_codecs);
1960 EXPECT_EQ(expected_codecs, vcd->codecs());
1961
1962 // Now, attempt to add RTX for H264-SVC.
1963 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1964 f1_.set_video_codecs(f1_codecs);
1965
kwiberg31022942016-03-11 14:18:21 -08001966 std::unique_ptr<SessionDescription> updated_offer(
Taylor Brandstetter6ec641b2016-03-04 16:47:56 -08001967 f1_.CreateOffer(opts, offer.get()));
1968 ASSERT_TRUE(updated_offer);
1969 vcd = GetFirstVideoContentDescription(updated_offer.get());
1970
1971 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id),
1972 &expected_codecs);
1973 EXPECT_EQ(expected_codecs, vcd->codecs());
1974}
1975
Noah Richards2e7a0982015-05-18 14:02:54 -07001976// Test that when RTX is used in conjunction with simulcast, an RTX ssrc is
1977// generated for each simulcast ssrc and correctly grouped.
1978TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
1979 MediaSessionOptions opts;
1980 opts.recv_video = true;
1981 opts.recv_audio = false;
1982
1983 // Add simulcast streams.
1984 opts.AddSendVideoStream("stream1", "stream1label", 3);
1985
1986 // Use a single real codec, and then add RTX for it.
1987 std::vector<VideoCodec> f1_codecs;
perkj26752742016-10-24 01:21:16 -07001988 f1_codecs.push_back(VideoCodec(97, "H264"));
Noah Richards2e7a0982015-05-18 14:02:54 -07001989 AddRtxCodec(VideoCodec::CreateRtxCodec(125, 97), &f1_codecs);
1990 f1_.set_video_codecs(f1_codecs);
1991
1992 // Ensure that the offer has an RTX ssrc for each regular ssrc, and that there
1993 // is a FID ssrc + grouping for each.
kwiberg31022942016-03-11 14:18:21 -08001994 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
Noah Richards2e7a0982015-05-18 14:02:54 -07001995 ASSERT_TRUE(offer.get() != NULL);
1996 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
1997 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1998 ASSERT_TRUE(desc != NULL);
1999 EXPECT_TRUE(desc->multistream());
2000 const StreamParamsVec& streams = desc->streams();
2001 // Single stream.
2002 ASSERT_EQ(1u, streams.size());
2003 // Stream should have 6 ssrcs: 3 for video, 3 for RTX.
2004 EXPECT_EQ(6u, streams[0].ssrcs.size());
2005 // And should have a SIM group for the simulcast.
2006 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2007 // And a FID group for RTX.
2008 EXPECT_TRUE(streams[0].has_ssrc_group("FID"));
Peter Boström0c4e06b2015-10-07 12:23:21 +02002009 std::vector<uint32_t> primary_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002010 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2011 EXPECT_EQ(3u, primary_ssrcs.size());
Peter Boström0c4e06b2015-10-07 12:23:21 +02002012 std::vector<uint32_t> fid_ssrcs;
Noah Richards2e7a0982015-05-18 14:02:54 -07002013 streams[0].GetFidSsrcs(primary_ssrcs, &fid_ssrcs);
2014 EXPECT_EQ(3u, fid_ssrcs.size());
2015}
2016
brandtr03d5fb12016-11-22 03:37:59 -08002017// Test that, when the FlexFEC codec is added, a FlexFEC ssrc is created
2018// together with a FEC-FR grouping.
2019TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
2020 MediaSessionOptions opts;
2021 opts.recv_video = true;
2022 opts.recv_audio = false;
2023
2024 // Add single stream.
2025 opts.AddSendVideoStream("stream1", "stream1label", 1);
2026
2027 // Use a single real codec, and then add FlexFEC for it.
2028 std::vector<VideoCodec> f1_codecs;
2029 f1_codecs.push_back(VideoCodec(97, "H264"));
2030 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2031 f1_.set_video_codecs(f1_codecs);
2032
2033 // Ensure that the offer has a single FlexFEC ssrc and that
2034 // there is no FEC-FR ssrc + grouping for each.
2035 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2036 ASSERT_TRUE(offer.get() != nullptr);
2037 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2038 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2039 ASSERT_TRUE(desc != nullptr);
2040 EXPECT_TRUE(desc->multistream());
2041 const StreamParamsVec& streams = desc->streams();
2042 // Single stream.
2043 ASSERT_EQ(1u, streams.size());
2044 // Stream should have 2 ssrcs: 1 for video, 1 for FlexFEC.
2045 EXPECT_EQ(2u, streams[0].ssrcs.size());
2046 // And should have a FEC-FR group for FlexFEC.
2047 EXPECT_TRUE(streams[0].has_ssrc_group("FEC-FR"));
2048 std::vector<uint32_t> primary_ssrcs;
2049 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2050 ASSERT_EQ(1u, primary_ssrcs.size());
2051 uint32_t flexfec_ssrc;
2052 EXPECT_TRUE(streams[0].GetFecFrSsrc(primary_ssrcs[0], &flexfec_ssrc));
2053 EXPECT_NE(flexfec_ssrc, 0u);
2054}
2055
2056// Test that FlexFEC is disabled for simulcast.
2057// TODO(brandtr): Remove this test when we support simulcast, either through
2058// multiple FlexfecSenders, or through multistream protection.
2059TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
2060 MediaSessionOptions opts;
2061 opts.recv_video = true;
2062 opts.recv_audio = false;
2063
2064 // Add simulcast streams.
2065 opts.AddSendVideoStream("stream1", "stream1label", 3);
2066
2067 // Use a single real codec, and then add FlexFEC for it.
2068 std::vector<VideoCodec> f1_codecs;
2069 f1_codecs.push_back(VideoCodec(97, "H264"));
2070 f1_codecs.push_back(VideoCodec(118, "flexfec-03"));
2071 f1_.set_video_codecs(f1_codecs);
2072
2073 // Ensure that the offer has no FlexFEC ssrcs for each regular ssrc, and that
2074 // there is no FEC-FR ssrc + grouping for each.
2075 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2076 ASSERT_TRUE(offer.get() != nullptr);
2077 VideoContentDescription* desc = static_cast<VideoContentDescription*>(
2078 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
2079 ASSERT_TRUE(desc != nullptr);
2080 EXPECT_FALSE(desc->multistream());
2081 const StreamParamsVec& streams = desc->streams();
2082 // Single stream.
2083 ASSERT_EQ(1u, streams.size());
2084 // Stream should have 3 ssrcs: 3 for video, 0 for FlexFEC.
2085 EXPECT_EQ(3u, streams[0].ssrcs.size());
2086 // And should have a SIM group for the simulcast.
2087 EXPECT_TRUE(streams[0].has_ssrc_group("SIM"));
2088 // And not a FEC-FR group for FlexFEC.
2089 EXPECT_FALSE(streams[0].has_ssrc_group("FEC-FR"));
2090 std::vector<uint32_t> primary_ssrcs;
2091 streams[0].GetPrimarySsrcs(&primary_ssrcs);
2092 EXPECT_EQ(3u, primary_ssrcs.size());
2093 for (uint32_t primary_ssrc : primary_ssrcs) {
2094 uint32_t flexfec_ssrc;
2095 EXPECT_FALSE(streams[0].GetFecFrSsrc(primary_ssrc, &flexfec_ssrc));
2096 }
2097}
2098
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002099// Create an updated offer after creating an answer to the original offer and
2100// verify that the RTP header extensions that were part of the original answer
2101// are not changed in the updated offer.
2102TEST_F(MediaSessionDescriptionFactoryTest,
2103 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
2104 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002105 opts.recv_audio = true;
2106 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002107
2108 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
2109 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
2110 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
2111 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
2112
kwiberg31022942016-03-11 14:18:21 -08002113 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
2114 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002115 f2_.CreateAnswer(offer.get(), opts, NULL));
2116
2117 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
2118 GetFirstAudioContentDescription(
2119 answer.get())->rtp_header_extensions());
2120 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
2121 GetFirstVideoContentDescription(
2122 answer.get())->rtp_header_extensions());
2123
kwiberg31022942016-03-11 14:18:21 -08002124 std::unique_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002125 f2_.CreateOffer(opts, answer.get()));
2126
2127 // The expected RTP header extensions in the new offer are the resulting
2128 // extensions from the first offer/answer exchange plus the extensions only
2129 // |f2_| offer.
2130 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002131 // |f1_| for another extensions, it is changed to 13.
isheriff6f8d6862016-05-26 11:24:55 -07002132 const RtpExtension kUpdatedAudioRtpExtensions[] = {
2133 kAudioRtpExtensionAnswer[0], RtpExtension(kAudioRtpExtension2[1].uri, 13),
2134 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002135 };
2136
2137 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00002138 // |f1_| for another extensions, is is changed to 12.
isheriff6f8d6862016-05-26 11:24:55 -07002139 const RtpExtension kUpdatedVideoRtpExtensions[] = {
2140 kVideoRtpExtensionAnswer[0], RtpExtension(kVideoRtpExtension2[1].uri, 12),
2141 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002142 };
2143
2144 const AudioContentDescription* updated_acd =
2145 GetFirstAudioContentDescription(updated_offer.get());
2146 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
2147 updated_acd->rtp_header_extensions());
2148
2149 const VideoContentDescription* updated_vcd =
2150 GetFirstVideoContentDescription(updated_offer.get());
2151 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
2152 updated_vcd->rtp_header_extensions());
2153}
2154
deadbeefa5b273a2015-08-20 17:30:13 -07002155// Verify that if the same RTP extension URI is used for audio and video, the
2156// same ID is used. Also verify that the ID isn't changed when creating an
2157// updated offer (this was previously a bug).
isheriff6f8d6862016-05-26 11:24:55 -07002158TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
deadbeefa5b273a2015-08-20 17:30:13 -07002159 MediaSessionOptions opts;
2160 opts.recv_audio = true;
2161 opts.recv_video = true;
2162
2163 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
2164 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
2165
kwiberg31022942016-03-11 14:18:21 -08002166 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
deadbeefa5b273a2015-08-20 17:30:13 -07002167
2168 // Since the audio extensions used ID 3 for "both_audio_and_video", so should
2169 // the video extensions.
isheriff6f8d6862016-05-26 11:24:55 -07002170 const RtpExtension kExpectedVideoRtpExtension[] = {
2171 kVideoRtpExtension3[0], kAudioRtpExtension3[1],
deadbeefa5b273a2015-08-20 17:30:13 -07002172 };
2173
2174 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2175 GetFirstAudioContentDescription(
2176 offer.get())->rtp_header_extensions());
2177 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2178 GetFirstVideoContentDescription(
2179 offer.get())->rtp_header_extensions());
2180
2181 // Nothing should change when creating a new offer
kwiberg31022942016-03-11 14:18:21 -08002182 std::unique_ptr<SessionDescription> updated_offer(
deadbeefa5b273a2015-08-20 17:30:13 -07002183 f1_.CreateOffer(opts, offer.get()));
2184
2185 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension3),
2186 GetFirstAudioContentDescription(
2187 updated_offer.get())->rtp_header_extensions());
2188 EXPECT_EQ(MAKE_VECTOR(kExpectedVideoRtpExtension),
2189 GetFirstVideoContentDescription(
2190 updated_offer.get())->rtp_header_extensions());
2191}
2192
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002193TEST(MediaSessionDescription, CopySessionDescription) {
2194 SessionDescription source;
2195 cricket::ContentGroup group(cricket::CN_AUDIO);
2196 source.AddGroup(group);
2197 AudioContentDescription* acd(new AudioContentDescription());
2198 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
2199 acd->AddLegacyStream(1);
2200 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
2201 VideoContentDescription* vcd(new VideoContentDescription());
2202 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
2203 vcd->AddLegacyStream(2);
2204 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
2205
kwiberg31022942016-03-11 14:18:21 -08002206 std::unique_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002207 ASSERT_TRUE(copy.get() != NULL);
2208 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
2209 const ContentInfo* ac = copy->GetContentByName("audio");
2210 const ContentInfo* vc = copy->GetContentByName("video");
2211 ASSERT_TRUE(ac != NULL);
2212 ASSERT_TRUE(vc != NULL);
2213 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
2214 const AudioContentDescription* acd_copy =
2215 static_cast<const AudioContentDescription*>(ac->description);
2216 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
2217 EXPECT_EQ(1u, acd->first_ssrc());
2218
2219 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
2220 const VideoContentDescription* vcd_copy =
2221 static_cast<const VideoContentDescription*>(vc->description);
2222 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
2223 EXPECT_EQ(2u, vcd->first_ssrc());
2224}
2225
2226// The below TestTransportInfoXXX tests create different offers/answers, and
2227// ensure the TransportInfo in the SessionDescription matches what we expect.
2228TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
2229 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002230 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002231 TestTransportInfo(true, options, false);
2232}
2233
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002234TEST_F(MediaSessionDescriptionFactoryTest,
2235 TestTransportInfoOfferIceRenomination) {
2236 MediaSessionOptions options;
2237 options.enable_ice_renomination = true;
2238 TestTransportInfo(true, options, false);
2239}
2240
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002241TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
2242 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002243 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002244 TestTransportInfo(true, options, true);
2245}
2246
2247TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
2248 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002249 options.recv_audio = true;
2250 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002251 options.data_channel_type = cricket::DCT_RTP;
2252 TestTransportInfo(true, options, false);
2253}
2254
2255TEST_F(MediaSessionDescriptionFactoryTest,
2256 TestTransportInfoOfferMultimediaCurrent) {
2257 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002258 options.recv_audio = true;
2259 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002260 options.data_channel_type = cricket::DCT_RTP;
2261 TestTransportInfo(true, options, true);
2262}
2263
2264TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
2265 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002266 options.recv_audio = true;
2267 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002268 options.data_channel_type = cricket::DCT_RTP;
2269 options.bundle_enabled = true;
2270 TestTransportInfo(true, options, false);
2271}
2272
2273TEST_F(MediaSessionDescriptionFactoryTest,
2274 TestTransportInfoOfferBundleCurrent) {
2275 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002276 options.recv_audio = true;
2277 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002278 options.data_channel_type = cricket::DCT_RTP;
2279 options.bundle_enabled = true;
2280 TestTransportInfo(true, options, true);
2281}
2282
2283TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
2284 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002285 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002286 TestTransportInfo(false, options, false);
2287}
2288
2289TEST_F(MediaSessionDescriptionFactoryTest,
Honghai Zhang4cedf2b2016-08-31 08:18:11 -07002290 TestTransportInfoAnswerIceRenomination) {
2291 MediaSessionOptions options;
2292 options.enable_ice_renomination = true;
2293 TestTransportInfo(false, options, false);
2294}
2295
2296TEST_F(MediaSessionDescriptionFactoryTest,
2297 TestTransportInfoAnswerAudioCurrent) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002298 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002299 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002300 TestTransportInfo(false, options, true);
2301}
2302
2303TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
2304 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002305 options.recv_audio = true;
2306 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002307 options.data_channel_type = cricket::DCT_RTP;
2308 TestTransportInfo(false, options, false);
2309}
2310
2311TEST_F(MediaSessionDescriptionFactoryTest,
2312 TestTransportInfoAnswerMultimediaCurrent) {
2313 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002314 options.recv_audio = true;
2315 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002316 options.data_channel_type = cricket::DCT_RTP;
2317 TestTransportInfo(false, options, true);
2318}
2319
2320TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
2321 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002322 options.recv_audio = true;
2323 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002324 options.data_channel_type = cricket::DCT_RTP;
2325 options.bundle_enabled = true;
2326 TestTransportInfo(false, options, false);
2327}
2328
2329TEST_F(MediaSessionDescriptionFactoryTest,
2330 TestTransportInfoAnswerBundleCurrent) {
2331 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002332 options.recv_audio = true;
2333 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002334 options.data_channel_type = cricket::DCT_RTP;
2335 options.bundle_enabled = true;
2336 TestTransportInfo(false, options, true);
2337}
2338
2339// Create an offer with bundle enabled and verify the crypto parameters are
2340// the common set of the available cryptos.
2341TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
2342 TestCryptoWithBundle(true);
2343}
2344
2345// Create an answer with bundle enabled and verify the crypto parameters are
2346// the common set of the available cryptos.
2347TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
2348 TestCryptoWithBundle(false);
2349}
2350
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002351// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
2352// DTLS is not enabled locally.
2353TEST_F(MediaSessionDescriptionFactoryTest,
2354 TestOfferDtlsSavpfWithoutDtlsFailed) {
2355 f1_.set_secure(SEC_ENABLED);
2356 f2_.set_secure(SEC_ENABLED);
2357 tdf1_.set_secure(SEC_DISABLED);
2358 tdf2_.set_secure(SEC_DISABLED);
2359
kwiberg31022942016-03-11 14:18:21 -08002360 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002361 f1_.CreateOffer(MediaSessionOptions(), NULL));
2362 ASSERT_TRUE(offer.get() != NULL);
2363 ContentInfo* offer_content = offer->GetContentByName("audio");
2364 ASSERT_TRUE(offer_content != NULL);
2365 AudioContentDescription* offer_audio_desc =
2366 static_cast<AudioContentDescription*>(offer_content->description);
2367 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2368
kwiberg31022942016-03-11 14:18:21 -08002369 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002370 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2371 ASSERT_TRUE(answer != NULL);
2372 ContentInfo* answer_content = answer->GetContentByName("audio");
2373 ASSERT_TRUE(answer_content != NULL);
2374
2375 ASSERT_TRUE(answer_content->rejected);
2376}
2377
2378// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2379// UDP/TLS/RTP/SAVPF.
2380TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2381 f1_.set_secure(SEC_ENABLED);
2382 f2_.set_secure(SEC_ENABLED);
2383 tdf1_.set_secure(SEC_ENABLED);
2384 tdf2_.set_secure(SEC_ENABLED);
2385
kwiberg31022942016-03-11 14:18:21 -08002386 std::unique_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002387 f1_.CreateOffer(MediaSessionOptions(), NULL));
2388 ASSERT_TRUE(offer.get() != NULL);
2389 ContentInfo* offer_content = offer->GetContentByName("audio");
2390 ASSERT_TRUE(offer_content != NULL);
2391 AudioContentDescription* offer_audio_desc =
2392 static_cast<AudioContentDescription*>(offer_content->description);
2393 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2394
kwiberg31022942016-03-11 14:18:21 -08002395 std::unique_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002396 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2397 ASSERT_TRUE(answer != NULL);
2398
2399 const ContentInfo* answer_content = answer->GetContentByName("audio");
2400 ASSERT_TRUE(answer_content != NULL);
2401 ASSERT_FALSE(answer_content->rejected);
2402
2403 const AudioContentDescription* answer_audio_desc =
2404 static_cast<const AudioContentDescription*>(answer_content->description);
2405 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2406 answer_audio_desc->protocol());
2407}
2408
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002409// Test that we include both SDES and DTLS in the offer, but only include SDES
2410// in the answer if DTLS isn't negotiated.
2411TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2412 f1_.set_secure(SEC_ENABLED);
2413 f2_.set_secure(SEC_ENABLED);
2414 tdf1_.set_secure(SEC_ENABLED);
2415 tdf2_.set_secure(SEC_DISABLED);
2416 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002417 options.recv_audio = true;
2418 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002419 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002420 const cricket::MediaContentDescription* audio_media_desc;
2421 const cricket::MediaContentDescription* video_media_desc;
2422 const cricket::TransportDescription* audio_trans_desc;
2423 const cricket::TransportDescription* video_trans_desc;
2424
2425 // Generate an offer with SDES and DTLS support.
2426 offer.reset(f1_.CreateOffer(options, NULL));
2427 ASSERT_TRUE(offer.get() != NULL);
2428
2429 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2430 offer->GetContentDescriptionByName("audio"));
2431 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002432 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002433 offer->GetContentDescriptionByName("video"));
2434 ASSERT_TRUE(video_media_desc != NULL);
2435 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2436 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2437
2438 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2439 ASSERT_TRUE(audio_trans_desc != NULL);
2440 video_trans_desc = offer->GetTransportDescriptionByName("video");
2441 ASSERT_TRUE(video_trans_desc != NULL);
2442 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2443 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2444
2445 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2446 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2447 ASSERT_TRUE(answer.get() != NULL);
2448
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002449 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002450 answer->GetContentDescriptionByName("audio"));
2451 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002452 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002453 answer->GetContentDescriptionByName("video"));
2454 ASSERT_TRUE(video_media_desc != NULL);
2455 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2456 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2457
2458 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2459 ASSERT_TRUE(audio_trans_desc != NULL);
2460 video_trans_desc = answer->GetTransportDescriptionByName("video");
2461 ASSERT_TRUE(video_trans_desc != NULL);
2462 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2463 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2464
2465 // Enable DTLS; the answer should now only have DTLS support.
2466 tdf2_.set_secure(SEC_ENABLED);
2467 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2468 ASSERT_TRUE(answer.get() != NULL);
2469
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002470 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002471 answer->GetContentDescriptionByName("audio"));
2472 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002473 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002474 answer->GetContentDescriptionByName("video"));
2475 ASSERT_TRUE(video_media_desc != NULL);
2476 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2477 EXPECT_TRUE(video_media_desc->cryptos().empty());
2478 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2479 audio_media_desc->protocol());
2480 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2481 video_media_desc->protocol());
2482
2483 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2484 ASSERT_TRUE(audio_trans_desc != NULL);
2485 video_trans_desc = answer->GetTransportDescriptionByName("video");
2486 ASSERT_TRUE(video_trans_desc != NULL);
2487 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2488 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002489
2490 // Try creating offer again. DTLS enabled now, crypto's should be empty
2491 // in new offer.
2492 offer.reset(f1_.CreateOffer(options, offer.get()));
2493 ASSERT_TRUE(offer.get() != NULL);
2494 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2495 offer->GetContentDescriptionByName("audio"));
2496 ASSERT_TRUE(audio_media_desc != NULL);
2497 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2498 offer->GetContentDescriptionByName("video"));
2499 ASSERT_TRUE(video_media_desc != NULL);
2500 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2501 EXPECT_TRUE(video_media_desc->cryptos().empty());
2502
2503 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2504 ASSERT_TRUE(audio_trans_desc != NULL);
2505 video_trans_desc = offer->GetTransportDescriptionByName("video");
2506 ASSERT_TRUE(video_trans_desc != NULL);
2507 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2508 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002509}
2510
2511// Test that an answer can't be created if cryptos are required but the offer is
2512// unsecure.
2513TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2514 MediaSessionOptions options;
2515 f1_.set_secure(SEC_DISABLED);
2516 tdf1_.set_secure(SEC_DISABLED);
2517 f2_.set_secure(SEC_REQUIRED);
2518 tdf1_.set_secure(SEC_ENABLED);
2519
kwiberg31022942016-03-11 14:18:21 -08002520 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002521 ASSERT_TRUE(offer.get() != NULL);
kwiberg31022942016-03-11 14:18:21 -08002522 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002523 f2_.CreateAnswer(offer.get(), options, NULL));
2524 EXPECT_TRUE(answer.get() == NULL);
2525}
2526
2527// Test that we accept a DTLS offer without SDES and create an appropriate
2528// answer.
2529TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2530 f1_.set_secure(SEC_DISABLED);
2531 f2_.set_secure(SEC_ENABLED);
2532 tdf1_.set_secure(SEC_ENABLED);
2533 tdf2_.set_secure(SEC_ENABLED);
2534 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002535 options.recv_audio = true;
2536 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002537 options.data_channel_type = cricket::DCT_RTP;
2538
kwiberg31022942016-03-11 14:18:21 -08002539 std::unique_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002540
2541 // Generate an offer with DTLS but without SDES.
2542 offer.reset(f1_.CreateOffer(options, NULL));
2543 ASSERT_TRUE(offer.get() != NULL);
2544
2545 const AudioContentDescription* audio_offer =
2546 GetFirstAudioContentDescription(offer.get());
2547 ASSERT_TRUE(audio_offer->cryptos().empty());
2548 const VideoContentDescription* video_offer =
2549 GetFirstVideoContentDescription(offer.get());
2550 ASSERT_TRUE(video_offer->cryptos().empty());
2551 const DataContentDescription* data_offer =
2552 GetFirstDataContentDescription(offer.get());
2553 ASSERT_TRUE(data_offer->cryptos().empty());
2554
2555 const cricket::TransportDescription* audio_offer_trans_desc =
2556 offer->GetTransportDescriptionByName("audio");
2557 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2558 const cricket::TransportDescription* video_offer_trans_desc =
2559 offer->GetTransportDescriptionByName("video");
2560 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2561 const cricket::TransportDescription* data_offer_trans_desc =
2562 offer->GetTransportDescriptionByName("data");
2563 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2564
2565 // Generate an answer with DTLS.
2566 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2567 ASSERT_TRUE(answer.get() != NULL);
2568
2569 const cricket::TransportDescription* audio_answer_trans_desc =
2570 answer->GetTransportDescriptionByName("audio");
2571 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2572 const cricket::TransportDescription* video_answer_trans_desc =
2573 answer->GetTransportDescriptionByName("video");
2574 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2575 const cricket::TransportDescription* data_answer_trans_desc =
2576 answer->GetTransportDescriptionByName("data");
2577 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2578}
2579
2580// Verifies if vad_enabled option is set to false, CN codecs are not present in
2581// offer or answer.
2582TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2583 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002584 options.recv_audio = true;
2585 options.recv_video = true;
kwiberg31022942016-03-11 14:18:21 -08002586 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002587 ASSERT_TRUE(offer.get() != NULL);
2588 const ContentInfo* audio_content = offer->GetContentByName("audio");
2589 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2590
2591 options.vad_enabled = false;
2592 offer.reset(f1_.CreateOffer(options, NULL));
2593 ASSERT_TRUE(offer.get() != NULL);
2594 audio_content = offer->GetContentByName("audio");
2595 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
kwiberg31022942016-03-11 14:18:21 -08002596 std::unique_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002597 f1_.CreateAnswer(offer.get(), options, NULL));
2598 ASSERT_TRUE(answer.get() != NULL);
2599 audio_content = answer->GetContentByName("audio");
2600 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2601}
deadbeef44f08192015-12-15 16:20:09 -08002602
2603// Test that the content name ("mid" in SDP) is unchanged when creating a
2604// new offer.
2605TEST_F(MediaSessionDescriptionFactoryTest,
2606 TestContentNameNotChangedInSubsequentOffers) {
2607 MediaSessionOptions opts;
2608 opts.recv_audio = true;
2609 opts.recv_video = true;
2610 opts.data_channel_type = cricket::DCT_SCTP;
2611 // Create offer and modify the default content names.
kwiberg31022942016-03-11 14:18:21 -08002612 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
deadbeef44f08192015-12-15 16:20:09 -08002613 for (ContentInfo& content : offer->contents()) {
2614 content.name.append("_modified");
2615 }
2616
kwiberg31022942016-03-11 14:18:21 -08002617 std::unique_ptr<SessionDescription> updated_offer(
deadbeef44f08192015-12-15 16:20:09 -08002618 f1_.CreateOffer(opts, offer.get()));
2619 const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
2620 const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
2621 const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
2622 ASSERT_TRUE(audio_content != nullptr);
2623 ASSERT_TRUE(video_content != nullptr);
2624 ASSERT_TRUE(data_content != nullptr);
2625 EXPECT_EQ("audio_modified", audio_content->name);
2626 EXPECT_EQ("video_modified", video_content->name);
2627 EXPECT_EQ("data_modified", data_content->name);
2628}
zhihuangcf5b37c2016-05-05 11:44:35 -07002629
2630class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
2631 public:
2632 MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
ossu075af922016-06-14 03:29:38 -07002633 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
2634 MAKE_VECTOR(kAudioCodecs1));
zhihuangcf5b37c2016-05-05 11:44:35 -07002635 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
2636 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
ossu075af922016-06-14 03:29:38 -07002637 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
2638 MAKE_VECTOR(kAudioCodecs2));
zhihuangcf5b37c2016-05-05 11:44:35 -07002639 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
2640 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
2641 f1_.set_secure(SEC_ENABLED);
2642 f2_.set_secure(SEC_ENABLED);
2643 tdf1_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002644 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002645 tdf2_.set_certificate(rtc::RTCCertificate::Create(
kwibergfd8be342016-05-14 19:44:11 -07002646 std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id2"))));
zhihuangcf5b37c2016-05-05 11:44:35 -07002647 tdf1_.set_secure(SEC_ENABLED);
2648 tdf2_.set_secure(SEC_ENABLED);
2649 }
2650
2651 protected:
2652 MediaSessionDescriptionFactory f1_;
2653 MediaSessionDescriptionFactory f2_;
2654 TransportDescriptionFactory tdf1_;
2655 TransportDescriptionFactory tdf2_;
2656};
2657
2658TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
2659 MediaSessionOptions opts;
2660 opts.recv_video = true;
2661 std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
2662 ASSERT_TRUE(offer.get() != nullptr);
2663 // Set the protocol for all the contents.
2664 for (auto content : offer.get()->contents()) {
2665 static_cast<MediaContentDescription*>(content.description)
2666 ->set_protocol(GetParam());
2667 }
2668 std::unique_ptr<SessionDescription> answer(
2669 f2_.CreateAnswer(offer.get(), opts, nullptr));
2670 const ContentInfo* ac = answer->GetContentByName("audio");
2671 const ContentInfo* vc = answer->GetContentByName("video");
2672 ASSERT_TRUE(ac != nullptr);
2673 ASSERT_TRUE(vc != nullptr);
2674 EXPECT_FALSE(ac->rejected); // the offer is accepted
2675 EXPECT_FALSE(vc->rejected);
2676 const AudioContentDescription* acd =
2677 static_cast<const AudioContentDescription*>(ac->description);
2678 const VideoContentDescription* vcd =
2679 static_cast<const VideoContentDescription*>(vc->description);
2680 EXPECT_EQ(GetParam(), acd->protocol());
2681 EXPECT_EQ(GetParam(), vcd->protocol());
2682}
2683
2684INSTANTIATE_TEST_CASE_P(MediaProtocolPatternTest,
2685 MediaProtocolTest,
2686 ::testing::ValuesIn(kMediaProtocols));
2687INSTANTIATE_TEST_CASE_P(MediaProtocolDtlsPatternTest,
2688 MediaProtocolTest,
2689 ::testing::ValuesIn(kMediaProtocolsDtls));
ossu075af922016-06-14 03:29:38 -07002690
2691TEST_F(MediaSessionDescriptionFactoryTest, TestSetAudioCodecs) {
2692 TransportDescriptionFactory tdf;
2693 MediaSessionDescriptionFactory sf(&tdf);
2694 std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2695 std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2696
2697 // The merged list of codecs should contain any send codecs that are also
2698 // nominally in the recieve codecs list. Payload types should be picked from
2699 // the send codecs and a number-of-channels of 0 and 1 should be equivalent
2700 // (set to 1). This equals what happens when the send codecs are used in an
2701 // offer and the receive codecs are used in the following answer.
2702 const std::vector<AudioCodec> sendrecv_codecs =
2703 MAKE_VECTOR(kAudioCodecsAnswer);
2704 const std::vector<AudioCodec> no_codecs;
2705
2706 RTC_CHECK_EQ(send_codecs[1].name, "iLBC")
2707 << "Please don't change shared test data!";
2708 RTC_CHECK_EQ(recv_codecs[2].name, "iLBC")
2709 << "Please don't change shared test data!";
2710 // Alter iLBC send codec to have zero channels, to test that that is handled
2711 // properly.
2712 send_codecs[1].channels = 0;
2713
2714 // Alther iLBC receive codec to be lowercase, to test that case conversions
2715 // are handled properly.
2716 recv_codecs[2].name = "ilbc";
2717
2718 // Test proper merge
2719 sf.set_audio_codecs(send_codecs, recv_codecs);
2720 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2721 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002722 EXPECT_TRUE(sf.audio_sendrecv_codecs() == sendrecv_codecs);
ossu075af922016-06-14 03:29:38 -07002723
2724 // Test empty send codecs list
2725 sf.set_audio_codecs(no_codecs, recv_codecs);
2726 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2727 EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
ossudedfd282016-06-14 07:12:39 -07002728 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002729
2730 // Test empty recv codecs list
2731 sf.set_audio_codecs(send_codecs, no_codecs);
2732 EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
2733 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002734 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002735
2736 // Test all empty codec lists
2737 sf.set_audio_codecs(no_codecs, no_codecs);
2738 EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
2739 EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
ossudedfd282016-06-14 07:12:39 -07002740 EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
ossu075af922016-06-14 03:29:38 -07002741}
2742
2743namespace {
2744void TestAudioCodecsOffer(MediaContentDirection direction,
2745 bool add_legacy_stream) {
2746 TransportDescriptionFactory tdf;
2747 MediaSessionDescriptionFactory sf(&tdf);
2748 const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
2749 const std::vector<AudioCodec> recv_codecs = MAKE_VECTOR(kAudioCodecs2);
2750 const std::vector<AudioCodec> sendrecv_codecs =
2751 MAKE_VECTOR(kAudioCodecsAnswer);
2752 sf.set_audio_codecs(send_codecs, recv_codecs);
2753 sf.set_add_legacy_streams(add_legacy_stream);
2754
2755 MediaSessionOptions opts;
2756 opts.recv_audio = (direction == cricket::MD_RECVONLY ||
2757 direction == cricket::MD_SENDRECV);
2758 opts.recv_video = false;
2759 if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV)
2760 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2761
2762 std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
2763 ASSERT_TRUE(offer.get() != NULL);
2764 const ContentInfo* ac = offer->GetContentByName("audio");
2765
2766 // If the factory didn't add any audio content to the offer, we cannot check
2767 // that the codecs put in are right. This happens when we neither want to send
2768 // nor receive audio. The checks are still in place if at some point we'd
2769 // instead create an inactive stream.
2770 if (ac) {
2771 AudioContentDescription* acd =
2772 static_cast<AudioContentDescription*>(ac->description);
2773 // sendrecv and inactive should both present lists as if the channel was to
2774 // be used for sending and receiving. Inactive essentially means it might
2775 // eventually be used anything, but we don't know more at this moment.
2776 if (acd->direction() == cricket::MD_SENDONLY) {
2777 EXPECT_TRUE(acd->codecs() == send_codecs);
2778 } else if (acd->direction() == cricket::MD_RECVONLY) {
2779 EXPECT_TRUE(acd->codecs() == recv_codecs);
2780 } else {
2781 EXPECT_TRUE(acd->codecs() == sendrecv_codecs);
2782 }
2783 }
2784}
2785
2786static const AudioCodec kOfferAnswerCodecs[] = {
2787 AudioCodec(0, "codec0", 16000, -1, 1),
2788 AudioCodec(1, "codec1", 8000, 13300, 1),
2789 AudioCodec(2, "codec2", 8000, 64000, 1),
2790 AudioCodec(3, "codec3", 8000, 64000, 1),
2791 AudioCodec(4, "codec4", 8000, 0, 2),
2792 AudioCodec(5, "codec5", 32000, 0, 1),
2793 AudioCodec(6, "codec6", 48000, 0, 1)
2794};
2795
2796
2797/* The codecs groups below are chosen as per the matrix below. The objective is
2798 * to have different sets of codecs in the inputs, to get unique sets of codecs
2799 * after negotiation, depending on offer and answer communication directions.
2800 * One-way directions in the offer should either result in the opposite
2801 * direction in the answer, or an inactive answer. Regardless, the choice of
2802 * codecs should be as if the answer contained the opposite direction.
2803 * Inactive offers should be treated as sendrecv/sendrecv.
2804 *
2805 * | Offer | Answer | Result
2806 * codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
2807 * 0 | x - - | - x - | x - - - -
2808 * 1 | x x x | - x - | x - - x -
2809 * 2 | - x - | x - - | - x - - -
2810 * 3 | x x x | x - - | - x x - -
2811 * 4 | - x - | x x x | - x - - -
2812 * 5 | x - - | x x x | x - - - -
2813 * 6 | x x x | x x x | x x x x x
2814 */
2815// Codecs used by offerer in the AudioCodecsAnswerTest
2816static const int kOfferSendCodecs[] = { 0, 1, 3, 5, 6 };
2817static const int kOfferRecvCodecs[] = { 1, 2, 3, 4, 6 };
2818// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
2819// jumbled to catch the answer not following the order in the offer.
2820static const int kAnswerSendCodecs[] = { 6, 5, 2, 3, 4 };
2821static const int kAnswerRecvCodecs[] = { 6, 5, 4, 1, 0 };
2822// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
2823static const int kResultSend_RecvCodecs[] = { 0, 1, 5, 6 };
2824static const int kResultRecv_SendCodecs[] = { 2, 3, 4, 6 };
2825static const int kResultSendrecv_SendCodecs[] = { 3, 6 };
2826static const int kResultSendrecv_RecvCodecs[] = { 1, 6 };
2827static const int kResultSendrecv_SendrecvCodecs[] = { 6 };
2828
2829template <typename T, int IDXS>
2830std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
2831 std::vector<T> out;
2832 out.reserve(IDXS);
2833 for (int idx : indices)
2834 out.push_back(array[idx]);
2835
2836 return out;
2837}
2838
2839void TestAudioCodecsAnswer(MediaContentDirection offer_direction,
2840 MediaContentDirection answer_direction,
2841 bool add_legacy_stream) {
2842 TransportDescriptionFactory offer_tdf;
2843 TransportDescriptionFactory answer_tdf;
2844 MediaSessionDescriptionFactory offer_factory(&offer_tdf);
2845 MediaSessionDescriptionFactory answer_factory(&answer_tdf);
2846 offer_factory.set_audio_codecs(
2847 VectorFromIndices(kOfferAnswerCodecs, kOfferSendCodecs),
2848 VectorFromIndices(kOfferAnswerCodecs, kOfferRecvCodecs));
2849 answer_factory.set_audio_codecs(
2850 VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
2851 VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
2852
2853 // Never add a legacy stream to offer - we want to control the offer
2854 // parameters exactly.
2855 offer_factory.set_add_legacy_streams(false);
2856 answer_factory.set_add_legacy_streams(add_legacy_stream);
2857 MediaSessionOptions offer_opts;
2858 offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY ||
2859 offer_direction == cricket::MD_SENDRECV);
2860 offer_opts.recv_video = false;
2861 if (offer_direction == cricket::MD_SENDONLY ||
2862 offer_direction == cricket::MD_SENDRECV) {
2863 offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2864 }
2865
2866 std::unique_ptr<SessionDescription> offer(
2867 offer_factory.CreateOffer(offer_opts, NULL));
2868 ASSERT_TRUE(offer.get() != NULL);
2869
2870 MediaSessionOptions answer_opts;
2871 answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY ||
2872 answer_direction == cricket::MD_SENDRECV);
2873 answer_opts.recv_video = false;
2874 if (answer_direction == cricket::MD_SENDONLY ||
2875 answer_direction == cricket::MD_SENDRECV) {
2876 answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
2877 }
2878 std::unique_ptr<SessionDescription> answer(
2879 answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
2880 const ContentInfo* ac = answer->GetContentByName("audio");
2881
2882 // If the factory didn't add any audio content to the answer, we cannot check
2883 // that the codecs put in are right. This happens when we neither want to send
2884 // nor receive audio. The checks are still in place if at some point we'd
2885 // instead create an inactive stream.
2886 if (ac) {
2887 const AudioContentDescription* acd =
2888 static_cast<const AudioContentDescription*>(ac->description);
2889 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
2890
2891
2892 std::vector<AudioCodec> target_codecs;
2893 // For offers with sendrecv or inactive, we should never reply with more
2894 // codecs than offered, with these codec sets.
2895 switch (offer_direction) {
2896 case cricket::MD_INACTIVE:
2897 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2898 kResultSendrecv_SendrecvCodecs);
2899 break;
2900 case cricket::MD_SENDONLY:
2901 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2902 kResultSend_RecvCodecs);
2903 break;
2904 case cricket::MD_RECVONLY:
2905 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2906 kResultRecv_SendCodecs);
2907 break;
2908 case cricket::MD_SENDRECV:
2909 if (acd->direction() == cricket::MD_SENDONLY) {
2910 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2911 kResultSendrecv_SendCodecs);
2912 } else if (acd->direction() == cricket::MD_RECVONLY) {
2913 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2914 kResultSendrecv_RecvCodecs);
2915 } else {
2916 target_codecs = VectorFromIndices(kOfferAnswerCodecs,
2917 kResultSendrecv_SendrecvCodecs);
2918 }
2919 break;
2920 }
2921
2922 auto format_codecs = [] (const std::vector<AudioCodec>& codecs) {
2923 std::stringstream os;
2924 bool first = true;
2925 os << "{";
2926 for (const auto& c : codecs) {
2927 os << (first ? " " : ", ") << c.id;
2928 first = false;
2929 }
2930 os << " }";
2931 return os.str();
2932 };
2933
2934 EXPECT_TRUE(acd->codecs() == target_codecs)
2935 << "Expected: " << format_codecs(target_codecs)
2936 << ", got: " << format_codecs(acd->codecs())
2937 << "; Offered: " << MediaContentDirectionToString(offer_direction)
2938 << ", answerer wants: "
2939 << MediaContentDirectionToString(answer_direction)
2940 << "; got: " << MediaContentDirectionToString(acd->direction());
2941 } else {
2942 EXPECT_EQ(offer_direction, cricket::MD_INACTIVE)
2943 << "Only inactive offers are allowed to not generate any audio content";
2944 }
2945}
brandtr03d5fb12016-11-22 03:37:59 -08002946
2947} // namespace
ossu075af922016-06-14 03:29:38 -07002948
2949class AudioCodecsOfferTest
2950 : public ::testing::TestWithParam<std::tr1::tuple<MediaContentDirection,
2951 bool>> {
2952};
2953
2954TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
2955 TestAudioCodecsOffer(std::tr1::get<0>(GetParam()),
2956 std::tr1::get<1>(GetParam()));
2957}
2958
2959INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
2960 AudioCodecsOfferTest,
2961 ::testing::Combine(
2962 ::testing::Values(cricket::MD_SENDONLY,
2963 cricket::MD_RECVONLY,
2964 cricket::MD_SENDRECV,
2965 cricket::MD_INACTIVE),
2966 ::testing::Bool()));
2967
2968class AudioCodecsAnswerTest
2969 : public ::testing::TestWithParam<std::tr1::tuple<MediaContentDirection,
2970 MediaContentDirection,
2971 bool>> {
2972};
2973
2974TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
2975 TestAudioCodecsAnswer(std::tr1::get<0>(GetParam()),
2976 std::tr1::get<1>(GetParam()),
2977 std::tr1::get<2>(GetParam()));
2978}
2979
2980INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
2981 AudioCodecsAnswerTest,
2982 ::testing::Combine(
2983 ::testing::Values(cricket::MD_SENDONLY,
2984 cricket::MD_RECVONLY,
2985 cricket::MD_SENDRECV,
2986 cricket::MD_INACTIVE),
2987 ::testing::Values(cricket::MD_SENDONLY,
2988 cricket::MD_RECVONLY,
2989 cricket::MD_SENDRECV,
2990 cricket::MD_INACTIVE),
2991 ::testing::Bool()));