pRevert 5371 "Revert 5367 "Update talk to 59410372.""

> Revert 5367 "Update talk to 59410372."
> 
> > Update talk to 59410372.
> > 
> > R=jiayl@webrtc.org, wu@webrtc.org
> > 
> > Review URL: https://webrtc-codereview.appspot.com/6929004
> 
> TBR=mallinath@webrtc.org
> 
> Review URL: https://webrtc-codereview.appspot.com/6999004

TBR=henrika@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/7109004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5381 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc
index 6c9e0bc..048e89a 100644
--- a/talk/app/webrtc/datachannel.cc
+++ b/talk/app/webrtc/datachannel.cc
@@ -29,9 +29,9 @@
 #include <string>
 
 #include "talk/app/webrtc/mediastreamprovider.h"
+#include "talk/app/webrtc/sctputils.h"
 #include "talk/base/logging.h"
 #include "talk/base/refcount.h"
-#include "talk/media/sctp/sctputils.h"
 
 namespace webrtc {
 
@@ -46,7 +46,7 @@
     DataChannelProviderInterface* provider,
     cricket::DataChannelType dct,
     const std::string& label,
-    const DataChannelInit* config) {
+    const InternalDataChannelInit& config) {
   talk_base::scoped_refptr<DataChannel> channel(
       new talk_base::RefCountedObject<DataChannel>(provider, dct, label));
   if (!channel->Init(config)) {
@@ -62,39 +62,40 @@
     : label_(label),
       observer_(NULL),
       state_(kConnecting),
-      was_ever_writable_(false),
-      connected_to_provider_(false),
       data_channel_type_(dct),
       provider_(provider),
+      waiting_for_open_ack_(false),
+      was_ever_writable_(false),
+      connected_to_provider_(false),
       send_ssrc_set_(false),
-      send_ssrc_(0),
       receive_ssrc_set_(false),
+      send_ssrc_(0),
       receive_ssrc_(0) {
 }
 
-bool DataChannel::Init(const DataChannelInit* config) {
+bool DataChannel::Init(const InternalDataChannelInit& config) {
   if (data_channel_type_ == cricket::DCT_RTP &&
-      (config->reliable ||
-       config->id != -1 ||
-       config->maxRetransmits != -1 ||
-       config->maxRetransmitTime != -1)) {
+      (config.reliable ||
+       config.id != -1 ||
+       config.maxRetransmits != -1 ||
+       config.maxRetransmitTime != -1)) {
     LOG(LS_ERROR) << "Failed to initialize the RTP data channel due to "
                   << "invalid DataChannelInit.";
     return false;
   } else if (data_channel_type_ == cricket::DCT_SCTP) {
-    if (config->id < -1 ||
-        config->maxRetransmits < -1 ||
-        config->maxRetransmitTime < -1) {
+    if (config.id < -1 ||
+        config.maxRetransmits < -1 ||
+        config.maxRetransmitTime < -1) {
       LOG(LS_ERROR) << "Failed to initialize the SCTP data channel due to "
                     << "invalid DataChannelInit.";
       return false;
     }
-    if (config->maxRetransmits != -1 && config->maxRetransmitTime != -1) {
+    if (config.maxRetransmits != -1 && config.maxRetransmitTime != -1) {
       LOG(LS_ERROR) <<
           "maxRetransmits and maxRetransmitTime should not be both set.";
       return false;
     }
-    config_ = *config;
+    config_ = config;
 
     // Try to connect to the transport in case the transport channel already
     // exists.
@@ -197,9 +198,44 @@
 
   cricket::SendDataResult send_result;
   bool retval = provider_->SendData(send_params, *buffer, &send_result);
-  if (!retval && send_result == cricket::SDR_BLOCK) {
+  if (retval) {
+    LOG(LS_INFO) << "Sent OPEN message on channel " << config_.id;
+    // Send data as ordered before we receive any mesage from the remote peer
+    // to make sure the remote peer will not receive any data before it receives
+    // the OPEN message.
+    waiting_for_open_ack_ = true;
+  } else if (send_result == cricket::SDR_BLOCK) {
     // Link is congested.  Queue for later.
     QueueControl(buffer.release());
+  } else {
+    LOG(LS_ERROR) << "Failed to send OPEN message with result "
+                  << send_result << " on channel " << config_.id;
+  }
+  return retval;
+}
+
+bool DataChannel::SendOpenAckMessage(const talk_base::Buffer* raw_buffer) {
+  ASSERT(data_channel_type_ == cricket::DCT_SCTP &&
+         was_ever_writable_ &&
+         config_.id >= 0);
+
+  talk_base::scoped_ptr<const talk_base::Buffer> buffer(raw_buffer);
+
+  cricket::SendDataParams send_params;
+  send_params.ssrc = config_.id;
+  send_params.ordered = config_.ordered;
+  send_params.type = cricket::DMT_CONTROL;
+
+  cricket::SendDataResult send_result;
+  bool retval = provider_->SendData(send_params, *buffer, &send_result);
+  if (retval) {
+    LOG(LS_INFO) << "Sent OPEN_ACK message on channel " << config_.id;
+  } else if (send_result == cricket::SDR_BLOCK) {
+    // Link is congested.  Queue for later.
+    QueueControl(buffer.release());
+  } else {
+    LOG(LS_ERROR) << "Failed to send OPEN_ACK message with result "
+                  << send_result << " on channel " << config_.id;
   }
   return retval;
 }
@@ -254,6 +290,35 @@
     return;
   }
 
+  if (params.type == cricket::DMT_CONTROL) {
+    ASSERT(data_channel_type_ == cricket::DCT_SCTP);
+    if (!waiting_for_open_ack_) {
+      // Ignore it if we are not expecting an ACK message.
+      LOG(LS_WARNING) << "DataChannel received unexpected CONTROL message, "
+                      << "sid = " << params.ssrc;
+      return;
+    }
+    if (ParseDataChannelOpenAckMessage(payload)) {
+      // We can send unordered as soon as we receive the ACK message.
+      waiting_for_open_ack_ = false;
+      LOG(LS_INFO) << "DataChannel received OPEN_ACK message, sid = "
+                   << params.ssrc;
+    } else {
+      LOG(LS_WARNING) << "DataChannel failed to parse OPEN_ACK message, sid = "
+                      << params.ssrc;
+    }
+    return;
+  }
+
+  ASSERT(params.type == cricket::DMT_BINARY ||
+         params.type == cricket::DMT_TEXT);
+
+  LOG(LS_VERBOSE) << "DataChannel received DATA message, sid = " << params.ssrc;
+  // We can send unordered as soon as we receive any DATA message since the
+  // remote side must have received the OPEN (and old clients do not send
+  // OPEN_ACK).
+  waiting_for_open_ack_ = false;
+
   bool binary = (params.type == cricket::DMT_BINARY);
   talk_base::scoped_ptr<DataBuffer> buffer(new DataBuffer(payload, binary));
   if (was_ever_writable_ && observer_) {
@@ -279,14 +344,17 @@
   if (!was_ever_writable_) {
     was_ever_writable_ = true;
 
-    if (data_channel_type_ == cricket::DCT_SCTP && !config_.negotiated) {
-      talk_base::Buffer* payload = new talk_base::Buffer;
-      if (!cricket::WriteDataChannelOpenMessage(label_, config_, payload)) {
-        // TODO(jiayl): close the data channel on this error.
-        LOG(LS_ERROR) << "Could not write data channel OPEN message";
-        return;
+    if (data_channel_type_ == cricket::DCT_SCTP) {
+      if (config_.open_handshake_role == InternalDataChannelInit::kOpener) {
+        talk_base::Buffer* payload = new talk_base::Buffer;
+        WriteDataChannelOpenMessage(label_, config_, payload);
+        SendOpenMessage(payload);
+      } else if (config_.open_handshake_role ==
+                 InternalDataChannelInit::kAcker) {
+        talk_base::Buffer* payload = new talk_base::Buffer;
+        WriteDataChannelOpenAckMessage(payload);
+        SendOpenAckMessage(payload);
       }
-      SendOpenMessage(payload);
     }
 
     UpdateState();
@@ -412,7 +480,12 @@
   while (!queued_control_data_.empty()) {
     const talk_base::Buffer* buf = queued_control_data_.front();
     queued_control_data_.pop();
-    SendOpenMessage(buf);
+    if (config_.open_handshake_role == InternalDataChannelInit::kOpener) {
+      SendOpenMessage(buf);
+    } else {
+      ASSERT(config_.open_handshake_role == InternalDataChannelInit::kAcker);
+      SendOpenAckMessage(buf);
+    }
   }
 }
 
@@ -430,6 +503,13 @@
 
   if (data_channel_type_ == cricket::DCT_SCTP) {
     send_params.ordered = config_.ordered;
+    // Send as ordered if it is waiting for the OPEN_ACK message.
+    if (waiting_for_open_ack_ && !config_.ordered) {
+      send_params.ordered = true;
+      LOG(LS_VERBOSE) << "Sending data as ordered for unordered DataChannel "
+                      << "because the OPEN_ACK message has not been received.";
+    }
+
     send_params.max_rtx_count = config_.maxRetransmits;
     send_params.max_rtx_ms = config_.maxRetransmitTime;
     send_params.ssrc = config_.id;
diff --git a/talk/app/webrtc/datachannel.h b/talk/app/webrtc/datachannel.h
index bf31aed..9256e0e 100644
--- a/talk/app/webrtc/datachannel.h
+++ b/talk/app/webrtc/datachannel.h
@@ -64,6 +64,25 @@
   virtual ~DataChannelProviderInterface() {}
 };
 
+struct InternalDataChannelInit : public DataChannelInit {
+  enum OpenHandshakeRole {
+    kOpener,
+    kAcker,
+    kNone
+  };
+  // The default role is kOpener because the default |negotiated| is false.
+  InternalDataChannelInit() : open_handshake_role(kOpener) {}
+  explicit InternalDataChannelInit(const DataChannelInit& base)
+      : DataChannelInit(base), open_handshake_role(kOpener) {
+    // If the channel is externally negotiated, do not send the OPEN message.
+    if (base.negotiated) {
+      open_handshake_role = kNone;
+    }
+  }
+
+  OpenHandshakeRole open_handshake_role;
+};
+
 // DataChannel is a an implementation of the DataChannelInterface based on
 // libjingle's data engine. It provides an implementation of unreliable or
 // reliabledata channels. Currently this class is specifically designed to use
@@ -87,7 +106,7 @@
       DataChannelProviderInterface* provider,
       cricket::DataChannelType dct,
       const std::string& label,
-      const DataChannelInit* config);
+      const InternalDataChannelInit& config);
 
   virtual void RegisterObserver(DataChannelObserver* observer);
   virtual void UnregisterObserver();
@@ -156,7 +175,7 @@
   virtual ~DataChannel();
 
  private:
-  bool Init(const DataChannelInit* config);
+  bool Init(const InternalDataChannelInit& config);
   void DoClose();
   void UpdateState();
   void SetState(DataState state);
@@ -172,19 +191,20 @@
                                    cricket::SendDataResult* send_result);
   bool QueueSendData(const DataBuffer& buffer);
   bool SendOpenMessage(const talk_base::Buffer* buffer);
-
+  bool SendOpenAckMessage(const talk_base::Buffer* buffer);
 
   std::string label_;
-  DataChannelInit config_;
+  InternalDataChannelInit config_;
   DataChannelObserver* observer_;
   DataState state_;
-  bool was_ever_writable_;
-  bool connected_to_provider_;
   cricket::DataChannelType data_channel_type_;
   DataChannelProviderInterface* provider_;
+  bool waiting_for_open_ack_;
+  bool was_ever_writable_;
+  bool connected_to_provider_;
   bool send_ssrc_set_;
-  uint32 send_ssrc_;
   bool receive_ssrc_set_;
+  uint32 send_ssrc_;
   uint32 receive_ssrc_;
   // Control messages that always have to get sent out before any queued
   // data.
@@ -197,7 +217,7 @@
  public:
   virtual talk_base::scoped_refptr<DataChannel> CreateDataChannel(
       const std::string& label,
-      const DataChannelInit* config) = 0;
+      const InternalDataChannelInit* config) = 0;
 
  protected:
   virtual ~DataChannelFactory() {}
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
index fdcd2f2..1be24e9 100644
--- a/talk/app/webrtc/datachannel_unittest.cc
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -26,6 +26,7 @@
  */
 
 #include "talk/app/webrtc/datachannel.h"
+#include "talk/app/webrtc/sctputils.h"
 #include "talk/app/webrtc/test/fakedatachannelprovider.h"
 #include "talk/base/gunit.h"
 #include "testing/base/public/gmock.h"
@@ -42,7 +43,8 @@
  protected:
   SctpDataChannelTest()
       : webrtc_data_channel_(
-          DataChannel::Create(&provider_, cricket::DCT_SCTP, "test", &init_)) {
+          DataChannel::Create(
+              &provider_, cricket::DCT_SCTP, "test", init_)) {
   }
 
   void SetChannelReady() {
@@ -59,7 +61,7 @@
     webrtc_data_channel_->RegisterObserver(observer_.get());
   }
 
-  webrtc::DataChannelInit init_;
+  webrtc::InternalDataChannelInit init_;
   FakeDataChannelProvider provider_;
   talk_base::scoped_ptr<FakeDataChannelObserver> observer_;
   talk_base::scoped_refptr<DataChannel> webrtc_data_channel_;
@@ -69,7 +71,7 @@
 TEST_F(SctpDataChannelTest, ConnectedToTransportOnCreated) {
   provider_.set_transport_available(true);
   talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
-      &provider_, cricket::DCT_SCTP, "test1", &init_);
+      &provider_, cricket::DCT_SCTP, "test1", init_);
 
   EXPECT_TRUE(provider_.IsConnected(dc.get()));
   // The sid is not set yet, so it should not have added the streams.
@@ -153,15 +155,69 @@
 // state.
 TEST_F(SctpDataChannelTest, LateCreatedChannelTransitionToOpen) {
   SetChannelReady();
-  webrtc::DataChannelInit init;
+  webrtc::InternalDataChannelInit init;
   init.id = 1;
-  talk_base::scoped_refptr<DataChannel> dc =
-      DataChannel::Create(&provider_, cricket::DCT_SCTP, "test1", &init);
+  talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+      &provider_, cricket::DCT_SCTP, "test1", init);
   EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, dc->state());
   EXPECT_TRUE_WAIT(webrtc::DataChannelInterface::kOpen == dc->state(),
                    1000);
 }
 
+// Tests that an unordered DataChannel sends data as ordered until the OPEN_ACK
+// message is received.
+TEST_F(SctpDataChannelTest, SendUnorderedAfterReceivesOpenAck) {
+  SetChannelReady();
+  webrtc::InternalDataChannelInit init;
+  init.id = 1;
+  init.ordered = false;
+  talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+      &provider_, cricket::DCT_SCTP, "test1", init);
+
+  EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
+
+  // Sends a message and verifies it's ordered.
+  webrtc::DataBuffer buffer("some data");
+  ASSERT_TRUE(dc->Send(buffer));
+  EXPECT_TRUE(provider_.last_send_data_params().ordered);
+
+  // Emulates receiving an OPEN_ACK message.
+  cricket::ReceiveDataParams params;
+  params.ssrc = init.id;
+  params.type = cricket::DMT_CONTROL;
+  talk_base::Buffer payload;
+  webrtc::WriteDataChannelOpenAckMessage(&payload);
+  dc->OnDataReceived(NULL, params, payload);
+
+  // Sends another message and verifies it's unordered.
+  ASSERT_TRUE(dc->Send(buffer));
+  EXPECT_FALSE(provider_.last_send_data_params().ordered);
+}
+
+// Tests that an unordered DataChannel sends unordered data after any DATA
+// message is received.
+TEST_F(SctpDataChannelTest, SendUnorderedAfterReceiveData) {
+  SetChannelReady();
+  webrtc::InternalDataChannelInit init;
+  init.id = 1;
+  init.ordered = false;
+  talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+      &provider_, cricket::DCT_SCTP, "test1", init);
+
+  EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
+
+  // Emulates receiving a DATA message.
+  cricket::ReceiveDataParams params;
+  params.ssrc = init.id;
+  params.type = cricket::DMT_TEXT;
+  webrtc::DataBuffer buffer("data");
+  dc->OnDataReceived(NULL, params, buffer.data);
+
+  // Sends a message and verifies it's unordered.
+  ASSERT_TRUE(dc->Send(buffer));
+  EXPECT_FALSE(provider_.last_send_data_params().ordered);
+}
+
 // Tests that messages are sent with the right ssrc.
 TEST_F(SctpDataChannelTest, SendDataSsrc) {
   webrtc_data_channel_->SetSctpSid(1);
@@ -199,3 +255,50 @@
 
   webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
 }
