Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / session / media / mediasession_unittest.cc
1 /*
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
31 #include "talk/media/base/codec.h"
32 #include "talk/media/base/testutils.h"
33 #include "talk/p2p/base/constants.h"
34 #include "talk/p2p/base/transportdescription.h"
35 #include "talk/p2p/base/transportinfo.h"
36 #include "talk/session/media/mediasession.h"
37 #include "talk/session/media/srtpfilter.h"
38 #include "webrtc/base/fakesslidentity.h"
39 #include "webrtc/base/gunit.h"
40 #include "webrtc/base/messagedigest.h"
41 #include "webrtc/base/ssladapter.h"
42
43 #ifdef HAVE_SRTP
44 #define ASSERT_CRYPTO(cd, s, cs) \
45     ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
46     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) \
50   ASSERT_EQ(cricket::CT_NONE, cd->crypto_required()); \
51   ASSERT_EQ(0U, cd->cryptos().size());
52 #endif
53
54 typedef std::vector<cricket::Candidate> Candidates;
55
56 using cricket::MediaContentDescription;
57 using cricket::MediaSessionDescriptionFactory;
58 using cricket::MediaSessionOptions;
59 using cricket::MediaType;
60 using cricket::SessionDescription;
61 using cricket::SsrcGroup;
62 using cricket::StreamParams;
63 using cricket::StreamParamsVec;
64 using cricket::TransportDescription;
65 using cricket::TransportDescriptionFactory;
66 using cricket::TransportInfo;
67 using cricket::ContentInfo;
68 using cricket::CryptoParamsVec;
69 using cricket::AudioContentDescription;
70 using cricket::VideoContentDescription;
71 using cricket::DataContentDescription;
72 using cricket::GetFirstAudioContentDescription;
73 using cricket::GetFirstVideoContentDescription;
74 using cricket::GetFirstDataContentDescription;
75 using cricket::kAutoBandwidth;
76 using cricket::AudioCodec;
77 using cricket::VideoCodec;
78 using cricket::DataCodec;
79 using cricket::NS_JINGLE_RTP;
80 using cricket::MEDIA_TYPE_AUDIO;
81 using cricket::MEDIA_TYPE_VIDEO;
82 using cricket::MEDIA_TYPE_DATA;
83 using cricket::RtpHeaderExtension;
84 using cricket::SEC_DISABLED;
85 using cricket::SEC_ENABLED;
86 using cricket::SEC_REQUIRED;
87 using cricket::CS_AES_CM_128_HMAC_SHA1_32;
88 using cricket::CS_AES_CM_128_HMAC_SHA1_80;
89
90 static 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
99 static const AudioCodec kAudioCodecs2[] = {
100   AudioCodec(126, "speex",  16000, 22000, 1, 3),
101   AudioCodec(0,   "PCMU",   8000,  64000, 1, 2),
102   AudioCodec(127, "iLBC",   8000,  13300, 1, 1),
103 };
104
105 static const AudioCodec kAudioCodecsAnswer[] = {
106   AudioCodec(102, "iLBC",   8000,  13300, 1, 5),
107   AudioCodec(0,   "PCMU",   8000,  64000, 1, 4),
108 };
109
110 static const VideoCodec kVideoCodecs1[] = {
111   VideoCodec(96, "H264-SVC", 320, 200, 30, 2),
112   VideoCodec(97, "H264", 320, 200, 30, 1)
113 };
114
115 static const VideoCodec kVideoCodecs2[] = {
116   VideoCodec(126, "H264", 320, 200, 30, 2),
117   VideoCodec(127, "H263", 320, 200, 30, 1)
118 };
119
120 static const VideoCodec kVideoCodecsAnswer[] = {
121   VideoCodec(97, "H264", 320, 200, 30, 1)
122 };
123
124 static const DataCodec kDataCodecs1[] = {
125   DataCodec(98, "binary-data", 2),
126   DataCodec(99, "utf8-text", 1)
127 };
128
129 static const DataCodec kDataCodecs2[] = {
130   DataCodec(126, "binary-data", 2),
131   DataCodec(127, "utf8-text", 1)
132 };
133
134 static const DataCodec kDataCodecsAnswer[] = {
135   DataCodec(98, "binary-data", 2),
136   DataCodec(99, "utf8-text", 1)
137 };
138
139 static 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
144 static const RtpHeaderExtension kAudioRtpExtension2[] = {
145   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 2),
146   RtpHeaderExtension("http://google.com/testing/audio_something_else", 8),
147   RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
148 };
149
150 static const RtpHeaderExtension kAudioRtpExtensionAnswer[] = {
151   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
152 };
153
154 static const RtpHeaderExtension kVideoRtpExtension1[] = {
155   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
156   RtpHeaderExtension("http://google.com/testing/video_something", 13),
157 };
158
159 static const RtpHeaderExtension kVideoRtpExtension2[] = {
160   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 2),
161   RtpHeaderExtension("http://google.com/testing/video_something_else", 14),
162   RtpHeaderExtension("http://google.com/testing/both_audio_and_video", 7),
163 };
164
165 static const RtpHeaderExtension kVideoRtpExtensionAnswer[] = {
166   RtpHeaderExtension("urn:ietf:params:rtp-hdrext:toffset", 14),
167 };
168
169 static const uint32 kSimulcastParamsSsrc[] = {10, 11, 20, 21, 30, 31};
170 static const uint32 kSimSsrc[] = {10, 20, 30};
171 static const uint32 kFec1Ssrc[] = {10, 11};
172 static const uint32 kFec2Ssrc[] = {20, 21};
173 static const uint32 kFec3Ssrc[] = {30, 31};
174
175 static const char kMediaStream1[] = "stream_1";
176 static const char kMediaStream2[] = "stream_2";
177 static const char kVideoTrack1[] = "video_1";
178 static const char kVideoTrack2[] = "video_2";
179 static const char kAudioTrack1[] = "audio_1";
180 static const char kAudioTrack2[] = "audio_2";
181 static const char kAudioTrack3[] = "audio_3";
182 static const char kDataTrack1[] = "data_1";
183 static const char kDataTrack2[] = "data_2";
184 static const char kDataTrack3[] = "data_3";
185
186 static 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
193 class MediaSessionDescriptionFactoryTest : public testing::Test {
194  public:
195   MediaSessionDescriptionFactoryTest()
196       : f1_(&tdf1_), f2_(&tdf2_), id1_("id1"), id2_("id2") {
197     f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1));
198     f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
199     f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
200     f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2));
201     f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
202     f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
203     tdf1_.set_identity(&id1_);
204     tdf2_.set_identity(&id2_);
205   }
206
207   static void SetUpTestCase() {
208     rtc::InitializeSSL();
209   }
210
211   static void TearDownTestCase() {
212     rtc::CleanupSSL();
213   }
214
215   // Create a video StreamParamsVec object with:
216   // - one video stream with 3 simulcast streams and FEC,
217   StreamParamsVec CreateComplexVideoStreamParamsVec() {
218     SsrcGroup sim_group("SIM", MAKE_VECTOR(kSimSsrc));
219     SsrcGroup fec_group1("FEC", MAKE_VECTOR(kFec1Ssrc));
220     SsrcGroup fec_group2("FEC", MAKE_VECTOR(kFec2Ssrc));
221     SsrcGroup fec_group3("FEC", MAKE_VECTOR(kFec3Ssrc));
222
223     std::vector<SsrcGroup> ssrc_groups;
224     ssrc_groups.push_back(sim_group);
225     ssrc_groups.push_back(fec_group1);
226     ssrc_groups.push_back(fec_group2);
227     ssrc_groups.push_back(fec_group3);
228
229     StreamParams simulcast_params;
230     simulcast_params.id = kVideoTrack1;
231     simulcast_params.ssrcs = MAKE_VECTOR(kSimulcastParamsSsrc);
232     simulcast_params.ssrc_groups = ssrc_groups;
233     simulcast_params.cname = "Video_SIM_FEC";
234     simulcast_params.sync_label = kMediaStream1;
235
236     StreamParamsVec video_streams;
237     video_streams.push_back(simulcast_params);
238
239     return video_streams;
240   }
241
242   bool CompareCryptoParams(const CryptoParamsVec& c1,
243                            const CryptoParamsVec& c2) {
244     if (c1.size() != c2.size())
245       return false;
246     for (size_t i = 0; i < c1.size(); ++i)
247       if (c1[i].tag != c2[i].tag || c1[i].cipher_suite != c2[i].cipher_suite ||
248           c1[i].key_params != c2[i].key_params ||
249           c1[i].session_params != c2[i].session_params)
250         return false;
251     return true;
252   }
253
254   void TestTransportInfo(bool offer, const MediaSessionOptions& options,
255                          bool has_current_desc) {
256     const std::string current_audio_ufrag = "current_audio_ufrag";
257     const std::string current_audio_pwd = "current_audio_pwd";
258     const std::string current_video_ufrag = "current_video_ufrag";
259     const std::string current_video_pwd = "current_video_pwd";
260     const std::string current_data_ufrag = "current_data_ufrag";
261     const std::string current_data_pwd = "current_data_pwd";
262     rtc::scoped_ptr<SessionDescription> current_desc;
263     rtc::scoped_ptr<SessionDescription> desc;
264     if (has_current_desc) {
265       current_desc.reset(new SessionDescription());
266       EXPECT_TRUE(current_desc->AddTransportInfo(
267           TransportInfo("audio",
268                         TransportDescription("",
269                                              current_audio_ufrag,
270                                              current_audio_pwd))));
271       EXPECT_TRUE(current_desc->AddTransportInfo(
272           TransportInfo("video",
273                         TransportDescription("",
274                                              current_video_ufrag,
275                                              current_video_pwd))));
276       EXPECT_TRUE(current_desc->AddTransportInfo(
277           TransportInfo("data",
278                         TransportDescription("",
279                                              current_data_ufrag,
280                                              current_data_pwd))));
281     }
282     if (offer) {
283       desc.reset(f1_.CreateOffer(options, current_desc.get()));
284     } else {
285       rtc::scoped_ptr<SessionDescription> offer;
286       offer.reset(f1_.CreateOffer(options, NULL));
287       desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
288     }
289     ASSERT_TRUE(desc.get() != NULL);
290     const TransportInfo* ti_audio = desc->GetTransportInfoByName("audio");
291     if (options.has_audio) {
292       EXPECT_TRUE(ti_audio != NULL);
293       if (has_current_desc) {
294         EXPECT_EQ(current_audio_ufrag, ti_audio->description.ice_ufrag);
295         EXPECT_EQ(current_audio_pwd, ti_audio->description.ice_pwd);
296       } else {
297         EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
298                   ti_audio->description.ice_ufrag.size());
299         EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
300                   ti_audio->description.ice_pwd.size());
301       }
302
303     } else {
304       EXPECT_TRUE(ti_audio == NULL);
305     }
306     const TransportInfo* ti_video = desc->GetTransportInfoByName("video");
307     if (options.has_video) {
308       EXPECT_TRUE(ti_video != NULL);
309       if (options.bundle_enabled) {
310         EXPECT_EQ(ti_audio->description.ice_ufrag,
311                   ti_video->description.ice_ufrag);
312         EXPECT_EQ(ti_audio->description.ice_pwd,
313                   ti_video->description.ice_pwd);
314       } else {
315         if (has_current_desc) {
316           EXPECT_EQ(current_video_ufrag, ti_video->description.ice_ufrag);
317           EXPECT_EQ(current_video_pwd, ti_video->description.ice_pwd);
318         } else {
319           EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
320                     ti_video->description.ice_ufrag.size());
321           EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
322                     ti_video->description.ice_pwd.size());
323         }
324       }
325     } else {
326       EXPECT_TRUE(ti_video == NULL);
327     }
328     const TransportInfo* ti_data = desc->GetTransportInfoByName("data");
329     if (options.has_data()) {
330       EXPECT_TRUE(ti_data != NULL);
331       if (options.bundle_enabled) {
332         EXPECT_EQ(ti_audio->description.ice_ufrag,
333                   ti_data->description.ice_ufrag);
334         EXPECT_EQ(ti_audio->description.ice_pwd,
335                   ti_data->description.ice_pwd);
336       } else {
337         if (has_current_desc) {
338           EXPECT_EQ(current_data_ufrag, ti_data->description.ice_ufrag);
339           EXPECT_EQ(current_data_pwd, ti_data->description.ice_pwd);
340         } else {
341           EXPECT_EQ(static_cast<size_t>(cricket::ICE_UFRAG_LENGTH),
342                     ti_data->description.ice_ufrag.size());
343           EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
344                     ti_data->description.ice_pwd.size());
345         }
346       }
347     } else {
348       EXPECT_TRUE(ti_video == NULL);
349     }
350   }
351
352   void TestCryptoWithBundle(bool offer) {
353     f1_.set_secure(SEC_ENABLED);
354     MediaSessionOptions options;
355     options.has_audio = true;
356     options.has_video = true;
357     options.data_channel_type = cricket::DCT_RTP;
358     rtc::scoped_ptr<SessionDescription> ref_desc;
359     rtc::scoped_ptr<SessionDescription> desc;
360     if (offer) {
361       options.bundle_enabled = false;
362       ref_desc.reset(f1_.CreateOffer(options, NULL));
363       options.bundle_enabled = true;
364       desc.reset(f1_.CreateOffer(options, ref_desc.get()));
365     } else {
366       options.bundle_enabled = true;
367       ref_desc.reset(f1_.CreateOffer(options, NULL));
368       desc.reset(f1_.CreateAnswer(ref_desc.get(), options, NULL));
369     }
370     ASSERT_TRUE(desc.get() != NULL);
371     const cricket::MediaContentDescription* audio_media_desc =
372         static_cast<const cricket::MediaContentDescription*>(
373             desc.get()->GetContentDescriptionByName("audio"));
374     ASSERT_TRUE(audio_media_desc != NULL);
375     const cricket::MediaContentDescription* video_media_desc =
376         static_cast<const cricket::MediaContentDescription*>(
377             desc.get()->GetContentDescriptionByName("video"));
378     ASSERT_TRUE(video_media_desc != NULL);
379     EXPECT_TRUE(CompareCryptoParams(audio_media_desc->cryptos(),
380                                     video_media_desc->cryptos()));
381     EXPECT_EQ(1u, audio_media_desc->cryptos().size());
382     EXPECT_EQ(std::string(CS_AES_CM_128_HMAC_SHA1_80),
383               audio_media_desc->cryptos()[0].cipher_suite);
384
385     // Verify the selected crypto is one from the reference audio
386     // media content.
387     const cricket::MediaContentDescription* ref_audio_media_desc =
388         static_cast<const cricket::MediaContentDescription*>(
389             ref_desc.get()->GetContentDescriptionByName("audio"));
390     bool found = false;
391     for (size_t i = 0; i < ref_audio_media_desc->cryptos().size(); ++i) {
392       if (ref_audio_media_desc->cryptos()[i].Matches(
393           audio_media_desc->cryptos()[0])) {
394         found = true;
395         break;
396       }
397     }
398     EXPECT_TRUE(found);
399   }
400
401   // This test that the audio and video media direction is set to
402   // |expected_direction_in_answer| in an answer if the offer direction is set
403   // to |direction_in_offer|.
404   void TestMediaDirectionInAnswer(
405       cricket::MediaContentDirection direction_in_offer,
406       cricket::MediaContentDirection expected_direction_in_answer) {
407     MediaSessionOptions opts;
408     opts.has_video = true;
409     rtc::scoped_ptr<SessionDescription> offer(
410         f1_.CreateOffer(opts, NULL));
411     ASSERT_TRUE(offer.get() != NULL);
412     ContentInfo* ac_offer= offer->GetContentByName("audio");
413     ASSERT_TRUE(ac_offer != NULL);
414     AudioContentDescription* acd_offer =
415         static_cast<AudioContentDescription*>(ac_offer->description);
416     acd_offer->set_direction(direction_in_offer);
417     ContentInfo* vc_offer= offer->GetContentByName("video");
418     ASSERT_TRUE(vc_offer != NULL);
419     VideoContentDescription* vcd_offer =
420         static_cast<VideoContentDescription*>(vc_offer->description);
421     vcd_offer->set_direction(direction_in_offer);
422
423     rtc::scoped_ptr<SessionDescription> answer(
424         f2_.CreateAnswer(offer.get(), opts, NULL));
425     const AudioContentDescription* acd_answer =
426         GetFirstAudioContentDescription(answer.get());
427     EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
428     const VideoContentDescription* vcd_answer =
429         GetFirstVideoContentDescription(answer.get());
430     EXPECT_EQ(expected_direction_in_answer, vcd_answer->direction());
431   }
432
433   bool VerifyNoCNCodecs(const cricket::ContentInfo* content) {
434     const cricket::ContentDescription* description = content->description;
435     ASSERT(description != NULL);
436     const cricket::AudioContentDescription* audio_content_desc =
437         static_cast<const cricket::AudioContentDescription*>(description);
438     ASSERT(audio_content_desc != NULL);
439     for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
440       if (audio_content_desc->codecs()[i].name == "CN")
441         return false;
442     }
443     return true;
444   }
445
446  protected:
447   MediaSessionDescriptionFactory f1_;
448   MediaSessionDescriptionFactory f2_;
449   TransportDescriptionFactory tdf1_;
450   TransportDescriptionFactory tdf2_;
451   rtc::FakeSSLIdentity id1_;
452   rtc::FakeSSLIdentity id2_;
453 };
454
455 // Create a typical audio offer, and ensure it matches what we expect.
456 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
457   f1_.set_secure(SEC_ENABLED);
458   rtc::scoped_ptr<SessionDescription> offer(
459       f1_.CreateOffer(MediaSessionOptions(), NULL));
460   ASSERT_TRUE(offer.get() != NULL);
461   const ContentInfo* ac = offer->GetContentByName("audio");
462   const ContentInfo* vc = offer->GetContentByName("video");
463   ASSERT_TRUE(ac != NULL);
464   ASSERT_TRUE(vc == NULL);
465   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
466   const AudioContentDescription* acd =
467       static_cast<const AudioContentDescription*>(ac->description);
468   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
469   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
470   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
471   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
472   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
473   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
474   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
475 }
476
477 // Create a typical video offer, and ensure it matches what we expect.
478 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
479   MediaSessionOptions opts;
480   opts.has_video = true;
481   f1_.set_secure(SEC_ENABLED);
482   rtc::scoped_ptr<SessionDescription>
483       offer(f1_.CreateOffer(opts, NULL));
484   ASSERT_TRUE(offer.get() != NULL);
485   const ContentInfo* ac = offer->GetContentByName("audio");
486   const ContentInfo* vc = offer->GetContentByName("video");
487   ASSERT_TRUE(ac != NULL);
488   ASSERT_TRUE(vc != NULL);
489   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
490   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
491   const AudioContentDescription* acd =
492       static_cast<const AudioContentDescription*>(ac->description);
493   const VideoContentDescription* vcd =
494       static_cast<const VideoContentDescription*>(vc->description);
495   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
496   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
497   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
498   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
499   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
500   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
501   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
502   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
503   EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
504   EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
505   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
506   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
507   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
508   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
509 }
510
511 // Test creating an offer with bundle where the Codecs have the same dynamic
512 // RTP playlod type. The test verifies that the offer don't contain the
513 // duplicate RTP payload types.
514 TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
515   const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
516   const AudioCodec& offered_audio_codec = f2_.audio_codecs()[0];
517   const DataCodec& offered_data_codec = f2_.data_codecs()[0];
518   ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
519   ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
520
521   MediaSessionOptions opts;
522   opts.has_audio = true;
523   opts.has_video = true;
524   opts.data_channel_type = cricket::DCT_RTP;
525   opts.bundle_enabled = true;
526   rtc::scoped_ptr<SessionDescription>
527   offer(f2_.CreateOffer(opts, NULL));
528   const VideoContentDescription* vcd =
529       GetFirstVideoContentDescription(offer.get());
530   const AudioContentDescription* acd =
531       GetFirstAudioContentDescription(offer.get());
532   const DataContentDescription* dcd =
533       GetFirstDataContentDescription(offer.get());
534   ASSERT_TRUE(NULL != vcd);
535   ASSERT_TRUE(NULL != acd);
536   ASSERT_TRUE(NULL != dcd);
537   EXPECT_NE(vcd->codecs()[0].id, acd->codecs()[0].id);
538   EXPECT_NE(vcd->codecs()[0].id, dcd->codecs()[0].id);
539   EXPECT_NE(acd->codecs()[0].id, dcd->codecs()[0].id);
540   EXPECT_EQ(vcd->codecs()[0].name, offered_video_codec.name);
541   EXPECT_EQ(acd->codecs()[0].name, offered_audio_codec.name);
542   EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
543 }
544
545 // Test creating an updated offer with with bundle, audio, video and data
546 // after an audio only session has been negotiated.
547 TEST_F(MediaSessionDescriptionFactoryTest,
548        TestCreateUpdatedVideoOfferWithBundle) {
549   f1_.set_secure(SEC_ENABLED);
550   f2_.set_secure(SEC_ENABLED);
551   MediaSessionOptions opts;
552   opts.has_audio = true;
553   opts.has_video = false;
554   opts.data_channel_type = cricket::DCT_NONE;
555   opts.bundle_enabled = true;
556   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
557   rtc::scoped_ptr<SessionDescription> answer(
558       f2_.CreateAnswer(offer.get(), opts, NULL));
559
560   MediaSessionOptions updated_opts;
561   updated_opts.has_audio = true;
562   updated_opts.has_video = true;
563   updated_opts.data_channel_type = cricket::DCT_RTP;
564   updated_opts.bundle_enabled = true;
565   rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
566       updated_opts, answer.get()));
567
568   const AudioContentDescription* acd =
569       GetFirstAudioContentDescription(updated_offer.get());
570   const VideoContentDescription* vcd =
571       GetFirstVideoContentDescription(updated_offer.get());
572   const DataContentDescription* dcd =
573       GetFirstDataContentDescription(updated_offer.get());
574   EXPECT_TRUE(NULL != vcd);
575   EXPECT_TRUE(NULL != acd);
576   EXPECT_TRUE(NULL != dcd);
577
578   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
579   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
580   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
581   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
582   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
583   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
584 }
585 // Create a RTP data offer, and ensure it matches what we expect.
586 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
587   MediaSessionOptions opts;
588   opts.data_channel_type = cricket::DCT_RTP;
589   f1_.set_secure(SEC_ENABLED);
590   rtc::scoped_ptr<SessionDescription>
591       offer(f1_.CreateOffer(opts, NULL));
592   ASSERT_TRUE(offer.get() != NULL);
593   const ContentInfo* ac = offer->GetContentByName("audio");
594   const ContentInfo* dc = offer->GetContentByName("data");
595   ASSERT_TRUE(ac != NULL);
596   ASSERT_TRUE(dc != NULL);
597   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
598   EXPECT_EQ(std::string(NS_JINGLE_RTP), dc->type);
599   const AudioContentDescription* acd =
600       static_cast<const AudioContentDescription*>(ac->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   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
606   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
607   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
608   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
609   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
610   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
611   EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
612   EXPECT_NE(0U, dcd->first_ssrc());             // a random nonzero ssrc
613   EXPECT_EQ(cricket::kDataMaxBandwidth,
614             dcd->bandwidth());                  // default bandwidth (auto)
615   EXPECT_TRUE(dcd->rtcp_mux());                 // rtcp-mux defaults on
616   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
617   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
618 }
619
620 // Create an SCTP data offer with bundle without error.
621 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
622   MediaSessionOptions opts;
623   opts.has_audio = false;
624   opts.bundle_enabled = true;
625   opts.data_channel_type = cricket::DCT_SCTP;
626   f1_.set_secure(SEC_ENABLED);
627   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
628   EXPECT_TRUE(offer.get() != NULL);
629   EXPECT_TRUE(offer->GetContentByName("data") != NULL);
630 }
631
632 // Create an audio, video offer without legacy StreamParams.
633 TEST_F(MediaSessionDescriptionFactoryTest,
634        TestCreateOfferWithoutLegacyStreams) {
635   MediaSessionOptions opts;
636   opts.has_video = true;
637   f1_.set_add_legacy_streams(false);
638   rtc::scoped_ptr<SessionDescription>
639       offer(f1_.CreateOffer(opts, NULL));
640   ASSERT_TRUE(offer.get() != NULL);
641   const ContentInfo* ac = offer->GetContentByName("audio");
642   const ContentInfo* vc = offer->GetContentByName("video");
643   ASSERT_TRUE(ac != NULL);
644   ASSERT_TRUE(vc != NULL);
645   const AudioContentDescription* acd =
646       static_cast<const AudioContentDescription*>(ac->description);
647   const VideoContentDescription* vcd =
648       static_cast<const VideoContentDescription*>(vc->description);
649
650   EXPECT_FALSE(vcd->has_ssrcs());             // No StreamParams.
651   EXPECT_FALSE(acd->has_ssrcs());             // No StreamParams.
652 }
653
654 // Verifies that the order of the media contents in the current
655 // SessionDescription is preserved in the new SessionDescription.
656 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
657   MediaSessionOptions opts;
658   opts.has_audio = false;
659   opts.has_video = false;
660   opts.data_channel_type = cricket::DCT_SCTP;
661
662   rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
663   ASSERT_TRUE(offer1.get() != NULL);
664   EXPECT_EQ(1u, offer1->contents().size());
665   EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
666
667   opts.has_video = true;
668   rtc::scoped_ptr<SessionDescription> offer2(
669       f1_.CreateOffer(opts, offer1.get()));
670   ASSERT_TRUE(offer2.get() != NULL);
671   EXPECT_EQ(2u, offer2->contents().size());
672   EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
673   EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
674
675   opts.has_audio = true;
676   rtc::scoped_ptr<SessionDescription> offer3(
677       f1_.CreateOffer(opts, offer2.get()));
678   ASSERT_TRUE(offer3.get() != NULL);
679   EXPECT_EQ(3u, offer3->contents().size());
680   EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
681   EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
682   EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
683
684   // Verifies the default order is audio-video-data, so that the previous checks
685   // didn't pass by accident.
686   rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
687   ASSERT_TRUE(offer4.get() != NULL);
688   EXPECT_EQ(3u, offer4->contents().size());
689   EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
690   EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
691   EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
692 }
693
694 // Create a typical audio answer, and ensure it matches what we expect.
695 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
696   f1_.set_secure(SEC_ENABLED);
697   f2_.set_secure(SEC_ENABLED);
698   rtc::scoped_ptr<SessionDescription> offer(
699       f1_.CreateOffer(MediaSessionOptions(), NULL));
700   ASSERT_TRUE(offer.get() != NULL);
701   rtc::scoped_ptr<SessionDescription> answer(
702       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
703   const ContentInfo* ac = answer->GetContentByName("audio");
704   const ContentInfo* vc = answer->GetContentByName("video");
705   ASSERT_TRUE(ac != NULL);
706   ASSERT_TRUE(vc == NULL);
707   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
708   const AudioContentDescription* acd =
709       static_cast<const AudioContentDescription*>(ac->description);
710   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
711   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
712   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
713   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
714   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
715   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
716   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
717 }
718
719 // Create a typical video answer, and ensure it matches what we expect.
720 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
721   MediaSessionOptions opts;
722   opts.has_video = true;
723   f1_.set_secure(SEC_ENABLED);
724   f2_.set_secure(SEC_ENABLED);
725   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
726   ASSERT_TRUE(offer.get() != NULL);
727   rtc::scoped_ptr<SessionDescription> answer(
728       f2_.CreateAnswer(offer.get(), opts, NULL));
729   const ContentInfo* ac = answer->GetContentByName("audio");
730   const ContentInfo* vc = answer->GetContentByName("video");
731   ASSERT_TRUE(ac != NULL);
732   ASSERT_TRUE(vc != NULL);
733   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
734   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
735   const AudioContentDescription* acd =
736       static_cast<const AudioContentDescription*>(ac->description);
737   const VideoContentDescription* vcd =
738       static_cast<const VideoContentDescription*>(vc->description);
739   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
740   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
741   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
742   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
743   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
744   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
745   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
746   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
747   EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
748   EXPECT_TRUE(vcd->rtcp_mux());                 // negotiated rtcp-mux
749   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
750   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
751 }
752
753 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
754   MediaSessionOptions opts;
755   opts.data_channel_type = cricket::DCT_RTP;
756   f1_.set_secure(SEC_ENABLED);
757   f2_.set_secure(SEC_ENABLED);
758   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
759   ASSERT_TRUE(offer.get() != NULL);
760   rtc::scoped_ptr<SessionDescription> answer(
761       f2_.CreateAnswer(offer.get(), opts, NULL));
762   const ContentInfo* ac = answer->GetContentByName("audio");
763   const ContentInfo* vc = answer->GetContentByName("data");
764   ASSERT_TRUE(ac != NULL);
765   ASSERT_TRUE(vc != NULL);
766   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
767   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
768   const AudioContentDescription* acd =
769       static_cast<const AudioContentDescription*>(ac->description);
770   const DataContentDescription* vcd =
771       static_cast<const DataContentDescription*>(vc->description);
772   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
773   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
774   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
775   EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
776   EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
777   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
778   EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
779   EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
780   EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
781   EXPECT_TRUE(vcd->rtcp_mux());                 // negotiated rtcp-mux
782   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
783   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
784 }
785
786 // Verifies that the order of the media contents in the offer is preserved in
787 // the answer.
788 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
789   MediaSessionOptions opts;
790
791   // Creates a data only offer.
792   opts.has_audio = false;
793   opts.data_channel_type = cricket::DCT_SCTP;
794   rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
795   ASSERT_TRUE(offer1.get() != NULL);
796
797   // Appends audio to the offer.
798   opts.has_audio = true;
799   rtc::scoped_ptr<SessionDescription> offer2(
800       f1_.CreateOffer(opts, offer1.get()));
801   ASSERT_TRUE(offer2.get() != NULL);
802
803   // Appends video to the offer.
804   opts.has_video = true;
805   rtc::scoped_ptr<SessionDescription> offer3(
806       f1_.CreateOffer(opts, offer2.get()));
807   ASSERT_TRUE(offer3.get() != NULL);
808
809   rtc::scoped_ptr<SessionDescription> answer(
810       f2_.CreateAnswer(offer3.get(), opts, NULL));
811   ASSERT_TRUE(answer.get() != NULL);
812   EXPECT_EQ(3u, answer->contents().size());
813   EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
814   EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
815   EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
816 }
817
818 // This test that the media direction is set to send/receive in an answer if
819 // the offer is send receive.
820 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
821   TestMediaDirectionInAnswer(cricket::MD_SENDRECV, cricket::MD_SENDRECV);
822 }
823
824 // This test that the media direction is set to receive only in an answer if
825 // the offer is send only.
826 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendOnlyOffer) {
827   TestMediaDirectionInAnswer(cricket::MD_SENDONLY, cricket::MD_RECVONLY);
828 }
829
830 // This test that the media direction is set to send only in an answer if
831 // the offer is recv only.
832 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToRecvOnlyOffer) {
833   TestMediaDirectionInAnswer(cricket::MD_RECVONLY, cricket::MD_SENDONLY);
834 }
835
836 // This test that the media direction is set to inactive in an answer if
837 // the offer is inactive.
838 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToInactiveOffer) {
839   TestMediaDirectionInAnswer(cricket::MD_INACTIVE, cricket::MD_INACTIVE);
840 }
841
842 // Test that a data content with an unknown protocol is rejected in an answer.
843 TEST_F(MediaSessionDescriptionFactoryTest,
844        CreateDataAnswerToOfferWithUnknownProtocol) {
845   MediaSessionOptions opts;
846   opts.data_channel_type = cricket::DCT_RTP;
847   opts.has_audio = false;
848   f1_.set_secure(SEC_ENABLED);
849   f2_.set_secure(SEC_ENABLED);
850   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
851   ContentInfo* dc_offer= offer->GetContentByName("data");
852   ASSERT_TRUE(dc_offer != NULL);
853   DataContentDescription* dcd_offer =
854       static_cast<DataContentDescription*>(dc_offer->description);
855   ASSERT_TRUE(dcd_offer != NULL);
856   std::string protocol = "a weird unknown protocol";
857   dcd_offer->set_protocol(protocol);
858
859   rtc::scoped_ptr<SessionDescription> answer(
860       f2_.CreateAnswer(offer.get(), opts, NULL));
861
862   const ContentInfo* dc_answer = answer->GetContentByName("data");
863   ASSERT_TRUE(dc_answer != NULL);
864   EXPECT_TRUE(dc_answer->rejected);
865   const DataContentDescription* dcd_answer =
866       static_cast<const DataContentDescription*>(dc_answer->description);
867   ASSERT_TRUE(dcd_answer != NULL);
868   EXPECT_EQ(protocol, dcd_answer->protocol());
869 }
870
871 // Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
872 TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
873   MediaSessionOptions opts;
874   f1_.set_secure(SEC_DISABLED);
875   f2_.set_secure(SEC_DISABLED);
876   tdf1_.set_secure(SEC_DISABLED);
877   tdf2_.set_secure(SEC_DISABLED);
878
879   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
880   const AudioContentDescription* offer_acd =
881       GetFirstAudioContentDescription(offer.get());
882   ASSERT_TRUE(offer_acd != NULL);
883   EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
884
885   rtc::scoped_ptr<SessionDescription> answer(
886       f2_.CreateAnswer(offer.get(), opts, NULL));
887
888   const ContentInfo* ac_answer = answer->GetContentByName("audio");
889   ASSERT_TRUE(ac_answer != NULL);
890   EXPECT_FALSE(ac_answer->rejected);
891
892   const AudioContentDescription* answer_acd =
893       GetFirstAudioContentDescription(answer.get());
894   ASSERT_TRUE(answer_acd != NULL);
895   EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), answer_acd->protocol());
896 }
897
898 // Create a video offer and answer and ensure the RTP header extensions
899 // matches what we expect.
900 TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
901   MediaSessionOptions opts;
902   opts.has_video = true;
903
904   f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
905   f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
906   f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
907   f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
908
909   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
910   ASSERT_TRUE(offer.get() != NULL);
911   rtc::scoped_ptr<SessionDescription> answer(
912       f2_.CreateAnswer(offer.get(), opts, NULL));
913
914   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
915             GetFirstAudioContentDescription(
916                 offer.get())->rtp_header_extensions());
917   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtension1),
918             GetFirstVideoContentDescription(
919                 offer.get())->rtp_header_extensions());
920   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
921             GetFirstAudioContentDescription(
922                 answer.get())->rtp_header_extensions());
923   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
924             GetFirstVideoContentDescription(
925                 answer.get())->rtp_header_extensions());
926 }
927
928 // Create an audio, video, data answer without legacy StreamParams.
929 TEST_F(MediaSessionDescriptionFactoryTest,
930        TestCreateAnswerWithoutLegacyStreams) {
931   MediaSessionOptions opts;
932   opts.has_video = true;
933   opts.data_channel_type = cricket::DCT_RTP;
934   f1_.set_add_legacy_streams(false);
935   f2_.set_add_legacy_streams(false);
936   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
937   ASSERT_TRUE(offer.get() != NULL);
938   rtc::scoped_ptr<SessionDescription> answer(
939       f2_.CreateAnswer(offer.get(), opts, NULL));
940   const ContentInfo* ac = answer->GetContentByName("audio");
941   const ContentInfo* vc = answer->GetContentByName("video");
942   const ContentInfo* dc = answer->GetContentByName("data");
943   ASSERT_TRUE(ac != NULL);
944   ASSERT_TRUE(vc != NULL);
945   const AudioContentDescription* acd =
946       static_cast<const AudioContentDescription*>(ac->description);
947   const VideoContentDescription* vcd =
948       static_cast<const VideoContentDescription*>(vc->description);
949   const DataContentDescription* dcd =
950       static_cast<const DataContentDescription*>(dc->description);
951
952   EXPECT_FALSE(acd->has_ssrcs());  // No StreamParams.
953   EXPECT_FALSE(vcd->has_ssrcs());  // No StreamParams.
954   EXPECT_FALSE(dcd->has_ssrcs());  // No StreamParams.
955 }
956
957 TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
958   MediaSessionOptions opts;
959   opts.has_video = true;
960   opts.data_channel_type = cricket::DCT_RTP;
961   f1_.set_secure(SEC_ENABLED);
962   rtc::scoped_ptr<SessionDescription>
963       offer(f1_.CreateOffer(opts, NULL));
964   ASSERT_TRUE(offer.get() != NULL);
965   const ContentInfo* ac = offer->GetContentByName("audio");
966   const ContentInfo* vc = offer->GetContentByName("video");
967   const ContentInfo* dc = offer->GetContentByName("data");
968   AudioContentDescription* acd = const_cast<AudioContentDescription*>(
969       static_cast<const AudioContentDescription*>(ac->description));
970   VideoContentDescription* vcd = const_cast<VideoContentDescription*>(
971       static_cast<const VideoContentDescription*>(vc->description));
972   DataContentDescription* dcd = const_cast<DataContentDescription*>(
973       static_cast<const DataContentDescription*>(dc->description));
974
975   EXPECT_FALSE(acd->partial());  // default is false.
976   acd->set_partial(true);
977   EXPECT_TRUE(acd->partial());
978   acd->set_partial(false);
979   EXPECT_FALSE(acd->partial());
980
981   EXPECT_FALSE(vcd->partial());  // default is false.
982   vcd->set_partial(true);
983   EXPECT_TRUE(vcd->partial());
984   vcd->set_partial(false);
985   EXPECT_FALSE(vcd->partial());
986
987   EXPECT_FALSE(dcd->partial());  // default is false.
988   dcd->set_partial(true);
989   EXPECT_TRUE(dcd->partial());
990   dcd->set_partial(false);
991   EXPECT_FALSE(dcd->partial());
992 }
993
994 // Create a typical video answer, and ensure it matches what we expect.
995 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
996   MediaSessionOptions offer_opts;
997   MediaSessionOptions answer_opts;
998   answer_opts.has_video = true;
999   offer_opts.has_video = true;
1000   answer_opts.data_channel_type = cricket::DCT_RTP;
1001   offer_opts.data_channel_type = cricket::DCT_RTP;
1002
1003   rtc::scoped_ptr<SessionDescription> offer;
1004   rtc::scoped_ptr<SessionDescription> answer;
1005
1006   offer_opts.rtcp_mux_enabled = true;
1007   answer_opts.rtcp_mux_enabled = true;
1008
1009   offer.reset(f1_.CreateOffer(offer_opts, NULL));
1010   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1011   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1012   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1013   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1014   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1015   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1016   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1017   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1018   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1019   EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1020   EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1021   EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1022   EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1023
1024   offer_opts.rtcp_mux_enabled = true;
1025   answer_opts.rtcp_mux_enabled = false;
1026
1027   offer.reset(f1_.CreateOffer(offer_opts, NULL));
1028   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1029   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1030   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1031   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1032   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1033   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1034   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1035   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1036   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1037   EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1038   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1039   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1040   EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1041
1042   offer_opts.rtcp_mux_enabled = false;
1043   answer_opts.rtcp_mux_enabled = true;
1044
1045   offer.reset(f1_.CreateOffer(offer_opts, NULL));
1046   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1047   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1048   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1049   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1050   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1051   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1052   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1053   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1054   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1055   EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1056   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1057   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1058   EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1059
1060   offer_opts.rtcp_mux_enabled = false;
1061   answer_opts.rtcp_mux_enabled = false;
1062
1063   offer.reset(f1_.CreateOffer(offer_opts, NULL));
1064   answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
1065   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
1066   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
1067   ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
1068   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
1069   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
1070   ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
1071   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
1072   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
1073   EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
1074   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
1075   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
1076   EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
1077 }
1078
1079 // Create an audio-only answer to a video offer.
1080 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
1081   MediaSessionOptions opts;
1082   opts.has_video = true;
1083   rtc::scoped_ptr<SessionDescription>
1084       offer(f1_.CreateOffer(opts, NULL));
1085   ASSERT_TRUE(offer.get() != NULL);
1086   rtc::scoped_ptr<SessionDescription> answer(
1087       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1088   const ContentInfo* ac = answer->GetContentByName("audio");
1089   const ContentInfo* vc = answer->GetContentByName("video");
1090   ASSERT_TRUE(ac != NULL);
1091   ASSERT_TRUE(vc != NULL);
1092   ASSERT_TRUE(vc->description != NULL);
1093   EXPECT_TRUE(vc->rejected);
1094 }
1095
1096 // Create an audio-only answer to an offer with data.
1097 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
1098   MediaSessionOptions opts;
1099   opts.data_channel_type = cricket::DCT_RTP;
1100   rtc::scoped_ptr<SessionDescription>
1101       offer(f1_.CreateOffer(opts, NULL));
1102   ASSERT_TRUE(offer.get() != NULL);
1103   rtc::scoped_ptr<SessionDescription> answer(
1104       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1105   const ContentInfo* ac = answer->GetContentByName("audio");
1106   const ContentInfo* dc = answer->GetContentByName("data");
1107   ASSERT_TRUE(ac != NULL);
1108   ASSERT_TRUE(dc != NULL);
1109   ASSERT_TRUE(dc->description != NULL);
1110   EXPECT_TRUE(dc->rejected);
1111 }
1112
1113 // Create an answer that rejects the contents which are rejected in the offer.
1114 TEST_F(MediaSessionDescriptionFactoryTest,
1115        CreateAnswerToOfferWithRejectedMedia) {
1116   MediaSessionOptions opts;
1117   opts.has_video = true;
1118   opts.data_channel_type = cricket::DCT_RTP;
1119   rtc::scoped_ptr<SessionDescription>
1120       offer(f1_.CreateOffer(opts, NULL));
1121   ASSERT_TRUE(offer.get() != NULL);
1122   ContentInfo* ac = offer->GetContentByName("audio");
1123   ContentInfo* vc = offer->GetContentByName("video");
1124   ContentInfo* dc = offer->GetContentByName("data");
1125   ASSERT_TRUE(ac != NULL);
1126   ASSERT_TRUE(vc != NULL);
1127   ASSERT_TRUE(dc != NULL);
1128   ac->rejected = true;
1129   vc->rejected = true;
1130   dc->rejected = true;
1131   rtc::scoped_ptr<SessionDescription> answer(
1132       f2_.CreateAnswer(offer.get(), opts, NULL));
1133   ac = answer->GetContentByName("audio");
1134   vc = answer->GetContentByName("video");
1135   dc = answer->GetContentByName("data");
1136   ASSERT_TRUE(ac != NULL);
1137   ASSERT_TRUE(vc != NULL);
1138   ASSERT_TRUE(dc != NULL);
1139   EXPECT_TRUE(ac->rejected);
1140   EXPECT_TRUE(vc->rejected);
1141   EXPECT_TRUE(dc->rejected);
1142 }
1143
1144 // Create an audio and video offer with:
1145 // - one video track
1146 // - two audio tracks
1147 // - two data tracks
1148 // and ensure it matches what we expect. Also updates the initial offer by
1149 // adding a new video track and replaces one of the audio tracks.
1150 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
1151   MediaSessionOptions opts;
1152   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1153   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1154   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
1155   opts.data_channel_type = cricket::DCT_RTP;
1156   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1157   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
1158
1159   f1_.set_secure(SEC_ENABLED);
1160   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1161
1162   ASSERT_TRUE(offer.get() != NULL);
1163   const ContentInfo* ac = offer->GetContentByName("audio");
1164   const ContentInfo* vc = offer->GetContentByName("video");
1165   const ContentInfo* dc = offer->GetContentByName("data");
1166   ASSERT_TRUE(ac != NULL);
1167   ASSERT_TRUE(vc != NULL);
1168   ASSERT_TRUE(dc != NULL);
1169   const AudioContentDescription* acd =
1170       static_cast<const AudioContentDescription*>(ac->description);
1171   const VideoContentDescription* vcd =
1172       static_cast<const VideoContentDescription*>(vc->description);
1173   const DataContentDescription* dcd =
1174       static_cast<const DataContentDescription*>(dc->description);
1175   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1176   EXPECT_EQ(f1_.audio_codecs(), acd->codecs());
1177
1178   const StreamParamsVec& audio_streams = acd->streams();
1179   ASSERT_EQ(2U, audio_streams.size());
1180   EXPECT_EQ(audio_streams[0].cname , audio_streams[1].cname);
1181   EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1182   ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1183   EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1184   EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1185   ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1186   EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1187
1188   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
1189   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
1190   ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1191
1192   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1193   EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
1194   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1195
1196   const StreamParamsVec& video_streams = vcd->streams();
1197   ASSERT_EQ(1U, video_streams.size());
1198   EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1199   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1200   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
1201   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
1202
1203   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1204   EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
1205   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1206
1207   const StreamParamsVec& data_streams = dcd->streams();
1208   ASSERT_EQ(2U, data_streams.size());
1209   EXPECT_EQ(data_streams[0].cname , data_streams[1].cname);
1210   EXPECT_EQ(kDataTrack1, data_streams[0].id);
1211   ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1212   EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1213   EXPECT_EQ(kDataTrack2, data_streams[1].id);
1214   ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1215   EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1216
1217   EXPECT_EQ(cricket::kDataMaxBandwidth,
1218             dcd->bandwidth());                  // default bandwidth (auto)
1219   EXPECT_TRUE(dcd->rtcp_mux());                 // rtcp-mux defaults on
1220   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1221
1222
1223   // Update the offer. Add a new video track that is not synched to the
1224   // other tracks and replace audio track 2 with audio track 3.
1225   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1226   opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1227   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
1228   opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
1229   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
1230   rtc::scoped_ptr<SessionDescription>
1231       updated_offer(f1_.CreateOffer(opts, offer.get()));
1232
1233   ASSERT_TRUE(updated_offer.get() != NULL);
1234   ac = updated_offer->GetContentByName("audio");
1235   vc = updated_offer->GetContentByName("video");
1236   dc = updated_offer->GetContentByName("data");
1237   ASSERT_TRUE(ac != NULL);
1238   ASSERT_TRUE(vc != NULL);
1239   ASSERT_TRUE(dc != NULL);
1240   const AudioContentDescription* updated_acd =
1241       static_cast<const AudioContentDescription*>(ac->description);
1242   const VideoContentDescription* updated_vcd =
1243       static_cast<const VideoContentDescription*>(vc->description);
1244   const DataContentDescription* updated_dcd =
1245       static_cast<const DataContentDescription*>(dc->description);
1246
1247   EXPECT_EQ(acd->type(), updated_acd->type());
1248   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1249   EXPECT_EQ(vcd->type(), updated_vcd->type());
1250   EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1251   EXPECT_EQ(dcd->type(), updated_dcd->type());
1252   EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1253   ASSERT_CRYPTO(updated_acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
1254   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1255   ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1256   EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1257   ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1258   EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1259
1260   const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1261   ASSERT_EQ(2U, updated_audio_streams.size());
1262   EXPECT_EQ(audio_streams[0], updated_audio_streams[0]);
1263   EXPECT_EQ(kAudioTrack3, updated_audio_streams[1].id);  // New audio track.
1264   ASSERT_EQ(1U, updated_audio_streams[1].ssrcs.size());
1265   EXPECT_NE(0U, updated_audio_streams[1].ssrcs[0]);
1266   EXPECT_EQ(updated_audio_streams[0].cname, updated_audio_streams[1].cname);
1267
1268   const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1269   ASSERT_EQ(2U, updated_video_streams.size());
1270   EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1271   EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1272   EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1273
1274   const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1275   ASSERT_EQ(2U, updated_data_streams.size());
1276   EXPECT_EQ(data_streams[0], updated_data_streams[0]);
1277   EXPECT_EQ(kDataTrack3, updated_data_streams[1].id);  // New data track.
1278   ASSERT_EQ(1U, updated_data_streams[1].ssrcs.size());
1279   EXPECT_NE(0U, updated_data_streams[1].ssrcs[0]);
1280   EXPECT_EQ(updated_data_streams[0].cname, updated_data_streams[1].cname);
1281 }
1282
1283 // Create an offer with simulcast video stream.
1284 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
1285   MediaSessionOptions opts;
1286   const int num_sim_layers = 3;
1287   opts.AddVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
1288   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1289
1290   ASSERT_TRUE(offer.get() != NULL);
1291   const ContentInfo* vc = offer->GetContentByName("video");
1292   ASSERT_TRUE(vc != NULL);
1293   const VideoContentDescription* vcd =
1294       static_cast<const VideoContentDescription*>(vc->description);
1295
1296   const StreamParamsVec& video_streams = vcd->streams();
1297   ASSERT_EQ(1U, video_streams.size());
1298   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1299   const SsrcGroup* sim_ssrc_group =
1300       video_streams[0].get_ssrc_group(cricket::kSimSsrcGroupSemantics);
1301   ASSERT_TRUE(sim_ssrc_group != NULL);
1302   EXPECT_EQ(static_cast<size_t>(num_sim_layers), sim_ssrc_group->ssrcs.size());
1303 }
1304
1305 // Create an audio and video answer to a standard video offer with:
1306 // - one video track
1307 // - two audio tracks
1308 // - two data tracks
1309 // and ensure it matches what we expect. Also updates the initial answer by
1310 // adding a new video track and removes one of the audio tracks.
1311 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
1312   MediaSessionOptions offer_opts;
1313   offer_opts.has_video = true;
1314   offer_opts.data_channel_type = cricket::DCT_RTP;
1315   f1_.set_secure(SEC_ENABLED);
1316   f2_.set_secure(SEC_ENABLED);
1317   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
1318                                                                   NULL));
1319
1320   MediaSessionOptions opts;
1321   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
1322   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
1323   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
1324   opts.data_channel_type = cricket::DCT_RTP;
1325   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
1326   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
1327
1328   rtc::scoped_ptr<SessionDescription>
1329       answer(f2_.CreateAnswer(offer.get(), opts, NULL));
1330
1331   ASSERT_TRUE(answer.get() != NULL);
1332   const ContentInfo* ac = answer->GetContentByName("audio");
1333   const ContentInfo* vc = answer->GetContentByName("video");
1334   const ContentInfo* dc = answer->GetContentByName("data");
1335   ASSERT_TRUE(ac != NULL);
1336   ASSERT_TRUE(vc != NULL);
1337   ASSERT_TRUE(dc != NULL);
1338   const AudioContentDescription* acd =
1339       static_cast<const AudioContentDescription*>(ac->description);
1340   const VideoContentDescription* vcd =
1341       static_cast<const VideoContentDescription*>(vc->description);
1342   const DataContentDescription* dcd =
1343       static_cast<const DataContentDescription*>(dc->description);
1344   ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1345   ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1346   ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1347
1348   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
1349   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1350
1351   const StreamParamsVec& audio_streams = acd->streams();
1352   ASSERT_EQ(2U, audio_streams.size());
1353   EXPECT_TRUE(audio_streams[0].cname ==  audio_streams[1].cname);
1354   EXPECT_EQ(kAudioTrack1, audio_streams[0].id);
1355   ASSERT_EQ(1U, audio_streams[0].ssrcs.size());
1356   EXPECT_NE(0U, audio_streams[0].ssrcs[0]);
1357   EXPECT_EQ(kAudioTrack2, audio_streams[1].id);
1358   ASSERT_EQ(1U, audio_streams[1].ssrcs.size());
1359   EXPECT_NE(0U, audio_streams[1].ssrcs[0]);
1360
1361   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // default bandwidth (auto)
1362   EXPECT_TRUE(acd->rtcp_mux());                 // rtcp-mux defaults on
1363
1364   EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
1365   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1366
1367   const StreamParamsVec& video_streams = vcd->streams();
1368   ASSERT_EQ(1U, video_streams.size());
1369   EXPECT_EQ(video_streams[0].cname, audio_streams[0].cname);
1370   EXPECT_EQ(kVideoTrack1, video_streams[0].id);
1371   EXPECT_EQ(kAutoBandwidth, vcd->bandwidth());  // default bandwidth (auto)
1372   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
1373
1374   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
1375   EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
1376
1377   const StreamParamsVec& data_streams = dcd->streams();
1378   ASSERT_EQ(2U, data_streams.size());
1379   EXPECT_TRUE(data_streams[0].cname ==  data_streams[1].cname);
1380   EXPECT_EQ(kDataTrack1, data_streams[0].id);
1381   ASSERT_EQ(1U, data_streams[0].ssrcs.size());
1382   EXPECT_NE(0U, data_streams[0].ssrcs[0]);
1383   EXPECT_EQ(kDataTrack2, data_streams[1].id);
1384   ASSERT_EQ(1U, data_streams[1].ssrcs.size());
1385   EXPECT_NE(0U, data_streams[1].ssrcs[0]);
1386
1387   EXPECT_EQ(cricket::kDataMaxBandwidth,
1388             dcd->bandwidth());                  // default bandwidth (auto)
1389   EXPECT_TRUE(dcd->rtcp_mux());                 // rtcp-mux defaults on
1390
1391   // Update the answer. Add a new video track that is not synched to the
1392   // other traacks and remove 1 audio track.
1393   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
1394   opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
1395   opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
1396   rtc::scoped_ptr<SessionDescription>
1397       updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
1398
1399   ASSERT_TRUE(updated_answer.get() != NULL);
1400   ac = updated_answer->GetContentByName("audio");
1401   vc = updated_answer->GetContentByName("video");
1402   dc = updated_answer->GetContentByName("data");
1403   ASSERT_TRUE(ac != NULL);
1404   ASSERT_TRUE(vc != NULL);
1405   ASSERT_TRUE(dc != NULL);
1406   const AudioContentDescription* updated_acd =
1407       static_cast<const AudioContentDescription*>(ac->description);
1408   const VideoContentDescription* updated_vcd =
1409       static_cast<const VideoContentDescription*>(vc->description);
1410   const DataContentDescription* updated_dcd =
1411       static_cast<const DataContentDescription*>(dc->description);
1412
1413   ASSERT_CRYPTO(updated_acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
1414   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
1415   ASSERT_CRYPTO(updated_vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1416   EXPECT_TRUE(CompareCryptoParams(vcd->cryptos(), updated_vcd->cryptos()));
1417   ASSERT_CRYPTO(updated_dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
1418   EXPECT_TRUE(CompareCryptoParams(dcd->cryptos(), updated_dcd->cryptos()));
1419
1420   EXPECT_EQ(acd->type(), updated_acd->type());
1421   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
1422   EXPECT_EQ(vcd->type(), updated_vcd->type());
1423   EXPECT_EQ(vcd->codecs(), updated_vcd->codecs());
1424   EXPECT_EQ(dcd->type(), updated_dcd->type());
1425   EXPECT_EQ(dcd->codecs(), updated_dcd->codecs());
1426
1427   const StreamParamsVec& updated_audio_streams = updated_acd->streams();
1428   ASSERT_EQ(1U, updated_audio_streams.size());
1429   EXPECT_TRUE(audio_streams[0] ==  updated_audio_streams[0]);
1430
1431   const StreamParamsVec& updated_video_streams = updated_vcd->streams();
1432   ASSERT_EQ(2U, updated_video_streams.size());
1433   EXPECT_EQ(video_streams[0], updated_video_streams[0]);
1434   EXPECT_EQ(kVideoTrack2, updated_video_streams[1].id);
1435   EXPECT_NE(updated_video_streams[1].cname, updated_video_streams[0].cname);
1436
1437   const StreamParamsVec& updated_data_streams = updated_dcd->streams();
1438   ASSERT_EQ(1U, updated_data_streams.size());
1439   EXPECT_TRUE(data_streams[0] == updated_data_streams[0]);
1440 }
1441
1442
1443 // Create an updated offer after creating an answer to the original offer and
1444 // verify that the codecs that were part of the original answer are not changed
1445 // in the updated offer.
1446 TEST_F(MediaSessionDescriptionFactoryTest,
1447        RespondentCreatesOfferAfterCreatingAnswer) {
1448   MediaSessionOptions opts;
1449   opts.has_audio = true;
1450   opts.has_video = true;
1451
1452   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1453   rtc::scoped_ptr<SessionDescription> answer(
1454       f2_.CreateAnswer(offer.get(), opts, NULL));
1455
1456   const AudioContentDescription* acd =
1457       GetFirstAudioContentDescription(answer.get());
1458   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1459
1460   const VideoContentDescription* vcd =
1461       GetFirstVideoContentDescription(answer.get());
1462   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
1463
1464   rtc::scoped_ptr<SessionDescription> updated_offer(
1465       f2_.CreateOffer(opts, answer.get()));
1466
1467   // The expected audio codecs are the common audio codecs from the first
1468   // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
1469   // preference order.
1470   // TODO(wu): |updated_offer| should not include the codec
1471   // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
1472   const AudioCodec kUpdatedAudioCodecOffer[] = {
1473     kAudioCodecsAnswer[0],
1474     kAudioCodecsAnswer[1],
1475     kAudioCodecs2[0],
1476   };
1477
1478   // The expected video codecs are the common video codecs from the first
1479   // offer/answer exchange plus the video codecs only |f2_| offer, sorted in
1480   // preference order.
1481   const VideoCodec kUpdatedVideoCodecOffer[] = {
1482     kVideoCodecsAnswer[0],
1483     kVideoCodecs2[1],
1484   };
1485
1486   const AudioContentDescription* updated_acd =
1487       GetFirstAudioContentDescription(updated_offer.get());
1488   EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioCodecOffer), updated_acd->codecs());
1489
1490   const VideoContentDescription* updated_vcd =
1491       GetFirstVideoContentDescription(updated_offer.get());
1492   EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoCodecOffer), updated_vcd->codecs());
1493 }
1494
1495 // Create an updated offer after creating an answer to the original offer and
1496 // verify that the codecs that were part of the original answer are not changed
1497 // in the updated offer. In this test Rtx is enabled.
1498 TEST_F(MediaSessionDescriptionFactoryTest,
1499        RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
1500   MediaSessionOptions opts;
1501   opts.has_video = true;
1502   opts.has_audio = false;
1503   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1504   VideoCodec rtx_f1;
1505   rtx_f1.id = 126;
1506   rtx_f1.name = cricket::kRtxCodecName;
1507
1508   // This creates rtx for H264 with the payload type |f1_| uses.
1509   rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
1510       rtc::ToString<int>(kVideoCodecs1[1].id);
1511   f1_codecs.push_back(rtx_f1);
1512   f1_.set_video_codecs(f1_codecs);
1513
1514   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1515   VideoCodec rtx_f2;
1516   rtx_f2.id = 127;
1517   rtx_f2.name = cricket::kRtxCodecName;
1518
1519   // This creates rtx for H264 with the payload type |f2_| uses.
1520   rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
1521       rtc::ToString<int>(kVideoCodecs2[0].id);
1522   f2_codecs.push_back(rtx_f2);
1523   f2_.set_video_codecs(f2_codecs);
1524
1525   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1526   ASSERT_TRUE(offer.get() != NULL);
1527   rtc::scoped_ptr<SessionDescription> answer(
1528       f2_.CreateAnswer(offer.get(), opts, NULL));
1529
1530   const VideoContentDescription* vcd =
1531       GetFirstVideoContentDescription(answer.get());
1532
1533   std::vector<VideoCodec> expected_codecs = MAKE_VECTOR(kVideoCodecsAnswer);
1534   expected_codecs.push_back(rtx_f1);
1535
1536   EXPECT_EQ(expected_codecs, vcd->codecs());
1537
1538   // Now, make sure we get same result, except for the preference order,
1539   // if |f2_| creates an updated offer even though the default payload types
1540   // are different from |f1_|.
1541   expected_codecs[0].preference = f1_codecs[1].preference;
1542
1543   rtc::scoped_ptr<SessionDescription> updated_offer(
1544       f2_.CreateOffer(opts, answer.get()));
1545   ASSERT_TRUE(updated_offer);
1546   rtc::scoped_ptr<SessionDescription> updated_answer(
1547       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1548
1549   const VideoContentDescription* updated_vcd =
1550       GetFirstVideoContentDescription(updated_answer.get());
1551
1552   EXPECT_EQ(expected_codecs, updated_vcd->codecs());
1553 }
1554
1555 // Create an updated offer that adds video after creating an audio only answer
1556 // to the original offer. This test verifies that if a video codec and the RTX
1557 // codec have the same default payload type as an audio codec that is already in
1558 // use, the added codecs payload types are changed.
1559 TEST_F(MediaSessionDescriptionFactoryTest,
1560        RespondentCreatesOfferWithVideoAndRtxAfterCreatingAudioAnswer) {
1561   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1562   VideoCodec rtx_f1;
1563   rtx_f1.id = 126;
1564   rtx_f1.name = cricket::kRtxCodecName;
1565
1566   // This creates rtx for H264 with the payload type |f1_| uses.
1567   rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
1568       rtc::ToString<int>(kVideoCodecs1[1].id);
1569   f1_codecs.push_back(rtx_f1);
1570   f1_.set_video_codecs(f1_codecs);
1571
1572   MediaSessionOptions opts;
1573   opts.has_audio = true;
1574   opts.has_video = false;
1575
1576   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1577   rtc::scoped_ptr<SessionDescription> answer(
1578       f2_.CreateAnswer(offer.get(), opts, NULL));
1579
1580   const AudioContentDescription* acd =
1581       GetFirstAudioContentDescription(answer.get());
1582   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
1583
1584   // Now - let |f2_| add video with RTX and let the payload type the RTX codec
1585   // reference  be the same as an audio codec that was negotiated in the
1586   // first offer/answer exchange.
1587   opts.has_audio = true;
1588   opts.has_video = true;
1589
1590   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1591   int used_pl_type = acd->codecs()[0].id;
1592   f2_codecs[0].id = used_pl_type;  // Set the payload type for H264.
1593   VideoCodec rtx_f2;
1594   rtx_f2.id = 127;
1595   rtx_f2.name = cricket::kRtxCodecName;
1596   rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
1597       rtc::ToString<int>(used_pl_type);
1598   f2_codecs.push_back(rtx_f2);
1599   f2_.set_video_codecs(f2_codecs);
1600
1601   rtc::scoped_ptr<SessionDescription> updated_offer(
1602       f2_.CreateOffer(opts, answer.get()));
1603   ASSERT_TRUE(updated_offer);
1604   rtc::scoped_ptr<SessionDescription> updated_answer(
1605       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
1606
1607   const AudioContentDescription* updated_acd =
1608       GetFirstAudioContentDescription(answer.get());
1609   EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), updated_acd->codecs());
1610
1611   const VideoContentDescription* updated_vcd =
1612       GetFirstVideoContentDescription(updated_answer.get());
1613
1614   ASSERT_EQ("H264", updated_vcd->codecs()[0].name);
1615   ASSERT_EQ(std::string(cricket::kRtxCodecName), updated_vcd->codecs()[1].name);
1616   int new_h264_pl_type =  updated_vcd->codecs()[0].id;
1617   EXPECT_NE(used_pl_type, new_h264_pl_type);
1618   VideoCodec rtx = updated_vcd->codecs()[1];
1619   int pt_referenced_by_rtx = rtc::FromString<int>(
1620       rtx.params[cricket::kCodecParamAssociatedPayloadType]);
1621   EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
1622 }
1623
1624 // Test that RTX is ignored when there is no associated payload type parameter.
1625 TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
1626   MediaSessionOptions opts;
1627   opts.has_video = true;
1628   opts.has_audio = false;
1629   std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
1630   VideoCodec rtx_f1;
1631   rtx_f1.id = 126;
1632   rtx_f1.name = cricket::kRtxCodecName;
1633
1634   f1_codecs.push_back(rtx_f1);
1635   f1_.set_video_codecs(f1_codecs);
1636
1637   std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
1638   VideoCodec rtx_f2;
1639   rtx_f2.id = 127;
1640   rtx_f2.name = cricket::kRtxCodecName;
1641
1642   // This creates rtx for H264 with the payload type |f2_| uses.
1643   rtx_f2.SetParam(cricket::kCodecParamAssociatedPayloadType,
1644                   rtc::ToString<int>(kVideoCodecs2[0].id));
1645   f2_codecs.push_back(rtx_f2);
1646   f2_.set_video_codecs(f2_codecs);
1647
1648   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1649   ASSERT_TRUE(offer.get() != NULL);
1650   // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
1651   // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
1652   // is possible to test that that RTX is dropped when
1653   // kCodecParamAssociatedPayloadType is missing in the offer.
1654   VideoContentDescription* desc =
1655       static_cast<cricket::VideoContentDescription*>(
1656           offer->GetContentDescriptionByName(cricket::CN_VIDEO));
1657   ASSERT_TRUE(desc != NULL);
1658   std::vector<VideoCodec> codecs = desc->codecs();
1659   for (std::vector<VideoCodec>::iterator iter = codecs.begin();
1660        iter != codecs.end(); ++iter) {
1661     if (iter->name.find(cricket::kRtxCodecName) == 0) {
1662       iter->params.clear();
1663     }
1664   }
1665   desc->set_codecs(codecs);
1666
1667   rtc::scoped_ptr<SessionDescription> answer(
1668       f2_.CreateAnswer(offer.get(), opts, NULL));
1669
1670   const VideoContentDescription* vcd =
1671       GetFirstVideoContentDescription(answer.get());
1672
1673   for (std::vector<VideoCodec>::const_iterator iter = vcd->codecs().begin();
1674        iter != vcd->codecs().end(); ++iter) {
1675     ASSERT_STRNE(iter->name.c_str(), cricket::kRtxCodecName);
1676   }
1677 }
1678
1679 // Create an updated offer after creating an answer to the original offer and
1680 // verify that the RTP header extensions that were part of the original answer
1681 // are not changed in the updated offer.
1682 TEST_F(MediaSessionDescriptionFactoryTest,
1683        RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
1684   MediaSessionOptions opts;
1685   opts.has_audio = true;
1686   opts.has_video = true;
1687
1688   f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
1689   f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
1690   f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
1691   f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
1692
1693   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
1694   rtc::scoped_ptr<SessionDescription> answer(
1695       f2_.CreateAnswer(offer.get(), opts, NULL));
1696
1697   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
1698             GetFirstAudioContentDescription(
1699                 answer.get())->rtp_header_extensions());
1700   EXPECT_EQ(MAKE_VECTOR(kVideoRtpExtensionAnswer),
1701             GetFirstVideoContentDescription(
1702                 answer.get())->rtp_header_extensions());
1703
1704   rtc::scoped_ptr<SessionDescription> updated_offer(
1705       f2_.CreateOffer(opts, answer.get()));
1706
1707   // The expected RTP header extensions in the new offer are the resulting
1708   // extensions from the first offer/answer exchange plus the extensions only
1709   // |f2_| offer.
1710   // Since the default local extension id |f2_| uses has already been used by
1711   // |f1_| for another extensions, it is changed to 13.
1712   const RtpHeaderExtension kUpdatedAudioRtpExtensions[] = {
1713     kAudioRtpExtensionAnswer[0],
1714     RtpHeaderExtension(kAudioRtpExtension2[1].uri, 13),
1715     kAudioRtpExtension2[2],
1716   };
1717
1718   // Since the default local extension id |f2_| uses has already been used by
1719   // |f1_| for another extensions, is is changed to 12.
1720   const RtpHeaderExtension kUpdatedVideoRtpExtensions[] = {
1721     kVideoRtpExtensionAnswer[0],
1722     RtpHeaderExtension(kVideoRtpExtension2[1].uri, 12),
1723     kVideoRtpExtension2[2],
1724   };
1725
1726   const AudioContentDescription* updated_acd =
1727       GetFirstAudioContentDescription(updated_offer.get());
1728   EXPECT_EQ(MAKE_VECTOR(kUpdatedAudioRtpExtensions),
1729             updated_acd->rtp_header_extensions());
1730
1731   const VideoContentDescription* updated_vcd =
1732       GetFirstVideoContentDescription(updated_offer.get());
1733   EXPECT_EQ(MAKE_VECTOR(kUpdatedVideoRtpExtensions),
1734             updated_vcd->rtp_header_extensions());
1735 }
1736
1737 TEST(MediaSessionDescription, CopySessionDescription) {
1738   SessionDescription source;
1739   cricket::ContentGroup group(cricket::CN_AUDIO);
1740   source.AddGroup(group);
1741   AudioContentDescription* acd(new AudioContentDescription());
1742   acd->set_codecs(MAKE_VECTOR(kAudioCodecs1));
1743   acd->AddLegacyStream(1);
1744   source.AddContent(cricket::CN_AUDIO, cricket::NS_JINGLE_RTP, acd);
1745   VideoContentDescription* vcd(new VideoContentDescription());
1746   vcd->set_codecs(MAKE_VECTOR(kVideoCodecs1));
1747   vcd->AddLegacyStream(2);
1748   source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
1749
1750   rtc::scoped_ptr<SessionDescription> copy(source.Copy());
1751   ASSERT_TRUE(copy.get() != NULL);
1752   EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
1753   const ContentInfo* ac = copy->GetContentByName("audio");
1754   const ContentInfo* vc = copy->GetContentByName("video");
1755   ASSERT_TRUE(ac != NULL);
1756   ASSERT_TRUE(vc != NULL);
1757   EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
1758   const AudioContentDescription* acd_copy =
1759       static_cast<const AudioContentDescription*>(ac->description);
1760   EXPECT_EQ(acd->codecs(), acd_copy->codecs());
1761   EXPECT_EQ(1u, acd->first_ssrc());
1762
1763   EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
1764   const VideoContentDescription* vcd_copy =
1765       static_cast<const VideoContentDescription*>(vc->description);
1766   EXPECT_EQ(vcd->codecs(), vcd_copy->codecs());
1767   EXPECT_EQ(2u, vcd->first_ssrc());
1768 }
1769
1770 // The below TestTransportInfoXXX tests create different offers/answers, and
1771 // ensure the TransportInfo in the SessionDescription matches what we expect.
1772 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
1773   MediaSessionOptions options;
1774   options.has_audio = true;
1775   TestTransportInfo(true, options, false);
1776 }
1777
1778 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
1779   MediaSessionOptions options;
1780   options.has_audio = true;
1781   TestTransportInfo(true, options, true);
1782 }
1783
1784 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
1785   MediaSessionOptions options;
1786   options.has_audio = true;
1787   options.has_video = true;
1788   options.data_channel_type = cricket::DCT_RTP;
1789   TestTransportInfo(true, options, false);
1790 }
1791
1792 TEST_F(MediaSessionDescriptionFactoryTest,
1793     TestTransportInfoOfferMultimediaCurrent) {
1794   MediaSessionOptions options;
1795   options.has_audio = true;
1796   options.has_video = true;
1797   options.data_channel_type = cricket::DCT_RTP;
1798   TestTransportInfo(true, options, true);
1799 }
1800
1801 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
1802   MediaSessionOptions options;
1803   options.has_audio = true;
1804   options.has_video = true;
1805   options.data_channel_type = cricket::DCT_RTP;
1806   options.bundle_enabled = true;
1807   TestTransportInfo(true, options, false);
1808 }
1809
1810 TEST_F(MediaSessionDescriptionFactoryTest,
1811        TestTransportInfoOfferBundleCurrent) {
1812   MediaSessionOptions options;
1813   options.has_audio = true;
1814   options.has_video = true;
1815   options.data_channel_type = cricket::DCT_RTP;
1816   options.bundle_enabled = true;
1817   TestTransportInfo(true, options, true);
1818 }
1819
1820 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
1821   MediaSessionOptions options;
1822   options.has_audio = true;
1823   TestTransportInfo(false, options, false);
1824 }
1825
1826 TEST_F(MediaSessionDescriptionFactoryTest,
1827     TestTransportInfoAnswerAudioCurrent) {
1828   MediaSessionOptions options;
1829   options.has_audio = true;
1830   TestTransportInfo(false, options, true);
1831 }
1832
1833 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
1834   MediaSessionOptions options;
1835   options.has_audio = true;
1836   options.has_video = true;
1837   options.data_channel_type = cricket::DCT_RTP;
1838   TestTransportInfo(false, options, false);
1839 }
1840
1841 TEST_F(MediaSessionDescriptionFactoryTest,
1842     TestTransportInfoAnswerMultimediaCurrent) {
1843   MediaSessionOptions options;
1844   options.has_audio = true;
1845   options.has_video = true;
1846   options.data_channel_type = cricket::DCT_RTP;
1847   TestTransportInfo(false, options, true);
1848 }
1849
1850 TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
1851   MediaSessionOptions options;
1852   options.has_audio = true;
1853   options.has_video = true;
1854   options.data_channel_type = cricket::DCT_RTP;
1855   options.bundle_enabled = true;
1856   TestTransportInfo(false, options, false);
1857 }
1858
1859 TEST_F(MediaSessionDescriptionFactoryTest,
1860     TestTransportInfoAnswerBundleCurrent) {
1861   MediaSessionOptions options;
1862   options.has_audio = true;
1863   options.has_video = true;
1864   options.data_channel_type = cricket::DCT_RTP;
1865   options.bundle_enabled = true;
1866   TestTransportInfo(false, options, true);
1867 }
1868
1869 // Create an offer with bundle enabled and verify the crypto parameters are
1870 // the common set of the available cryptos.
1871 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithOfferBundle) {
1872   TestCryptoWithBundle(true);
1873 }
1874
1875 // Create an answer with bundle enabled and verify the crypto parameters are
1876 // the common set of the available cryptos.
1877 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
1878   TestCryptoWithBundle(false);
1879 }
1880
1881 // Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
1882 // DTLS is not enabled locally.
1883 TEST_F(MediaSessionDescriptionFactoryTest,
1884        TestOfferDtlsSavpfWithoutDtlsFailed) {
1885   f1_.set_secure(SEC_ENABLED);
1886   f2_.set_secure(SEC_ENABLED);
1887   tdf1_.set_secure(SEC_DISABLED);
1888   tdf2_.set_secure(SEC_DISABLED);
1889
1890   rtc::scoped_ptr<SessionDescription> offer(
1891       f1_.CreateOffer(MediaSessionOptions(), NULL));
1892   ASSERT_TRUE(offer.get() != NULL);
1893   ContentInfo* offer_content = offer->GetContentByName("audio");
1894   ASSERT_TRUE(offer_content != NULL);
1895   AudioContentDescription* offer_audio_desc =
1896       static_cast<AudioContentDescription*>(offer_content->description);
1897   offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1898
1899   rtc::scoped_ptr<SessionDescription> answer(
1900       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1901   ASSERT_TRUE(answer != NULL);
1902   ContentInfo* answer_content = answer->GetContentByName("audio");
1903   ASSERT_TRUE(answer_content != NULL);
1904
1905   ASSERT_TRUE(answer_content->rejected);
1906 }
1907
1908 // Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
1909 // UDP/TLS/RTP/SAVPF.
1910 TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
1911   f1_.set_secure(SEC_ENABLED);
1912   f2_.set_secure(SEC_ENABLED);
1913   tdf1_.set_secure(SEC_ENABLED);
1914   tdf2_.set_secure(SEC_ENABLED);
1915
1916   rtc::scoped_ptr<SessionDescription> offer(
1917       f1_.CreateOffer(MediaSessionOptions(), NULL));
1918   ASSERT_TRUE(offer.get() != NULL);
1919   ContentInfo* offer_content = offer->GetContentByName("audio");
1920   ASSERT_TRUE(offer_content != NULL);
1921   AudioContentDescription* offer_audio_desc =
1922       static_cast<AudioContentDescription*>(offer_content->description);
1923   offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
1924
1925   rtc::scoped_ptr<SessionDescription> answer(
1926       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
1927   ASSERT_TRUE(answer != NULL);
1928
1929   const ContentInfo* answer_content = answer->GetContentByName("audio");
1930   ASSERT_TRUE(answer_content != NULL);
1931   ASSERT_FALSE(answer_content->rejected);
1932
1933   const AudioContentDescription* answer_audio_desc =
1934       static_cast<const AudioContentDescription*>(answer_content->description);
1935   EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
1936                         answer_audio_desc->protocol());
1937 }
1938
1939 // Test that we include both SDES and DTLS in the offer, but only include SDES
1940 // in the answer if DTLS isn't negotiated.
1941 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
1942   f1_.set_secure(SEC_ENABLED);
1943   f2_.set_secure(SEC_ENABLED);
1944   tdf1_.set_secure(SEC_ENABLED);
1945   tdf2_.set_secure(SEC_DISABLED);
1946   MediaSessionOptions options;
1947   options.has_audio = true;
1948   options.has_video = true;
1949   rtc::scoped_ptr<SessionDescription> offer, answer;
1950   const cricket::MediaContentDescription* audio_media_desc;
1951   const cricket::MediaContentDescription* video_media_desc;
1952   const cricket::TransportDescription* audio_trans_desc;
1953   const cricket::TransportDescription* video_trans_desc;
1954
1955   // Generate an offer with SDES and DTLS support.
1956   offer.reset(f1_.CreateOffer(options, NULL));
1957   ASSERT_TRUE(offer.get() != NULL);
1958
1959   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1960       offer->GetContentDescriptionByName("audio"));
1961   ASSERT_TRUE(audio_media_desc != NULL);
1962   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
1963       offer->GetContentDescriptionByName("video"));
1964   ASSERT_TRUE(video_media_desc != NULL);
1965   EXPECT_EQ(2u, audio_media_desc->cryptos().size());
1966   EXPECT_EQ(1u, video_media_desc->cryptos().size());
1967
1968   audio_trans_desc = offer->GetTransportDescriptionByName("audio");
1969   ASSERT_TRUE(audio_trans_desc != NULL);
1970   video_trans_desc = offer->GetTransportDescriptionByName("video");
1971   ASSERT_TRUE(video_trans_desc != NULL);
1972   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
1973   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
1974
1975   // Generate an answer with only SDES support, since tdf2 has crypto disabled.
1976   answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1977   ASSERT_TRUE(answer.get() != NULL);
1978
1979   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
1980       answer->GetContentDescriptionByName("audio"));
1981   ASSERT_TRUE(audio_media_desc != NULL);
1982   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
1983       answer->GetContentDescriptionByName("video"));
1984   ASSERT_TRUE(video_media_desc != NULL);
1985   EXPECT_EQ(1u, audio_media_desc->cryptos().size());
1986   EXPECT_EQ(1u, video_media_desc->cryptos().size());
1987
1988   audio_trans_desc = answer->GetTransportDescriptionByName("audio");
1989   ASSERT_TRUE(audio_trans_desc != NULL);
1990   video_trans_desc = answer->GetTransportDescriptionByName("video");
1991   ASSERT_TRUE(video_trans_desc != NULL);
1992   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() == NULL);
1993   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() == NULL);
1994
1995   // Enable DTLS; the answer should now only have DTLS support.
1996   tdf2_.set_secure(SEC_ENABLED);
1997   answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
1998   ASSERT_TRUE(answer.get() != NULL);
1999
2000   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2001       answer->GetContentDescriptionByName("audio"));
2002   ASSERT_TRUE(audio_media_desc != NULL);
2003   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2004       answer->GetContentDescriptionByName("video"));
2005   ASSERT_TRUE(video_media_desc != NULL);
2006   EXPECT_TRUE(audio_media_desc->cryptos().empty());
2007   EXPECT_TRUE(video_media_desc->cryptos().empty());
2008   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2009             audio_media_desc->protocol());
2010   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf),
2011             video_media_desc->protocol());
2012
2013   audio_trans_desc = answer->GetTransportDescriptionByName("audio");
2014   ASSERT_TRUE(audio_trans_desc != NULL);
2015   video_trans_desc = answer->GetTransportDescriptionByName("video");
2016   ASSERT_TRUE(video_trans_desc != NULL);
2017   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2018   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2019
2020   // Try creating offer again. DTLS enabled now, crypto's should be empty
2021   // in new offer.
2022   offer.reset(f1_.CreateOffer(options, offer.get()));
2023   ASSERT_TRUE(offer.get() != NULL);
2024   audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
2025       offer->GetContentDescriptionByName("audio"));
2026   ASSERT_TRUE(audio_media_desc != NULL);
2027   video_media_desc = static_cast<const cricket::MediaContentDescription*>(
2028       offer->GetContentDescriptionByName("video"));
2029   ASSERT_TRUE(video_media_desc != NULL);
2030   EXPECT_TRUE(audio_media_desc->cryptos().empty());
2031   EXPECT_TRUE(video_media_desc->cryptos().empty());
2032
2033   audio_trans_desc = offer->GetTransportDescriptionByName("audio");
2034   ASSERT_TRUE(audio_trans_desc != NULL);
2035   video_trans_desc = offer->GetTransportDescriptionByName("video");
2036   ASSERT_TRUE(video_trans_desc != NULL);
2037   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
2038   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
2039 }
2040
2041 // Test that an answer can't be created if cryptos are required but the offer is
2042 // unsecure.
2043 TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
2044   MediaSessionOptions options;
2045   f1_.set_secure(SEC_DISABLED);
2046   tdf1_.set_secure(SEC_DISABLED);
2047   f2_.set_secure(SEC_REQUIRED);
2048   tdf1_.set_secure(SEC_ENABLED);
2049
2050   rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
2051                                                                   NULL));
2052   ASSERT_TRUE(offer.get() != NULL);
2053   rtc::scoped_ptr<SessionDescription> answer(
2054       f2_.CreateAnswer(offer.get(), options, NULL));
2055   EXPECT_TRUE(answer.get() == NULL);
2056 }
2057
2058 // Test that we accept a DTLS offer without SDES and create an appropriate
2059 // answer.
2060 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
2061   f1_.set_secure(SEC_DISABLED);
2062   f2_.set_secure(SEC_ENABLED);
2063   tdf1_.set_secure(SEC_ENABLED);
2064   tdf2_.set_secure(SEC_ENABLED);
2065   MediaSessionOptions options;
2066   options.has_audio = true;
2067   options.has_video = true;
2068   options.data_channel_type = cricket::DCT_RTP;
2069
2070   rtc::scoped_ptr<SessionDescription> offer, answer;
2071
2072   // Generate an offer with DTLS but without SDES.
2073   offer.reset(f1_.CreateOffer(options, NULL));
2074   ASSERT_TRUE(offer.get() != NULL);
2075
2076   const AudioContentDescription* audio_offer =
2077       GetFirstAudioContentDescription(offer.get());
2078   ASSERT_TRUE(audio_offer->cryptos().empty());
2079   const VideoContentDescription* video_offer =
2080       GetFirstVideoContentDescription(offer.get());
2081   ASSERT_TRUE(video_offer->cryptos().empty());
2082   const DataContentDescription* data_offer =
2083       GetFirstDataContentDescription(offer.get());
2084   ASSERT_TRUE(data_offer->cryptos().empty());
2085
2086   const cricket::TransportDescription* audio_offer_trans_desc =
2087       offer->GetTransportDescriptionByName("audio");
2088   ASSERT_TRUE(audio_offer_trans_desc->identity_fingerprint.get() != NULL);
2089   const cricket::TransportDescription* video_offer_trans_desc =
2090       offer->GetTransportDescriptionByName("video");
2091   ASSERT_TRUE(video_offer_trans_desc->identity_fingerprint.get() != NULL);
2092   const cricket::TransportDescription* data_offer_trans_desc =
2093       offer->GetTransportDescriptionByName("data");
2094   ASSERT_TRUE(data_offer_trans_desc->identity_fingerprint.get() != NULL);
2095
2096   // Generate an answer with DTLS.
2097   answer.reset(f2_.CreateAnswer(offer.get(), options, NULL));
2098   ASSERT_TRUE(answer.get() != NULL);
2099
2100   const cricket::TransportDescription* audio_answer_trans_desc =
2101       answer->GetTransportDescriptionByName("audio");
2102   EXPECT_TRUE(audio_answer_trans_desc->identity_fingerprint.get() != NULL);
2103   const cricket::TransportDescription* video_answer_trans_desc =
2104       answer->GetTransportDescriptionByName("video");
2105   EXPECT_TRUE(video_answer_trans_desc->identity_fingerprint.get() != NULL);
2106   const cricket::TransportDescription* data_answer_trans_desc =
2107       answer->GetTransportDescriptionByName("data");
2108   EXPECT_TRUE(data_answer_trans_desc->identity_fingerprint.get() != NULL);
2109 }
2110
2111 // Verifies if vad_enabled option is set to false, CN codecs are not present in
2112 // offer or answer.
2113 TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
2114   MediaSessionOptions options;
2115   options.has_audio = true;
2116   options.has_video = true;
2117   rtc::scoped_ptr<SessionDescription> offer(
2118       f1_.CreateOffer(options, NULL));
2119   ASSERT_TRUE(offer.get() != NULL);
2120   const ContentInfo* audio_content = offer->GetContentByName("audio");
2121   EXPECT_FALSE(VerifyNoCNCodecs(audio_content));
2122
2123   options.vad_enabled = false;
2124   offer.reset(f1_.CreateOffer(options, NULL));
2125   ASSERT_TRUE(offer.get() != NULL);
2126   audio_content = offer->GetContentByName("audio");
2127   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2128   rtc::scoped_ptr<SessionDescription> answer(
2129       f1_.CreateAnswer(offer.get(), options, NULL));
2130   ASSERT_TRUE(answer.get() != NULL);
2131   audio_content = answer->GetContentByName("audio");
2132   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
2133 }