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