+
+// Tests that no CONTROL message is sent if the datachannel is negotiated and
+// not created from an OPEN message.
+TEST_F(SctpDataChannelTest, NoMsgSentIfNegotiatedAndNotFromOpenMsg) {
+  webrtc::InternalDataChannelInit config;
+  config.id = 1;
+  config.negotiated = true;
+  config.open_handshake_role = webrtc::InternalDataChannelInit::kNone;
+
+  SetChannelReady();
+  talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+      &provider_, cricket::DCT_SCTP, "test1", config);
+
+  EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
+  EXPECT_EQ(0U, provider_.last_send_data_params().ssrc);
+}
+
+// Tests that OPEN_ACK message is sent if the datachannel is created from an
+// OPEN message.
+TEST_F(SctpDataChannelTest, OpenAckSentIfCreatedFromOpenMessage) {
+  webrtc::InternalDataChannelInit config;
+  config.id = 1;
+  config.negotiated = true;
+  config.open_handshake_role = webrtc::InternalDataChannelInit::kAcker;
+
+  SetChannelReady();
+  talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+      &provider_, cricket::DCT_SCTP, "test1", config);
+
+  EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, dc->state(), 1000);
+
+  EXPECT_EQ(static_cast<unsigned int>(config.id),
+            provider_.last_send_data_params().ssrc);
+  EXPECT_EQ(cricket::DMT_CONTROL, provider_.last_send_data_params().type);
+}
+
+// Tests the OPEN_ACK role assigned by InternalDataChannelInit.
+TEST_F(SctpDataChannelTest, OpenAckRoleInitialization) {
+  webrtc::InternalDataChannelInit init;
+  EXPECT_EQ(webrtc::InternalDataChannelInit::kOpener, init.open_handshake_role);
+  EXPECT_FALSE(init.negotiated);
+
+  webrtc::DataChannelInit base;
+  base.negotiated = true;
+  webrtc::InternalDataChannelInit init2(base);
+  EXPECT_EQ(webrtc::InternalDataChannelInit::kNone, init2.open_handshake_role);
+}
diff --git a/talk/app/webrtc/localaudiosource.cc b/talk/app/webrtc/localaudiosource.cc
index 3dc5c6c..7ac59fc 100644
--- a/talk/app/webrtc/localaudiosource.cc
+++ b/talk/app/webrtc/localaudiosource.cc
@@ -37,24 +37,6 @@
 
 namespace webrtc {
 
-// Constraint keys.
-// They are declared as static members in mediaconstraintsinterface.h
-const char MediaConstraintsInterface::kEchoCancellation[] =
-    "googEchoCancellation";
-const char MediaConstraintsInterface::kExperimentalEchoCancellation[] =
-    "googEchoCancellation2";
-const char MediaConstraintsInterface::kAutoGainControl[] =
-    "googAutoGainControl";
-const char MediaConstraintsInterface::kExperimentalAutoGainControl[] =
-    "googAutoGainControl2";
-const char MediaConstraintsInterface::kNoiseSuppression[] =
-    "googNoiseSuppression";
-const char MediaConstraintsInterface::kHighpassFilter[] =
-    "googHighpassFilter";
-const char MediaConstraintsInterface::kTypingNoiseDetection[] =
-    "googTypingNoiseDetection";
-const char MediaConstraintsInterface::kAudioMirroring[] = "googAudioMirroring";
-
 namespace {
 
 // Convert constraints to audio options. Return false if constraints are
diff --git a/talk/app/webrtc/mediaconstraintsinterface.cc b/talk/app/webrtc/mediaconstraintsinterface.cc
index 2e6af77..2512932 100644
--- a/talk/app/webrtc/mediaconstraintsinterface.cc
+++ b/talk/app/webrtc/mediaconstraintsinterface.cc
@@ -34,6 +34,64 @@
 const char MediaConstraintsInterface::kValueTrue[] = "true";
 const char MediaConstraintsInterface::kValueFalse[] = "false";
 
+// Constraints declared as static members in mediastreaminterface.h
+// Specified by draft-alvestrand-constraints-resolution-00b
+const char MediaConstraintsInterface::kMinAspectRatio[] = "minAspectRatio";
+const char MediaConstraintsInterface::kMaxAspectRatio[] = "maxAspectRatio";
+const char MediaConstraintsInterface::kMaxWidth[] = "maxWidth";
+const char MediaConstraintsInterface::kMinWidth[] = "minWidth";
+const char MediaConstraintsInterface::kMaxHeight[] = "maxHeight";
+const char MediaConstraintsInterface::kMinHeight[] = "minHeight";
+const char MediaConstraintsInterface::kMaxFrameRate[] = "maxFrameRate";
+const char MediaConstraintsInterface::kMinFrameRate[] = "minFrameRate";
+
+// Audio constraints.
+const char MediaConstraintsInterface::kEchoCancellation[] =
+    "googEchoCancellation";
+const char MediaConstraintsInterface::kExperimentalEchoCancellation[] =
+    "googEchoCancellation2";
+const char MediaConstraintsInterface::kAutoGainControl[] =
+    "googAutoGainControl";
+const char MediaConstraintsInterface::kExperimentalAutoGainControl[] =
+    "googAutoGainControl2";
+const char MediaConstraintsInterface::kNoiseSuppression[] =
+    "googNoiseSuppression";
+const char MediaConstraintsInterface::kHighpassFilter[] =
+    "googHighpassFilter";
+const char MediaConstraintsInterface::kTypingNoiseDetection[] =
+    "googTypingNoiseDetection";
+const char MediaConstraintsInterface::kAudioMirroring[] = "googAudioMirroring";
+
+// Google-specific constraint keys for a local video source (getUserMedia).
+const char MediaConstraintsInterface::kNoiseReduction[] = "googNoiseReduction";
+const char MediaConstraintsInterface::kLeakyBucket[] = "googLeakyBucket";
+const char MediaConstraintsInterface::kTemporalLayeredScreencast[] =
+    "googTemporalLayeredScreencast";
+// TODO(ronghuawu): Remove once cpu overuse detection is stable.
+const char MediaConstraintsInterface::kCpuOveruseDetection[] =
+    "googCpuOveruseDetection";
+
+// Constraint keys for CreateOffer / CreateAnswer defined in W3C specification.
+const char MediaConstraintsInterface::kOfferToReceiveAudio[] =
+    "OfferToReceiveAudio";
+const char MediaConstraintsInterface::kOfferToReceiveVideo[] =
+    "OfferToReceiveVideo";
+const char MediaConstraintsInterface::kVoiceActivityDetection[] =
+    "VoiceActivityDetection";
+const char MediaConstraintsInterface::kIceRestart[] =
+    "IceRestart";
+// Google specific constraint for BUNDLE enable/disable.
+const char MediaConstraintsInterface::kUseRtpMux[] =
+    "googUseRtpMUX";
+
+// Below constraints should be used during PeerConnection construction.
+const char MediaConstraintsInterface::kEnableDtlsSrtp[] =
+    "DtlsSrtpKeyAgreement";
+const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
+    "RtpDataChannels";
+const char MediaConstraintsInterface::kEnableDscp[] = "googDscp";
+const char MediaConstraintsInterface::kEnableIPv6[] = "googIPv6";
+
 // Set |value| to the value associated with the first appearance of |key|, or
 // return false if |key| is not found.
 bool MediaConstraintsInterface::Constraints::FindFirst(
diff --git a/talk/app/webrtc/mediaconstraintsinterface.h b/talk/app/webrtc/mediaconstraintsinterface.h
index 5cf2184..7a207e4 100644
--- a/talk/app/webrtc/mediaconstraintsinterface.h
+++ b/talk/app/webrtc/mediaconstraintsinterface.h
@@ -107,11 +107,10 @@
   static const char kEnableDtlsSrtp[];  // Enable DTLS-SRTP
   // Temporary pseudo-constraints used to enable DataChannels
   static const char kEnableRtpDataChannels[];  // Enable RTP DataChannels
-  // TODO(perkj): Remove kEnableSctpDataChannels once Chrome use
-  // PeerConnectionFactory::SetOptions.
-  static const char kEnableSctpDataChannels[];  // Enable SCTP DataChannels
   // Temporary pseudo-constraint for enabling DSCP through JS.
   static const char kEnableDscp[];
+  // Constraint to enable IPv6 through JS.
+  static const char kEnableIPv6[];
 
   // The prefix of internal-only constraints whose JS set values should be
   // stripped by Chrome before passed down to Libjingle.
diff --git a/talk/app/webrtc/mediastreamsignaling.cc b/talk/app/webrtc/mediastreamsignaling.cc
index 7586938..89129ac 100644
--- a/talk/app/webrtc/mediastreamsignaling.cc
+++ b/talk/app/webrtc/mediastreamsignaling.cc
@@ -34,6 +34,7 @@
 #include "talk/app/webrtc/mediaconstraintsinterface.h"
 #include "talk/app/webrtc/mediastreamtrackproxy.h"
 #include "talk/app/webrtc/remotevideocapturer.h"
+#include "talk/app/webrtc/sctputils.h"
 #include "talk/app/webrtc/videosource.h"
 #include "talk/app/webrtc/videotrack.h"
 #include "talk/base/bytebuffer.h"
@@ -49,18 +50,6 @@
 using talk_base::scoped_ptr;
 using talk_base::scoped_refptr;
 
-// Supported MediaConstraints.
-const char MediaConstraintsInterface::kOfferToReceiveAudio[] =
-    "OfferToReceiveAudio";
-const char MediaConstraintsInterface::kOfferToReceiveVideo[] =
-    "OfferToReceiveVideo";
-const char MediaConstraintsInterface::kIceRestart[] =
-    "IceRestart";
-const char MediaConstraintsInterface::kUseRtpMux[] =
-    "googUseRtpMUX";
-const char MediaConstraintsInterface::kVoiceActivityDetection[] =
-    "VoiceActivityDetection";
-
 static bool ParseConstraints(
     const MediaConstraintsInterface* constraints,
     cricket::MediaSessionOptions* options, bool is_answer) {
@@ -261,13 +250,24 @@
 }
 
 bool MediaStreamSignaling::AddDataChannelFromOpenMessage(
-    const std::string& label,
-    const DataChannelInit& config) {
+    const cricket::ReceiveDataParams& params,
+    const talk_base::Buffer& payload) {
   if (!data_channel_factory_) {
     LOG(LS_WARNING) << "Remote peer requested a DataChannel but DataChannels "
                     << "are not supported.";
     return false;
   }
+
+  std::string label;
+  InternalDataChannelInit config;
+  config.id = params.ssrc;
+  if (!ParseDataChannelOpenMessage(payload, &label, &config)) {
+    LOG(LS_WARNING) << "Failed to parse the OPEN message for sid "
+                    << params.ssrc;
+    return false;
+  }
+  config.open_handshake_role = InternalDataChannelInit::kAcker;
+
   scoped_refptr<DataChannel> channel(
       data_channel_factory_->CreateDataChannel(label, &config));
   if (!channel.get()) {
diff --git a/talk/app/webrtc/mediastreamsignaling.h b/talk/app/webrtc/mediastreamsignaling.h
index c600f06..6c54f40 100644
--- a/talk/app/webrtc/mediastreamsignaling.h
+++ b/talk/app/webrtc/mediastreamsignaling.h
@@ -194,8 +194,8 @@
   // be offered in a SessionDescription.
   bool AddDataChannel(DataChannel* data_channel);
   // After we receive an OPEN message, create a data channel and add it.
-  bool AddDataChannelFromOpenMessage(
-      const std::string& label, const DataChannelInit& config);
+  bool AddDataChannelFromOpenMessage(const cricket::ReceiveDataParams& params,
+                                     const talk_base::Buffer& payload);
 
   // Returns a MediaSessionOptions struct with options decided by |constraints|,
   // the local MediaStreams and DataChannels.
diff --git a/talk/app/webrtc/mediastreamsignaling_unittest.cc b/talk/app/webrtc/mediastreamsignaling_unittest.cc
index 5b88aa0..6debcfd 100644
--- a/talk/app/webrtc/mediastreamsignaling_unittest.cc
+++ b/talk/app/webrtc/mediastreamsignaling_unittest.cc
@@ -30,6 +30,7 @@
 #include "talk/app/webrtc/audiotrack.h"
 #include "talk/app/webrtc/mediastream.h"
 #include "talk/app/webrtc/mediastreamsignaling.h"
+#include "talk/app/webrtc/sctputils.h"
 #include "talk/app/webrtc/streamcollection.h"
 #include "talk/app/webrtc/test/fakeconstraints.h"
 #include "talk/app/webrtc/test/fakedatachannelprovider.h"
@@ -246,13 +247,19 @@
 
   virtual talk_base::scoped_refptr<webrtc::DataChannel> CreateDataChannel(
       const std::string& label,
-      const webrtc::DataChannelInit* config) {
-    return webrtc::DataChannel::Create(provider_, type_, label, config);
+      const webrtc::InternalDataChannelInit* config) {
+    last_init_ = *config;
+    return webrtc::DataChannel::Create(provider_, type_, label, *config);
+  }
+
+  const webrtc::InternalDataChannelInit& last_init() const {
+      return last_init_;
   }
 
  private:
   FakeDataChannelProvider* provider_;
   cricket::DataChannelType type_;
+  webrtc::InternalDataChannelInit last_init_;
 };
 
 class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
@@ -528,11 +535,11 @@
 
   talk_base::scoped_refptr<webrtc::DataChannel> AddDataChannel(
       cricket::DataChannelType type, const std::string& label, int id) {
-    webrtc::DataChannelInit config;
+    webrtc::InternalDataChannelInit config;
     config.id = id;
     talk_base::scoped_refptr<webrtc::DataChannel> data_channel(
         webrtc::DataChannel::Create(
-            data_channel_provider_.get(), type, label, &config));
+            data_channel_provider_.get(), type, label, config));
     EXPECT_TRUE(data_channel.get() != NULL);
     EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));
     return data_channel;
@@ -1078,10 +1085,10 @@
 TEST_F(MediaStreamSignalingTest, RtpDuplicatedLabelNotAllowed) {
   AddDataChannel(cricket::DCT_RTP, "a", -1);
 
-  webrtc::DataChannelInit config;
+  webrtc::InternalDataChannelInit config;
   talk_base::scoped_refptr<webrtc::DataChannel> data_channel =
       webrtc::DataChannel::Create(
-          data_channel_provider_.get(), cricket::DCT_RTP, "a", &config);
+          data_channel_provider_.get(), cricket::DCT_RTP, "a", config);
   ASSERT_TRUE(data_channel.get() != NULL);
   EXPECT_FALSE(signaling_->AddDataChannel(data_channel.get()));
 }
