Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / session / media / mediasession_unittest.cc
index ad7cc13..2d2e2c8 100644 (file)
@@ -28,9 +28,6 @@
 #include <string>
 #include <vector>
 
-#include "talk/base/gunit.h"
-#include "talk/base/fakesslidentity.h"
-#include "talk/base/messagedigest.h"
 #include "talk/media/base/codec.h"
 #include "talk/media/base/testutils.h"
 #include "talk/p2p/base/constants.h"
 #include "talk/p2p/base/transportinfo.h"
 #include "talk/session/media/mediasession.h"
 #include "talk/session/media/srtpfilter.h"
+#include "webrtc/base/fakesslidentity.h"
+#include "webrtc/base/gunit.h"
+#include "webrtc/base/messagedigest.h"
+#include "webrtc/base/ssladapter.h"
 
 #ifdef HAVE_SRTP
 #define ASSERT_CRYPTO(cd, s, cs) \
@@ -97,13 +98,13 @@ static const AudioCodec kAudioCodecs1[] = {
 
 static const AudioCodec kAudioCodecs2[] = {
   AudioCodec(126, "speex",  16000, 22000, 1, 3),
-  AudioCodec(127, "iLBC",   8000,  13300, 1, 2),
-  AudioCodec(0,   "PCMU",   8000,  64000, 1, 1),
+  AudioCodec(0,   "PCMU",   8000,  64000, 1, 2),
+  AudioCodec(127, "iLBC",   8000,  13300, 1, 1),
 };
 
 static const AudioCodec kAudioCodecsAnswer[] = {
-  AudioCodec(102, "iLBC",   8000,  13300, 1, 2),
-  AudioCodec(0,   "PCMU",   8000,  64000, 1, 1),
+  AudioCodec(102, "iLBC",   8000,  13300, 1, 5),
+  AudioCodec(0,   "PCMU",   8000,  64000, 1, 4),
 };
 
 static const VideoCodec kVideoCodecs1[] = {
@@ -117,7 +118,7 @@ static const VideoCodec kVideoCodecs2[] = {
 };
 
 static const VideoCodec kVideoCodecsAnswer[] = {
-  VideoCodec(97, "H264", 320, 200, 30, 2)
+  VideoCodec(97, "H264", 320, 200, 30, 1)
 };
 
 static const DataCodec kDataCodecs1[] = {
@@ -182,6 +183,13 @@ static const char kDataTrack1[] = "data_1";
 static const char kDataTrack2[] = "data_2";
 static const char kDataTrack3[] = "data_3";
 
+static bool IsMediaContentOfType(const ContentInfo* content,
+                                 MediaType media_type) {
+  const MediaContentDescription* mdesc =
+      static_cast<const MediaContentDescription*>(content->description);
+  return mdesc && mdesc->type() == media_type;
+}
+
 class MediaSessionDescriptionFactoryTest : public testing::Test {
  public:
   MediaSessionDescriptionFactoryTest()
@@ -196,6 +204,14 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
     tdf2_.set_identity(&id2_);
   }
 
+  static void SetUpTestCase() {
+    rtc::InitializeSSL();
+  }
+
+  static void TearDownTestCase() {
+    rtc::CleanupSSL();
+  }
+
   // Create a video StreamParamsVec object with:
   // - one video stream with 3 simulcast streams and FEC,
   StreamParamsVec CreateComplexVideoStreamParamsVec() {
@@ -243,8 +259,8 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
     const std::string current_video_pwd = "current_video_pwd";
     const std::string current_data_ufrag = "current_data_ufrag";
     const std::string current_data_pwd = "current_data_pwd";
-    talk_base::scoped_ptr<SessionDescription> current_desc;
-    talk_base::scoped_ptr<SessionDescription> desc;
+    rtc::scoped_ptr<SessionDescription> current_desc;
+    rtc::scoped_ptr<SessionDescription> desc;
     if (has_current_desc) {
       current_desc.reset(new SessionDescription());
       EXPECT_TRUE(current_desc->AddTransportInfo(
@@ -266,7 +282,7 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
     if (offer) {
       desc.reset(f1_.CreateOffer(options, current_desc.get()));
     } else {
-      talk_base::scoped_ptr<SessionDescription> offer;
+      rtc::scoped_ptr<SessionDescription> offer;
       offer.reset(f1_.CreateOffer(options, NULL));
       desc.reset(f1_.CreateAnswer(offer.get(), options, current_desc.get()));
     }
@@ -339,8 +355,8 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
     options.has_audio = true;
     options.has_video = true;
     options.data_channel_type = cricket::DCT_RTP;
-    talk_base::scoped_ptr<SessionDescription> ref_desc;
-    talk_base::scoped_ptr<SessionDescription> desc;
+    rtc::scoped_ptr<SessionDescription> ref_desc;
+    rtc::scoped_ptr<SessionDescription> desc;
     if (offer) {
       options.bundle_enabled = false;
       ref_desc.reset(f1_.CreateOffer(options, NULL));
@@ -390,7 +406,7 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
       cricket::MediaContentDirection expected_direction_in_answer) {
     MediaSessionOptions opts;
     opts.has_video = true;
-    talk_base::scoped_ptr<SessionDescription> offer(
+    rtc::scoped_ptr<SessionDescription> offer(
         f1_.CreateOffer(opts, NULL));
     ASSERT_TRUE(offer.get() != NULL);
     ContentInfo* ac_offer= offer->GetContentByName("audio");
@@ -404,7 +420,7 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
         static_cast<VideoContentDescription*>(vc_offer->description);
     vcd_offer->set_direction(direction_in_offer);
 
-    talk_base::scoped_ptr<SessionDescription> answer(
+    rtc::scoped_ptr<SessionDescription> answer(
         f2_.CreateAnswer(offer.get(), opts, NULL));
     const AudioContentDescription* acd_answer =
         GetFirstAudioContentDescription(answer.get());
@@ -432,14 +448,14 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
   MediaSessionDescriptionFactory f2_;
   TransportDescriptionFactory tdf1_;
   TransportDescriptionFactory tdf2_;
-  talk_base::FakeSSLIdentity id1_;
-  talk_base::FakeSSLIdentity id2_;
+  rtc::FakeSSLIdentity id1_;
+  rtc::FakeSSLIdentity id2_;
 };
 
 // Create a typical audio offer, and ensure it matches what we expect.
 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
   f1_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(
+  rtc::scoped_ptr<SessionDescription> offer(
       f1_.CreateOffer(MediaSessionOptions(), NULL));
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* ac = offer->GetContentByName("audio");
@@ -463,7 +479,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
   MediaSessionOptions opts;
   opts.has_video = true;
   f1_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* ac = offer->GetContentByName("audio");
@@ -507,7 +523,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
   opts.has_video = true;
   opts.data_channel_type = cricket::DCT_RTP;
   opts.bundle_enabled = true;
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
   offer(f2_.CreateOffer(opts, NULL));
   const VideoContentDescription* vcd =
       GetFirstVideoContentDescription(offer.get());
@@ -537,8 +553,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   opts.has_video = false;
   opts.data_channel_type = cricket::DCT_NONE;
   opts.bundle_enabled = true;
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   MediaSessionOptions updated_opts;
@@ -546,7 +562,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   updated_opts.has_video = true;
   updated_opts.data_channel_type = cricket::DCT_RTP;
   updated_opts.bundle_enabled = true;
-  talk_base::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
+  rtc::scoped_ptr<SessionDescription> updated_offer(f1_.CreateOffer(
       updated_opts, answer.get()));
 
   const AudioContentDescription* acd =
@@ -571,7 +587,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
   MediaSessionOptions opts;
   opts.data_channel_type = cricket::DCT_RTP;
   f1_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* ac = offer->GetContentByName("audio");
@@ -608,7 +624,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
   opts.bundle_enabled = true;
   opts.data_channel_type = cricket::DCT_SCTP;
   f1_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   EXPECT_TRUE(offer.get() != NULL);
   EXPECT_TRUE(offer->GetContentByName("data") != NULL);
 }
@@ -619,7 +635,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   MediaSessionOptions opts;
   opts.has_video = true;
   f1_.set_add_legacy_streams(false);
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* ac = offer->GetContentByName("audio");
@@ -635,14 +651,54 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   EXPECT_FALSE(acd->has_ssrcs());             // No StreamParams.
 }
 
+// Verifies that the order of the media contents in the current
+// SessionDescription is preserved in the new SessionDescription.
+TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
+  MediaSessionOptions opts;
+  opts.has_audio = false;
+  opts.has_video = false;
+  opts.data_channel_type = cricket::DCT_SCTP;
+
+  rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
+  ASSERT_TRUE(offer1.get() != NULL);
+  EXPECT_EQ(1u, offer1->contents().size());
+  EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
+
+  opts.has_video = true;
+  rtc::scoped_ptr<SessionDescription> offer2(
+      f1_.CreateOffer(opts, offer1.get()));
+  ASSERT_TRUE(offer2.get() != NULL);
+  EXPECT_EQ(2u, offer2->contents().size());
+  EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
+  EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
+
+  opts.has_audio = true;
+  rtc::scoped_ptr<SessionDescription> offer3(
+      f1_.CreateOffer(opts, offer2.get()));
+  ASSERT_TRUE(offer3.get() != NULL);
+  EXPECT_EQ(3u, offer3->contents().size());
+  EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
+  EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
+  EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
+
+  // Verifies the default order is audio-video-data, so that the previous checks
+  // didn't pass by accident.
+  rtc::scoped_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
+  ASSERT_TRUE(offer4.get() != NULL);
+  EXPECT_EQ(3u, offer4->contents().size());
+  EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
+  EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
+  EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
+}
+
 // Create a typical audio answer, and ensure it matches what we expect.
 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
   f1_.set_secure(SEC_ENABLED);
   f2_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(
+  rtc::scoped_ptr<SessionDescription> offer(
       f1_.CreateOffer(MediaSessionOptions(), NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
   const ContentInfo* ac = answer->GetContentByName("audio");
   const ContentInfo* vc = answer->GetContentByName("video");
@@ -666,9 +722,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
   opts.has_video = true;
   f1_.set_secure(SEC_ENABLED);
   f2_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
   const ContentInfo* ac = answer->GetContentByName("audio");
   const ContentInfo* vc = answer->GetContentByName("video");
@@ -699,9 +755,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
   opts.data_channel_type = cricket::DCT_RTP;
   f1_.set_secure(SEC_ENABLED);
   f2_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
   const ContentInfo* ac = answer->GetContentByName("audio");
   const ContentInfo* vc = answer->GetContentByName("data");
@@ -727,6 +783,38 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
   EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
 }
 
+// Verifies that the order of the media contents in the offer is preserved in
+// the answer.
+TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
+  MediaSessionOptions opts;
+
+  // Creates a data only offer.
+  opts.has_audio = false;
+  opts.data_channel_type = cricket::DCT_SCTP;
+  rtc::scoped_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
+  ASSERT_TRUE(offer1.get() != NULL);
+
+  // Appends audio to the offer.
+  opts.has_audio = true;
+  rtc::scoped_ptr<SessionDescription> offer2(
+      f1_.CreateOffer(opts, offer1.get()));
+  ASSERT_TRUE(offer2.get() != NULL);
+
+  // Appends video to the offer.
+  opts.has_video = true;
+  rtc::scoped_ptr<SessionDescription> offer3(
+      f1_.CreateOffer(opts, offer2.get()));
+  ASSERT_TRUE(offer3.get() != NULL);
+
+  rtc::scoped_ptr<SessionDescription> answer(
+      f2_.CreateAnswer(offer3.get(), opts, NULL));
+  ASSERT_TRUE(answer.get() != NULL);
+  EXPECT_EQ(3u, answer->contents().size());
+  EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[0], MEDIA_TYPE_DATA));
+  EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[1], MEDIA_TYPE_AUDIO));
+  EXPECT_TRUE(IsMediaContentOfType(&answer->contents()[2], MEDIA_TYPE_VIDEO));
+}
+
 // This test that the media direction is set to send/receive in an answer if
 // the offer is send receive.
 TEST_F(MediaSessionDescriptionFactoryTest, CreateAnswerToSendReceiveOffer) {
@@ -759,7 +847,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   opts.has_audio = false;
   f1_.set_secure(SEC_ENABLED);
   f2_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ContentInfo* dc_offer= offer->GetContentByName("data");
   ASSERT_TRUE(dc_offer != NULL);
   DataContentDescription* dcd_offer =
@@ -768,7 +856,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   std::string protocol = "a weird unknown protocol";
   dcd_offer->set_protocol(protocol);
 
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   const ContentInfo* dc_answer = answer->GetContentByName("data");
@@ -788,13 +876,13 @@ TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
   tdf1_.set_secure(SEC_DISABLED);
   tdf2_.set_secure(SEC_DISABLED);
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   const AudioContentDescription* offer_acd =
       GetFirstAudioContentDescription(offer.get());
   ASSERT_TRUE(offer_acd != NULL);
   EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), offer_acd->protocol());
 
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   const ContentInfo* ac_answer = answer->GetContentByName("audio");
@@ -818,9 +906,9 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
   f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
   f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtension1),
@@ -845,9 +933,9 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   opts.data_channel_type = cricket::DCT_RTP;
   f1_.set_add_legacy_streams(false);
   f2_.set_add_legacy_streams(false);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
   const ContentInfo* ac = answer->GetContentByName("audio");
   const ContentInfo* vc = answer->GetContentByName("video");
@@ -871,7 +959,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
   opts.has_video = true;
   opts.data_channel_type = cricket::DCT_RTP;
   f1_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* ac = offer->GetContentByName("audio");
@@ -912,8 +1000,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
   answer_opts.data_channel_type = cricket::DCT_RTP;
   offer_opts.data_channel_type = cricket::DCT_RTP;
 
-  talk_base::scoped_ptr<SessionDescription> offer;
-  talk_base::scoped_ptr<SessionDescription> answer;
+  rtc::scoped_ptr<SessionDescription> offer;
+  rtc::scoped_ptr<SessionDescription> answer;
 
   offer_opts.rtcp_mux_enabled = true;
   answer_opts.rtcp_mux_enabled = true;
@@ -992,10 +1080,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
   MediaSessionOptions opts;
   opts.has_video = true;
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
   const ContentInfo* ac = answer->GetContentByName("audio");
   const ContentInfo* vc = answer->GetContentByName("video");
@@ -1009,10 +1097,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
 TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
   MediaSessionOptions opts;
   opts.data_channel_type = cricket::DCT_RTP;
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
   const ContentInfo* ac = answer->GetContentByName("audio");
   const ContentInfo* dc = answer->GetContentByName("data");
@@ -1028,7 +1116,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   MediaSessionOptions opts;
   opts.has_video = true;
   opts.data_channel_type = cricket::DCT_RTP;
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   ContentInfo* ac = offer->GetContentByName("audio");
@@ -1040,7 +1128,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   ac->rejected = true;
   vc->rejected = true;
   dc->rejected = true;
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
   ac = answer->GetContentByName("audio");
   vc = answer->GetContentByName("video");
@@ -1069,7 +1157,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
 
   f1_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
 
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* ac = offer->GetContentByName("audio");
@@ -1139,7 +1227,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
   opts.AddStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
   opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       updated_offer(f1_.CreateOffer(opts, offer.get()));
 
   ASSERT_TRUE(updated_offer.get() != NULL);
@@ -1197,7 +1285,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
   MediaSessionOptions opts;
   const int num_sim_layers = 3;
   opts.AddVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
 
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* vc = offer->GetContentByName("video");
@@ -1226,7 +1314,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
   offer_opts.data_channel_type = cricket::DCT_RTP;
   f1_.set_secure(SEC_ENABLED);
   f2_.set_secure(SEC_ENABLED);
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts,
                                                                   NULL));
 
   MediaSessionOptions opts;
