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