@@ -1092,6 +1099,25 @@
   AddDataChannel(cricket::DCT_SCTP, "a", -1);
 }
 
+// Verifies the correct configuration is used to create DataChannel from an OPEN
+// message.
+TEST_F(MediaStreamSignalingTest, CreateDataChannelFromOpenMessage) {
+  FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
+                                      cricket::DCT_SCTP);
+  signaling_->SetDataChannelFactory(&fake_factory);
+  webrtc::DataChannelInit config;
+  config.id = 1;
+  talk_base::Buffer payload;
+  webrtc::WriteDataChannelOpenMessage("a", config, &payload);
+  cricket::ReceiveDataParams params;
+  params.ssrc = config.id;
+  EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
+  EXPECT_EQ(config.id, fake_factory.last_init().id);
+  EXPECT_FALSE(fake_factory.last_init().negotiated);
+  EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker,
+            fake_factory.last_init().open_handshake_role);
+}
+
 // Verifies that duplicated label from OPEN message is allowed.
 TEST_F(MediaStreamSignalingTest, DuplicatedLabelFromOpenMessageAllowed) {
   AddDataChannel(cricket::DCT_SCTP, "a", -1);
@@ -1101,5 +1127,9 @@
   signaling_->SetDataChannelFactory(&fake_factory);
   webrtc::DataChannelInit config;
   config.id = 0;
-  EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage("a", config));
+  talk_base::Buffer payload;
+  webrtc::WriteDataChannelOpenMessage("a", config, &payload);
+  cricket::ReceiveDataParams params;
+  params.ssrc = config.id;
+  EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage(params, payload));
 }
diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc
index e10e8fc..40640cf 100644
--- a/talk/app/webrtc/peerconnection.cc
+++ b/talk/app/webrtc/peerconnection.cc
@@ -32,6 +32,7 @@
 #include "talk/app/webrtc/dtmfsender.h"
 #include "talk/app/webrtc/jsepicecandidate.h"
 #include "talk/app/webrtc/jsepsessiondescription.h"
+#include "talk/app/webrtc/mediaconstraintsinterface.h"
 #include "talk/app/webrtc/mediastreamhandler.h"
 #include "talk/app/webrtc/streamcollection.h"
 #include "talk/base/logging.h"
@@ -359,11 +360,21 @@
   observer_ = observer;
   port_allocator_.reset(
       allocator_factory->CreatePortAllocator(stun_config, turn_config));
+
   // To handle both internal and externally created port allocator, we will
-  // enable BUNDLE here. Also enabling TURN and disable legacy relay service.
-  port_allocator_->set_flags(cricket::PORTALLOCATOR_ENABLE_BUNDLE |
-                             cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
-                             cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET);
+  // enable BUNDLE here.
+  int portallocator_flags = cricket::PORTALLOCATOR_ENABLE_BUNDLE |
+                            cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG |
+                            cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET;
+  bool value;
+  if (FindConstraint(
+        constraints,
+        MediaConstraintsInterface::kEnableIPv6,
+        &value, NULL) && value) {
+    portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_IPV6;
+  }
+
+  port_allocator_->set_flags(portallocator_flags);
   // No step delay is used while allocating ports.
   port_allocator_->set_step_delay(cricket::kMinimumStepDelay);
 
@@ -485,8 +496,12 @@
 PeerConnection::CreateDataChannel(
     const std::string& label,
     const DataChannelInit* config) {
+  talk_base::scoped_ptr<InternalDataChannelInit> internal_config;
+  if (config) {
+    internal_config.reset(new InternalDataChannelInit(*config));
+  }
   talk_base::scoped_refptr<DataChannelInterface> channel(
-      session_->CreateDataChannel(label, config));
+      session_->CreateDataChannel(label, internal_config.get()));
   if (!channel.get())
     return NULL;
 
diff --git a/talk/media/sctp/sctputils.cc b/talk/app/webrtc/sctputils.cc
similarity index 80%
rename from talk/media/sctp/sctputils.cc
rename to talk/app/webrtc/sctputils.cc
index 4073905..dcc6ba6 100644
--- a/talk/media/sctp/sctputils.cc
+++ b/talk/app/webrtc/sctputils.cc
@@ -25,19 +25,19 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "talk/media/sctp/sctputils.h"
+#include "talk/app/webrtc/sctputils.h"
 
-#include "talk/app/webrtc/datachannelinterface.h"
 #include "talk/base/buffer.h"
 #include "talk/base/bytebuffer.h"
 #include "talk/base/logging.h"
 
-namespace cricket {
+namespace webrtc {
 
 // Format defined at
-// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
+// http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-01#section
 
 static const uint8 DATA_CHANNEL_OPEN_MESSAGE_TYPE = 0x03;
+static const uint8 DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE = 0x02;
 
 enum DataChannelOpenMessageChannelType {
   DCOMCT_ORDERED_RELIABLE = 0x00,
@@ -48,10 +48,9 @@
   DCOMCT_UNORDERED_PARTIAL_TIME = 0x82,
 };
 
-bool ParseDataChannelOpenMessage(
-    const talk_base::Buffer& payload,
-    std::string* label,
-    webrtc::DataChannelInit* config) {
+bool ParseDataChannelOpenMessage(const talk_base::Buffer& payload,
+                                 std::string* label,
+                                 DataChannelInit* config) {
   // Format defined at
   // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
 
@@ -123,14 +122,28 @@
       config->maxRetransmitTime = reliability_param;
       break;
   }
-
   return true;
 }
 
-bool WriteDataChannelOpenMessage(
-    const std::string& label,
-    const webrtc::DataChannelInit& config,
-    talk_base::Buffer* payload) {
+bool ParseDataChannelOpenAckMessage(const talk_base::Buffer& payload) {
+  talk_base::ByteBuffer buffer(payload.data(), payload.length());
+
+  uint8 message_type;
+  if (!buffer.ReadUInt8(&message_type)) {
+    LOG(LS_WARNING) << "Could not read OPEN_ACK message type.";
+    return false;
+  }
+  if (message_type != DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE) {
+    LOG(LS_WARNING) << "Data Channel OPEN_ACK message of unexpected type: "
+                    << message_type;
+    return false;
+  }
+  return true;
+}
+
+bool WriteDataChannelOpenMessage(const std::string& label,
+                                 const DataChannelInit& config,
+                                 talk_base::Buffer* payload) {
   // Format defined at
   // http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
   uint8 channel_type = 0;
@@ -173,4 +186,9 @@
   return true;
 }
 
-}  // namespace cricket
+void WriteDataChannelOpenAckMessage(talk_base::Buffer* payload) {
+  talk_base::ByteBuffer buffer(talk_base::ByteBuffer::ORDER_NETWORK);
+  buffer.WriteUInt8(DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE);
+  payload->SetData(buffer.Data(), buffer.Length());
+}
+}  // namespace webrtc
diff --git a/talk/media/sctp/sctputils.h b/talk/app/webrtc/sctputils.h
similarity index 81%
rename from talk/media/sctp/sctputils.h
rename to talk/app/webrtc/sctputils.h
index d349274..d0b4e9c 100644
--- a/talk/media/sctp/sctputils.h
+++ b/talk/app/webrtc/sctputils.h
@@ -25,29 +25,31 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef TALK_MEDIA_BASE_SCTPUTILS_H_
-#define TALK_MEDIA_BASE_SCTPUTILS_H_
+#ifndef TALK_APP_WEBRTC_SCTPUTILS_H_
+#define TALK_APP_WEBRTC_SCTPUTILS_H_
 
 #include <string>
 
+#include "talk/app/webrtc/datachannelinterface.h"
+
 namespace talk_base {
 class Buffer;
 }  // namespace talk_base
 
 namespace webrtc {
 struct DataChannelInit;
-}  // namespace webrtc
-
-namespace cricket {
 
 bool ParseDataChannelOpenMessage(const talk_base::Buffer& payload,
                                  std::string* label,
-                                 webrtc::DataChannelInit* config);
+                                 DataChannelInit* config);
+
+bool ParseDataChannelOpenAckMessage(const talk_base::Buffer& payload);
 
 bool WriteDataChannelOpenMessage(const std::string& label,
-                                 const webrtc::DataChannelInit& config,
+                                 const DataChannelInit& config,
                                  talk_base::Buffer* payload);
 
-}  // namespace cricket
+void WriteDataChannelOpenAckMessage(talk_base::Buffer* payload);
+}  // namespace webrtc
 
-#endif  // TALK_MEDIA_BASE_SCTPUTILS_H_
+#endif  // TALK_APP_WEBRTC_SCTPUTILS_H_
diff --git a/talk/media/sctp/sctputils_unittest.cc b/talk/app/webrtc/sctputils_unittest.cc
similarity index 80%
rename from talk/media/sctp/sctputils_unittest.cc
rename to talk/app/webrtc/sctputils_unittest.cc
index 70f67b8..6a139a0 100644
--- a/talk/media/sctp/sctputils_unittest.cc
+++ b/talk/app/webrtc/sctputils_unittest.cc
@@ -25,10 +25,9 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "talk/app/webrtc/datachannelinterface.h"
 #include "talk/base/bytebuffer.h"
 #include "talk/base/gunit.h"
-#include "talk/media/sctp/sctputils.h"
+#include "talk/app/webrtc/sctputils.h"
 
 class SctpUtilsTest : public testing::Test {
  public:
@@ -80,23 +79,22 @@
   }
 };
 