@@ -1237,7 +1325,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
   opts.AddStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
 
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       answer(f2_.CreateAnswer(offer.get(), opts, NULL));
 
   ASSERT_TRUE(answer.get() != NULL);
@@ -1305,7 +1393,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
   opts.AddStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
   opts.RemoveStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
   opts.RemoveStream(MEDIA_TYPE_DATA, kDataTrack2);
-  talk_base::scoped_ptr<SessionDescription>
+  rtc::scoped_ptr<SessionDescription>
       updated_answer(f2_.CreateAnswer(offer.get(), opts, answer.get()));
 
   ASSERT_TRUE(updated_answer.get() != NULL);
@@ -1361,8 +1449,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   opts.has_audio = true;
   opts.has_video = true;
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   const AudioContentDescription* acd =
@@ -1373,16 +1461,18 @@ TEST_F(MediaSessionDescriptionFactoryTest,
       GetFirstVideoContentDescription(answer.get());
   EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
 
-  talk_base::scoped_ptr<SessionDescription> updated_offer(
+  rtc::scoped_ptr<SessionDescription> updated_offer(
       f2_.CreateOffer(opts, answer.get()));
 
   // The expected audio codecs are the common audio codecs from the first
   // offer/answer exchange plus the audio codecs only |f2_| offer, sorted in
   // preference order.
+  // TODO(wu): |updated_offer| should not include the codec
+  // (i.e. |kAudioCodecs2[0]|) the other side doesn't support.
   const AudioCodec kUpdatedAudioCodecOffer[] = {
-    kAudioCodecs2[0],
     kAudioCodecsAnswer[0],
     kAudioCodecsAnswer[1],
+    kAudioCodecs2[0],
   };
 
   // The expected video codecs are the common video codecs from the first
@@ -1417,7 +1507,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
 
   // This creates rtx for H264 with the payload type |f1_| uses.
   rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
-      talk_base::ToString<int>(kVideoCodecs1[1].id);
+      rtc::ToString<int>(kVideoCodecs1[1].id);
   f1_codecs.push_back(rtx_f1);
   f1_.set_video_codecs(f1_codecs);
 
@@ -1428,13 +1518,13 @@ TEST_F(MediaSessionDescriptionFactoryTest,
 
   // This creates rtx for H264 with the payload type |f2_| uses.
   rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
-      talk_base::ToString<int>(kVideoCodecs2[0].id);
+      rtc::ToString<int>(kVideoCodecs2[0].id);
   f2_codecs.push_back(rtx_f2);
   f2_.set_video_codecs(f2_codecs);
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   const VideoContentDescription* vcd =
@@ -1450,10 +1540,10 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   // are different from |f1_|.
   expected_codecs[0].preference = f1_codecs[1].preference;
 
-  talk_base::scoped_ptr<SessionDescription> updated_offer(
+  rtc::scoped_ptr<SessionDescription> updated_offer(
       f2_.CreateOffer(opts, answer.get()));
   ASSERT_TRUE(updated_offer);
-  talk_base::scoped_ptr<SessionDescription> updated_answer(
+  rtc::scoped_ptr<SessionDescription> updated_answer(
       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
 
   const VideoContentDescription* updated_vcd =
@@ -1475,7 +1565,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
 
   // This creates rtx for H264 with the payload type |f1_| uses.
   rtx_f1.params[cricket::kCodecParamAssociatedPayloadType] =
-      talk_base::ToString<int>(kVideoCodecs1[1].id);
+      rtc::ToString<int>(kVideoCodecs1[1].id);
   f1_codecs.push_back(rtx_f1);
   f1_.set_video_codecs(f1_codecs);
 
@@ -1483,8 +1573,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   opts.has_audio = true;
   opts.has_video = false;
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   const AudioContentDescription* acd =
@@ -1504,14 +1594,14 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   rtx_f2.id = 127;
   rtx_f2.name = cricket::kRtxCodecName;
   rtx_f2.params[cricket::kCodecParamAssociatedPayloadType] =
-      talk_base::ToString<int>(used_pl_type);
+      rtc::ToString<int>(used_pl_type);
   f2_codecs.push_back(rtx_f2);
   f2_.set_video_codecs(f2_codecs);
 
-  talk_base::scoped_ptr<SessionDescription> updated_offer(
+  rtc::scoped_ptr<SessionDescription> updated_offer(
       f2_.CreateOffer(opts, answer.get()));
   ASSERT_TRUE(updated_offer);
-  talk_base::scoped_ptr<SessionDescription> updated_answer(
+  rtc::scoped_ptr<SessionDescription> updated_answer(
       f1_.CreateAnswer(updated_offer.get(), opts, answer.get()));
 
   const AudioContentDescription* updated_acd =
@@ -1526,7 +1616,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   int new_h264_pl_type =  updated_vcd->codecs()[0].id;
   EXPECT_NE(used_pl_type, new_h264_pl_type);
   VideoCodec rtx = updated_vcd->codecs()[1];
-  int pt_referenced_by_rtx = talk_base::FromString<int>(
+  int pt_referenced_by_rtx = rtc::FromString<int>(
       rtx.params[cricket::kCodecParamAssociatedPayloadType]);
   EXPECT_EQ(new_h264_pl_type, pt_referenced_by_rtx);
 }
@@ -1551,11 +1641,11 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
 
   // This creates rtx for H264 with the payload type |f2_| uses.
   rtx_f2.SetParam(cricket::kCodecParamAssociatedPayloadType,
-                  talk_base::ToString<int>(kVideoCodecs2[0].id));
+                  rtc::ToString<int>(kVideoCodecs2[0].id));
   f2_codecs.push_back(rtx_f2);
   f2_.set_video_codecs(f2_codecs);
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   // kCodecParamAssociatedPayloadType will always be added to the offer when RTX
   // is selected. Manually remove kCodecParamAssociatedPayloadType so that it
@@ -1574,7 +1664,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
   }
   desc->set_codecs(codecs);
 
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   const VideoContentDescription* vcd =
@@ -1600,8 +1690,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
   f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
   f2_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension2));
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), opts, NULL));
 
   EXPECT_EQ(MAKE_VECTOR(kAudioRtpExtensionAnswer),
@@ -1611,7 +1701,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
             GetFirstVideoContentDescription(
                 answer.get())->rtp_header_extensions());
 
-  talk_base::scoped_ptr<SessionDescription> updated_offer(
+  rtc::scoped_ptr<SessionDescription> updated_offer(
       f2_.CreateOffer(opts, answer.get()));
 
   // The expected RTP header extensions in the new offer are the resulting
@@ -1657,7 +1747,7 @@ TEST(MediaSessionDescription, CopySessionDescription) {
   vcd->AddLegacyStream(2);
   source.AddContent(cricket::CN_VIDEO, cricket::NS_JINGLE_RTP, vcd);
 
-  talk_base::scoped_ptr<SessionDescription> copy(source.Copy());
+  rtc::scoped_ptr<SessionDescription> copy(source.Copy());
   ASSERT_TRUE(copy.get() != NULL);
   EXPECT_TRUE(copy->HasGroup(cricket::CN_AUDIO));
   const ContentInfo* ac = copy->GetContentByName("audio");
@@ -1788,6 +1878,64 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoWithAnswerBundle) {
   TestCryptoWithBundle(false);
 }
 
+// Verifies that creating answer fails if the offer has UDP/TLS/RTP/SAVPF but
+// DTLS is not enabled locally.
+TEST_F(MediaSessionDescriptionFactoryTest,
+       TestOfferDtlsSavpfWithoutDtlsFailed) {
+  f1_.set_secure(SEC_ENABLED);
+  f2_.set_secure(SEC_ENABLED);
+  tdf1_.set_secure(SEC_DISABLED);
+  tdf2_.set_secure(SEC_DISABLED);
+
+  rtc::scoped_ptr<SessionDescription> offer(
+      f1_.CreateOffer(MediaSessionOptions(), NULL));
+  ASSERT_TRUE(offer.get() != NULL);
+  ContentInfo* offer_content = offer->GetContentByName("audio");
+  ASSERT_TRUE(offer_content != NULL);
+  AudioContentDescription* offer_audio_desc =
+      static_cast<AudioContentDescription*>(offer_content->description);
+  offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
+
+  rtc::scoped_ptr<SessionDescription> answer(
+      f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
+  ASSERT_TRUE(answer != NULL);
+  ContentInfo* answer_content = answer->GetContentByName("audio");
+  ASSERT_TRUE(answer_content != NULL);
+
+  ASSERT_TRUE(answer_content->rejected);
+}
+
+// Offers UDP/TLS/RTP/SAVPF and verifies the answer can be created and contains
+// UDP/TLS/RTP/SAVPF.
+TEST_F(MediaSessionDescriptionFactoryTest, TestOfferDtlsSavpfCreateAnswer) {
+  f1_.set_secure(SEC_ENABLED);
+  f2_.set_secure(SEC_ENABLED);
+  tdf1_.set_secure(SEC_ENABLED);
+  tdf2_.set_secure(SEC_ENABLED);
+
+  rtc::scoped_ptr<SessionDescription> offer(
+      f1_.CreateOffer(MediaSessionOptions(), NULL));
+  ASSERT_TRUE(offer.get() != NULL);
+  ContentInfo* offer_content = offer->GetContentByName("audio");
+  ASSERT_TRUE(offer_content != NULL);
+  AudioContentDescription* offer_audio_desc =
+      static_cast<AudioContentDescription*>(offer_content->description);
+  offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
+
+  rtc::scoped_ptr<SessionDescription> answer(
+      f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
+  ASSERT_TRUE(answer != NULL);
+
+  const ContentInfo* answer_content = answer->GetContentByName("audio");
+  ASSERT_TRUE(answer_content != NULL);
+  ASSERT_FALSE(answer_content->rejected);
+
+  const AudioContentDescription* answer_audio_desc =
+      static_cast<const AudioContentDescription*>(answer_content->description);
+  EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf),
+                        answer_audio_desc->protocol());
+}
+
 // Test that we include both SDES and DTLS in the offer, but only include SDES
 // in the answer if DTLS isn't negotiated.
 TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
@@ -1798,7 +1946,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoDtls) {
   MediaSessionOptions options;
   options.has_audio = true;
   options.has_video = true;
-  talk_base::scoped_ptr<SessionDescription> offer, answer;
+  rtc::scoped_ptr<SessionDescription> offer, answer;
   const cricket::MediaContentDescription* audio_media_desc;
   const cricket::MediaContentDescription* video_media_desc;
   const cricket::TransportDescription* audio_trans_desc;
@@ -1899,10 +2047,10 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
   f2_.set_secure(SEC_REQUIRED);
   tdf1_.set_secure(SEC_ENABLED);
 
-  talk_base::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
+  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(options,
                                                                   NULL));
   ASSERT_TRUE(offer.get() != NULL);
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f2_.CreateAnswer(offer.get(), options, NULL));
   EXPECT_TRUE(answer.get() == NULL);
 }
@@ -1919,7 +2067,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
   options.has_video = true;
   options.data_channel_type = cricket::DCT_RTP;
 
-  talk_base::scoped_ptr<SessionDescription> offer, answer;
+  rtc::scoped_ptr<SessionDescription> offer, answer;
 
   // Generate an offer with DTLS but without SDES.
   offer.reset(f1_.CreateOffer(options, NULL));
@@ -1966,7 +2114,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
   MediaSessionOptions options;
   options.has_audio = true;
   options.has_video = true;
-  talk_base::scoped_ptr<SessionDescription> offer(
+  rtc::scoped_ptr<SessionDescription> offer(
       f1_.CreateOffer(options, NULL));
   ASSERT_TRUE(offer.get() != NULL);
   const ContentInfo* audio_content = offer->GetContentByName("audio");
@@ -1977,7 +2125,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
   ASSERT_TRUE(offer.get() != NULL);
   audio_content = offer->GetContentByName("audio");
   EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
-  talk_base::scoped_ptr<SessionDescription> answer(
+  rtc::scoped_ptr<SessionDescription> answer(
       f1_.CreateAnswer(offer.get(), options, NULL));
   ASSERT_TRUE(answer.get() != NULL);
   audio_content = answer->GetContentByName("audio");