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