-TEST_F(SctpUtilsTest, WriteParseMessageWithOrderedReliable) {
-  std::string input_label = "abc";
+TEST_F(SctpUtilsTest, WriteParseOpenMessageWithOrderedReliable) {
   webrtc::DataChannelInit config;
+  std::string label = "abc";
   config.protocol = "y";
 
   talk_base::Buffer packet;
-  ASSERT_TRUE(
-      cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
+  ASSERT_TRUE(webrtc::WriteDataChannelOpenMessage(label, config, &packet));
 
-  VerifyOpenMessageFormat(packet, input_label, config);
+  VerifyOpenMessageFormat(packet, label, config);
 
   std::string output_label;
   webrtc::DataChannelInit output_config;
-  ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
+  ASSERT_TRUE(webrtc::ParseDataChannelOpenMessage(
       packet, &output_label, &output_config));
 
-  EXPECT_EQ(input_label, output_label);
+  EXPECT_EQ(label, output_label);
   EXPECT_EQ(config.protocol, output_config.protocol);
   EXPECT_EQ(config.ordered, output_config.ordered);
   EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
@@ -104,24 +102,23 @@
 }
 
 TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmitTime) {
-  std::string input_label = "abc";
   webrtc::DataChannelInit config;
+  std::string label = "abc";
   config.ordered = false;
   config.maxRetransmitTime = 10;
   config.protocol = "y";
 
   talk_base::Buffer packet;
-  ASSERT_TRUE(
-      cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
+  ASSERT_TRUE(webrtc::WriteDataChannelOpenMessage(label, config, &packet));
 
-  VerifyOpenMessageFormat(packet, input_label, config);
+  VerifyOpenMessageFormat(packet, label, config);
 
   std::string output_label;
   webrtc::DataChannelInit output_config;
-  ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
+  ASSERT_TRUE(webrtc::ParseDataChannelOpenMessage(
       packet, &output_label, &output_config));
 
-  EXPECT_EQ(input_label, output_label);
+  EXPECT_EQ(label, output_label);
   EXPECT_EQ(config.protocol, output_config.protocol);
   EXPECT_EQ(config.ordered, output_config.ordered);
   EXPECT_EQ(config.maxRetransmitTime, output_config.maxRetransmitTime);
@@ -129,25 +126,36 @@
 }
 
 TEST_F(SctpUtilsTest, WriteParseOpenMessageWithMaxRetransmits) {
-  std::string input_label = "abc";
   webrtc::DataChannelInit config;
+  std::string label = "abc";
   config.maxRetransmits = 10;
   config.protocol = "y";
 
   talk_base::Buffer packet;
-  ASSERT_TRUE(
-      cricket::WriteDataChannelOpenMessage(input_label, config, &packet));
+  ASSERT_TRUE(webrtc::WriteDataChannelOpenMessage(label, config, &packet));
 
-  VerifyOpenMessageFormat(packet, input_label, config);
+  VerifyOpenMessageFormat(packet, label, config);
 
   std::string output_label;
   webrtc::DataChannelInit output_config;
-  ASSERT_TRUE(cricket::ParseDataChannelOpenMessage(
+  ASSERT_TRUE(webrtc::ParseDataChannelOpenMessage(
       packet, &output_label, &output_config));
 
-  EXPECT_EQ(input_label, output_label);
+  EXPECT_EQ(label, output_label);
   EXPECT_EQ(config.protocol, output_config.protocol);
   EXPECT_EQ(config.ordered, output_config.ordered);
   EXPECT_EQ(config.maxRetransmits, output_config.maxRetransmits);
   EXPECT_EQ(-1, output_config.maxRetransmitTime);
 }
+
+TEST_F(SctpUtilsTest, WriteParseAckMessage) {
+  talk_base::Buffer packet;
+  webrtc::WriteDataChannelOpenAckMessage(&packet);
+
+  uint8 message_type;
+  talk_base::ByteBuffer buffer(packet.data(), packet.length());
+  ASSERT_TRUE(buffer.ReadUInt8(&message_type));
+  EXPECT_EQ(0x02, message_type);
+
+  EXPECT_TRUE(webrtc::ParseDataChannelOpenAckMessage(packet));
+}
diff --git a/talk/app/webrtc/videosource.cc b/talk/app/webrtc/videosource.cc
index f0182f4..b36a811 100644
--- a/talk/app/webrtc/videosource.cc
+++ b/talk/app/webrtc/videosource.cc
@@ -36,30 +36,6 @@
 using webrtc::MediaConstraintsInterface;
 using webrtc::MediaSourceInterface;
 
-namespace webrtc {
-
-// Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b
-// They are declared as static members in mediastreaminterface.h
-const char MediaConstraintsInterface::kMinAspectRatio[] = "minAspectRatio";
-const char MediaConstraintsInterface::kMaxAspectRatio[] = "maxAspectRatio";
-const char MediaConstraintsInterface::kMaxWidth[] = "maxWidth";
-const char MediaConstraintsInterface::kMinWidth[] = "minWidth";
-const char MediaConstraintsInterface::kMaxHeight[] = "maxHeight";
-const char MediaConstraintsInterface::kMinHeight[] = "minHeight";
-const char MediaConstraintsInterface::kMaxFrameRate[] = "maxFrameRate";
-const char MediaConstraintsInterface::kMinFrameRate[] = "minFrameRate";
-
-// Google-specific keys
-const char MediaConstraintsInterface::kNoiseReduction[] = "googNoiseReduction";
-const char MediaConstraintsInterface::kLeakyBucket[] = "googLeakyBucket";
-const char MediaConstraintsInterface::kTemporalLayeredScreencast[] =
-    "googTemporalLayeredScreencast";
-// TODO(ronghuawu): Remove once cpu overuse detection is stable.
-const char MediaConstraintsInterface::kCpuOveruseDetection[] =
-    "googCpuOveruseDetection";
-
-}  // namespace webrtc
-
 namespace {
 
 const double kRoundingTruncation = 0.0005;
diff --git a/talk/app/webrtc/webrtcsdp_unittest.cc b/talk/app/webrtc/webrtcsdp_unittest.cc
index 5418683..8415197 100644
--- a/talk/app/webrtc/webrtcsdp_unittest.cc
+++ b/talk/app/webrtc/webrtcsdp_unittest.cc
@@ -1172,6 +1172,7 @@
         "m=video 3457 RTP/SAVPF 101\r\n"
         "a=rtpmap:101 VP8/90000\r\n"
         "a=rtcp-fb:101 nack\r\n"
+        "a=rtcp-fb:101 nack pli\r\n"
         "a=rtcp-fb:101 goog-remb\r\n"
         "a=rtcp-fb:101 ccm fir\r\n";
     std::ostringstream os;
@@ -1204,6 +1205,9 @@
         cricket::FeedbackParam(cricket::kRtcpFbParamNack,
                                cricket::kParamValueEmpty)));
     EXPECT_TRUE(vp8.HasFeedbackParam(
+        cricket::FeedbackParam(cricket::kRtcpFbParamNack,
+                               cricket::kRtcpFbNackParamPli)));
+    EXPECT_TRUE(vp8.HasFeedbackParam(
         cricket::FeedbackParam(cricket::kRtcpFbParamRemb,
                                cricket::kParamValueEmpty)));
     EXPECT_TRUE(vp8.HasFeedbackParam(
@@ -1902,6 +1906,9 @@
   // Missing space.
   const char kSdpInvalidLine6[] = "a=fingerprint:sha-1"
       "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB";
+  // MD5 is not allowed in fingerprints.
+  const char kSdpInvalidLine7[] = "a=fingerprint:md5 "
+      "4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B";
 
   // Broken session description
   ReplaceAndTryToParse("v=", kSdpDestroyer);
@@ -1925,6 +1932,7 @@
   ReplaceAndTryToParse("a=sendrecv", kSdpInvalidLine4);
   ReplaceAndTryToParse("a=sendrecv", kSdpInvalidLine5);
   ReplaceAndTryToParse("a=sendrecv", kSdpInvalidLine6);
+  ReplaceAndTryToParse("a=sendrecv", kSdpInvalidLine7);
 }
 
 TEST_F(WebRtcSdpTest, DeserializeSdpWithReorderedPltypes) {
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index 7e153b3..404d963 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -54,23 +54,6 @@
 
 namespace webrtc {
 
-const char MediaConstraintsInterface::kInternalConstraintPrefix[] = "internal";
-
-// Supported MediaConstraints.
-// DSCP constraints.
-const char MediaConstraintsInterface::kEnableDscp[] = "googDscp";
-// DTLS-SRTP pseudo-constraints.
-const char MediaConstraintsInterface::kEnableDtlsSrtp[] =
-    "DtlsSrtpKeyAgreement";
-// DataChannel pseudo constraints.
-const char MediaConstraintsInterface::kEnableRtpDataChannels[] =
-    "RtpDataChannels";
-// This constraint is for internal use only, representing the Chrome command
-// line flag. So it is prefixed with kInternalConstraintPrefix so JS values
-// will be removed.
-const char MediaConstraintsInterface::kEnableSctpDataChannels[] =
-    "deprecatedSctpDataChannels";
-
 // Error messages
 const char kSetLocalSdpFailed[] = "SetLocalDescription failed: ";
 const char kSetRemoteSdpFailed[] = "SetRemoteDescription failed: ";
@@ -1022,7 +1005,7 @@
 
 talk_base::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
     const std::string& label,
-    const DataChannelInit* config) {
+    const InternalDataChannelInit* config) {
   if (state() == STATE_RECEIVEDTERMINATE) {
     return NULL;
   }
@@ -1030,8 +1013,8 @@
     LOG(LS_ERROR) << "CreateDataChannel: Data is not supported in this call.";
     return NULL;
   }
-  DataChannelInit new_config = config ? (*config) : DataChannelInit();
-
+  InternalDataChannelInit new_config =
+      config ? (*config) : InternalDataChannelInit();
   if (data_channel_type_ == cricket::DCT_SCTP) {
     if (new_config.id < 0) {
       talk_base::SSLRole role;
@@ -1047,8 +1030,8 @@
     }
   }
 
-  talk_base::scoped_refptr<DataChannel> channel(
-      DataChannel::Create(this, data_channel_type_, label, &new_config));
+  talk_base::scoped_refptr<DataChannel> channel(DataChannel::Create(
+      this, data_channel_type_, label, new_config));
   if (channel && !mediastream_signaling_->AddDataChannel(channel))
     return NULL;
 
@@ -1398,8 +1381,8 @@
   }
   if (sctp) {
     mediastream_signaling_->OnDataTransportCreatedForSctp();
-    data_channel_->SignalNewStreamReceived.connect(
-        this, &WebRtcSession::OnNewDataChannelReceived);
+    data_channel_->SignalDataReceived.connect(
+        this, &WebRtcSession::OnDataChannelMessageReceived);
   }
   return true;
 }
@@ -1417,14 +1400,17 @@
   saved_candidates_.clear();
 }
 
-void WebRtcSession::OnNewDataChannelReceived(
-    const std::string& label, const DataChannelInit& init) {
+void WebRtcSession::OnDataChannelMessageReceived(
+    cricket::DataChannel* channel,
+    const cricket::ReceiveDataParams& params,
+    const talk_base::Buffer& payload) {
   ASSERT(data_channel_type_ == cricket::DCT_SCTP);
-  if (!mediastream_signaling_->AddDataChannelFromOpenMessage(
-          label, init)) {
-    LOG(LS_WARNING) << "Failed to create data channel from OPEN message.";
-    return;
+  if (params.type == cricket::DMT_CONTROL &&
+      mediastream_signaling_->IsSctpSidAvailable(params.ssrc)) {
+    // Received CONTROL on unused sid, process as an OPEN message.
+    mediastream_signaling_->AddDataChannelFromOpenMessage(params, payload);
   }
+  // otherwise ignore the message.
 }
 
 // Returns false if bundle is enabled and rtcp_mux is disabled.
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 4c83906..6b58877 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -195,9 +195,10 @@
   virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE;
   virtual bool ReadyToSendData() const OVERRIDE;
 
+  // Implements DataChannelFactory.
   talk_base::scoped_refptr<DataChannel> CreateDataChannel(
       const std::string& label,
-      const DataChannelInit* config);
+      const InternalDataChannelInit* config) OVERRIDE;
 
   cricket::DataChannelType data_channel_type() const;
 
@@ -275,8 +276,11 @@
   // The |saved_candidates_| will be cleared after this function call.
   void CopySavedCandidates(SessionDescriptionInterface* dest_desc);
 
-  void OnNewDataChannelReceived(const std::string& label,
-                                const DataChannelInit& init);
+  // Listens to SCTP CONTROL messages on unused SIDs and process them as OPEN
+  // messages.
+  void OnDataChannelMessageReceived(cricket::DataChannel* channel,
+                                    const cricket::ReceiveDataParams& params,
+                                    const talk_base::Buffer& payload);
 
   bool GetLocalTrackId(uint32 ssrc, std::string* track_id);
   bool GetRemoteTrackId(uint32 ssrc, std::string* track_id);
diff --git a/talk/app/webrtc/webrtcsession_unittest.cc b/talk/app/webrtc/webrtcsession_unittest.cc
index 5ec880a..3fa4775 100644
--- a/talk/app/webrtc/webrtcsession_unittest.cc
+++ b/talk/app/webrtc/webrtcsession_unittest.cc
@@ -874,7 +874,7 @@
   }
 
   void SetLocalDescriptionWithDataChannel() {
-    webrtc::DataChannelInit dci;
+    webrtc::InternalDataChannelInit dci;
     dci.reliable = false;
     session_->CreateDataChannel("datachannel", &dci);
     SessionDescriptionInterface* offer = CreateOffer(NULL);
@@ -2675,7 +2675,7 @@
 
   // TEST PLAN: Set the port number to something new, set it in the SDP,
   // and pass it all the way down.
-  webrtc::DataChannelInit dci;
+  webrtc::InternalDataChannelInit dci;
   dci.reliable = true;
   EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type());
   talk_base::scoped_refptr<webrtc::DataChannel> dc =
diff --git a/talk/base/asyncsocket.h b/talk/base/asyncsocket.h
index 97859a7..2854558 100644
--- a/talk/base/asyncsocket.h
+++ b/talk/base/asyncsocket.h
@@ -27,6 +27,7 @@
 
 #ifndef TALK_BASE_ASYNCSOCKET_H_
 #define TALK_BASE_ASYNCSOCKET_H_
+#ifndef __native_client__
 
 #include "talk/base/common.h"
 #include "talk/base/sigslot.h"
@@ -138,4 +139,5 @@
 
 }  // namespace talk_base
 
+#endif  //  __native_client__
 #endif  // TALK_BASE_ASYNCSOCKET_H_
diff --git a/talk/base/byteorder.h b/talk/base/byteorder.h
index c6d0dbb..cf26a12 100644
--- a/talk/base/byteorder.h
+++ b/talk/base/byteorder.h
@@ -28,7 +28,7 @@
 #ifndef TALK_BASE_BYTEORDER_H_
 #define TALK_BASE_BYTEORDER_H_
 
-#ifdef POSIX
+#if defined(POSIX) && !defined(__native_client__)
 #include <arpa/inet.h>
 #endif
 
diff --git a/talk/base/logging.cc b/talk/base/logging.cc
index 4c7eae1..c1d0a53 100644
--- a/talk/base/logging.cc
+++ b/talk/base/logging.cc
@@ -349,6 +349,9 @@
   }
 #endif  // WIN32
 
+  LogToDebug(debug_level);
+
+#if !defined(__native_client__)  // No logging to file in NaCl.
   scoped_ptr<FileStream> stream;
   if (NO_LOGGING != file_level) {
     stream.reset(new FileStream);
@@ -357,8 +360,8 @@
     }
   }
 
-  LogToDebug(debug_level);
   LogToStream(stream.release(), file_level);
+#endif
 }
 
 int LogMessage::ParseLogSeverity(const std::string& value) {
diff --git a/talk/base/logging.h b/talk/base/logging.h
index 49e126b..01636e8 100644
--- a/talk/base/logging.h
+++ b/talk/base/logging.h
@@ -376,6 +376,13 @@
   LOG_GLE(sev)
 #define LAST_SYSTEM_ERROR \
   (::GetLastError())
+#elif __native_client__
+#define LOG_ERR_EX(sev, err) \
+  LOG(sev)
+#define LOG_ERR(sev) \
+  LOG(sev)
+#define LAST_SYSTEM_ERROR \
+  (0)
 #elif POSIX
 #define LOG_ERR_EX(sev, err) \
   LOG_ERRNO_EX(sev, err)
diff --git a/talk/base/messagedigest.cc b/talk/base/messagedigest.cc
index d91d067..975991d 100644
--- a/talk/base/messagedigest.cc
+++ b/talk/base/messagedigest.cc
@@ -70,6 +70,19 @@
 #endif
 }
 
+bool IsFips180DigestAlgorithm(const std::string& alg) {
+  // These are the FIPS 180 algorithms.  According to RFC 4572 Section 5,
+  // "Self-signed certificates (for which legacy certificates are not a
+  // consideration) MUST use one of the FIPS 180 algorithms (SHA-1,
+  // SHA-224, SHA-256, SHA-384, or SHA-512) as their signature algorithm,
+  // and thus also MUST use it to calculate certificate fingerprints."
+  return alg == DIGEST_SHA_1 ||
+         alg == DIGEST_SHA_224 ||
+         alg == DIGEST_SHA_256 ||
+         alg == DIGEST_SHA_384 ||
+         alg == DIGEST_SHA_512;
+}
+
 size_t ComputeDigest(MessageDigest* digest, const void* input, size_t in_len,
                      void* output, size_t out_len) {
   digest->Update(input, in_len);
diff --git a/talk/base/messagedigest.h b/talk/base/messagedigest.h
index 734082b..e8f303f 100644
--- a/talk/base/messagedigest.h
+++ b/talk/base/messagedigest.h
@@ -60,6 +60,9 @@
   static MessageDigest* Create(const std::string& alg);
 };
 
+// A whitelist of approved digest algorithms from RFC 4572 (FIPS 180).
+bool IsFips180DigestAlgorithm(const std::string& alg);
+
 // Functions to create hashes.
 
 // Computes the hash of |in_len| bytes of |input|, using the |digest| hash
diff --git a/talk/base/messagequeue.cc b/talk/base/messagequeue.cc
index 15b700f..64e63ae 100644
--- a/talk/base/messagequeue.cc
+++ b/talk/base/messagequeue.cc
@@ -32,8 +32,13 @@
 #include "talk/base/common.h"
 #include "talk/base/logging.h"
 #include "talk/base/messagequeue.h"
+#if defined(__native_client__)
+#include "talk/base/nullsocketserver.h"
+typedef talk_base::NullSocketServer DefaultSocketServer;
+#else
 #include "talk/base/physicalsocketserver.h"
-
+typedef talk_base::PhysicalSocketServer DefaultSocketServer;
+#endif
 
 namespace talk_base {
 
@@ -129,7 +134,7 @@
     // server, and provide it to the MessageQueue, since the Thread controls
     // the I/O model, and MQ is agnostic to those details.  Anyway, this causes
     // messagequeue_unittest to depend on network libraries... yuck.
-    default_ss_.reset(new PhysicalSocketServer());
+    default_ss_.reset(new DefaultSocketServer());
     ss_ = default_ss_.get();
   }
   ss_->SetMessageQueue(this);
