blob: f487baa9c56e4774713cdd7ec9617f294f69c1c6 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include <string>
29#include <vector>
30
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031#include "talk/media/base/codec.h"
32#include "talk/media/base/testutils.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033#include "webrtc/p2p/base/constants.h"
34#include "webrtc/p2p/base/transportdescription.h"
35#include "webrtc/p2p/base/transportinfo.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000036#include "talk/session/media/mediasession.h"
37#include "talk/session/media/srtpfilter.h"
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000038#include "webrtc/base/fakesslidentity.h"
39#include "webrtc/base/gunit.h"
40#include "webrtc/base/messagedigest.h"
41#include "webrtc/base/ssladapter.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042
43#ifdef HAVE_SRTP
44#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000045 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046 ASSERT_EQ(s, cd->cryptos().size()); \
47 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
48#else
49#define ASSERT_CRYPTO(cd, s, cs) \
henrike@webrtc.orgb90991d2014-03-04 19:54:57 +000050 ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051 ASSERT_EQ(0U, cd->cryptos().size());
52#endif
53
54typedef std::vector<cricket::Candidate> Candidates;
55
56using cricket::MediaContentDescription;
57using cricket::MediaSessionDescriptionFactory;
58using cricket::MediaSessionOptions;
59using cricket::MediaType;
60using cricket::SessionDescription;
61using cricket::SsrcGroup;
62using cricket::StreamParams;
63using cricket::StreamParamsVec;
64using cricket::TransportDescription;
65using cricket::TransportDescriptionFactory;
66using cricket::TransportInfo;
67using cricket::ContentInfo;
68using cricket::CryptoParamsVec;
69using cricket::AudioContentDescription;
70using cricket::VideoContentDescription;
71using cricket::DataContentDescription;
72using cricket::GetFirstAudioContentDescription;
73using cricket::GetFirstVideoContentDescription;
74using cricket::GetFirstDataContentDescription;
75using cricket::kAutoBandwidth;
76using cricket::AudioCodec;
77using cricket::VideoCodec;
78using cricket::DataCodec;
79using cricket::NS_JINGLE_RTP;
80using cricket::MEDIA_TYPE_AUDIO;
81using cricket::MEDIA_TYPE_VIDEO;
82using cricket::MEDIA_TYPE_DATA;
83using cricket::RtpHeaderExtension;
84using cricket::SEC_DISABLED;
85using cricket::SEC_ENABLED;
86using cricket::SEC_REQUIRED;
87using cricket::CS_AES_CM_128_HMAC_SHA1_32;
88using cricket::CS_AES_CM_128_HMAC_SHA1_80;
89
90static const AudioCodec kAudioCodecs1[] = {
91 AudioCodec(103, "ISAC", 16000, -1, 1, 6),
92 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
93 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
94 AudioCodec(8, "PCMA", 8000, 64000, 1, 3),
95 AudioCodec(117, "red", 8000, 0, 1, 2),
96 AudioCodec(107, "CN", 48000, 0, 1, 1)
97};
98
99static const AudioCodec kAudioCodecs2[] = {
100 AudioCodec(126, "speex", 16000, 22000, 1, 3),
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000101 AudioCodec(0, "PCMU", 8000, 64000, 1, 2),
102 AudioCodec(127, "iLBC", 8000, 13300, 1, 1),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103};
104
105static const AudioCodec kAudioCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000106 AudioCodec(102, "iLBC", 8000, 13300, 1, 5),
107 AudioCodec(0, "PCMU", 8000, 64000, 1, 4),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000108};
109
110static const VideoCodec kVideoCodecs1[] = {
111 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
112 VideoCodec(97, "H264", 320, 200, 30, 1)
113};
114
115static const VideoCodec kVideoCodecs2[] = {
116 VideoCodec(126, "H264", 320, 200, 30, 2),
117 VideoCodec(127, "H263", 320, 200, 30, 1)
118};
119
120static const VideoCodec kVideoCodecsAnswer[] = {
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +0000121 VideoCodec(97, "H264", 320, 200, 30, 1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000122};
123
124static const DataCodec kDataCodecs1[] = {
125 DataCodec(98, "binary-data", 2),
126 DataCodec(99, "utf8-text", 1)
127};
128
129static const DataCodec kDataCodecs2[] = {
130 DataCodec(126, "binary-data", 2),
131 DataCodec(127, "utf8-text", 1)
132};
133
134static const DataCodec kDataCodecsAnswer[] = {
135 DataCodec(98, "binary-data", 2),
136 DataCodec(99, "utf8-text", 1)
137};
138
139static const RtpHeaderExtension kAudioRtpExtension1[] = {
140 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
141 RtpHeaderExtension("http://google.com/testing/audio_something", 10),
142};
143
144static const RtpHeaderExtension kAudioRtpExtension2[] = {
145 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
146 RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000147 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148};
149
150static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
151 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
152};
153
154static const RtpHeaderExtension kVideoRtpExtension1[] = {
155 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000156 RtpHeaderExtension("http://google.com/testing/video_something", 13),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157};
158
159static const RtpHeaderExtension kVideoRtpExtension2[] = {
160 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
161 RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
henrike@webrtc.org79047f92014-03-06 23:46:59 +0000162 RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163};
164
165static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
166 RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
167};
168
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000169static const uint32 kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
170static const uint32 kSimSsrc[] = {10, 20, 30};
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000171static const uint32 kFec1Ssrc[] = {10, 11};
172static const uint32 kFec2Ssrc[] = {20, 21};
173static const uint32 kFec3Ssrc[] = {30, 31};
174
175static const char kMediaStream1[] = "stream_1";
176static const char kMediaStream2[] = "stream_2";
177static const char kVideoTrack1[] = "video_1";
178static const char kVideoTrack2[] = "video_2";
179static const char kAudioTrack1[] = "audio_1";
180static const char kAudioTrack2[] = "audio_2";
181static const char kAudioTrack3[] = "audio_3";
182static const char kDataTrack1[] = "data_1";
183static const char kDataTrack2[] = "data_2";
184static const char kDataTrack3[] = "data_3";
185
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000186static bool IsMediaContentOfType(const ContentInfo* content,
187 MediaType media_type) {
188 const MediaContentDescription* mdesc =
189 static_cast<const MediaContentDescription*>(content->description);
190 return mdesc && mdesc->type() == media_type;
191}
192
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000193static cricket::MediaContentDirection
194GetMediaDirection(const ContentInfo* content) {
195 cricket::MediaContentDescription* desc =
196 reinterpret_cast<cricket::MediaContentDescription*>(content->description);
197 return desc->direction();
198}
199
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +0000200static void AddRtxCodec(const VideoCodec& rtx_codec,
201 std::vector<VideoCodec>* codecs) {
202 VideoCodec rtx;
203 ASSERT_FALSE(cricket::FindCodecById(*codecs, rtx_codec.id, &rtx));
204 codecs->push_back(rtx_codec);
205}
206
207template <class T>
208static std::vector<std::string> GetCodecNames(const std::vector<T>& codecs) {
209 std::vector<std::string> codec_names;
210 for (const auto& codec : codecs) {
211 codec_names.push_back(codec.name);
212 }
213 return codec_names;
214}
215
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000216class MediaSessionDescriptionFactoryTest : public testing::Test {
217 public:
218 MediaSessionDescriptionFactoryTest()
219 : f1_(&tdf1_), f2_(&tdf2_), id1_("id1"), id2_("id2") {
220 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
221 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
222 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
223 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
224 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
225 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
226 tdf1_.set_identity(&id1_);
227 tdf2_.set_identity(&id2_);
228 }
229
henrike@webrtc.org704bf9e2014-02-27 17:52:04 +0000230 // Create a video StreamParamsVec object with:
231 // - one video stream with 3 simulcast streams and FEC,
232 StreamParamsVec CreateComplexVideoStreamParamsVec() {
233 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
234 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
235 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
236 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
237
238 std::vector<SsrcGroup> ssrc_groups;
239 ssrc_groups.push_back(sim_group);
240 ssrc_groups.push_back(fec_group1);
241 ssrc_groups.push_back(fec_group2);
242 ssrc_groups.push_back(fec_group3);
243
244 StreamParams simulcast_params;
245 simulcast_params.id = kVideoTrack1;
246 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
247 simulcast_params.ssrc_groups = ssrc_groups;
248 simulcast_params.cname = "Video_SIM_FEC";
249 simulcast_params.sync_label = kMediaStream1;
250
251 StreamParamsVec video_streams;
252 video_streams.push_back(simulcast_params);
253
254 return video_streams;
255 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000256
257 bool CompareCryptoParams(const CryptoParamsVec& c1,
258 const CryptoParamsVec& c2) {
259 if (c1.size() != c2.size())
260 return false;
261 for (size_t i = 0; i < c1.size(); ++i)
262 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
263 c1[i].key_params != c2[i].key_params ||
264 c1[i].session_params != c2[i].session_params)
265 return false;
266 return true;
267 }
268
269 void TestTransportInfo(bool offer, const MediaSessionOptions& options,
270 bool has_current_desc) {
271 const std::string current_audio_ufrag = "current_audio_ufrag";
272 const std::string current_audio_pwd = "current_audio_pwd";
273 const std::string current_video_ufrag = "current_video_ufrag";
274 const std::string current_video_pwd = "current_video_pwd";
275 const std::string current_data_ufrag = "current_data_ufrag";
276 const std::string current_data_pwd = "current_data_pwd";
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000277 rtc::scoped_ptr<SessionDescription> current_desc;
278 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000279 if (has_current_desc) {
280 current_desc.reset(new SessionDescription());
281 EXPECT_TRUE(current_desc->AddTransportInfo(
282 TransportInfo("audio",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000283 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000284 current_audio_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000285 current_audio_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000286 EXPECT_TRUE(current_desc->AddTransportInfo(
287 TransportInfo("video",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000288 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 current_video_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000290 current_video_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000291 EXPECT_TRUE(current_desc->AddTransportInfo(
292 TransportInfo("data",
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000293 TransportDescription("",
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000294 current_data_ufrag,
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000295 current_data_pwd))));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 }
297 if (offer) {
298 desc.reset(f1_.CreateOffer(options, current_desc.get()));
299 } else {
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000300 rtc::scoped_ptr<SessionDescription> offer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000301 offer.reset(f1_.CreateOffer(options, NULL));
302 desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
303 }
304 ASSERT_TRUE(desc.get() != NULL);
305 const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000306 if (options.has_audio()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000307 EXPECT_TRUE(ti_audio != NULL);
308 if (has_current_desc) {
309 EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
310 EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
311 } else {
312 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
313 ti_audio->description.ice_ufrag.size());
314 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
315 ti_audio->description.ice_pwd.size());
316 }
317
318 } else {
319 EXPECT_TRUE(ti_audio == NULL);
320 }
321 const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000322 if (options.has_video()) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000323 EXPECT_TRUE(ti_video != NULL);
324 if (options.bundle_enabled) {
325 EXPECT_EQ(ti_audio->description.ice_ufrag,
326 ti_video->description.ice_ufrag);
327 EXPECT_EQ(ti_audio->description.ice_pwd,
328 ti_video->description.ice_pwd);
329 } else {
330 if (has_current_desc) {
331 EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
332 EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
333 } else {
334 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
335 ti_video->description.ice_ufrag.size());
336 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
337 ti_video->description.ice_pwd.size());
338 }
339 }
340 } else {
341 EXPECT_TRUE(ti_video == NULL);
342 }
343 const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
344 if (options.has_data()) {
345 EXPECT_TRUE(ti_data != NULL);
346 if (options.bundle_enabled) {
347 EXPECT_EQ(ti_audio->description.ice_ufrag,
348 ti_data->description.ice_ufrag);
349 EXPECT_EQ(ti_audio->description.ice_pwd,
350 ti_data->description.ice_pwd);
351 } else {
352 if (has_current_desc) {
353 EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
354 EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
355 } else {
356 EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
357 ti_data->description.ice_ufrag.size());
358 EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
359 ti_data->description.ice_pwd.size());
360 }
361 }
362 } else {
363 EXPECT_TRUE(ti_video == NULL);
364 }
365 }
366
367 void TestCryptoWithBundle(bool offer) {
368 f1_.set_secure(SEC_ENABLED);
369 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000370 options.recv_audio = true;
371 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000372 options.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000373 rtc::scoped_ptr<SessionDescription> ref_desc;
374 rtc::scoped_ptr<SessionDescription> desc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000375 if (offer) {
376 options.bundle_enabled = false;
377 ref_desc.reset(f1_.CreateOffer(options, NULL));
378 options.bundle_enabled = true;
379 desc.reset(f1_.CreateOffer(options, ref_desc.get()));
380 } else {
381 options.bundle_enabled = true;
382 ref_desc.reset(f1_.CreateOffer(options, NULL));
383 desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
384 }
385 ASSERT_TRUE(desc.get() != NULL);
386 const cricket::MediaContentDescription* audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000387 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000388 desc.get()->GetContentDescriptionByName("audio"));
389 ASSERT_TRUE(audio_media_desc != NULL);
390 const cricket::MediaContentDescription* video_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000391 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000392 desc.get()->GetContentDescriptionByName("video"));
393 ASSERT_TRUE(video_media_desc != NULL);
394 EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
395 video_media_desc->cryptos()));
396 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
397 EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
398 audio_media_desc->cryptos()[0].cipher_suite);
399
400 // Verify the selected crypto is one from the reference audio
401 // media content.
402 const cricket::MediaContentDescription* ref_audio_media_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000403 static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000404 ref_desc.get()->GetContentDescriptionByName("audio"));
405 bool found = false;
406 for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
407 if (ref_audio_media_desc->cryptos()[i].Matches(
408 audio_media_desc->cryptos()[0])) {
409 found = true;
410 break;
411 }
412 }
413 EXPECT_TRUE(found);
414 }
415
416 // This test that the audio and video media direction is set to
417 // |expected_direction_in_answer| in an answer if the offer direction is set
418 // to |direction_in_offer|.
419 void TestMediaDirectionInAnswer(
420 cricket::MediaContentDirection direction_in_offer,
421 cricket::MediaContentDirection expected_direction_in_answer) {
422 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000423 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000424 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425 f1_.CreateOffer(opts, NULL));
426 ASSERT_TRUE(offer.get() != NULL);
427 ContentInfo* ac_offer= offer->GetContentByName("audio");
428 ASSERT_TRUE(ac_offer != NULL);
429 AudioContentDescription* acd_offer =
430 static_cast<AudioContentDescription*>(ac_offer->description);
431 acd_offer->set_direction(direction_in_offer);
432 ContentInfo* vc_offer= offer->GetContentByName("video");
433 ASSERT_TRUE(vc_offer != NULL);
434 VideoContentDescription* vcd_offer =
435 static_cast<VideoContentDescription*>(vc_offer->description);
436 vcd_offer->set_direction(direction_in_offer);
437
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000438 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000439 f2_.CreateAnswer(offer.get(), opts, NULL));
440 const AudioContentDescription* acd_answer =
441 GetFirstAudioContentDescription(answer.get());
442 EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
443 const VideoContentDescription* vcd_answer =
444 GetFirstVideoContentDescription(answer.get());
445 EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
446 }
447
448 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
449 const cricket::ContentDescription* description = content->description;
450 ASSERT(description != NULL);
451 const cricket::AudioContentDescription* audio_content_desc =
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000452 static_cast<const cricket::AudioContentDescription*>(description);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000453 ASSERT(audio_content_desc != NULL);
454 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
455 if (audio_content_desc->codecs()[i].name == "CN")
456 return false;
457 }
458 return true;
459 }
460
461 protected:
462 MediaSessionDescriptionFactory f1_;
463 MediaSessionDescriptionFactory f2_;
464 TransportDescriptionFactory tdf1_;
465 TransportDescriptionFactory tdf2_;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000466 rtc::FakeSSLIdentity id1_;
467 rtc::FakeSSLIdentity id2_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000468};
469
470// Create a typical audio offer, and ensure it matches what we expect.
471TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
472 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000473 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000474 f1_.CreateOffer(MediaSessionOptions(), NULL));
475 ASSERT_TRUE(offer.get() != NULL);
476 const ContentInfo* ac = offer->GetContentByName("audio");
477 const ContentInfo* vc = offer->GetContentByName("video");
478 ASSERT_TRUE(ac != NULL);
479 ASSERT_TRUE(vc == NULL);
480 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
481 const AudioContentDescription* acd =
482 static_cast<const AudioContentDescription*>(ac->description);
483 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
484 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
485 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
486 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
487 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
488 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
489 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
490}
491
492// Create a typical video offer, and ensure it matches what we expect.
493TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
494 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000495 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000496 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000497 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000498 offer(f1_.CreateOffer(opts, NULL));
499 ASSERT_TRUE(offer.get() != NULL);
500 const ContentInfo* ac = offer->GetContentByName("audio");
501 const ContentInfo* vc = offer->GetContentByName("video");
502 ASSERT_TRUE(ac != NULL);
503 ASSERT_TRUE(vc != NULL);
504 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
505 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
506 const AudioContentDescription* acd =
507 static_cast<const AudioContentDescription*>(ac->description);
508 const VideoContentDescription* vcd =
509 static_cast<const VideoContentDescription*>(vc->description);
510 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
511 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
512 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
513 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
514 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
515 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
516 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
517 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
518 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
519 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
520 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
521 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
522 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
523 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
524}
525
526// Test creating an offer with bundle where the Codecs have the same dynamic
527// RTP playlod type. The test verifies that the offer don't contain the
528// duplicate RTP payload types.
529TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
530 const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
531 const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
532 const DataCodec& offered_data_codec = f2_.data_codecs()[0];
533 ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
534 ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
535
536 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000537 opts.recv_audio = true;
538 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000539 opts.data_channel_type = cricket::DCT_RTP;
540 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000541 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000542 offer(f2_.CreateOffer(opts, NULL));
543 const VideoContentDescription* vcd =
544 GetFirstVideoContentDescription(offer.get());
545 const AudioContentDescription* acd =
546 GetFirstAudioContentDescription(offer.get());
547 const DataContentDescription* dcd =
548 GetFirstDataContentDescription(offer.get());
549 ASSERT_TRUE(NULL != vcd);
550 ASSERT_TRUE(NULL != acd);
551 ASSERT_TRUE(NULL != dcd);
552 EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
553 EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
554 EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
555 EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
556 EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
557 EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
558}
559
560// Test creating an updated offer with with bundle, audio, video and data
561// after an audio only session has been negotiated.
562TEST_F(MediaSessionDescriptionFactoryTest,
563 TestCreateUpdatedVideoOfferWithBundle) {
564 f1_.set_secure(SEC_ENABLED);
565 f2_.set_secure(SEC_ENABLED);
566 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000567 opts.recv_audio = true;
568 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000569 opts.data_channel_type = cricket::DCT_NONE;
570 opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000571 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
572 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000573 f2_.CreateAnswer(offer.get(), opts, NULL));
574
575 MediaSessionOptions updated_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000576 updated_opts.recv_audio = true;
577 updated_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000578 updated_opts.data_channel_type = cricket::DCT_RTP;
579 updated_opts.bundle_enabled = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000580 rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000581 updated_opts, answer.get()));
582
583 const AudioContentDescription* acd =
584 GetFirstAudioContentDescription(updated_offer.get());
585 const VideoContentDescription* vcd =
586 GetFirstVideoContentDescription(updated_offer.get());
587 const DataContentDescription* dcd =
588 GetFirstDataContentDescription(updated_offer.get());
589 EXPECT_TRUE(NULL != vcd);
590 EXPECT_TRUE(NULL != acd);
591 EXPECT_TRUE(NULL != dcd);
592
593 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
594 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
595 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
596 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
597 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
598 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
599}
wu@webrtc.org78187522013-10-07 23:32:02 +0000600// Create a RTP data offer, and ensure it matches what we expect.
601TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000602 MediaSessionOptions opts;
603 opts.data_channel_type = cricket::DCT_RTP;
604 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000605 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000606 offer(f1_.CreateOffer(opts, NULL));
607 ASSERT_TRUE(offer.get() != NULL);
608 const ContentInfo* ac = offer->GetContentByName("audio");
609 const ContentInfo* dc = offer->GetContentByName("data");
610 ASSERT_TRUE(ac != NULL);
611 ASSERT_TRUE(dc != NULL);
612 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
613 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
614 const AudioContentDescription* acd =
615 static_cast<const AudioContentDescription*>(ac->description);
616 const DataContentDescription* dcd =
617 static_cast<const DataContentDescription*>(dc->description);
618 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
619 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
620 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
621 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
622 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
623 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
624 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
625 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
626 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
627 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
628 EXPECT_EQ(cricket::kDataMaxBandwidth,
629 dcd->bandwidth()); // default bandwidth (auto)
630 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
631 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
632 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
633}
634
wu@webrtc.org78187522013-10-07 23:32:02 +0000635// Create an SCTP data offer with bundle without error.
636TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
637 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000638 opts.recv_audio = false;
wu@webrtc.org78187522013-10-07 23:32:02 +0000639 opts.bundle_enabled = true;
640 opts.data_channel_type = cricket::DCT_SCTP;
641 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000642 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.org78187522013-10-07 23:32:02 +0000643 EXPECT_TRUE(offer.get() != NULL);
644 EXPECT_TRUE(offer->GetContentByName("data") != NULL);
645}
646
tommi@webrtc.orgf15dee62014-10-27 22:15:04 +0000647// Test creating an sctp data channel from an already generated offer.
648TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
649 MediaSessionOptions opts;
650 opts.recv_audio = false;
651 opts.bundle_enabled = true;
652 opts.data_channel_type = cricket::DCT_SCTP;
653 f1_.set_secure(SEC_ENABLED);
654 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
655 ASSERT_TRUE(offer1.get() != NULL);
656 const ContentInfo* data = offer1->GetContentByName("data");
657 ASSERT_TRUE(data != NULL);
658 const MediaContentDescription* mdesc =
659 static_cast<const MediaContentDescription*>(data->description);
660 ASSERT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
661
662 // Now set data_channel_type to 'none' (default) and make sure that the
663 // datachannel type that gets generated from the previous offer, is of the
664 // same type.
665 opts.data_channel_type = cricket::DCT_NONE;
666 rtc::scoped_ptr<SessionDescription> offer2(
667 f1_.CreateOffer(opts, offer1.get()));
668 data = offer2->GetContentByName("data");
669 ASSERT_TRUE(data != NULL);
670 mdesc = static_cast<const MediaContentDescription*>(data->description);
671 EXPECT_EQ(cricket::kMediaProtocolSctp, mdesc->protocol());
672}
673
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674// Create an audio, video offer without legacy StreamParams.
675TEST_F(MediaSessionDescriptionFactoryTest,
676 TestCreateOfferWithoutLegacyStreams) {
677 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000678 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000679 f1_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000680 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000681 offer(f1_.CreateOffer(opts, NULL));
682 ASSERT_TRUE(offer.get() != NULL);
683 const ContentInfo* ac = offer->GetContentByName("audio");
684 const ContentInfo* vc = offer->GetContentByName("video");
685 ASSERT_TRUE(ac != NULL);
686 ASSERT_TRUE(vc != NULL);
687 const AudioContentDescription* acd =
688 static_cast<const AudioContentDescription*>(ac->description);
689 const VideoContentDescription* vcd =
690 static_cast<const VideoContentDescription*>(vc->description);
691
692 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
693 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
694}
695
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000696// Creates an audio+video sendonly offer.
697TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
698 MediaSessionOptions options;
699 options.recv_audio = false;
700 options.recv_video = false;
701 options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
702 options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
703
704 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
705 ASSERT_TRUE(offer.get() != NULL);
706 EXPECT_EQ(2u, offer->contents().size());
707 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
708 EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[1], MEDIA_TYPE_VIDEO));
709
710 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[0]));
711 EXPECT_EQ(cricket::MD_SENDONLY, GetMediaDirection(&offer->contents()[1]));
712}
713
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000714// Verifies that the order of the media contents in the current
715// SessionDescription is preserved in the new SessionDescription.
716TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
717 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000718 opts.recv_audio = false;
719 opts.recv_video = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000720 opts.data_channel_type = cricket::DCT_SCTP;
721
722 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
723 ASSERT_TRUE(offer1.get() != NULL);
724 EXPECT_EQ(1u, offer1->contents().size());
725 EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
726
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000727 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000728 rtc::scoped_ptr<SessionDescription> offer2(
729 f1_.CreateOffer(opts, offer1.get()));
730 ASSERT_TRUE(offer2.get() != NULL);
731 EXPECT_EQ(2u, offer2->contents().size());
732 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
733 EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
734
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000735 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000736 rtc::scoped_ptr<SessionDescription> offer3(
737 f1_.CreateOffer(opts, offer2.get()));
738 ASSERT_TRUE(offer3.get() != NULL);
739 EXPECT_EQ(3u, offer3->contents().size());
740 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
741 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
742 EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
743
744 // Verifies the default order is audio-video-data, so that the previous checks
745 // didn't pass by accident.
746 rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
747 ASSERT_TRUE(offer4.get() != NULL);
748 EXPECT_EQ(3u, offer4->contents().size());
749 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
750 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
751 EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
752}
753
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000754// Create a typical audio answer, and ensure it matches what we expect.
755TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
756 f1_.set_secure(SEC_ENABLED);
757 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000758 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000759 f1_.CreateOffer(MediaSessionOptions(), NULL));
760 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000761 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000762 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
763 const ContentInfo* ac = answer->GetContentByName("audio");
764 const ContentInfo* vc = answer->GetContentByName("video");
765 ASSERT_TRUE(ac != NULL);
766 ASSERT_TRUE(vc == NULL);
767 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
768 const AudioContentDescription* acd =
769 static_cast<const AudioContentDescription*>(ac->description);
770 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
771 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
772 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
773 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
774 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
775 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
776 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
777}
778
779// Create a typical video answer, and ensure it matches what we expect.
780TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
781 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000782 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000783 f1_.set_secure(SEC_ENABLED);
784 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000785 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000786 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000787 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000788 f2_.CreateAnswer(offer.get(), opts, NULL));
789 const ContentInfo* ac = answer->GetContentByName("audio");
790 const ContentInfo* vc = answer->GetContentByName("video");
791 ASSERT_TRUE(ac != NULL);
792 ASSERT_TRUE(vc != NULL);
793 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
794 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
795 const AudioContentDescription* acd =
796 static_cast<const AudioContentDescription*>(ac->description);
797 const VideoContentDescription* vcd =
798 static_cast<const VideoContentDescription*>(vc->description);
799 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
800 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
801 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
802 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
803 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
804 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
805 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
806 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
807 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
808 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
809 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
810 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
811}
812
813TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
814 MediaSessionOptions opts;
815 opts.data_channel_type = cricket::DCT_RTP;
816 f1_.set_secure(SEC_ENABLED);
817 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000818 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000819 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000820 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000821 f2_.CreateAnswer(offer.get(), opts, NULL));
822 const ContentInfo* ac = answer->GetContentByName("audio");
823 const ContentInfo* vc = answer->GetContentByName("data");
824 ASSERT_TRUE(ac != NULL);
825 ASSERT_TRUE(vc != NULL);
826 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
827 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
828 const AudioContentDescription* acd =
829 static_cast<const AudioContentDescription*>(ac->description);
830 const DataContentDescription* vcd =
831 static_cast<const DataContentDescription*>(vc->description);
832 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
833 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
834 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
835 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
836 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
837 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
838 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
839 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
840 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
841 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
842 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
843 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
844}
845
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000846// Verifies that the order of the media contents in the offer is preserved in
847// the answer.
848TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
849 MediaSessionOptions opts;
850
851 // Creates a data only offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000852 opts.recv_audio = false;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000853 opts.data_channel_type = cricket::DCT_SCTP;
854 rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
855 ASSERT_TRUE(offer1.get() != NULL);
856
857 // Appends audio to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000858 opts.recv_audio = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000859 rtc::scoped_ptr<SessionDescription> offer2(
860 f1_.CreateOffer(opts, offer1.get()));
861 ASSERT_TRUE(offer2.get() != NULL);
862
863 // Appends video to the offer.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000864 opts.recv_video = true;
jiayl@webrtc.orge7d47a12014-08-05 19:19:05 +0000865 rtc::scoped_ptr<SessionDescription> offer3(
866 f1_.CreateOffer(opts, offer2.get()));
867 ASSERT_TRUE(offer3.get() != NULL);
868
869 rtc::scoped_ptr<SessionDescription> answer(
870 f2_.CreateAnswer(offer3.get(), opts, NULL));
871 ASSERT_TRUE(answer.get() != NULL);
872 EXPECT_EQ(3u, answer->contents().size());
873 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
874 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
875 EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
876}
877
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000878// This test that the media direction is set to send/receive in an answer if
879// the offer is send receive.
880TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
881 TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
882}
883
884// This test that the media direction is set to receive only in an answer if
885// the offer is send only.
886TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
887 TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
888}
889
890// This test that the media direction is set to send only in an answer if
891// the offer is recv only.
892TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
893 TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
894}
895
896// This test that the media direction is set to inactive in an answer if
897// the offer is inactive.
898TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
899 TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
900}
901
902// Test that a data content with an unknown protocol is rejected in an answer.
903TEST_F(MediaSessionDescriptionFactoryTest,
904 CreateDataAnswerToOfferWithUnknownProtocol) {
905 MediaSessionOptions opts;
906 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000907 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000908 f1_.set_secure(SEC_ENABLED);
909 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000910 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000911 ContentInfo* dc_offer= offer->GetContentByName("data");
912 ASSERT_TRUE(dc_offer != NULL);
913 DataContentDescription* dcd_offer =
914 static_cast<DataContentDescription*>(dc_offer->description);
915 ASSERT_TRUE(dcd_offer != NULL);
916 std::string protocol = "a weird unknown protocol";
917 dcd_offer->set_protocol(protocol);
918
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000919 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000920 f2_.CreateAnswer(offer.get(), opts, NULL));
921
922 const ContentInfo* dc_answer = answer->GetContentByName("data");
923 ASSERT_TRUE(dc_answer != NULL);
924 EXPECT_TRUE(dc_answer->rejected);
925 const DataContentDescription* dcd_answer =
926 static_cast<const DataContentDescription*>(dc_answer->description);
927 ASSERT_TRUE(dcd_answer != NULL);
928 EXPECT_EQ(protocol, dcd_answer->protocol());
929}
930
931// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
932TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
933 MediaSessionOptions opts;
934 f1_.set_secure(SEC_DISABLED);
935 f2_.set_secure(SEC_DISABLED);
936 tdf1_.set_secure(SEC_DISABLED);
937 tdf2_.set_secure(SEC_DISABLED);
938
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000939 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000940 const AudioContentDescription* offer_acd =
941 GetFirstAudioContentDescription(offer.get());
942 ASSERT_TRUE(offer_acd != NULL);
943 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
944
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000945 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000946 f2_.CreateAnswer(offer.get(), opts, NULL));
947
948 const ContentInfo* ac_answer = answer->GetContentByName("audio");
949 ASSERT_TRUE(ac_answer != NULL);
950 EXPECT_FALSE(ac_answer->rejected);
951
952 const AudioContentDescription* answer_acd =
953 GetFirstAudioContentDescription(answer.get());
954 ASSERT_TRUE(answer_acd != NULL);
955 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
956}
957
958// Create a video offer and answer and ensure the RTP header extensions
959// matches what we expect.
960TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
961 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000962 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000963
964 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
965 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
966 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
967 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
968
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000969 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000970 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000971 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000972 f2_.CreateAnswer(offer.get(), opts, NULL));
973
974 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
975 GetFirstAudioContentDescription(
976 offer.get())->rtp_header_extensions());
977 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
978 GetFirstVideoContentDescription(
979 offer.get())->rtp_header_extensions());
980 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
981 GetFirstAudioContentDescription(
982 answer.get())->rtp_header_extensions());
983 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
984 GetFirstVideoContentDescription(
985 answer.get())->rtp_header_extensions());
986}
987
988// Create an audio, video, data answer without legacy StreamParams.
989TEST_F(MediaSessionDescriptionFactoryTest,
990 TestCreateAnswerWithoutLegacyStreams) {
991 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +0000992 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000993 opts.data_channel_type = cricket::DCT_RTP;
994 f1_.set_add_legacy_streams(false);
995 f2_.set_add_legacy_streams(false);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000996 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000997 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000998 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000999 f2_.CreateAnswer(offer.get(), opts, NULL));
1000 const ContentInfo* ac = answer->GetContentByName("audio");
1001 const ContentInfo* vc = answer->GetContentByName("video");
1002 const ContentInfo* dc = answer->GetContentByName("data");
1003 ASSERT_TRUE(ac != NULL);
1004 ASSERT_TRUE(vc != NULL);
1005 const AudioContentDescription* acd =
1006 static_cast<const AudioContentDescription*>(ac->description);
1007 const VideoContentDescription* vcd =
1008 static_cast<const VideoContentDescription*>(vc->description);
1009 const DataContentDescription* dcd =
1010 static_cast<const DataContentDescription*>(dc->description);
1011
1012 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
1013 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
1014 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
1015}
1016
1017TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
1018 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001019 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001020 opts.data_channel_type = cricket::DCT_RTP;
1021 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001022 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001023 offer(f1_.CreateOffer(opts, NULL));
1024 ASSERT_TRUE(offer.get() != NULL);
1025 const ContentInfo* ac = offer->GetContentByName("audio");
1026 const ContentInfo* vc = offer->GetContentByName("video");
1027 const ContentInfo* dc = offer->GetContentByName("data");
1028 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
1029 static_cast<const AudioContentDescription*>(ac->description));
1030 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
1031 static_cast<const VideoContentDescription*>(vc->description));
1032 DataContentDescription* dcd = const_cast<DataContentDescription*>(
1033 static_cast<const DataContentDescription*>(dc->description));
1034
1035 EXPECT_FALSE(acd->partial()); // default is false.
1036 acd->set_partial(true);
1037 EXPECT_TRUE(acd->partial());
1038 acd->set_partial(false);
1039 EXPECT_FALSE(acd->partial());
1040
1041 EXPECT_FALSE(vcd->partial()); // default is false.
1042 vcd->set_partial(true);
1043 EXPECT_TRUE(vcd->partial());
1044 vcd->set_partial(false);
1045 EXPECT_FALSE(vcd->partial());
1046
1047 EXPECT_FALSE(dcd->partial()); // default is false.
1048 dcd->set_partial(true);
1049 EXPECT_TRUE(dcd->partial());
1050 dcd->set_partial(false);
1051 EXPECT_FALSE(dcd->partial());
1052}
1053
1054// Create a typical video answer, and ensure it matches what we expect.
1055TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
1056 MediaSessionOptions offer_opts;
1057 MediaSessionOptions answer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001058 answer_opts.recv_video = true;
1059 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001060 answer_opts.data_channel_type = cricket::DCT_RTP;
1061 offer_opts.data_channel_type = cricket::DCT_RTP;
1062
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001063 rtc::scoped_ptr<SessionDescription> offer;
1064 rtc::scoped_ptr<SessionDescription> answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001065
1066 offer_opts.rtcp_mux_enabled = true;
1067 answer_opts.rtcp_mux_enabled = true;
1068
1069 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1070 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1071 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1072 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1073 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1074 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1075 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1076 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1077 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1078 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1079 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1080 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1081 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1082 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1083
1084 offer_opts.rtcp_mux_enabled = true;
1085 answer_opts.rtcp_mux_enabled = false;
1086
1087 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1088 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1089 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1090 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1091 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1092 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1093 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1094 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1095 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1096 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1097 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1098 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1099 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1100 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1101
1102 offer_opts.rtcp_mux_enabled = false;
1103 answer_opts.rtcp_mux_enabled = true;
1104
1105 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1106 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1107 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1108 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1109 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1110 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1111 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1112 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1113 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1114 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1115 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1116 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1117 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1118 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1119
1120 offer_opts.rtcp_mux_enabled = false;
1121 answer_opts.rtcp_mux_enabled = false;
1122
1123 offer.reset(f1_.CreateOffer(offer_opts, NULL));
1124 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1125 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1126 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1127 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1128 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1129 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1130 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1131 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1132 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1133 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1134 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1135 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1136 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1137}
1138
1139// Create an audio-only answer to a video offer.
1140TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1141 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001142 opts.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001143 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001144 offer(f1_.CreateOffer(opts, NULL));
1145 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001146 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001147 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1148 const ContentInfo* ac = answer->GetContentByName("audio");
1149 const ContentInfo* vc = answer->GetContentByName("video");
1150 ASSERT_TRUE(ac != NULL);
1151 ASSERT_TRUE(vc != NULL);
1152 ASSERT_TRUE(vc->description != NULL);
1153 EXPECT_TRUE(vc->rejected);
1154}
1155
1156// Create an audio-only answer to an offer with data.
1157TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1158 MediaSessionOptions opts;
1159 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001160 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001161 offer(f1_.CreateOffer(opts, NULL));
1162 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001163 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001164 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1165 const ContentInfo* ac = answer->GetContentByName("audio");
1166 const ContentInfo* dc = answer->GetContentByName("data");
1167 ASSERT_TRUE(ac != NULL);
1168 ASSERT_TRUE(dc != NULL);
1169 ASSERT_TRUE(dc->description != NULL);
1170 EXPECT_TRUE(dc->rejected);
1171}
1172
1173// Create an answer that rejects the contents which are rejected in the offer.
1174TEST_F(MediaSessionDescriptionFactoryTest,
1175 CreateAnswerToOfferWithRejectedMedia) {
1176 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001177 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001178 opts.data_channel_type = cricket::DCT_RTP;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001179 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001180 offer(f1_.CreateOffer(opts, NULL));
1181 ASSERT_TRUE(offer.get() != NULL);
1182 ContentInfo* ac = offer->GetContentByName("audio");
1183 ContentInfo* vc = offer->GetContentByName("video");
1184 ContentInfo* dc = offer->GetContentByName("data");
1185 ASSERT_TRUE(ac != NULL);
1186 ASSERT_TRUE(vc != NULL);
1187 ASSERT_TRUE(dc != NULL);
1188 ac->rejected = true;
1189 vc->rejected = true;
1190 dc->rejected = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001191 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001192 f2_.CreateAnswer(offer.get(), opts, NULL));
1193 ac = answer->GetContentByName("audio");
1194 vc = answer->GetContentByName("video");
1195 dc = answer->GetContentByName("data");
1196 ASSERT_TRUE(ac != NULL);
1197 ASSERT_TRUE(vc != NULL);
1198 ASSERT_TRUE(dc != NULL);
1199 EXPECT_TRUE(ac->rejected);
1200 EXPECT_TRUE(vc->rejected);
1201 EXPECT_TRUE(dc->rejected);
1202}
1203
1204// Create an audio and video offer with:
1205// - one video track
1206// - two audio tracks
1207// - two data tracks
1208// and ensure it matches what we expect. Also updates the initial offer by
1209// adding a new video track and replaces one of the audio tracks.
1210TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1211 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001212 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1213 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1214 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001215 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001216 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1217 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001218
1219 f1_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001220 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001221
1222 ASSERT_TRUE(offer.get() != NULL);
1223 const ContentInfo* ac = offer->GetContentByName("audio");
1224 const ContentInfo* vc = offer->GetContentByName("video");
1225 const ContentInfo* dc = offer->GetContentByName("data");
1226 ASSERT_TRUE(ac != NULL);
1227 ASSERT_TRUE(vc != NULL);
1228 ASSERT_TRUE(dc != NULL);
1229 const AudioContentDescription* acd =
1230 static_cast<const AudioContentDescription*>(ac->description);
1231 const VideoContentDescription* vcd =
1232 static_cast<const VideoContentDescription*>(vc->description);
1233 const DataContentDescription* dcd =
1234 static_cast<const DataContentDescription*>(dc->description);
1235 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1236 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1237
1238 const StreamParamsVec& audio_streams = acd->streams();
1239 ASSERT_EQ(2U, audio_streams.size());
1240 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1241 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1242 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1243 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1244 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1245 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1246 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1247
1248 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1249 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1250 ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1251
1252 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1253 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1254 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1255
1256 const StreamParamsVec& video_streams = vcd->streams();
1257 ASSERT_EQ(1U, video_streams.size());
1258 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1259 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1260 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1261 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1262
1263 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1264 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1265 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1266
1267 const StreamParamsVec& data_streams = dcd->streams();
1268 ASSERT_EQ(2U, data_streams.size());
1269 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1270 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1271 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1272 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1273 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1274 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1275 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1276
1277 EXPECT_EQ(cricket::kDataMaxBandwidth,
1278 dcd->bandwidth()); // default bandwidth (auto)
1279 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1280 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1281
1282
1283 // Update the offer. Add a new video track that is not synched to the
1284 // other tracks and replace audio track 2 with audio track 3.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001285 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1286 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1287 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1288 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
1289 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001290 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001291 updated_offer(f1_.CreateOffer(opts, offer.get()));
1292
1293 ASSERT_TRUE(updated_offer.get() != NULL);
1294 ac = updated_offer->GetContentByName("audio");
1295 vc = updated_offer->GetContentByName("video");
1296 dc = updated_offer->GetContentByName("data");
1297 ASSERT_TRUE(ac != NULL);
1298 ASSERT_TRUE(vc != NULL);
1299 ASSERT_TRUE(dc != NULL);
1300 const AudioContentDescription* updated_acd =
1301 static_cast<const AudioContentDescription*>(ac->description);
1302 const VideoContentDescription* updated_vcd =
1303 static_cast<const VideoContentDescription*>(vc->description);
1304 const DataContentDescription* updated_dcd =
1305 static_cast<const DataContentDescription*>(dc->description);
1306
1307 EXPECT_EQ(acd->type(), updated_acd->type());
1308 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1309 EXPECT_EQ(vcd->type(), updated_vcd->type());
1310 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1311 EXPECT_EQ(dcd->type(), updated_dcd->type());
1312 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1313 ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1314 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1315 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1316 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1317 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1318 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1319
1320 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1321 ASSERT_EQ(2U, updated_audio_streams.size());
1322 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1323 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id); // New audio track.
1324 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1325 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1326 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1327
1328 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1329 ASSERT_EQ(2U, updated_video_streams.size());
1330 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1331 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1332 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1333
1334 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1335 ASSERT_EQ(2U, updated_data_streams.size());
1336 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1337 EXPECT_EQ(kDataTrack3, updated_data_streams[1].id); // New data track.
1338 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1339 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1340 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1341}
1342
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001343// Create an offer with simulcast video stream.
1344TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1345 MediaSessionOptions opts;
1346 const int num_sim_layers = 3;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001347 opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001348 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
wu@webrtc.orgcecfd182013-10-30 05:18:12 +00001349
1350 ASSERT_TRUE(offer.get() != NULL);
1351 const ContentInfo* vc = offer->GetContentByName("video");
1352 ASSERT_TRUE(vc != NULL);
1353 const VideoContentDescription* vcd =
1354 static_cast<const VideoContentDescription*>(vc->description);
1355
1356 const StreamParamsVec& video_streams = vcd->streams();
1357 ASSERT_EQ(1U, video_streams.size());
1358 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1359 const SsrcGroup* sim_ssrc_group =
1360 video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1361 ASSERT_TRUE(sim_ssrc_group != NULL);
1362 EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1363}
1364
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001365// Create an audio and video answer to a standard video offer with:
1366// - one video track
1367// - two audio tracks
1368// - two data tracks
1369// and ensure it matches what we expect. Also updates the initial answer by
1370// adding a new video track and removes one of the audio tracks.
1371TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1372 MediaSessionOptions offer_opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001373 offer_opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001374 offer_opts.data_channel_type = cricket::DCT_RTP;
1375 f1_.set_secure(SEC_ENABLED);
1376 f2_.set_secure(SEC_ENABLED);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001377 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001378 NULL));
1379
1380 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001381 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1382 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1383 opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001384 opts.data_channel_type = cricket::DCT_RTP;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001385 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1386 opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001387
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001388 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001389 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1390
1391 ASSERT_TRUE(answer.get() != NULL);
1392 const ContentInfo* ac = answer->GetContentByName("audio");
1393 const ContentInfo* vc = answer->GetContentByName("video");
1394 const ContentInfo* dc = answer->GetContentByName("data");
1395 ASSERT_TRUE(ac != NULL);
1396 ASSERT_TRUE(vc != NULL);
1397 ASSERT_TRUE(dc != NULL);
1398 const AudioContentDescription* acd =
1399 static_cast<const AudioContentDescription*>(ac->description);
1400 const VideoContentDescription* vcd =
1401 static_cast<const VideoContentDescription*>(vc->description);
1402 const DataContentDescription* dcd =
1403 static_cast<const DataContentDescription*>(dc->description);
1404 ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1405 ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1406 ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1407
1408 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1409 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1410
1411 const StreamParamsVec& audio_streams = acd->streams();
1412 ASSERT_EQ(2U, audio_streams.size());
1413 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
1414 EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1415 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1416 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1417 EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1418 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1419 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1420
1421 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
1422 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
1423
1424 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1425 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1426
1427 const StreamParamsVec& video_streams = vcd->streams();
1428 ASSERT_EQ(1U, video_streams.size());
1429 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1430 EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1431 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
1432 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
1433
1434 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1435 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1436
1437 const StreamParamsVec& data_streams = dcd->streams();
1438 ASSERT_EQ(2U, data_streams.size());
1439 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
1440 EXPECT_EQ(kDataTrack1, data_streams[0].id);
1441 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1442 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1443 EXPECT_EQ(kDataTrack2, data_streams[1].id);
1444 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1445 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1446
1447 EXPECT_EQ(cricket::kDataMaxBandwidth,
1448 dcd->bandwidth()); // default bandwidth (auto)
1449 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
1450
1451 // Update the answer. Add a new video track that is not synched to the
1452 // other traacks and remove 1 audio track.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001453 opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1454 opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1455 opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001456 rtc::scoped_ptr<SessionDescription>
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001457 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1458
1459 ASSERT_TRUE(updated_answer.get() != NULL);
1460 ac = updated_answer->GetContentByName("audio");
1461 vc = updated_answer->GetContentByName("video");
1462 dc = updated_answer->GetContentByName("data");
1463 ASSERT_TRUE(ac != NULL);
1464 ASSERT_TRUE(vc != NULL);
1465 ASSERT_TRUE(dc != NULL);
1466 const AudioContentDescription* updated_acd =
1467 static_cast<const AudioContentDescription*>(ac->description);
1468 const VideoContentDescription* updated_vcd =
1469 static_cast<const VideoContentDescription*>(vc->description);
1470 const DataContentDescription* updated_dcd =
1471 static_cast<const DataContentDescription*>(dc->description);
1472
1473 ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1474 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1475 ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1476 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1477 ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1478 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1479
1480 EXPECT_EQ(acd->type(), updated_acd->type());
1481 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1482 EXPECT_EQ(vcd->type(), updated_vcd->type());
1483 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1484 EXPECT_EQ(dcd->type(), updated_dcd->type());
1485 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1486
1487 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1488 ASSERT_EQ(1U, updated_audio_streams.size());
1489 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
1490
1491 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1492 ASSERT_EQ(2U, updated_video_streams.size());
1493 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1494 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1495 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1496
1497 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1498 ASSERT_EQ(1U, updated_data_streams.size());
1499 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1500}
1501
1502
1503// Create an updated offer after creating an answer to the original offer and
1504// verify that the codecs that were part of the original answer are not changed
1505// in the updated offer.
1506TEST_F(MediaSessionDescriptionFactoryTest,
1507 RespondentCreatesOfferAfterCreatingAnswer) {
1508 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001509 opts.recv_audio = true;
1510 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001511
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001512 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1513 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001514 f2_.CreateAnswer(offer.get(), opts, NULL));
1515
1516 const AudioContentDescription* acd =
1517 GetFirstAudioContentDescription(answer.get());
1518 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1519
1520 const VideoContentDescription* vcd =
1521 GetFirstVideoContentDescription(answer.get());
1522 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1523
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001524 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001525 f2_.CreateOffer(opts, answer.get()));
1526
1527 // The expected audio codecs are the common audio codecs from the first
1528 // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1529 // preference order.
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001530 // TODO(wu): |updated_offer| should not include the codec
1531 // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001532 const AudioCodec kUpdatedAudioCodecOffer[] = {
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001533 kAudioCodecsAnswer[0],
1534 kAudioCodecsAnswer[1],
wu@webrtc.orgff1b1bf2014-06-20 20:57:42 +00001535 kAudioCodecs2[0],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001536 };
1537
1538 // The expected video codecs are the common video codecs from the first
1539 // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1540 // preference order.
1541 const VideoCodec kUpdatedVideoCodecOffer[] = {
1542 kVideoCodecsAnswer[0],
1543 kVideoCodecs2[1],
1544 };
1545
1546 const AudioContentDescription* updated_acd =
1547 GetFirstAudioContentDescription(updated_offer.get());
1548 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1549
1550 const VideoContentDescription* updated_vcd =
1551 GetFirstVideoContentDescription(updated_offer.get());
1552 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1553}
1554
1555// Create an updated offer after creating an answer to the original offer and
1556// verify that the codecs that were part of the original answer are not changed
1557// in the updated offer. In this test Rtx is enabled.
1558TEST_F(MediaSessionDescriptionFactoryTest,
1559 RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1560 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001561 opts.recv_video = true;
1562 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001563 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001564 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001565 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001566 f1_.set_video_codecs(f1_codecs);
1567
1568 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001569 // This creates rtx for H264 with the payload type |f2_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001570 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001571 f2_.set_video_codecs(f2_codecs);
1572
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001573 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001574 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001575 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001576 f2_.CreateAnswer(offer.get(), opts, NULL));
1577
1578 const VideoContentDescription* vcd =
1579 GetFirstVideoContentDescription(answer.get());
1580
1581 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001582 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1583 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001584
1585 EXPECT_EQ(expected_codecs, vcd->codecs());
1586
1587 // Now, make sure we get same result, except for the preference order,
1588 // if |f2_| creates an updated offer even though the default payload types
1589 // are different from |f1_|.
1590 expected_codecs[0].preference = f1_codecs[1].preference;
1591
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001592 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001593 f2_.CreateOffer(opts, answer.get()));
1594 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001595 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001596 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1597
1598 const VideoContentDescription* updated_vcd =
1599 GetFirstVideoContentDescription(updated_answer.get());
1600
1601 EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1602}
1603
1604// Create an updated offer that adds video after creating an audio only answer
1605// to the original offer. This test verifies that if a video codec and the RTX
1606// codec have the same default payload type as an audio codec that is already in
1607// use, the added codecs payload types are changed.
1608TEST_F(MediaSessionDescriptionFactoryTest,
1609 RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1610 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001611 // This creates rtx for H264 with the payload type |f1_| uses.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001612 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001613 f1_.set_video_codecs(f1_codecs);
1614
1615 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001616 opts.recv_audio = true;
1617 opts.recv_video = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001618
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001619 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1620 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001621 f2_.CreateAnswer(offer.get(), opts, NULL));
1622
1623 const AudioContentDescription* acd =
1624 GetFirstAudioContentDescription(answer.get());
1625 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1626
1627 // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1628 // reference be the same as an audio codec that was negotiated in the
1629 // first offer/answer exchange.
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001630 opts.recv_audio = true;
1631 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001632
1633 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1634 int used_pl_type = acd->codecs()[0].id;
1635 f2_codecs[0].id = used_pl_type; // Set the payload type for H264.
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001636 AddRtxCodec(VideoCodec::CreateRtxCodec(125, used_pl_type), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001637 f2_.set_video_codecs(f2_codecs);
1638
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001639 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001640 f2_.CreateOffer(opts, answer.get()));
1641 ASSERT_TRUE(updated_offer);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001642 rtc::scoped_ptr<SessionDescription> updated_answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001643 f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1644
1645 const AudioContentDescription* updated_acd =
1646 GetFirstAudioContentDescription(answer.get());
1647 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1648
1649 const VideoContentDescription* updated_vcd =
1650 GetFirstVideoContentDescription(updated_answer.get());
1651
1652 ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
sergeyu@chromium.org32f485b2013-12-05 22:36:21 +00001653 ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001654 int new_h264_pl_type = updated_vcd->codecs()[0].id;
1655 EXPECT_NE(used_pl_type, new_h264_pl_type);
1656 VideoCodec rtx = updated_vcd->codecs()[1];
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001657 int pt_referenced_by_rtx = rtc::FromString<int>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001658 rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1659 EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1660}
1661
1662// Test that RTX is ignored when there is no associated payload type parameter.
1663TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1664 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001665 opts.recv_video = true;
1666 opts.recv_audio = false;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001667 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001668 // This creates RTX without associated payload type parameter.
1669 AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName, 0, 0, 0, 0), &f1_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001670 f1_.set_video_codecs(f1_codecs);
1671
1672 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001673 // This creates RTX for H264 with the payload type |f2_| uses.
1674 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[0].id), &f2_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001675 f2_.set_video_codecs(f2_codecs);
1676
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001677 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001678 ASSERT_TRUE(offer.get() != NULL);
1679 // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1680 // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1681 // is possible to test that that RTX is dropped when
1682 // kCodecParamAssociatedPayloadType is missing in the offer.
1683 VideoContentDescription* desc =
1684 static_cast<cricket::VideoContentDescription*>(
1685 offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1686 ASSERT_TRUE(desc != NULL);
1687 std::vector<VideoCodec> codecs = desc->codecs();
1688 for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1689 iter != codecs.end(); ++iter) {
1690 if (iter->name.find(cricket::kRtxCodecName) == 0) {
1691 iter->params.clear();
1692 }
1693 }
1694 desc->set_codecs(codecs);
1695
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001696 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001697 f2_.CreateAnswer(offer.get(), opts, NULL));
1698
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001699 std::vector<std::string> codec_names =
1700 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1701 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1702 cricket::kRtxCodecName));
1703}
1704
1705// Test that RTX will be filtered out in the answer if its associated payload
1706// type doesn't match the local value.
1707TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
1708 MediaSessionOptions opts;
1709 opts.recv_video = true;
1710 opts.recv_audio = false;
1711 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1712 // This creates RTX for H264 in sender.
1713 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1714 f1_.set_video_codecs(f1_codecs);
1715
1716 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1717 // This creates RTX for H263 in receiver.
1718 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs2[1].id), &f2_codecs);
1719 f2_.set_video_codecs(f2_codecs);
1720
1721 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1722 ASSERT_TRUE(offer.get() != NULL);
1723 // Associated payload type doesn't match, therefore, RTX codec is removed in
1724 // the answer.
1725 rtc::scoped_ptr<SessionDescription> answer(
1726 f2_.CreateAnswer(offer.get(), opts, NULL));
1727
1728 std::vector<std::string> codec_names =
1729 GetCodecNames(GetFirstVideoContentDescription(answer.get())->codecs());
1730 EXPECT_EQ(codec_names.end(), std::find(codec_names.begin(), codec_names.end(),
1731 cricket::kRtxCodecName));
1732}
1733
1734// Test that when multiple RTX codecs are offered, only the matched RTX codec
1735// is added in the answer, and the unsupported RTX codec is filtered out.
1736TEST_F(MediaSessionDescriptionFactoryTest,
1737 FilterOutUnsupportedRtxWhenCreatingAnswer) {
1738 MediaSessionOptions opts;
1739 opts.recv_video = true;
1740 opts.recv_audio = false;
1741 std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1742 // This creates RTX for H264-SVC in sender.
1743 AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
1744 f1_.set_video_codecs(f1_codecs);
1745
1746 // This creates RTX for H264 in sender.
1747 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
1748 f1_.set_video_codecs(f1_codecs);
1749
1750 std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1751 // This creates RTX for H264 in receiver.
1752 AddRtxCodec(VideoCodec::CreateRtxCodec(124, kVideoCodecs2[0].id), &f2_codecs);
1753 f2_.set_video_codecs(f2_codecs);
1754
1755 // H264-SVC codec is removed in the answer, therefore, associated RTX codec
1756 // for H264-SVC should also be removed.
1757 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1758 ASSERT_TRUE(offer.get() != NULL);
1759 rtc::scoped_ptr<SessionDescription> answer(
1760 f2_.CreateAnswer(offer.get(), opts, NULL));
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001761 const VideoContentDescription* vcd =
1762 GetFirstVideoContentDescription(answer.get());
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001763 std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1764 AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id),
1765 &expected_codecs);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001766
changbin.shao@webrtc.org2d25b442015-03-16 04:14:34 +00001767 EXPECT_EQ(expected_codecs, vcd->codecs());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001768}
1769
1770// Create an updated offer after creating an answer to the original offer and
1771// verify that the RTP header extensions that were part of the original answer
1772// are not changed in the updated offer.
1773TEST_F(MediaSessionDescriptionFactoryTest,
1774 RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1775 MediaSessionOptions opts;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001776 opts.recv_audio = true;
1777 opts.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001778
1779 f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1780 f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1781 f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1782 f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1783
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001784 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1785 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001786 f2_.CreateAnswer(offer.get(), opts, NULL));
1787
1788 EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1789 GetFirstAudioContentDescription(
1790 answer.get())->rtp_header_extensions());
1791 EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1792 GetFirstVideoContentDescription(
1793 answer.get())->rtp_header_extensions());
1794
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001795 rtc::scoped_ptr<SessionDescription> updated_offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001796 f2_.CreateOffer(opts, answer.get()));
1797
1798 // The expected RTP header extensions in the new offer are the resulting
1799 // extensions from the first offer/answer exchange plus the extensions only
1800 // |f2_| offer.
1801 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001802 // |f1_| for another extensions, it is changed to 13.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001803 const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1804 kAudioRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001805 RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1806 kAudioRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001807 };
1808
1809 // Since the default local extension id |f2_| uses has already been used by
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001810 // |f1_| for another extensions, is is changed to 12.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001811 const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1812 kVideoRtpExtensionAnswer[0],
henrike@webrtc.org79047f92014-03-06 23:46:59 +00001813 RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1814 kVideoRtpExtension2[2],
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001815 };
1816
1817 const AudioContentDescription* updated_acd =
1818 GetFirstAudioContentDescription(updated_offer.get());
1819 EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1820 updated_acd->rtp_header_extensions());
1821
1822 const VideoContentDescription* updated_vcd =
1823 GetFirstVideoContentDescription(updated_offer.get());
1824 EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1825 updated_vcd->rtp_header_extensions());
1826}
1827
1828TEST(MediaSessionDescription, CopySessionDescription) {
1829 SessionDescription source;
1830 cricket::ContentGroup group(cricket::CN_AUDIO);
1831 source.AddGroup(group);
1832 AudioContentDescription* acd(new AudioContentDescription());
1833 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1834 acd->AddLegacyStream(1);
1835 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1836 VideoContentDescription* vcd(new VideoContentDescription());
1837 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1838 vcd->AddLegacyStream(2);
1839 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1840
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001841 rtc::scoped_ptr<SessionDescription> copy(source.Copy());
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001842 ASSERT_TRUE(copy.get() != NULL);
1843 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1844 const ContentInfo* ac = copy->GetContentByName("audio");
1845 const ContentInfo* vc = copy->GetContentByName("video");
1846 ASSERT_TRUE(ac != NULL);
1847 ASSERT_TRUE(vc != NULL);
1848 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1849 const AudioContentDescription* acd_copy =
1850 static_cast<const AudioContentDescription*>(ac->description);
1851 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1852 EXPECT_EQ(1u, acd->first_ssrc());
1853
1854 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1855 const VideoContentDescription* vcd_copy =
1856 static_cast<const VideoContentDescription*>(vc->description);
1857 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1858 EXPECT_EQ(2u, vcd->first_ssrc());
1859}
1860
1861// The below TestTransportInfoXXX tests create different offers/answers, and
1862// ensure the TransportInfo in the SessionDescription matches what we expect.
1863TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1864 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001865 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001866 TestTransportInfo(true, options, false);
1867}
1868
1869TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1870 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001871 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001872 TestTransportInfo(true, options, true);
1873}
1874
1875TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1876 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001877 options.recv_audio = true;
1878 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001879 options.data_channel_type = cricket::DCT_RTP;
1880 TestTransportInfo(true, options, false);
1881}
1882
1883TEST_F(MediaSessionDescriptionFactoryTest,
1884 TestTransportInfoOfferMultimediaCurrent) {
1885 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001886 options.recv_audio = true;
1887 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001888 options.data_channel_type = cricket::DCT_RTP;
1889 TestTransportInfo(true, options, true);
1890}
1891
1892TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1893 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001894 options.recv_audio = true;
1895 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001896 options.data_channel_type = cricket::DCT_RTP;
1897 options.bundle_enabled = true;
1898 TestTransportInfo(true, options, false);
1899}
1900
1901TEST_F(MediaSessionDescriptionFactoryTest,
1902 TestTransportInfoOfferBundleCurrent) {
1903 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001904 options.recv_audio = true;
1905 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001906 options.data_channel_type = cricket::DCT_RTP;
1907 options.bundle_enabled = true;
1908 TestTransportInfo(true, options, true);
1909}
1910
1911TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
1912 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001913 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001914 TestTransportInfo(false, options, false);
1915}
1916
1917TEST_F(MediaSessionDescriptionFactoryTest,
1918 TestTransportInfoAnswerAudioCurrent) {
1919 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001920 options.recv_audio = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001921 TestTransportInfo(false, options, true);
1922}
1923
1924TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
1925 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001926 options.recv_audio = true;
1927 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001928 options.data_channel_type = cricket::DCT_RTP;
1929 TestTransportInfo(false, options, false);
1930}
1931
1932TEST_F(MediaSessionDescriptionFactoryTest,
1933 TestTransportInfoAnswerMultimediaCurrent) {
1934 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001935 options.recv_audio = true;
1936 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001937 options.data_channel_type = cricket::DCT_RTP;
1938 TestTransportInfo(false, options, true);
1939}
1940
1941TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
1942 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001943 options.recv_audio = true;
1944 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001945 options.data_channel_type = cricket::DCT_RTP;
1946 options.bundle_enabled = true;
1947 TestTransportInfo(false, options, false);
1948}
1949
1950TEST_F(MediaSessionDescriptionFactoryTest,
1951 TestTransportInfoAnswerBundleCurrent) {
1952 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00001953 options.recv_audio = true;
1954 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001955 options.data_channel_type = cricket::DCT_RTP;
1956 options.bundle_enabled = true;
1957 TestTransportInfo(false, options, true);
1958}
1959
1960// Create an offer with bundle enabled and verify the crypto parameters are
1961// the common set of the available cryptos.
1962TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
1963 TestCryptoWithBundle(true);
1964}
1965
1966// Create an answer with bundle enabled and verify the crypto parameters are
1967// the common set of the available cryptos.
1968TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
1969 TestCryptoWithBundle(false);
1970}
1971
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001972// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
1973// DTLS is not enabled locally.
1974TEST_F(MediaSessionDescriptionFactoryTest,
1975 TestOfferDtlsSavpfWithoutDtlsFailed) {
1976 f1_.set_secure(SEC_ENABLED);
1977 f2_.set_secure(SEC_ENABLED);
1978 tdf1_.set_secure(SEC_DISABLED);
1979 tdf2_.set_secure(SEC_DISABLED);
1980
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001981 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001982 f1_.CreateOffer(MediaSessionOptions(), NULL));
1983 ASSERT_TRUE(offer.get() != NULL);
1984 ContentInfo* offer_content = offer->GetContentByName("audio");
1985 ASSERT_TRUE(offer_content != NULL);
1986 AudioContentDescription* offer_audio_desc =
1987 static_cast<AudioContentDescription*>(offer_content->description);
1988 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1989
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00001990 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00001991 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1992 ASSERT_TRUE(answer != NULL);
1993 ContentInfo* answer_content = answer->GetContentByName("audio");
1994 ASSERT_TRUE(answer_content != NULL);
1995
1996 ASSERT_TRUE(answer_content->rejected);
1997}
1998
1999// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
2000// UDP/TLS/RTP/SAVPF.
2001TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
2002 f1_.set_secure(SEC_ENABLED);
2003 f2_.set_secure(SEC_ENABLED);
2004 tdf1_.set_secure(SEC_ENABLED);
2005 tdf2_.set_secure(SEC_ENABLED);
2006
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002007 rtc::scoped_ptr<SessionDescription> offer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002008 f1_.CreateOffer(MediaSessionOptions(), NULL));
2009 ASSERT_TRUE(offer.get() != NULL);
2010 ContentInfo* offer_content = offer->GetContentByName("audio");
2011 ASSERT_TRUE(offer_content != NULL);
2012 AudioContentDescription* offer_audio_desc =
2013 static_cast<AudioContentDescription*>(offer_content->description);
2014 offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
2015
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002016 rtc::scoped_ptr<SessionDescription> answer(
jiayl@webrtc.org8dcd43c2014-05-29 22:07:59 +00002017 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
2018 ASSERT_TRUE(answer != NULL);
2019
2020 const ContentInfo* answer_content = answer->GetContentByName("audio");
2021 ASSERT_TRUE(answer_content != NULL);
2022 ASSERT_FALSE(answer_content->rejected);
2023
2024 const AudioContentDescription* answer_audio_desc =
2025 static_cast<const AudioContentDescription*>(answer_content->description);
2026 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
2027 answer_audio_desc->protocol());
2028}
2029
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002030// Test that we include both SDES and DTLS in the offer, but only include SDES
2031// in the answer if DTLS isn't negotiated.
2032TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
2033 f1_.set_secure(SEC_ENABLED);
2034 f2_.set_secure(SEC_ENABLED);
2035 tdf1_.set_secure(SEC_ENABLED);
2036 tdf2_.set_secure(SEC_DISABLED);
2037 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002038 options.recv_audio = true;
2039 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002040 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002041 const cricket::MediaContentDescription* audio_media_desc;
2042 const cricket::MediaContentDescription* video_media_desc;
2043 const cricket::TransportDescription* audio_trans_desc;
2044 const cricket::TransportDescription* video_trans_desc;
2045
2046 // Generate an offer with SDES and DTLS support.
2047 offer.reset(f1_.CreateOffer(options, NULL));
2048 ASSERT_TRUE(offer.get() != NULL);
2049
2050 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2051 offer->GetContentDescriptionByName("audio"));
2052 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002053 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002054 offer->GetContentDescriptionByName("video"));
2055 ASSERT_TRUE(video_media_desc != NULL);
2056 EXPECT_EQ(2u, audio_media_desc->cryptos().size());
2057 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2058
2059 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2060 ASSERT_TRUE(audio_trans_desc != NULL);
2061 video_trans_desc = offer->GetTransportDescriptionByName("video");
2062 ASSERT_TRUE(video_trans_desc != NULL);
2063 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2064 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2065
2066 // Generate an answer with only SDES support, since tdf2 has crypto disabled.
2067 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2068 ASSERT_TRUE(answer.get() != NULL);
2069
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002070 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002071 answer->GetContentDescriptionByName("audio"));
2072 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002073 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002074 answer->GetContentDescriptionByName("video"));
2075 ASSERT_TRUE(video_media_desc != NULL);
2076 EXPECT_EQ(1u, audio_media_desc->cryptos().size());
2077 EXPECT_EQ(1u, video_media_desc->cryptos().size());
2078
2079 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2080 ASSERT_TRUE(audio_trans_desc != NULL);
2081 video_trans_desc = answer->GetTransportDescriptionByName("video");
2082 ASSERT_TRUE(video_trans_desc != NULL);
2083 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
2084 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
2085
2086 // Enable DTLS; the answer should now only have DTLS support.
2087 tdf2_.set_secure(SEC_ENABLED);
2088 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2089 ASSERT_TRUE(answer.get() != NULL);
2090
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002091 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002092 answer->GetContentDescriptionByName("audio"));
2093 ASSERT_TRUE(audio_media_desc != NULL);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +00002094 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002095 answer->GetContentDescriptionByName("video"));
2096 ASSERT_TRUE(video_media_desc != NULL);
2097 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2098 EXPECT_TRUE(video_media_desc->cryptos().empty());
2099 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2100 audio_media_desc->protocol());
2101 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2102 video_media_desc->protocol());
2103
2104 audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2105 ASSERT_TRUE(audio_trans_desc != NULL);
2106 video_trans_desc = answer->GetTransportDescriptionByName("video");
2107 ASSERT_TRUE(video_trans_desc != NULL);
2108 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2109 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
mallinath@webrtc.org19f27e62013-10-13 17:18:27 +00002110
2111 // Try creating offer again. DTLS enabled now, crypto's should be empty
2112 // in new offer.
2113 offer.reset(f1_.CreateOffer(options, offer.get()));
2114 ASSERT_TRUE(offer.get() != NULL);
2115 audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2116 offer->GetContentDescriptionByName("audio"));
2117 ASSERT_TRUE(audio_media_desc != NULL);
2118 video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2119 offer->GetContentDescriptionByName("video"));
2120 ASSERT_TRUE(video_media_desc != NULL);
2121 EXPECT_TRUE(audio_media_desc->cryptos().empty());
2122 EXPECT_TRUE(video_media_desc->cryptos().empty());
2123
2124 audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2125 ASSERT_TRUE(audio_trans_desc != NULL);
2126 video_trans_desc = offer->GetTransportDescriptionByName("video");
2127 ASSERT_TRUE(video_trans_desc != NULL);
2128 ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2129 ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002130}
2131
2132// Test that an answer can't be created if cryptos are required but the offer is
2133// unsecure.
2134TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2135 MediaSessionOptions options;
2136 f1_.set_secure(SEC_DISABLED);
2137 tdf1_.set_secure(SEC_DISABLED);
2138 f2_.set_secure(SEC_REQUIRED);
2139 tdf1_.set_secure(SEC_ENABLED);
2140
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002141 rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002142 NULL));
2143 ASSERT_TRUE(offer.get() != NULL);
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002144 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002145 f2_.CreateAnswer(offer.get(), options, NULL));
2146 EXPECT_TRUE(answer.get() == NULL);
2147}
2148
2149// Test that we accept a DTLS offer without SDES and create an appropriate
2150// answer.
2151TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2152 f1_.set_secure(SEC_DISABLED);
2153 f2_.set_secure(SEC_ENABLED);
2154 tdf1_.set_secure(SEC_ENABLED);
2155 tdf2_.set_secure(SEC_ENABLED);
2156 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002157 options.recv_audio = true;
2158 options.recv_video = true;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002159 options.data_channel_type = cricket::DCT_RTP;
2160
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002161 rtc::scoped_ptr<SessionDescription> offer, answer;
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002162
2163 // Generate an offer with DTLS but without SDES.
2164 offer.reset(f1_.CreateOffer(options, NULL));
2165 ASSERT_TRUE(offer.get() != NULL);
2166
2167 const AudioContentDescription* audio_offer =
2168 GetFirstAudioContentDescription(offer.get());
2169 ASSERT_TRUE(audio_offer->cryptos().empty());
2170 const VideoContentDescription* video_offer =
2171 GetFirstVideoContentDescription(offer.get());
2172 ASSERT_TRUE(video_offer->cryptos().empty());
2173 const DataContentDescription* data_offer =
2174 GetFirstDataContentDescription(offer.get());
2175 ASSERT_TRUE(data_offer->cryptos().empty());
2176
2177 const cricket::TransportDescription* audio_offer_trans_desc =
2178 offer->GetTransportDescriptionByName("audio");
2179 ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2180 const cricket::TransportDescription* video_offer_trans_desc =
2181 offer->GetTransportDescriptionByName("video");
2182 ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2183 const cricket::TransportDescription* data_offer_trans_desc =
2184 offer->GetTransportDescriptionByName("data");
2185 ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2186
2187 // Generate an answer with DTLS.
2188 answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2189 ASSERT_TRUE(answer.get() != NULL);
2190
2191 const cricket::TransportDescription* audio_answer_trans_desc =
2192 answer->GetTransportDescriptionByName("audio");
2193 EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2194 const cricket::TransportDescription* video_answer_trans_desc =
2195 answer->GetTransportDescriptionByName("video");
2196 EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2197 const cricket::TransportDescription* data_answer_trans_desc =
2198 answer->GetTransportDescriptionByName("data");
2199 EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2200}
2201
2202// Verifies if vad_enabled option is set to false, CN codecs are not present in
2203// offer or answer.
2204TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2205 MediaSessionOptions options;
jiayl@webrtc.org742922b2014-10-07 21:32:43 +00002206 options.recv_audio = true;
2207 options.recv_video = true;
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002208 rtc::scoped_ptr<SessionDescription> offer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002209 f1_.CreateOffer(options, NULL));
2210 ASSERT_TRUE(offer.get() != NULL);
2211 const ContentInfo* audio_content = offer->GetContentByName("audio");
2212 EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2213
2214 options.vad_enabled = false;
2215 offer.reset(f1_.CreateOffer(options, NULL));
2216 ASSERT_TRUE(offer.get() != NULL);
2217 audio_content = offer->GetContentByName("audio");
2218 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +00002219 rtc::scoped_ptr<SessionDescription> answer(
henrike@webrtc.org28e20752013-07-10 00:45:36 +00002220 f1_.CreateAnswer(offer.get(), options, NULL));
2221 ASSERT_TRUE(answer.get() != NULL);
2222 audio_content = answer->GetContentByName("audio");
2223 EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2224}