1 /*
2 * libjingle
3 * Copyright 2004--2011, 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
31 #include "talk/base/gunit.h"
32 #include "talk/p2p/base/constants.h"
33 #include "talk/session/phone/codec.h"
34 #include "talk/session/phone/mediasession.h"
35 #include "talk/session/phone/srtpfilter.h"
36 #include "talk/session/phone/testutils.h"
37
38 #ifdef HAVE_SRTP
39 #define ASSERT_CRYPTO(cd, r, s, cs) \
40 ASSERT_EQ(r, cd->crypto_required()); \
41 ASSERT_EQ(s, cd->cryptos().size()); \
42 ASSERT_EQ(std::string(cs), cd->cryptos()[0].cipher_suite)
43 #else
44 #define ASSERT_CRYPTO(c, r, s, cs) \
45 ASSERT_EQ(false, cd->crypto_required()); \
46 ASSERT_EQ(0U, cd->cryptos().size());
47 #endif
48
49 using cricket::MediaSessionDescriptionFactory;
50 using cricket::MediaSessionOptions;
51 using cricket::MediaType;
52 using cricket::SessionDescription;
53 using cricket::SsrcGroup;
54 using cricket::StreamParams;
55 using cricket::StreamParamsVec;
56 using cricket::ContentInfo;
57 using cricket::CryptoParamsVec;
58 using cricket::AudioContentDescription;
59 using cricket::VideoContentDescription;
60 using cricket::DataContentDescription;
61 using cricket::GetFirstAudioContentDescription;
62 using cricket::GetFirstVideoContentDescription;
63 using cricket::GetFirstDataContentDescription;
64 using cricket::kAutoBandwidth;
65 using cricket::AudioCodec;
66 using cricket::VideoCodec;
67 using cricket::DataCodec;
68 using cricket::NS_JINGLE_RTP;
69 using cricket::MEDIA_TYPE_AUDIO;
70 using cricket::MEDIA_TYPE_VIDEO;
71 using cricket::MEDIA_TYPE_DATA;
72 using cricket::SEC_ENABLED;
73 using cricket::CS_AES_CM_128_HMAC_SHA1_32;
74 using cricket::CS_AES_CM_128_HMAC_SHA1_80;
75
76 static const AudioCodec kAudioCodecs1[] = {
77 AudioCodec(103, "ISAC", 16000, -1, 1, 5),
78 AudioCodec(102, "iLBC", 8000, 13300, 1, 4),
79 AudioCodec(0, "PCMU", 8000, 64000, 1, 3),
80 AudioCodec(8, "PCMA", 8000, 64000, 1, 2),
81 AudioCodec(117, "red", 8000, 0, 1, 1),
82 };
83
84 static const AudioCodec kAudioCodecs2[] = {
85 AudioCodec(126, "speex", 16000, 22000, 1, 3),
86 AudioCodec(127, "iLBC", 8000, 13300, 1, 2),
87 AudioCodec(0, "PCMU", 8000, 64000, 1, 1),
88 };
89
90 static const AudioCodec kAudioCodecsAnswer[] = {
91 AudioCodec(102, "iLBC", 8000, 13300, 1, 2),
92 AudioCodec(0, "PCMU", 8000, 64000, 1, 1),
93 };
94
95 static const VideoCodec kVideoCodecs1[] = {
96 VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
97 VideoCodec(97, "H264", 320, 200, 30, 1)
98 };
99
100 static const VideoCodec kVideoCodecs2[] = {
101 VideoCodec(126, "H264", 320, 200, 30, 2),
102 VideoCodec(127, "H263", 320, 200, 30, 1)
103 };
104
105 static const VideoCodec kVideoCodecsAnswer[] = {
106 VideoCodec(97, "H264", 320, 200, 30, 2)
107 };
108
109 static const DataCodec kDataCodecs1[] = {
110 DataCodec(96, "binary-data", 2),
111 DataCodec(97, "utf8-text", 1)
112 };
113
114 static const DataCodec kDataCodecs2[] = {
115 DataCodec(126, "binary-data", 2),
116 DataCodec(127, "utf8-text", 1)
117 };
118
119 static const DataCodec kDataCodecsAnswer[] = {
120 DataCodec(96, "binary-data", 2),
121 DataCodec(97, "utf8-text", 1)
122 };
123
124 static const uint32 kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
125 static const uint32 kSimSsrc[] = {10, 20, 30};
126 static const uint32 kFec1Ssrc[] = {10, 11};
127 static const uint32 kFec2Ssrc[] = {20, 21};
128 static const uint32 kFec3Ssrc[] = {30, 31};
129
130 static const char kMediaStream1[] = "stream_1";
131 static const char kMediaStream2[] = "stream_2";
132 static const char kVideoTrack1[] = "video_1";
133 static const char kVideoTrack2[] = "video_2";
134 static const char kAudioTrack1[] = "audio_1";
135 static const char kAudioTrack2[] = "audio_2";
136 static const char kAudioTrack3[] = "audio_3";
137 static const char kDataTrack1[] = "data_1";
138 static const char kDataTrack2[] = "data_2";
139 static const char kDataTrack3[] = "data_3";
140
141 class MediaSessionDescriptionFactoryTest : public testing::Test {
142 public:
MediaSessionDescriptionFactoryTest()143 MediaSessionDescriptionFactoryTest() {
144 f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
145 f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
146 f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
147 f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
148 f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
149 f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
150 }
151
152 // Create a video StreamParamsVec object with:
153 // - one video stream with 3 simulcast streams and FEC,
CreateComplexVideoStreamParamsVec()154 StreamParamsVec CreateComplexVideoStreamParamsVec() {
155 SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
156 SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
157 SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
158 SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
159
160 std::vector<SsrcGroup> ssrc_groups;
161 ssrc_groups.push_back(sim_group);
162 ssrc_groups.push_back(fec_group1);
163 ssrc_groups.push_back(fec_group2);
164 ssrc_groups.push_back(fec_group3);
165
166 StreamParams simulcast_params;
167 simulcast_params.name = kVideoTrack1;
168 simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
169 simulcast_params.ssrc_groups = ssrc_groups;
170 simulcast_params.cname = "Video_SIM_FEC";
171 simulcast_params.sync_label = kMediaStream1;
172
173 StreamParamsVec video_streams;
174 video_streams.push_back(simulcast_params);
175
176 return video_streams;
177 }
CompareCryptoParams(const CryptoParamsVec & c1,const CryptoParamsVec & c2)178 bool CompareCryptoParams(const CryptoParamsVec& c1,
179 const CryptoParamsVec& c2) {
180 if (c1.size() != c2.size())
181 return false;
182 for (size_t i = 0; i < c1.size(); ++i)
183 if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
184 c1[i].key_params != c2[i].key_params ||
185 c1[i].session_params != c2[i].session_params)
186 return false;
187 return true;
188 }
189
190 protected:
191 MediaSessionDescriptionFactory f1_;
192 MediaSessionDescriptionFactory f2_;
193 };
194
195 // Create a typical audio offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioOffer)196 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
197 f1_.set_secure(SEC_ENABLED);
198 talk_base::scoped_ptr<SessionDescription> offer(
199 f1_.CreateOffer(MediaSessionOptions(), NULL));
200 ASSERT_TRUE(offer.get() != NULL);
201 const ContentInfo* ac = offer->GetContentByName("audio");
202 const ContentInfo* vc = offer->GetContentByName("video");
203 ASSERT_TRUE(ac != NULL);
204 ASSERT_TRUE(vc == NULL);
205 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
206 const AudioContentDescription* acd =
207 static_cast<const AudioContentDescription*>(ac->description);
208 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
209 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
210 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
211 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
212 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
213 ASSERT_CRYPTO(acd, false, 2U, CS_AES_CM_128_HMAC_SHA1_32);
214 }
215
216 // Create a typical video offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoOffer)217 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
218 MediaSessionOptions opts;
219 opts.has_video = true;
220 f1_.set_secure(SEC_ENABLED);
221 talk_base::scoped_ptr<SessionDescription>
222 offer(f1_.CreateOffer(opts, NULL));
223 ASSERT_TRUE(offer.get() != NULL);
224 const ContentInfo* ac = offer->GetContentByName("audio");
225 const ContentInfo* vc = offer->GetContentByName("video");
226 ASSERT_TRUE(ac != NULL);
227 ASSERT_TRUE(vc != NULL);
228 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
229 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
230 const AudioContentDescription* acd =
231 static_cast<const AudioContentDescription*>(ac->description);
232 const VideoContentDescription* vcd =
233 static_cast<const VideoContentDescription*>(vc->description);
234 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
235 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
236 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
237 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
238 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
239 ASSERT_CRYPTO(acd, false, 2U, CS_AES_CM_128_HMAC_SHA1_32);
240 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
241 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
242 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
243 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
244 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
245 ASSERT_CRYPTO(vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
246 }
247
248 // Create a typical data offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataOffer)249 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataOffer) {
250 MediaSessionOptions opts;
251 opts.has_data = true;
252 f1_.set_secure(SEC_ENABLED);
253 talk_base::scoped_ptr<SessionDescription>
254 offer(f1_.CreateOffer(opts, NULL));
255 ASSERT_TRUE(offer.get() != NULL);
256 const ContentInfo* ac = offer->GetContentByName("audio");
257 const ContentInfo* dc = offer->GetContentByName("data");
258 ASSERT_TRUE(ac != NULL);
259 ASSERT_TRUE(dc != NULL);
260 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
261 EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
262 const AudioContentDescription* acd =
263 static_cast<const AudioContentDescription*>(ac->description);
264 const DataContentDescription* dcd =
265 static_cast<const DataContentDescription*>(dc->description);
266 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
267 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
268 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
269 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
270 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
271 ASSERT_CRYPTO(acd, false, 2U, CS_AES_CM_128_HMAC_SHA1_32);
272 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
273 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
274 EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
275 EXPECT_EQ(cricket::kDataMaxBandwidth,
276 dcd->bandwidth()); // default bandwidth (auto)
277 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
278 ASSERT_CRYPTO(dcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
279 }
280
281 // Create an audio, video offer without legacy StreamParams.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateOfferWithoutLegacyStreams)282 TEST_F(MediaSessionDescriptionFactoryTest,
283 TestCreateOfferWithoutLegacyStreams) {
284 MediaSessionOptions opts;
285 opts.has_video = true;
286 f1_.set_add_legacy_streams(false);
287 talk_base::scoped_ptr<SessionDescription>
288 offer(f1_.CreateOffer(opts, NULL));
289 ASSERT_TRUE(offer.get() != NULL);
290 const ContentInfo* ac = offer->GetContentByName("audio");
291 const ContentInfo* vc = offer->GetContentByName("video");
292 ASSERT_TRUE(ac != NULL);
293 ASSERT_TRUE(vc != NULL);
294 const AudioContentDescription* acd =
295 static_cast<const AudioContentDescription*>(ac->description);
296 const VideoContentDescription* vcd =
297 static_cast<const VideoContentDescription*>(vc->description);
298
299 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
300 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
301 }
302
303 // Create a typical audio answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioAnswer)304 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
305 f1_.set_secure(SEC_ENABLED);
306 f2_.set_secure(SEC_ENABLED);
307 talk_base::scoped_ptr<SessionDescription> offer(
308 f1_.CreateOffer(MediaSessionOptions(), NULL));
309 ASSERT_TRUE(offer.get() != NULL);
310 talk_base::scoped_ptr<SessionDescription> answer(
311 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
312 const ContentInfo* ac = answer->GetContentByName("audio");
313 const ContentInfo* vc = answer->GetContentByName("video");
314 ASSERT_TRUE(ac != NULL);
315 ASSERT_TRUE(vc == NULL);
316 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
317 const AudioContentDescription* acd =
318 static_cast<const AudioContentDescription*>(ac->description);
319 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
320 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
321 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
322 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
323 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
324 ASSERT_CRYPTO(acd, false, 1U, CS_AES_CM_128_HMAC_SHA1_32);
325 }
326
327 // Create a typical video answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswer)328 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
329 MediaSessionOptions opts;
330 opts.has_video = true;
331 f1_.set_secure(SEC_ENABLED);
332 f2_.set_secure(SEC_ENABLED);
333 talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
334 ASSERT_TRUE(offer.get() != NULL);
335 talk_base::scoped_ptr<SessionDescription> answer(
336 f2_.CreateAnswer(offer.get(), opts, NULL));
337 const ContentInfo* ac = answer->GetContentByName("audio");
338 const ContentInfo* vc = answer->GetContentByName("video");
339 ASSERT_TRUE(ac != NULL);
340 ASSERT_TRUE(vc != NULL);
341 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
342 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
343 const AudioContentDescription* acd =
344 static_cast<const AudioContentDescription*>(ac->description);
345 const VideoContentDescription* vcd =
346 static_cast<const VideoContentDescription*>(vc->description);
347 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
348 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
349 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
350 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
351 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
352 ASSERT_CRYPTO(acd, false, 1U, CS_AES_CM_128_HMAC_SHA1_32);
353 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
354 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
355 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
356 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
357 ASSERT_CRYPTO(vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
358 }
359
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateDataAnswer)360 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
361 MediaSessionOptions opts;
362 opts.has_data = true;
363 f1_.set_secure(SEC_ENABLED);
364 f2_.set_secure(SEC_ENABLED);
365 talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
366 ASSERT_TRUE(offer.get() != NULL);
367 talk_base::scoped_ptr<SessionDescription> answer(
368 f2_.CreateAnswer(offer.get(), opts, NULL));
369 const ContentInfo* ac = answer->GetContentByName("audio");
370 const ContentInfo* vc = answer->GetContentByName("data");
371 ASSERT_TRUE(ac != NULL);
372 ASSERT_TRUE(vc != NULL);
373 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
374 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
375 const AudioContentDescription* acd =
376 static_cast<const AudioContentDescription*>(ac->description);
377 const DataContentDescription* vcd =
378 static_cast<const DataContentDescription*>(vc->description);
379 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
380 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
381 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
382 EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
383 EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
384 ASSERT_CRYPTO(acd, false, 1U, CS_AES_CM_128_HMAC_SHA1_32);
385 EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
386 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
387 EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
388 EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
389 ASSERT_CRYPTO(vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
390 }
391
392 // Create an audio, video, data answer without legacy StreamParams.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAnswerWithoutLegacyStreams)393 TEST_F(MediaSessionDescriptionFactoryTest,
394 TestCreateAnswerWithoutLegacyStreams) {
395 MediaSessionOptions opts;
396 opts.has_video = true;
397 opts.has_data = true;
398 f1_.set_add_legacy_streams(false);
399 f2_.set_add_legacy_streams(false);
400 talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
401 ASSERT_TRUE(offer.get() != NULL);
402 talk_base::scoped_ptr<SessionDescription> answer(
403 f2_.CreateAnswer(offer.get(), opts, NULL));
404 const ContentInfo* ac = answer->GetContentByName("audio");
405 const ContentInfo* vc = answer->GetContentByName("video");
406 const ContentInfo* dc = answer->GetContentByName("data");
407 ASSERT_TRUE(ac != NULL);
408 ASSERT_TRUE(vc != NULL);
409 const AudioContentDescription* acd =
410 static_cast<const AudioContentDescription*>(ac->description);
411 const VideoContentDescription* vcd =
412 static_cast<const VideoContentDescription*>(vc->description);
413 const DataContentDescription* dcd =
414 static_cast<const DataContentDescription*>(dc->description);
415
416 EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
417 EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
418 EXPECT_FALSE(dcd->has_ssrcs()); // No StreamParams.
419 }
420
TEST_F(MediaSessionDescriptionFactoryTest,TestPartial)421 TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
422 MediaSessionOptions opts;
423 opts.has_video = true;
424 opts.has_data = true;
425 f1_.set_secure(SEC_ENABLED);
426 talk_base::scoped_ptr<SessionDescription>
427 offer(f1_.CreateOffer(opts, NULL));
428 ASSERT_TRUE(offer.get() != NULL);
429 const ContentInfo* ac = offer->GetContentByName("audio");
430 const ContentInfo* vc = offer->GetContentByName("video");
431 const ContentInfo* dc = offer->GetContentByName("data");
432 AudioContentDescription* acd = const_cast<AudioContentDescription*>(
433 static_cast<const AudioContentDescription*>(ac->description));
434 VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
435 static_cast<const VideoContentDescription*>(vc->description));
436 DataContentDescription* dcd = const_cast<DataContentDescription*>(
437 static_cast<const DataContentDescription*>(dc->description));
438
439 EXPECT_FALSE(acd->partial()); // default is false.
440 acd->set_partial(true);
441 EXPECT_TRUE(acd->partial());
442 acd->set_partial(false);
443 EXPECT_FALSE(acd->partial());
444
445 EXPECT_FALSE(vcd->partial()); // default is false.
446 vcd->set_partial(true);
447 EXPECT_TRUE(vcd->partial());
448 vcd->set_partial(false);
449 EXPECT_FALSE(vcd->partial());
450
451 EXPECT_FALSE(dcd->partial()); // default is false.
452 dcd->set_partial(true);
453 EXPECT_TRUE(dcd->partial());
454 dcd->set_partial(false);
455 EXPECT_FALSE(dcd->partial());
456 }
457
458 // Create a typical video answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateVideoAnswerRtcpMux)459 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
460 MediaSessionOptions offer_opts;
461 MediaSessionOptions answer_opts;
462 answer_opts.has_video = true;
463 offer_opts.has_video = true;
464 answer_opts.has_data = true;
465 offer_opts.has_data = true;
466
467 talk_base::scoped_ptr<SessionDescription> offer(NULL);
468 talk_base::scoped_ptr<SessionDescription> answer(NULL);
469
470 offer_opts.rtcp_mux_enabled = true;
471 answer_opts.rtcp_mux_enabled = true;
472
473 offer.reset(f1_.CreateOffer(offer_opts, NULL));
474 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
475 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
476 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
477 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
478 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
479 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
480 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
481 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
482 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
483 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
484 EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
485 EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
486 EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
487
488 offer_opts.rtcp_mux_enabled = true;
489 answer_opts.rtcp_mux_enabled = false;
490
491 offer.reset(f1_.CreateOffer(offer_opts, NULL));
492 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
493 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
494 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
495 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
496 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
497 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
498 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
499 EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
500 EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
501 EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
502 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
503 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
504 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
505
506 offer_opts.rtcp_mux_enabled = false;
507 answer_opts.rtcp_mux_enabled = true;
508
509 offer.reset(f1_.CreateOffer(offer_opts, NULL));
510 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
511 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
512 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
513 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
514 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
515 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
516 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
517 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
518 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
519 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
520 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
521 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
522 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
523
524 offer_opts.rtcp_mux_enabled = false;
525 answer_opts.rtcp_mux_enabled = false;
526
527 offer.reset(f1_.CreateOffer(offer_opts, NULL));
528 answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
529 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
530 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
531 ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
532 ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
533 ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
534 ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
535 EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
536 EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
537 EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
538 EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
539 EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
540 EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
541 }
542
543 // Create an audio-only answer to a video offer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateAudioAnswerToVideo)544 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
545 MediaSessionOptions opts;
546 opts.has_video = true;
547 talk_base::scoped_ptr<SessionDescription>
548 offer(f1_.CreateOffer(opts, NULL));
549 ASSERT_TRUE(offer.get() != NULL);
550 talk_base::scoped_ptr<SessionDescription> answer(
551 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
552 const ContentInfo* ac = answer->GetContentByName("audio");
553 const ContentInfo* vc = answer->GetContentByName("video");
554 ASSERT_TRUE(ac != NULL);
555 ASSERT_TRUE(vc == NULL);
556 }
557
558 // Create an audio-only answer to a video offer.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateNoDataAnswerToDataOffer)559 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
560 MediaSessionOptions opts;
561 opts.has_data = true;
562 talk_base::scoped_ptr<SessionDescription>
563 offer(f1_.CreateOffer(opts, NULL));
564 ASSERT_TRUE(offer.get() != NULL);
565 talk_base::scoped_ptr<SessionDescription> answer(
566 f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
567 const ContentInfo* ac = answer->GetContentByName("audio");
568 const ContentInfo* dc = answer->GetContentByName("data");
569 ASSERT_TRUE(ac != NULL);
570 ASSERT_TRUE(dc == NULL);
571 }
572
573 // Create an audio and video offer with:
574 // - one video track
575 // - two audio tracks
576 // - two data tracks
577 // and ensure it matches what we expect. Also updates the initial offer by
578 // adding a new video track and replaces one of the audio tracks.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateMultiStreamVideoOffer)579 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
580 MediaSessionOptions opts;
581 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
582 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
583 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
584 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
585 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
586
587 f1_.set_secure(SEC_ENABLED);
588 talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
589
590 ASSERT_TRUE(offer.get() != NULL);
591 const ContentInfo* ac = offer->GetContentByName("audio");
592 const ContentInfo* vc = offer->GetContentByName("video");
593 const ContentInfo* dc = offer->GetContentByName("data");
594 ASSERT_TRUE(ac != NULL);
595 ASSERT_TRUE(vc != NULL);
596 ASSERT_TRUE(dc != NULL);
597 const AudioContentDescription* acd =
598 static_cast<const AudioContentDescription*>(ac->description);
599 const VideoContentDescription* vcd =
600 static_cast<const VideoContentDescription*>(vc->description);
601 const DataContentDescription* dcd =
602 static_cast<const DataContentDescription*>(dc->description);
603 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
604 EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
605
606 const StreamParamsVec& audio_streams = acd->streams();
607 ASSERT_EQ(2U, audio_streams.size());
608 EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
609 EXPECT_EQ(kAudioTrack1, audio_streams[0].name);
610 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
611 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
612 EXPECT_EQ(kAudioTrack2, audio_streams[1].name);
613 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
614 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
615
616 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
617 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
618 ASSERT_CRYPTO(acd, false, 2U, CS_AES_CM_128_HMAC_SHA1_32);
619
620 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
621 EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
622 ASSERT_CRYPTO(vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
623
624 const StreamParamsVec& video_streams = vcd->streams();
625 ASSERT_EQ(1U, video_streams.size());
626 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
627 EXPECT_EQ(kVideoTrack1, video_streams[0].name);
628 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
629 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
630
631 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
632 EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
633 ASSERT_CRYPTO(dcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
634
635 const StreamParamsVec& data_streams = dcd->streams();
636 ASSERT_EQ(2U, data_streams.size());
637 EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
638 EXPECT_EQ(kDataTrack1, data_streams[0].name);
639 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
640 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
641 EXPECT_EQ(kDataTrack2, data_streams[1].name);
642 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
643 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
644
645 EXPECT_EQ(cricket::kDataMaxBandwidth,
646 dcd->bandwidth()); // default bandwidth (auto)
647 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
648 ASSERT_CRYPTO(dcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
649
650 // Update the offer. Add a new video track that is not synched to the
651 // other tracks and replace audio track 2 with audio track 3.
652 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
653 opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
654 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
655 opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
656 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
657 talk_base::scoped_ptr<SessionDescription>
658 updated_offer(f1_.CreateOffer(opts, offer.get()));
659
660 ASSERT_TRUE(updated_offer.get() != NULL);
661 ac = updated_offer->GetContentByName("audio");
662 vc = updated_offer->GetContentByName("video");
663 dc = updated_offer->GetContentByName("data");
664 ASSERT_TRUE(ac != NULL);
665 ASSERT_TRUE(vc != NULL);
666 ASSERT_TRUE(dc != NULL);
667 const AudioContentDescription* updated_acd =
668 static_cast<const AudioContentDescription*>(ac->description);
669 const VideoContentDescription* updated_vcd =
670 static_cast<const VideoContentDescription*>(vc->description);
671 const DataContentDescription* updated_dcd =
672 static_cast<const DataContentDescription*>(dc->description);
673
674 EXPECT_EQ(acd->type(), updated_acd->type());
675 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
676 EXPECT_EQ(vcd->type(), updated_vcd->type());
677 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
678 EXPECT_EQ(dcd->type(), updated_dcd->type());
679 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
680 ASSERT_CRYPTO(updated_acd, false, 2U, CS_AES_CM_128_HMAC_SHA1_32);
681 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
682 ASSERT_CRYPTO(updated_vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
683 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
684 ASSERT_CRYPTO(updated_dcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
685 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
686
687 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
688 ASSERT_EQ(2U, updated_audio_streams.size());
689 EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
690 EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].name); // New audio track.
691 ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
692 EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
693 EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
694
695 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
696 ASSERT_EQ(2U, updated_video_streams.size());
697 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
698 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].name);
699 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
700
701 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
702 ASSERT_EQ(2U, updated_data_streams.size());
703 EXPECT_EQ(data_streams[0], updated_data_streams[0]);
704 EXPECT_EQ(kDataTrack3, updated_data_streams[1].name); // New data track.
705 ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
706 EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
707 EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
708 }
709
710 // Create an audio and video answer to a standard video offer with:
711 // - one video track
712 // - two audio tracks
713 // - two data tracks
714 // and ensure it matches what we expect. Also updates the initial answer by
715 // adding a new video track and removes one of the audio tracks.
TEST_F(MediaSessionDescriptionFactoryTest,TestCreateMultiStreamVideoAnswer)716 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
717 MediaSessionOptions offer_opts;
718 offer_opts.has_video = true;
719 offer_opts.has_data = true;
720 f1_.set_secure(SEC_ENABLED);
721 f2_.set_secure(SEC_ENABLED);
722 talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
723 NULL));
724
725 MediaSessionOptions opts;
726 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
727 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
728 opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
729 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
730 opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
731
732 talk_base::scoped_ptr<SessionDescription>
733 answer(f2_.CreateAnswer(offer.get(), opts, NULL));
734
735 ASSERT_TRUE(answer.get() != NULL);
736 const ContentInfo* ac = answer->GetContentByName("audio");
737 const ContentInfo* vc = answer->GetContentByName("video");
738 const ContentInfo* dc = answer->GetContentByName("data");
739 ASSERT_TRUE(ac != NULL);
740 ASSERT_TRUE(vc != NULL);
741 ASSERT_TRUE(dc != NULL);
742 const AudioContentDescription* acd =
743 static_cast<const AudioContentDescription*>(ac->description);
744 const VideoContentDescription* vcd =
745 static_cast<const VideoContentDescription*>(vc->description);
746 const DataContentDescription* dcd =
747 static_cast<const DataContentDescription*>(dc->description);
748 ASSERT_CRYPTO(acd, false, 1U, CS_AES_CM_128_HMAC_SHA1_32);
749 ASSERT_CRYPTO(vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
750 ASSERT_CRYPTO(dcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
751
752 EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
753 EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
754
755 const StreamParamsVec& audio_streams = acd->streams();
756 ASSERT_EQ(2U, audio_streams.size());
757 EXPECT_TRUE(audio_streams[0].cname == audio_streams[1].cname);
758 EXPECT_EQ(kAudioTrack1, audio_streams[0].name);
759 ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
760 EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
761 EXPECT_EQ(kAudioTrack2, audio_streams[1].name);
762 ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
763 EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
764
765 EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
766 EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
767
768 EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
769 EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
770
771 const StreamParamsVec& video_streams = vcd->streams();
772 ASSERT_EQ(1U, video_streams.size());
773 EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
774 EXPECT_EQ(kVideoTrack1, video_streams[0].name);
775 EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
776 EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
777
778 EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
779 EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
780
781 const StreamParamsVec& data_streams = dcd->streams();
782 ASSERT_EQ(2U, data_streams.size());
783 EXPECT_TRUE(data_streams[0].cname == data_streams[1].cname);
784 EXPECT_EQ(kDataTrack1, data_streams[0].name);
785 ASSERT_EQ(1U, data_streams[0].ssrcs.size());
786 EXPECT_NE(0U, data_streams[0].ssrcs[0]);
787 EXPECT_EQ(kDataTrack2, data_streams[1].name);
788 ASSERT_EQ(1U, data_streams[1].ssrcs.size());
789 EXPECT_NE(0U, data_streams[1].ssrcs[0]);
790
791 EXPECT_EQ(cricket::kDataMaxBandwidth,
792 dcd->bandwidth()); // default bandwidth (auto)
793 EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
794
795 // Update the answer. Add a new video track that is not synched to the
796 // other traacks and remove 1 audio track.
797 opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
798 opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
799 opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
800 talk_base::scoped_ptr<SessionDescription>
801 updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
802
803 ASSERT_TRUE(updated_answer.get() != NULL);
804 ac = updated_answer->GetContentByName("audio");
805 vc = updated_answer->GetContentByName("video");
806 dc = updated_answer->GetContentByName("data");
807 ASSERT_TRUE(ac != NULL);
808 ASSERT_TRUE(vc != NULL);
809 ASSERT_TRUE(dc != NULL);
810 const AudioContentDescription* updated_acd =
811 static_cast<const AudioContentDescription*>(ac->description);
812 const VideoContentDescription* updated_vcd =
813 static_cast<const VideoContentDescription*>(vc->description);
814 const DataContentDescription* updated_dcd =
815 static_cast<const DataContentDescription*>(dc->description);
816
817 ASSERT_CRYPTO(updated_acd, false, 1U, CS_AES_CM_128_HMAC_SHA1_32);
818 EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
819 ASSERT_CRYPTO(updated_vcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
820 EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
821 ASSERT_CRYPTO(updated_dcd, false, 1U, CS_AES_CM_128_HMAC_SHA1_80);
822 EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
823
824 EXPECT_EQ(acd->type(), updated_acd->type());
825 EXPECT_EQ(acd->codecs(), updated_acd->codecs());
826 EXPECT_EQ(vcd->type(), updated_vcd->type());
827 EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
828 EXPECT_EQ(dcd->type(), updated_dcd->type());
829 EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
830
831 const StreamParamsVec& updated_audio_streams = updated_acd->streams();
832 ASSERT_EQ(1U, updated_audio_streams.size());
833 EXPECT_TRUE(audio_streams[0] == updated_audio_streams[0]);
834
835 const StreamParamsVec& updated_video_streams = updated_vcd->streams();
836 ASSERT_EQ(2U, updated_video_streams.size());
837 EXPECT_EQ(video_streams[0], updated_video_streams[0]);
838 EXPECT_EQ(kVideoTrack2, updated_video_streams[1].name);
839 EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
840
841 const StreamParamsVec& updated_data_streams = updated_dcd->streams();
842 ASSERT_EQ(1U, updated_data_streams.size());
843 EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
844 }
845
TEST(MediaSessionDescription,CopySessionDescription)846 TEST(MediaSessionDescription, CopySessionDescription) {
847 SessionDescription source;
848 cricket::ContentGroup group(cricket::CN_AUDIO);
849 source.AddGroup(group);
850 AudioContentDescription* acd(new AudioContentDescription());
851 acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
852 acd->AddLegacyStream(1);
853 source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
854 VideoContentDescription* vcd(new VideoContentDescription());
855 vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
856 vcd->AddLegacyStream(2);
857 source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
858
859 talk_base::scoped_ptr<SessionDescription> copy(source.Copy());
860 ASSERT_TRUE(copy.get() != NULL);
861 EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
862 const ContentInfo* ac = copy->GetContentByName("audio");
863 const ContentInfo* vc = copy->GetContentByName("video");
864 ASSERT_TRUE(ac != NULL);
865 ASSERT_TRUE(vc != NULL);
866 EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
867 const AudioContentDescription* acd_copy =
868 static_cast<const AudioContentDescription*>(ac->description);
869 EXPECT_EQ(acd->codecs(), acd_copy->codecs());
870 EXPECT_EQ(1u, acd->first_ssrc());
871
872 EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
873 const VideoContentDescription* vcd_copy =
874 static_cast<const VideoContentDescription*>(vc->description);
875 EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
876 EXPECT_EQ(2u, vcd->first_ssrc());
877 }
878