diff --git a/talk/base/socket.h b/talk/base/socket.h
index e738060..56e3ebc 100644
--- a/talk/base/socket.h
+++ b/talk/base/socket.h
@@ -28,6 +28,14 @@
 #ifndef TALK_BASE_SOCKET_H__
 #define TALK_BASE_SOCKET_H__
 
+#if defined(__native_client__)
+namespace talk_base {
+// These should never be defined or instantiated.
+class Socket;
+class AsyncSocket;
+}  // namespace talk_base
+#else
+
 #include <errno.h>
 
 #ifdef POSIX
@@ -199,4 +207,5 @@
 
 }  // namespace talk_base
 
+#endif  // !__native_client__
 #endif  // TALK_BASE_SOCKET_H__
diff --git a/talk/base/sslfingerprint.h b/talk/base/sslfingerprint.h
index b857789..0dfcdd9 100644
--- a/talk/base/sslfingerprint.h
+++ b/talk/base/sslfingerprint.h
@@ -65,7 +65,7 @@
 
   static SSLFingerprint* CreateFromRfc4572(const std::string& algorithm,
                                            const std::string& fingerprint) {
-    if (algorithm.empty())
+    if (algorithm.empty() || !talk_base::IsFips180DigestAlgorithm(algorithm))
       return NULL;
 
     if (fingerprint.empty())
diff --git a/talk/base/stream.cc b/talk/base/stream.cc
index b6b48f1d..02ae409 100644
--- a/talk/base/stream.cc
+++ b/talk/base/stream.cc
@@ -711,7 +711,7 @@
   }
 }
 
-#ifdef POSIX
+#if defined(POSIX) && !defined(__native_client__)
 
 // Have to identically rewrite the FileStream destructor or else it would call
 // the base class's Close() instead of the sub-class's.
diff --git a/talk/base/stream.h b/talk/base/stream.h
index d30be29..fceb4a8 100644
--- a/talk/base/stream.h
+++ b/talk/base/stream.h
@@ -28,6 +28,8 @@
 #ifndef TALK_BASE_STREAM_H_
 #define TALK_BASE_STREAM_H_
 
+#include <stdio.h>
+
 #include "talk/base/basictypes.h"
 #include "talk/base/buffer.h"
 #include "talk/base/criticalsection.h"
@@ -497,7 +499,6 @@
   size_t read_segment_available_;
 };
 
-
 // A stream which pushes writes onto a separate thread and
 // returns from the write call immediately.
 class AsyncWriteStream : public StreamInterface {
@@ -539,7 +540,7 @@
 };
 
 
-#ifdef POSIX
+#if defined(POSIX) && !defined(__native_client__)
 // A FileStream that is actually not a file, but the output or input of a
 // sub-command. See "man 3 popen" for documentation of the underlying OS popen()
 // function.
diff --git a/talk/base/unixfilesystem.cc b/talk/base/unixfilesystem.cc
index 3c8f4d2..1a5b75e 100644
--- a/talk/base/unixfilesystem.cc
+++ b/talk/base/unixfilesystem.cc
@@ -50,7 +50,6 @@
 #include <limits.h>
 #include <pwd.h>
 #include <stdio.h>
-#include <unistd.h>
 #endif  // POSIX && !OSX
 
 #if defined(LINUX)
@@ -368,6 +367,8 @@
   if (success)
     path->SetPathname(path8);
   return success;
+#elif defined(__native_client__)
+  return false;
 #else  // OSX
   char buffer[NAME_MAX+1];
   size_t len = readlink("/proc/self/exe", buffer, ARRAY_SIZE(buffer) - 1);
@@ -453,6 +454,7 @@
   if (!CreateFolder(*path, 0700)) {
     return false;
   }
+#if !defined(__native_client__)
   // If the folder already exists, it may have the wrong mode or be owned by
   // someone else, both of which are security problems. Setting the mode
   // avoids both issues since it will fail if the path is not owned by us.
@@ -460,6 +462,7 @@
     LOG_ERR(LS_ERROR) << "Can't set mode on " << path;
     return false;
   }
+#endif
   return true;
 }
 
@@ -553,3 +556,11 @@
 }
 
 }  // namespace talk_base
+
+#if defined(__native_client__)
+extern "C" int __attribute__((weak))
+link(const char* oldpath, const char* newpath) {
+  errno = EACCES;
+  return -1;
+}
+#endif
diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp
index 7e4767b..0b43435 100755
--- a/talk/libjingle.gyp
+++ b/talk/libjingle.gyp
@@ -847,8 +847,6 @@
         # TODO(ronghuawu): Enable when SCTP is ready.
         # 'media/sctp/sctpdataengine.cc',
         # 'media/sctp/sctpdataengine.h',
-        'media/sctp/sctputils.cc',
-        'media/sctp/sctputils.h',
         'media/webrtc/webrtccommon.h',
         'media/webrtc/webrtcexport.h',
         'media/webrtc/webrtcmediaengine.h',
@@ -1169,6 +1167,8 @@
         'app/webrtc/proxy.h',
         'app/webrtc/remotevideocapturer.cc',
         'app/webrtc/remotevideocapturer.h',
+        'app/webrtc/sctputils.cc',
+        'app/webrtc/sctputils.h',
         'app/webrtc/statscollector.cc',
         'app/webrtc/statscollector.h',
         'app/webrtc/statstypes.h',
diff --git a/talk/libjingle.scons b/talk/libjingle.scons
index 87b43f5..bab18b2 100644
--- a/talk/libjingle.scons
+++ b/talk/libjingle.scons
@@ -290,7 +290,6 @@
                "media/base/videoframe.cc",
                "media/devices/devicemanager.cc",
                "media/devices/filevideocapturer.cc",
-               "media/sctp/sctputils.cc",
                "session/media/audiomonitor.cc",
                "session/media/call.cc",
                "session/media/channel.cc",
diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp
index 7bfea59..47fcc2b 100755
--- a/talk/libjingle_tests.gyp
+++ b/talk/libjingle_tests.gyp
@@ -389,6 +389,7 @@
         'app/webrtc/peerconnectioninterface_unittest.cc',
         # 'app/webrtc/peerconnectionproxy_unittest.cc',
         'app/webrtc/remotevideocapturer_unittest.cc',
+        'app/webrtc/sctputils.cc',
         'app/webrtc/test/fakeaudiocapturemodule.cc',
         'app/webrtc/test/fakeaudiocapturemodule.h',
         'app/webrtc/test/fakeaudiocapturemodule_unittest.cc',
diff --git a/talk/media/base/constants.cc b/talk/media/base/constants.cc
index 9162ce4..a8a0da7 100644
--- a/talk/media/base/constants.cc
+++ b/talk/media/base/constants.cc
@@ -78,6 +78,7 @@
 const int kPreferredUseInbandFec = 0;
 
 const char kRtcpFbParamNack[] = "nack";
+const char kRtcpFbNackParamPli[] = "pli";
 const char kRtcpFbParamRemb[] = "goog-remb";
 
 const char kRtcpFbParamCcm[] = "ccm";
diff --git a/talk/media/base/constants.h b/talk/media/base/constants.h
index b80c0fc..5414db5 100644
--- a/talk/media/base/constants.h
+++ b/talk/media/base/constants.h
@@ -89,6 +89,7 @@
 
 // rtcp-fb messages according to RFC 4585
 extern const char kRtcpFbParamNack[];
+extern const char kRtcpFbNackParamPli[];
 // rtcp-fb messages according to
 // http://tools.ietf.org/html/draft-alvestrand-rmcat-remb-00
 extern const char kRtcpFbParamRemb[];
diff --git a/talk/media/base/fakevideorenderer.h b/talk/media/base/fakevideorenderer.h
index 362e592..cab77dd 100644
--- a/talk/media/base/fakevideorenderer.h
+++ b/talk/media/base/fakevideorenderer.h
@@ -48,6 +48,7 @@
   }
 
   virtual bool SetSize(int width, int height, int reserved) {
+    talk_base::CritScope cs(&crit_);
     width_ = width;
     height_ = height;
     ++num_set_sizes_;
@@ -56,6 +57,7 @@
   }
 
   virtual bool RenderFrame(const VideoFrame* frame) {
+    talk_base::CritScope cs(&crit_);
     // TODO(zhurunz) Check with VP8 team to see if we can remove this
     // tolerance on Y values.
     black_frame_ = CheckFrameColorYuv(6, 48, 128, 128, 128, 128, frame);
@@ -79,11 +81,26 @@
   }
 
   int errors() const { return errors_; }
-  int width() const { return width_; }
-  int height() const { return height_; }
-  int num_set_sizes() const { return num_set_sizes_; }
-  int num_rendered_frames() const { return num_rendered_frames_; }
-  bool black_frame() const { return black_frame_; }
+  int width() const {
+    talk_base::CritScope cs(&crit_);
+    return width_;
+  }
+  int height() const {
+    talk_base::CritScope cs(&crit_);
+    return height_;
+  }
+  int num_set_sizes() const {
+    talk_base::CritScope cs(&crit_);
+    return num_set_sizes_;
+  }
+  int num_rendered_frames() const {
+    talk_base::CritScope cs(&crit_);
+    return num_rendered_frames_;
+  }
+  bool black_frame() const {
+    talk_base::CritScope cs(&crit_);
+    return black_frame_;
+  }
 
   sigslot::signal3<int, int, int> SignalSetSize;
   sigslot::signal1<const VideoFrame*> SignalRenderFrame;
@@ -143,6 +160,7 @@
   int num_set_sizes_;
   int num_rendered_frames_;
   bool black_frame_;
+  mutable talk_base::CriticalSection crit_;
 };
 
 }  // namespace cricket
diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h
index 94ae03f..9c74762 100644
--- a/talk/media/base/mediachannel.h
+++ b/talk/media/base/mediachannel.h
@@ -50,10 +50,6 @@
 class Timing;
 }
 
-namespace webrtc {
-struct DataChannelInit;
-}
-
 namespace cricket {
 
 class AudioRenderer;
@@ -1157,11 +1153,6 @@
   // Signal when the media channel is ready to send the stream. Arguments are:
   //     writable(bool)
   sigslot::signal1<bool> SignalReadyToSend;
-  // Signal for notifying when a new stream is added from the remote side. Used
-  // for the in-band negotioation through the OPEN message for SCTP data
-  // channel.
-  sigslot::signal2<const std::string&, const webrtc::DataChannelInit&>
-      SignalNewStreamReceived;
 };
 
 }  // namespace cricket
diff --git a/talk/media/base/videoengine_unittest.h b/talk/media/base/videoengine_unittest.h
index d9266f2..2ffd14b 100644
--- a/talk/media/base/videoengine_unittest.h
+++ b/talk/media/base/videoengine_unittest.h
@@ -893,8 +893,11 @@
     talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
       new cricket::FakeVideoCapturer);
     capturer->SetScreencast(true);
-    cricket::VideoFormat format(1024, 768,
-                                cricket::VideoFormat::FpsToInterval(5), 0);
+    const int kTestWidth = 160;
+    const int kTestHeight = 120;
+    cricket::VideoFormat format(kTestWidth, kTestHeight,
+                                cricket::VideoFormat::FpsToInterval(5),
+                                cricket::FOURCC_I420);
     EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
     EXPECT_TRUE(channel_->AddSendStream(
         cricket::StreamParams::CreateLegacy(5678)));
@@ -902,8 +905,10 @@
     EXPECT_TRUE(channel_->AddRecvStream(
         cricket::StreamParams::CreateLegacy(5678)));
     EXPECT_TRUE(channel_->SetRenderer(5678, &renderer1));
-    EXPECT_TRUE(capturer->CaptureCustomFrame(1024, 768, cricket::FOURCC_I420));
-    EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, 1024, 768, kTimeout);
+    EXPECT_TRUE(capturer->CaptureCustomFrame(
+        kTestWidth, kTestHeight, cricket::FOURCC_I420));
+    EXPECT_FRAME_ON_RENDERER_WAIT(
+        renderer1, 1, kTestWidth, kTestHeight, kTimeout);
 
     // Get stats, and make sure they are correct for two senders.
     cricket::VideoMediaInfo info;
@@ -917,8 +922,8 @@
     EXPECT_EQ(DefaultCodec().height, info.senders[0].frame_height);
     EXPECT_EQ(1U, info.senders[1].ssrcs().size());
     EXPECT_EQ(5678U, info.senders[1].ssrcs()[0]);
-    EXPECT_EQ(1024, info.senders[1].frame_width);
-    EXPECT_EQ(768, info.senders[1].frame_height);
+    EXPECT_EQ(kTestWidth, info.senders[1].frame_width);
+    EXPECT_EQ(kTestHeight, info.senders[1].frame_height);
     // The capturer must be unregistered here as it runs out of it's scope next.
     EXPECT_TRUE(channel_->SetCapturer(5678, NULL));
   }
