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