@@ -1221,9 +1226,11 @@
 
   // Tests that we can add and remove capturers and frames are sent out properly
   void AddRemoveCapturer() {
-    const cricket::VideoCodec codec(DefaultCodec());
+    cricket::VideoCodec codec = DefaultCodec();
+    codec.width = 320;
+    codec.height = 240;
     const int time_between_send = TimeBetweenSend(codec);
-    EXPECT_TRUE(SetDefaultCodec());
+    EXPECT_TRUE(SetOneCodec(codec));
     EXPECT_TRUE(SetSend(true));
     EXPECT_TRUE(channel_->SetRender(true));
     EXPECT_EQ(0, renderer_.num_rendered_frames());
@@ -1232,8 +1239,9 @@
     talk_base::scoped_ptr<cricket::FakeVideoCapturer> capturer(
         new cricket::FakeVideoCapturer);
     capturer->SetScreencast(true);
-    cricket::VideoFormat format(1024, 768,
-                                cricket::VideoFormat::FpsToInterval(30), 0);
+    cricket::VideoFormat format(480, 360,
+                                cricket::VideoFormat::FpsToInterval(30),
+                                cricket::FOURCC_I420);
     EXPECT_EQ(cricket::CS_RUNNING, capturer->Start(format));
     // All capturers start generating frames with the same timestamp. ViE does
     // not allow the same timestamp to be used. Capture one frame before
@@ -1305,11 +1313,6 @@
   void AddRemoveCapturerMultipleSources() {
     // WebRTC implementation will drop frames if pushed to quickly. Wait the
     // interval time to avoid that.
-    const cricket::VideoFormat send_format(
-        1024,
-        768,
-        cricket::VideoFormat::FpsToInterval(30),
-        0);
     // WebRTC implementation will drop frames if pushed to quickly. Wait the
     // interval time to avoid that.
     // Set up the stream associated with the engine.
@@ -1352,11 +1355,17 @@
     EXPECT_TRUE(SetSend(true));
     EXPECT_TRUE(channel_->SetRender(true));
     // Test capturer associated with engine.
-    EXPECT_TRUE(capturer1->CaptureCustomFrame(1024, 768, cricket::FOURCC_I420));
-    EXPECT_FRAME_ON_RENDERER_WAIT(renderer1, 1, 1024, 768, kTimeout);
+    const int kTestWidth = 160;
+    const int kTestHeight = 120;
+    EXPECT_TRUE(capturer1->CaptureCustomFrame(
+        kTestWidth, kTestHeight, cricket::FOURCC_I420));
+    EXPECT_FRAME_ON_RENDERER_WAIT(
+        renderer1, 1, kTestWidth, kTestHeight, kTimeout);
     // Capture a frame with additional capturer2, frames should be received
-    EXPECT_TRUE(capturer2->CaptureCustomFrame(1024, 768, cricket::FOURCC_I420));
-    EXPECT_FRAME_ON_RENDERER_WAIT(renderer2, 1, 1024, 768, kTimeout);
+    EXPECT_TRUE(capturer2->CaptureCustomFrame(
+        kTestWidth, kTestHeight, cricket::FOURCC_I420));
+    EXPECT_FRAME_ON_RENDERER_WAIT(
+        renderer2, 1, kTestWidth, kTestHeight, kTimeout);
     // Successfully remove the capturer.
     EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
     // Fail to re-remove the capturer.
diff --git a/talk/media/sctp/sctpdataengine.cc b/talk/media/sctp/sctpdataengine.cc
index 16ce9de..03bbdca 100644
--- a/talk/media/sctp/sctpdataengine.cc
+++ b/talk/media/sctp/sctpdataengine.cc
@@ -32,14 +32,12 @@
 #include <sstream>
 #include <vector>
 
-#include "talk/app/webrtc/datachannelinterface.h"
 #include "talk/base/buffer.h"
 #include "talk/base/helpers.h"
 #include "talk/base/logging.h"
 #include "talk/media/base/codec.h"
 #include "talk/media/base/constants.h"
 #include "talk/media/base/streamparams.h"
-#include "talk/media/sctp/sctputils.h"
 #include "usrsctplib/usrsctp.h"
 
 namespace {
@@ -497,11 +495,17 @@
 }
 
 bool SctpDataMediaChannel::AddRecvStream(const StreamParams& stream) {
-  return AddStream(stream);
+  // SCTP DataChannels are always bi-directional and calling AddSendStream will
+  // enable both sending and receiving on the stream. So AddRecvStream is a
+  // no-op.
+  return true;
 }
 
 bool SctpDataMediaChannel::RemoveRecvStream(uint32 ssrc) {
-  return ResetStream(ssrc);
+  // SCTP DataChannels are always bi-directional and calling RemoveSendStream
+  // will disable both sending and receiving on the stream. So RemoveRecvStream
+  // is a no-op.
+  return true;
 }
 
 bool SctpDataMediaChannel::SendData(
@@ -619,34 +623,12 @@
 
 void SctpDataMediaChannel::OnDataFromSctpToChannel(
     const ReceiveDataParams& params, talk_base::Buffer* buffer) {
-  if (open_streams_.find(params.ssrc) == open_streams_.end()) {
-    if (params.type == DMT_CONTROL) {
-      std::string label;
-      webrtc::DataChannelInit config;
-      if (ParseDataChannelOpenMessage(*buffer, &label, &config)) {
-        config.id = params.ssrc;
-        // Do not send the OPEN message for this data channel.
-        config.negotiated = true;
-        SignalNewStreamReceived(label, config);
-
-        // Add the stream immediately.
-        StreamParams sparams = StreamParams::CreateLegacy(params.ssrc);
-        AddSendStream(sparams);
-        AddRecvStream(sparams);
-      } else {
-        LOG(LS_ERROR) << debug_name_ << "->OnDataFromSctpToChannel(...): "
-                      << "Received malformed control message";
-      }
-    } else {
-      LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): "
-                      << "Received packet for unknown ssrc: " << params.ssrc;
-    }
-    return;
-  }
-
   if (receiving_) {
     LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): "
-                    << "Posting with length: " << buffer->length();
+                    << "Posting with length: " << buffer->length()
+                    << " on stream " << params.ssrc;
+    // Reports all received messages to upper layers, no matter whether the sid
+    // is known.
     SignalDataReceived(params, buffer->data(), buffer->length());
   } else {
     LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): "
@@ -663,9 +645,7 @@
 
   const uint32 ssrc = stream.first_ssrc();
   if (open_streams_.find(ssrc) != open_streams_.end()) {
-    // We usually get an AddSendStream and an AddRecvStream for each stream, so
-    // this is really unlikely to be a useful warning message.
-    LOG(LS_VERBOSE) << debug_name_ << "->Add(Send|Recv)Stream(...): "
+    LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
                     << "Not adding data stream '" << stream.id
                     << "' with ssrc=" << ssrc
                     << " because stream is already open.";
@@ -976,5 +956,4 @@
     }
   }
 }
-
 }  // namespace cricket
diff --git a/talk/media/sctp/sctpdataengine.h b/talk/media/sctp/sctpdataengine.h
index 8a5b4be..b34a810 100644
--- a/talk/media/sctp/sctpdataengine.h
+++ b/talk/media/sctp/sctpdataengine.h
@@ -30,7 +30,7 @@
 
 #include <errno.h>
 #include <string>
-#include <vector>
+#include <set>
 
 namespace cricket {
 // Some ERRNO values get re-#defined to WSA* equivalents in some talk/
@@ -216,7 +216,6 @@
                                talk_base::Buffer* buffer);
   void OnNotificationFromSctp(talk_base::Buffer* buffer);
   void OnNotificationAssocChange(const sctp_assoc_change& change);
-
   void OnStreamResetEvent(const struct sctp_stream_reset_event* evt);
 
   // Responsible for marshalling incoming data to the channels listeners, and
diff --git a/talk/media/sctp/sctpdataengine_unittest.cc b/talk/media/sctp/sctpdataengine_unittest.cc
index a6ae804..6371300 100644
--- a/talk/media/sctp/sctpdataengine_unittest.cc
+++ b/talk/media/sctp/sctpdataengine_unittest.cc
@@ -31,7 +31,6 @@
 #include <string>
 #include <vector>
 
-#include "talk/app/webrtc/datachannelinterface.h"
 #include "talk/base/bind.h"
 #include "talk/base/buffer.h"
 #include "talk/base/criticalsection.h"
@@ -44,7 +43,6 @@
 #include "talk/media/base/constants.h"
 #include "talk/media/base/mediachannel.h"
 #include "talk/media/sctp/sctpdataengine.h"
-#include "talk/media/sctp/sctputils.h"
 
 enum {
   MSG_PACKET = 1,
@@ -276,8 +274,6 @@
     // When data is received, pass it to the SctpFakeDataReceiver.
     channel->SignalDataReceived.connect(
         recv, &SctpFakeDataReceiver::OnDataReceived);
-    channel->SignalNewStreamReceived.connect(
-        this, &SctpDataMediaChannelTest::OnNewStreamReceived);
     return channel;
   }
 
@@ -286,6 +282,7 @@
                 cricket::SendDataResult* result) {
     cricket::SendDataParams params;
     params.ssrc = ssrc;
+
     return chan->SendData(params, talk_base::Buffer(
         msg.data(), msg.length()), result);
   }
@@ -313,15 +310,6 @@
   SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
   SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
 
-  void OnNewStreamReceived(const std::string& label,
-                           const webrtc::DataChannelInit& init) {
-    last_label_ = label;
-    last_dc_init_ = init;
-  }
-
-  std::string last_label() { return last_label_; }
-  webrtc::DataChannelInit last_dc_init() { return last_dc_init_; }
-
  private:
   talk_base::scoped_ptr<cricket::SctpDataEngine> engine_;
   talk_base::scoped_ptr<SctpFakeNetworkInterface> net1_;
@@ -330,8 +318,6 @@
   talk_base::scoped_ptr<SctpFakeDataReceiver> recv2_;
   talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan1_;
   talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan2_;
-  std::string last_label_;
-  webrtc::DataChannelInit last_dc_init_;
 };
 
 // Verifies that SignalReadyToSend is fired.
@@ -389,33 +375,6 @@
                   << "recv1.last_data=" << receiver1()->last_data();
 }
 
-TEST_F(SctpDataMediaChannelTest, SendReceiveOpenMessage) {
-  SetupConnectedChannels();
-
-  std::string label("x");
-  webrtc::DataChannelInit config;
-  config.id = 10;
-
-  // Send the OPEN message on a unknown ssrc.
-  channel1()->AddSendStream(cricket::StreamParams::CreateLegacy(config.id));
-  cricket::SendDataParams params;
-  params.ssrc = config.id;
-  params.type = cricket::DMT_CONTROL;
-  cricket::SendDataResult result;
-  talk_base::Buffer buffer;
-  ASSERT_TRUE(cricket::WriteDataChannelOpenMessage(label, config, &buffer));
-  ASSERT_TRUE(channel1()->SendData(params, buffer, &result));
-  // Send data on the new ssrc immediately after sending the OPEN message.
-  ASSERT_TRUE(SendData(channel1(), config.id, "hi chan2", &result));
-
-  // Verifies the received OPEN message.
-  EXPECT_TRUE_WAIT(last_label() == label, 1000);
-  EXPECT_EQ(config.id, last_dc_init().id);
-  EXPECT_EQ(true, last_dc_init().negotiated);
-  // Verifies the received data.
-  EXPECT_TRUE_WAIT(ReceivedData(receiver2(), config.id, "hi chan2"), 1000);
-}
-
 TEST_F(SctpDataMediaChannelTest, ClosesRemoteStream) {
   SetupConnectedChannels();
   SignalChannelClosedObserver chan_1_sig_receiver, chan_2_sig_receiver;
diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc
index 88e09fc..f33d6f0 100644
--- a/talk/media/webrtc/webrtcvideoengine.cc
+++ b/talk/media/webrtc/webrtcvideoengine.cc
@@ -1310,6 +1310,8 @@
   codec->AddFeedbackParam(kFir);
   const FeedbackParam kNack(kRtcpFbParamNack, kParamValueEmpty);
   codec->AddFeedbackParam(kNack);
+  const FeedbackParam kPli(kRtcpFbParamNack, kRtcpFbNackParamPli);
+  codec->AddFeedbackParam(kPli);
   const FeedbackParam kRemb(kRtcpFbParamRemb, kParamValueEmpty);
   codec->AddFeedbackParam(kRemb);
 }
@@ -2787,7 +2789,7 @@
   }
   if (dscp_option_changed) {
     talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT;
-    if (options.dscp.GetWithDefaultIfUnset(false))
+    if (options_.dscp.GetWithDefaultIfUnset(false))
       dscp = kVideoDscpValue;
     if (MediaChannel::SetDscp(dscp) != 0) {
       LOG(LS_WARNING) << "Failed to set DSCP settings for video channel";
diff --git a/talk/media/webrtc/webrtcvideoengine_unittest.cc b/talk/media/webrtc/webrtcvideoengine_unittest.cc
index d5886a1..b10b11f 100644
--- a/talk/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine_unittest.cc
@@ -147,6 +147,20 @@
     channel_->SendFrame(&capturer, &frame);
     return true;
   }
+  void VerifyCodecFeedbackParams(const cricket::VideoCodec& codec) {
+    EXPECT_TRUE(codec.HasFeedbackParam(
+        cricket::FeedbackParam(cricket::kRtcpFbParamNack,
+                               cricket::kParamValueEmpty)));
+    EXPECT_TRUE(codec.HasFeedbackParam(
+        cricket::FeedbackParam(cricket::kRtcpFbParamNack,
+                               cricket::kRtcpFbNackParamPli)));
+    EXPECT_TRUE(codec.HasFeedbackParam(
+        cricket::FeedbackParam(cricket::kRtcpFbParamRemb,
+                               cricket::kParamValueEmpty)));
+    EXPECT_TRUE(codec.HasFeedbackParam(
+        cricket::FeedbackParam(cricket::kRtcpFbParamCcm,
+                               cricket::kRtcpFbCcmParamFir)));
+  }
   void VerifyVP8SendCodec(int channel_num,
                           unsigned int width,
                           unsigned int height,
@@ -237,8 +251,10 @@
   EXPECT_EQ(talk_base::LS_INFO, talk_base::LogMessage::GetLogToStream(&stream));
   webrtc::Trace::Add(webrtc::kTraceStateInfo, webrtc::kTraceUndefined, 0,
                      webrtc_log);
-  EXPECT_TRUE_WAIT(std::string::npos != str.find(webrtc_log), 10);
+  talk_base::Thread::Current()->ProcessMessages(100);
   talk_base::LogMessage::RemoveLogToStream(&stream);
+  // Access |str| after LogMessage is done with it to avoid data racing.
+  EXPECT_NE(std::string::npos, str.find(webrtc_log));
 }
 
 // Tests that webrtc logs are not logged when they should't be.
@@ -889,6 +905,17 @@
   EXPECT_EQ(channel_num, vie_.GetLastChannel());
 }
 
+// Test that NACK, PLI and REMB are enabled for internal codec.
+TEST_F(WebRtcVideoEngineTestFake, InternalCodecFeedbackParams) {
+  EXPECT_TRUE(SetupEngine());
+
+  std::vector<cricket::VideoCodec> codecs(engine_.codecs());
+  // Vp8 will appear at the beginning.
+  size_t pos = 0;
+  EXPECT_EQ("VP8", codecs[pos].name);
+  VerifyCodecFeedbackParams(codecs[pos]);
+}
+
 // Test that AddRecvStream doesn't change remb for 1:1 call.
 TEST_F(WebRtcVideoEngineTestFake, NoRembChangeAfterAddRecvStream) {
   EXPECT_TRUE(SetupEngine());
@@ -1395,6 +1422,322 @@
 }
 
 
+TEST_F(WebRtcVideoEngineTestFake, ResetCodecOnScreencast) {
+  EXPECT_TRUE(SetupEngine());
+  cricket::VideoOptions options;
+  options.video_noise_reduction.Set(true);
+  EXPECT_TRUE(channel_->SetOptions(options));
+
+  // Set send codec.
+  cricket::VideoCodec codec(kVP8Codec);
+  std::vector<cricket::VideoCodec> codec_list;
+  codec_list.push_back(codec);
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(123)));
+  EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
+  EXPECT_TRUE(channel_->SetSend(true));
+  EXPECT_EQ(1, vie_.num_set_send_codecs());
+
+  webrtc::VideoCodec gcodec;
+  memset(&gcodec, 0, sizeof(gcodec));
+  int channel_num = vie_.GetLastChannel();
+  EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec));
+  EXPECT_TRUE(gcodec.codecSpecific.VP8.denoisingOn);
+
+  // Send a screencast frame with the same size.
+  // Verify that denoising is turned off.
+  SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height);
+  EXPECT_EQ(2, vie_.num_set_send_codecs());
+  EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec));
+  EXPECT_FALSE(gcodec.codecSpecific.VP8.denoisingOn);
+}
+
+
+TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderIfFactoryIsNotGiven) {
+  engine_.SetExternalDecoderFactory(NULL);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+
+  EXPECT_EQ(0, vie_.GetNumExternalDecoderRegistered(channel_num));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, RegisterDecoderIfFactoryIsGiven) {
+  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
+  engine_.SetExternalDecoderFactory(&decoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+
+  EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 100));
+  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderMultipleTimes) {
+  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
+  engine_.SetExternalDecoderFactory(&decoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+
+  EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 100));
+  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
+  EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders());
+
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
+  EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders());
+}
+
+TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderForNonVP8) {
+  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
+  engine_.SetExternalDecoderFactory(&decoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kRedCodec);
+  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+
+  EXPECT_EQ(0, vie_.GetNumExternalDecoderRegistered(channel_num));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderIfFactoryIsNotGiven) {
+  engine_.SetExternalEncoderFactory(NULL);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  EXPECT_EQ(0, vie_.GetNumExternalEncoderRegistered(channel_num));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderIfFactoryIsGiven) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(kSsrc)));
+
+  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+
+  // Remove stream previously added to free the external encoder instance.
+  EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(kSsrc)));
+
+  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+  // Remove stream previously added to free the external encoder instance.
+  EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
+}
+
+TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderWithMultipleSendStreams) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+  EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered());
+
+  // When we add the first stream (1234), it reuses the default send channel,
+  // so it doesn't increase the registration count of external encoders.
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(1234)));
+  EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered());
+
+  // When we add the second stream (2345), it creates a new channel and
+  // increments the registration count.
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(2345)));
+  EXPECT_EQ(2, vie_.GetTotalNumExternalEncoderRegistered());
+
+  // At this moment the total registration count is two, but only one encoder
+  // is registered per channel.
+  int channel_num = vie_.GetLastChannel();
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+
+  // Removing send streams decrements the registration count.
+  EXPECT_TRUE(channel_->RemoveSendStream(1234));
+  EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered());
+
+  // When we remove the last send stream, it also destroys the last send
+  // channel and causes the registration count to drop to zero. It is a little
+  // weird, but not a bug.
+  EXPECT_TRUE(channel_->RemoveSendStream(2345));
+  EXPECT_EQ(0, vie_.GetTotalNumExternalEncoderRegistered());
+}
+
+TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderForNonVP8) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
+                                              "GENERIC");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  // Note: unlike the SetRecvCodecs, we must set a valid video codec for
+  // channel_->SetSendCodecs() to succeed.
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  EXPECT_EQ(0, vie_.GetNumExternalEncoderRegistered(channel_num));
+}
+
+// Test that NACK, PLI and REMB are enabled for external codec.
+TEST_F(WebRtcVideoEngineTestFake, ExternalCodecFeedbackParams) {
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
+                                              "GENERIC");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  encoder_factory_.NotifyCodecsAvailable();
+  EXPECT_TRUE(SetupEngine());
+
+  std::vector<cricket::VideoCodec> codecs(engine_.codecs());
+  // The external codec will appear at last.
+  size_t pos = codecs.size() - 1;
+  EXPECT_EQ("GENERIC", codecs[pos].name);
+  VerifyCodecFeedbackParams(codecs[pos]);
+}
+
+// Test external codec with be added to the end of the supported codec list.
+TEST_F(WebRtcVideoEngineTestFake, ExternalCodecAddedToTheEnd) {
+  EXPECT_TRUE(SetupEngine());
+
+  std::vector<cricket::VideoCodec> codecs(engine_.codecs());
+  EXPECT_EQ("VP8", codecs[0].name);
+
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
+                                              "GENERIC");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  encoder_factory_.NotifyCodecsAvailable();
+
+  codecs = engine_.codecs();
+  cricket::VideoCodec internal_codec = codecs[0];
+  cricket::VideoCodec external_codec = codecs[codecs.size() - 1];
+  // The external codec will appear at last.
+  EXPECT_EQ("GENERIC", external_codec.name);
+  // The internal codec is preferred.
+  EXPECT_GE(internal_codec.preference, external_codec.preference);
+}
+
+// Test that external codec with be ignored if it has the same name as one of
+// the internal codecs.
+TEST_F(WebRtcVideoEngineTestFake, ExternalCodecIgnored) {
+  EXPECT_TRUE(SetupEngine());
+
+  std::vector<cricket::VideoCodec> internal_codecs(engine_.codecs());
+  EXPECT_EQ("VP8", internal_codecs[0].name);
+
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  encoder_factory_.NotifyCodecsAvailable();
+
+  std::vector<cricket::VideoCodec> codecs = engine_.codecs();
+  EXPECT_EQ("VP8", codecs[0].name);
+  EXPECT_EQ(internal_codecs[0].height, codecs[0].height);
+  EXPECT_EQ(internal_codecs[0].width, codecs[0].width);
+  // Verify the last codec is not the external codec.
+  EXPECT_NE("VP8", codecs[codecs.size() - 1].name);
+}
+
+TEST_F(WebRtcVideoEngineTestFake, UpdateEncoderCodecsAfterSetFactory) {
+  engine_.SetExternalEncoderFactory(&encoder_factory_);
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+
+  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
+  encoder_factory_.NotifyCodecsAvailable();
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(kSsrc)));
+
+  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
+  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
+  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
+
+  // Remove stream previously added to free the external encoder instance.
+  EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
+}
+
+// Tests that OnReadyToSend will be propagated into ViE.
+TEST_F(WebRtcVideoEngineTestFake, OnReadyToSend) {
+  EXPECT_TRUE(SetupEngine());
+  int channel_num = vie_.GetLastChannel();
+  EXPECT_TRUE(vie_.GetIsTransmitting(channel_num));
+
+  channel_->OnReadyToSend(false);
+  EXPECT_FALSE(vie_.GetIsTransmitting(channel_num));
+
+  channel_->OnReadyToSend(true);
+  EXPECT_TRUE(vie_.GetIsTransmitting(channel_num));
+}
+
+#if 0
+TEST_F(WebRtcVideoEngineTestFake, CaptureFrameTimestampToNtpTimestamp) {
+  EXPECT_TRUE(SetupEngine());
+  int capture_id = vie_.GetCaptureId(vie_.GetLastChannel());
+
+  // Set send codec.
+  cricket::VideoCodec codec(kVP8Codec);
+  std::vector<cricket::VideoCodec> codec_list;
+  codec_list.push_back(codec);
+  EXPECT_TRUE(channel_->AddSendStream(
+      cricket::StreamParams::CreateLegacy(123)));
+  EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
+  EXPECT_TRUE(channel_->SetSend(true));
+
+  int64 timestamp = time(NULL) * talk_base::kNumNanosecsPerSec;
+  SendI420ScreencastFrameWithTimestamp(
+      kVP8Codec.width, kVP8Codec.height, timestamp);
+  EXPECT_EQ(talk_base::UnixTimestampNanosecsToNtpMillisecs(timestamp),
+      vie_.GetCaptureLastTimestamp(capture_id));
+
+  SendI420ScreencastFrameWithTimestamp(kVP8Codec.width, kVP8Codec.height, 0);
+  EXPECT_EQ(0, vie_.GetCaptureLastTimestamp(capture_id));
+}
+#endif
+
 /////////////////////////
 // Tests with real ViE //
 /////////////////////////
@@ -1619,6 +1962,10 @@
   options.dscp.Set(true);
   EXPECT_TRUE(channel_->SetOptions(options));
   EXPECT_EQ(talk_base::DSCP_AF41, network_interface->dscp());
+  // Verify previous value is not modified if dscp option is not set.
+  cricket::VideoOptions options1;
+  EXPECT_TRUE(channel_->SetOptions(options1));
+  EXPECT_EQ(talk_base::DSCP_AF41, network_interface->dscp());
   options.dscp.Set(false);
   EXPECT_TRUE(channel_->SetOptions(options));
   EXPECT_EQ(talk_base::DSCP_DEFAULT, network_interface->dscp());
@@ -1697,327 +2044,3 @@
   Base::TwoStreamsReUseFirstStream(cricket::VideoCodec(100, "VP8", 640, 400, 30,
                                                        0));
 }
-
-TEST_F(WebRtcVideoEngineTestFake, ResetCodecOnScreencast) {
-  EXPECT_TRUE(SetupEngine());
-  cricket::VideoOptions options;
-  options.video_noise_reduction.Set(true);
-  EXPECT_TRUE(channel_->SetOptions(options));
-
-  // Set send codec.
-  cricket::VideoCodec codec(kVP8Codec);
-  std::vector<cricket::VideoCodec> codec_list;
-  codec_list.push_back(codec);
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(123)));
-  EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
-  EXPECT_TRUE(channel_->SetSend(true));
-  EXPECT_EQ(1, vie_.num_set_send_codecs());
-
-  webrtc::VideoCodec gcodec;
-  memset(&gcodec, 0, sizeof(gcodec));
-  int channel_num = vie_.GetLastChannel();
-  EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec));
-  EXPECT_TRUE(gcodec.codecSpecific.VP8.denoisingOn);
-
-  // Send a screencast frame with the same size.
-  // Verify that denoising is turned off.
-  SendI420ScreencastFrame(kVP8Codec.width, kVP8Codec.height);
-  EXPECT_EQ(2, vie_.num_set_send_codecs());
-  EXPECT_EQ(0, vie_.GetSendCodec(channel_num, gcodec));
-  EXPECT_FALSE(gcodec.codecSpecific.VP8.denoisingOn);
-}
-
-
-TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderIfFactoryIsNotGiven) {
-  engine_.SetExternalDecoderFactory(NULL);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
-
-  EXPECT_EQ(0, vie_.GetNumExternalDecoderRegistered(channel_num));
-}
-
-TEST_F(WebRtcVideoEngineTestFake, RegisterDecoderIfFactoryIsGiven) {
-  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
-  engine_.SetExternalDecoderFactory(&decoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
-
-  EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 100));
-  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
-}
-
-TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderMultipleTimes) {
-  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
-  engine_.SetExternalDecoderFactory(&decoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
-
-  EXPECT_TRUE(vie_.ExternalDecoderRegistered(channel_num, 100));
-  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
-  EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders());
-
-  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
-  EXPECT_EQ(1, vie_.GetNumExternalDecoderRegistered(channel_num));
-  EXPECT_EQ(1, decoder_factory_.GetNumCreatedDecoders());
-}
-
-TEST_F(WebRtcVideoEngineTestFake, DontRegisterDecoderForNonVP8) {
-  decoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8);
-  engine_.SetExternalDecoderFactory(&decoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kRedCodec);
-  EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
-
-  EXPECT_EQ(0, vie_.GetNumExternalDecoderRegistered(channel_num));
-}
-
-TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderIfFactoryIsNotGiven) {
-  engine_.SetExternalEncoderFactory(NULL);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-
-  EXPECT_EQ(0, vie_.GetNumExternalEncoderRegistered(channel_num));
-}
-
-TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderIfFactoryIsGiven) {
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(kSsrc)));
-
-  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
-  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
-
-  // Remove stream previously added to free the external encoder instance.
-  EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
-}
-
-TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderMultipleTimes) {
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(kSsrc)));
-
-  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
-  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
-  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
-
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
-  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
-
-  // Remove stream previously added to free the external encoder instance.
-  EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
-}
-
-TEST_F(WebRtcVideoEngineTestFake, RegisterEncoderWithMultipleSendStreams) {
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-  EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered());
-
-  // When we add the first stream (1234), it reuses the default send channel,
-  // so it doesn't increase the registration count of external encoders.
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(1234)));
-  EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered());
-
-  // When we add the second stream (2345), it creates a new channel and
-  // increments the registration count.
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(2345)));
-  EXPECT_EQ(2, vie_.GetTotalNumExternalEncoderRegistered());
-
-  // At this moment the total registration count is two, but only one encoder
-  // is registered per channel.
-  int channel_num = vie_.GetLastChannel();
-  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
-
-  // Removing send streams decrements the registration count.
-  EXPECT_TRUE(channel_->RemoveSendStream(1234));
-  EXPECT_EQ(1, vie_.GetTotalNumExternalEncoderRegistered());
-
-  // When we remove the last send stream, it also destroys the last send
-  // channel and causes the registration count to drop to zero. It is a little
-  // weird, but not a bug.
-  EXPECT_TRUE(channel_->RemoveSendStream(2345));
-  EXPECT_EQ(0, vie_.GetTotalNumExternalEncoderRegistered());
-}
-
-TEST_F(WebRtcVideoEngineTestFake, DontRegisterEncoderForNonVP8) {
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
-                                              "GENERIC");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  // Note: unlike the SetRecvCodecs, we must set a valid video codec for
-  // channel_->SetSendCodecs() to succeed.
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-
-  EXPECT_EQ(0, vie_.GetNumExternalEncoderRegistered(channel_num));
-}
-
-// Test that NACK and REMB are enabled for external codec.
-TEST_F(WebRtcVideoEngineTestFake, FeedbackParamsForNonVP8) {
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
-                                              "GENERIC");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  encoder_factory_.NotifyCodecsAvailable();
-  EXPECT_TRUE(SetupEngine());
-
-  std::vector<cricket::VideoCodec> codecs(engine_.codecs());
-  // The external codec will appear at last.
-  size_t pos = codecs.size() - 1;
-  EXPECT_EQ("GENERIC", codecs[pos].name);
-  EXPECT_TRUE(codecs[pos].HasFeedbackParam(
-      cricket::FeedbackParam(cricket::kRtcpFbParamNack,
-                             cricket::kParamValueEmpty)));
-  EXPECT_TRUE(codecs[pos].HasFeedbackParam(
-      cricket::FeedbackParam(cricket::kRtcpFbParamRemb,
-                             cricket::kParamValueEmpty)));
-  EXPECT_TRUE(codecs[pos].HasFeedbackParam(
-      cricket::FeedbackParam(cricket::kRtcpFbParamCcm,
-                             cricket::kRtcpFbCcmParamFir)));
-}
-
-// Test external codec with be added to the end of the supported codec list.
-TEST_F(WebRtcVideoEngineTestFake, ExternalCodecAddedToTheEnd) {
-  EXPECT_TRUE(SetupEngine());
-
-  std::vector<cricket::VideoCodec> codecs(engine_.codecs());
-  EXPECT_EQ("VP8", codecs[0].name);
-
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecGeneric,
-                                              "GENERIC");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  encoder_factory_.NotifyCodecsAvailable();
-
-  codecs = engine_.codecs();
-  cricket::VideoCodec internal_codec = codecs[0];
-  cricket::VideoCodec external_codec = codecs[codecs.size() - 1];
-  // The external codec will appear at last.
-  EXPECT_EQ("GENERIC", external_codec.name);
-  // The internal codec is preferred.
-  EXPECT_GE(internal_codec.preference, external_codec.preference);
-}
-
-// Test that external codec with be ignored if it has the same name as one of
-// the internal codecs.
-TEST_F(WebRtcVideoEngineTestFake, ExternalCodecIgnored) {
-  EXPECT_TRUE(SetupEngine());
-
-  std::vector<cricket::VideoCodec> internal_codecs(engine_.codecs());
-  EXPECT_EQ("VP8", internal_codecs[0].name);
-
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  encoder_factory_.NotifyCodecsAvailable();
-
-  std::vector<cricket::VideoCodec> codecs = engine_.codecs();
-  EXPECT_EQ("VP8", codecs[0].name);
-  EXPECT_EQ(internal_codecs[0].height, codecs[0].height);
-  EXPECT_EQ(internal_codecs[0].width, codecs[0].width);
-  // Verify the last codec is not the external codec.
-  EXPECT_NE("VP8", codecs[codecs.size() - 1].name);
-}
-
-TEST_F(WebRtcVideoEngineTestFake, UpdateEncoderCodecsAfterSetFactory) {
-  engine_.SetExternalEncoderFactory(&encoder_factory_);
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-
-  encoder_factory_.AddSupportedVideoCodecType(webrtc::kVideoCodecVP8, "VP8");
-  encoder_factory_.NotifyCodecsAvailable();
-  std::vector<cricket::VideoCodec> codecs;
-  codecs.push_back(kVP8Codec);
-  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
-
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(kSsrc)));
-
-  EXPECT_TRUE(vie_.ExternalEncoderRegistered(channel_num, 100));
-  EXPECT_EQ(1, vie_.GetNumExternalEncoderRegistered(channel_num));
-  EXPECT_EQ(1, encoder_factory_.GetNumCreatedEncoders());
-
-  // Remove stream previously added to free the external encoder instance.
-  EXPECT_TRUE(channel_->RemoveSendStream(kSsrc));
-}
-
-// Tests that OnReadyToSend will be propagated into ViE.
-TEST_F(WebRtcVideoEngineTestFake, OnReadyToSend) {
-  EXPECT_TRUE(SetupEngine());
-  int channel_num = vie_.GetLastChannel();
-  EXPECT_TRUE(vie_.GetIsTransmitting(channel_num));
-
-  channel_->OnReadyToSend(false);
-  EXPECT_FALSE(vie_.GetIsTransmitting(channel_num));
-
-  channel_->OnReadyToSend(true);
-  EXPECT_TRUE(vie_.GetIsTransmitting(channel_num));
-}
-
-#if 0
-TEST_F(WebRtcVideoEngineTestFake, CaptureFrameTimestampToNtpTimestamp) {
-  EXPECT_TRUE(SetupEngine());
-  int capture_id = vie_.GetCaptureId(vie_.GetLastChannel());
-
-  // Set send codec.
-  cricket::VideoCodec codec(kVP8Codec);
-  std::vector<cricket::VideoCodec> codec_list;
-  codec_list.push_back(codec);
-  EXPECT_TRUE(channel_->AddSendStream(
-      cricket::StreamParams::CreateLegacy(123)));
-  EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
-  EXPECT_TRUE(channel_->SetSend(true));
-
-  int64 timestamp = time(NULL) * talk_base::kNumNanosecsPerSec;
-  SendI420ScreencastFrameWithTimestamp(
-      kVP8Codec.width, kVP8Codec.height, timestamp);
-  EXPECT_EQ(talk_base::UnixTimestampNanosecsToNtpMillisecs(timestamp),
-      vie_.GetCaptureLastTimestamp(capture_id));
-
-  SendI420ScreencastFrameWithTimestamp(kVP8Codec.width, kVP8Codec.height, 0);
-  EXPECT_EQ(0, vie_.GetCaptureLastTimestamp(capture_id));
-}
-#endif
diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc
index 2aa6b8c..95e8c85 100644
--- a/talk/media/webrtc/webrtcvoiceengine.cc
+++ b/talk/media/webrtc/webrtcvoiceengine.cc
@@ -1769,7 +1769,7 @@
   }
   if (dscp_option_changed) {
     talk_base::DiffServCodePoint dscp = talk_base::DSCP_DEFAULT;
-    if (options.dscp.GetWithDefaultIfUnset(false))
+    if (options_.dscp.GetWithDefaultIfUnset(false))
       dscp = kAudioDscpValue;
     if (MediaChannel::SetDscp(dscp) != 0) {
       LOG(LS_WARNING) << "Failed to set DSCP settings for audio channel";
@@ -1879,7 +1879,7 @@
     // this, but double-check to be sure.
     webrtc::CodecInst voe_codec;
     if (!engine()->FindWebRtcCodec(*it, &voe_codec)) {
-      LOG(LS_WARNING) << "Unknown codec " << ToString(voe_codec);
+      LOG(LS_WARNING) << "Unknown codec " << ToString(*it);
       continue;
     }
 
@@ -2431,14 +2431,14 @@
   }
 
   // Use the same SSRC as our default channel (so the RTCP reports are correct).
-  unsigned int send_ssrc;
+  unsigned int send_ssrc = 0;
   webrtc::VoERTP_RTCP* rtp = engine()->voe()->rtp();
   if (rtp->GetLocalSSRC(voe_channel(), send_ssrc) == -1) {
-    LOG_RTCERR2(GetSendSSRC, channel, send_ssrc);
+    LOG_RTCERR1(GetSendSSRC, channel);
     return false;
   }
   if (rtp->SetLocalSSRC(channel, send_ssrc) == -1) {
-    LOG_RTCERR2(SetSendSSRC, channel, send_ssrc);
+    LOG_RTCERR1(SetSendSSRC, channel);
     return false;
   }
 
diff --git a/talk/media/webrtc/webrtcvoiceengine_unittest.cc b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
index dc725c0..7fa5834 100644
--- a/talk/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -2718,6 +2718,10 @@
   options.dscp.Set(true);
   EXPECT_TRUE(channel->SetOptions(options));
   EXPECT_EQ(talk_base::DSCP_EF, network_interface->dscp());
+  // Verify previous value is not modified if dscp option is not set.
+  cricket::AudioOptions options1;
+  EXPECT_TRUE(channel->SetOptions(options1));
+  EXPECT_EQ(talk_base::DSCP_EF, network_interface->dscp());
   options.dscp.Set(false);
   EXPECT_TRUE(channel->SetOptions(options));
   EXPECT_EQ(talk_base::DSCP_DEFAULT, network_interface->dscp());
diff --git a/talk/p2p/base/portallocator.h b/talk/p2p/base/portallocator.h
index 3481021..e2cb3fd 100644
--- a/talk/p2p/base/portallocator.h
+++ b/talk/p2p/base/portallocator.h
@@ -54,7 +54,6 @@
 const uint32 PORTALLOCATOR_ENABLE_SHARED_UFRAG = 0x80;
 const uint32 PORTALLOCATOR_ENABLE_SHARED_SOCKET = 0x100;
 const uint32 PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE = 0x200;
-const uint32 PORTALLOCATOR_USE_LARGE_SOCKET_SEND_BUFFERS = 0x400;
 
 const uint32 kDefaultPortAllocatorFlags = 0;
 
diff --git a/talk/p2p/client/basicportallocator.cc b/talk/p2p/client/basicportallocator.cc
index e568e75..9e2ce07 100644
--- a/talk/p2p/client/basicportallocator.cc
+++ b/talk/p2p/client/basicportallocator.cc
@@ -65,10 +65,6 @@
 
 const int kNumPhases = 4;
 
-// Both these values are in bytes.
-const int kLargeSocketSendBufferSize = 128 * 1024;
-const int kNormalSocketSendBufferSize = 64 * 1024;
-
 const int SHAKE_MIN_DELAY = 45 * 1000;  // 45 seconds
 const int SHAKE_MAX_DELAY = 90 * 1000;  // 90 seconds
 
@@ -490,16 +486,6 @@
   port->set_send_retransmit_count_attribute((allocator_->flags() &
       PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
 
-  if (content_name().compare(CN_VIDEO) == 0 &&
-      component_ == cricket::ICE_CANDIDATE_COMPONENT_RTP) {
-    // For video RTP alone, we set send-buffer sizes. This used to be set in the
-    // engines/channels.
-    int sendBufSize = (flags() & PORTALLOCATOR_USE_LARGE_SOCKET_SEND_BUFFERS)
-                      ? kLargeSocketSendBufferSize
-                      : kNormalSocketSendBufferSize;
-    port->SetOption(talk_base::Socket::OPT_SNDBUF, sendBufSize);
-  }
-
   PortData data(port, seq);
   ports_.push_back(data);
 
diff --git a/talk/p2p/client/portallocator_unittest.cc b/talk/p2p/client/portallocator_unittest.cc
index 6966e44..f3400f1 100644
--- a/talk/p2p/client/portallocator_unittest.cc
+++ b/talk/p2p/client/portallocator_unittest.cc
@@ -331,56 +331,7 @@
   // If we Stop gathering now, we shouldn't get a second "done" callback.
   session_->StopGettingPorts();
 
-  // All ports should have normal send-buffer sizes (64KB).
-  CheckSendBufferSizesOfAllPorts(64 * 1024);
-}
-
-TEST_F(PortAllocatorTest, TestSetupVideoRtpPortsWithLargeSendBuffers) {
-  AddInterface(kClientAddr);
-  allocator_->set_flags(allocator_->flags() |
-                        cricket::PORTALLOCATOR_USE_LARGE_SOCKET_SEND_BUFFERS);
-  EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP,
-                            cricket::CN_VIDEO));
-  session_->StartGettingPorts();
-  ASSERT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout);
-  EXPECT_TRUE(candidate_allocation_done_);
-  // If we Stop gathering now, we shouldn't get a second "done" callback.
-  session_->StopGettingPorts();
-
-  // All ports should have large send-buffer sizes (128KB).
-  CheckSendBufferSizesOfAllPorts(128 * 1024);
-}
-
-TEST_F(PortAllocatorTest, TestSetupVideoRtcpPortsAndCheckSendBuffers) {
-  AddInterface(kClientAddr);
-  allocator_->set_flags(allocator_->flags() |
-                        cricket::PORTALLOCATOR_USE_LARGE_SOCKET_SEND_BUFFERS);
-  EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTCP,
-                            cricket::CN_DATA));
-  session_->StartGettingPorts();
-  ASSERT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout);
-  EXPECT_TRUE(candidate_allocation_done_);
-  // If we Stop gathering now, we shouldn't get a second "done" callback.
-  session_->StopGettingPorts();
-
-  // No ports should have send-buffer size set.
-  CheckSendBufferSizesOfAllPorts(-1);
-}
-
-
-TEST_F(PortAllocatorTest, TestSetupNonVideoPortsAndCheckSendBuffers) {
-  AddInterface(kClientAddr);
-  allocator_->set_flags(allocator_->flags() |
-                        cricket::PORTALLOCATOR_USE_LARGE_SOCKET_SEND_BUFFERS);
-  EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP,
-                            cricket::CN_DATA));
-  session_->StartGettingPorts();
-  ASSERT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout);
-  EXPECT_TRUE(candidate_allocation_done_);
-  // If we Stop gathering now, we shouldn't get a second "done" callback.
-  session_->StopGettingPorts();
-
-  // No ports should have send-buffer size set.
+  // All ports should have unset send-buffer sizes.
   CheckSendBufferSizesOfAllPorts(-1);
 }
 
diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc
index 9a8559a..61bc3d7 100644
--- a/talk/session/media/channel.cc
+++ b/talk/session/media/channel.cc
@@ -81,7 +81,6 @@
   MSG_SETSCREENCASTFACTORY,
   MSG_FIRSTPACKETRECEIVED,
   MSG_SESSION_ERROR,
-  MSG_NEWSTREAMRECEIVED,
 };
 
 // Value specified in RFC 5764.
@@ -2515,8 +2514,6 @@
       this, &DataChannel::OnDataChannelError);
   media_channel()->SignalReadyToSend.connect(
       this, &DataChannel::OnDataChannelReadyToSend);
-  media_channel()->SignalNewStreamReceived.connect(
-      this, &DataChannel::OnDataChannelNewStreamReceived);
   srtp_filter()->SignalSrtpError.connect(
       this, &DataChannel::OnSrtpError);
   return true;
@@ -2740,13 +2737,6 @@
       delete data;
       break;
     }
-    case MSG_NEWSTREAMRECEIVED: {
-      DataChannelNewStreamReceivedMessageData* data =
-          static_cast<DataChannelNewStreamReceivedMessageData*>(pmsg->pdata);
-      SignalNewStreamReceived(data->label, data->init);
-      delete data;
-      break;
-    }
     default:
       BaseChannel::OnMessage(pmsg);
       break;
@@ -2802,14 +2792,6 @@
                            new DataChannelReadyToSendMessageData(writable));
 }
 
-void DataChannel::OnDataChannelNewStreamReceived(
-    const std::string& label, const webrtc::DataChannelInit& init) {
-  signaling_thread()->Post(
-      this,
-      MSG_NEWSTREAMRECEIVED,
-      new DataChannelNewStreamReceivedMessageData(label, init));
-}
-
 void DataChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode,
                               SrtpFilter::Error error) {
   switch (error) {
diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h
index d297ee4..bf9a837 100644
--- a/talk/session/media/channel.h
+++ b/talk/session/media/channel.h
@@ -31,7 +31,6 @@
 #include <string>
 #include <vector>
 
-#include "talk/app/webrtc/datachannelinterface.h"
 #include "talk/base/asyncudpsocket.h"
 #include "talk/base/criticalsection.h"
 #include "talk/base/network.h"
@@ -634,11 +633,6 @@
   // That occurs when the channel is enabled, the transport is writable,
   // both local and remote descriptions are set, and the channel is unblocked.
   sigslot::signal1<bool> SignalReadyToSendData;
-  // Signal for notifying when a new stream is added from the remote side. Used
-  // for the in-band negotioation through the OPEN message for SCTP data
-  // channel.
-  sigslot::signal2<const std::string&, const webrtc::DataChannelInit&>
-      SignalNewStreamReceived;
 
  protected:
   // downcasts a MediaChannel.
@@ -678,17 +672,6 @@
 
   typedef talk_base::TypedMessageData<bool> DataChannelReadyToSendMessageData;
 
-  struct DataChannelNewStreamReceivedMessageData
-      : public talk_base::MessageData {
-    DataChannelNewStreamReceivedMessageData(
-        const std::string& label, const webrtc::DataChannelInit& init)
-        : label(label),
-          init(init) {
-    }
-    const std::string label;
-    const webrtc::DataChannelInit init;
-  };
-
   // overrides from BaseChannel
   virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
   // If data_channel_type_ is DCT_NONE, set it.  Otherwise, check that
@@ -717,8 +700,6 @@
       const ReceiveDataParams& params, const char* data, size_t len);
   void OnDataChannelError(uint32 ssrc, DataMediaChannel::Error error);
   void OnDataChannelReadyToSend(bool writable);
-  void OnDataChannelNewStreamReceived(const std::string& label,
-                                      const webrtc::DataChannelInit& init);
   void OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode, SrtpFilter::Error error);
 
   talk_base::scoped_ptr<DataMediaMonitor> media_monitor_;