Update stable to r5267.

git-svn-id: http://webrtc.googlecode.com/svn/stable/talk@5268 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/app/webrtc/statscollector.cc b/app/webrtc/statscollector.cc
index 18ab459..b00d19c 100644
--- a/app/webrtc/statscollector.cc
+++ b/app/webrtc/statscollector.cc
@@ -53,6 +53,8 @@
 const char StatsReport::kStatsValueNameBytesSent[] = "bytesSent";
 const char StatsReport::kStatsValueNameCaptureJitterMs[] =
     "googCaptureJitterMs";
+const char StatsReport::kStatsValueNameCaptureQueueDelayMsPerS[] =
+    "googCaptureQueueDelayMsPerS";
 const char StatsReport::kStatsValueNameChannelId[] = "googChannelId";
 const char StatsReport::kStatsValueNameCodecName[] = "googCodecName";
 const char StatsReport::kStatsValueNameComponent[] = "googComponent";
@@ -70,6 +72,8 @@
 const char StatsReport::kStatsValueNameEchoReturnLossEnhancement[] =
     "googEchoCancellationReturnLossEnhancement";
 
+const char StatsReport::kStatsValueNameEncodeUsagePercent[] =
+    "googEncodeUsagePercent";
 const char StatsReport::kStatsValueNameFingerprint[] = "googFingerprint";
 const char StatsReport::kStatsValueNameFingerprintAlgorithm[] =
     "googFingerprintAlgorithm";
@@ -298,6 +302,10 @@
   report->AddValue(StatsReport::kStatsValueNameAvgEncodeMs, info.avg_encode_ms);
   report->AddValue(StatsReport::kStatsValueNameCaptureJitterMs,
                    info.capture_jitter_ms);
+  report->AddValue(StatsReport::kStatsValueNameCaptureQueueDelayMsPerS,
+                   info.capture_queue_delay_ms_per_s);
+  report->AddValue(StatsReport::kStatsValueNameEncodeUsagePercent,
+                   info.encode_usage_percent);
 }
 
 void ExtractStats(const cricket::BandwidthEstimationInfo& info,
diff --git a/app/webrtc/statstypes.h b/app/webrtc/statstypes.h
index 15210b6..6afc8d7 100644
--- a/app/webrtc/statstypes.h
+++ b/app/webrtc/statstypes.h
@@ -129,7 +129,9 @@
 
   // Internal StatsValue names
   static const char kStatsValueNameAvgEncodeMs[];
+  static const char kStatsValueNameEncodeUsagePercent[];
   static const char kStatsValueNameCaptureJitterMs[];
+  static const char kStatsValueNameCaptureQueueDelayMsPerS[];
   static const char kStatsValueNameCodecName[];
   static const char kStatsValueNameEchoCancellationQualityMin[];
   static const char kStatsValueNameEchoDelayMedian[];
diff --git a/base/common.h b/base/common.h
index d557639..a76748b 100644
--- a/base/common.h
+++ b/base/common.h
@@ -187,6 +187,10 @@
 // (because it won't see this pragma).
 #pragma clang diagnostic ignored "-Wc++11-extensions"
 #define OVERRIDE override
+#elif defined(__GNUC__) && __cplusplus >= 201103 && \
+    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
+// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
+#define OVERRIDE override
 #else
 #define OVERRIDE
 #endif
diff --git a/base/sslstreamadapter_unittest.cc b/base/sslstreamadapter_unittest.cc
index e7335be..4b2fd6d 100644
--- a/base/sslstreamadapter_unittest.cc
+++ b/base/sslstreamadapter_unittest.cc
@@ -762,7 +762,7 @@
 };
 
 // Test a handshake with small MTU
-TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithSmallMtu) {
+TEST_F(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) {
   MAYBE_SKIP_TEST(HaveDtls);
   SetMtu(700);
   SetHandshakeWait(20000);
diff --git a/build/isolate.gypi b/build/isolate.gypi
index 83dd502..7b0ac12 100644
--- a/build/isolate.gypi
+++ b/build/isolate.gypi
@@ -71,9 +71,9 @@
       'extension': 'isolate',
       'inputs': [
         # Files that are known to be involved in this step.
-        '<(DEPTH)/tools/swarm_client/isolate.py',
-        '<(DEPTH)/tools/swarm_client/run_isolated.py',
-        '<(DEPTH)/tools/swarm_client/googletest/run_test_cases.py',
+        '<(DEPTH)/tools/swarming_client/isolate.py',
+        '<(DEPTH)/tools/swarming_client/run_isolated.py',
+        '<(DEPTH)/tools/swarming_client/googletest/run_test_cases.py',
 
         # Disable file tracking by the build driver for now. This means the
         # project must have the proper build-time dependency for their runtime
@@ -94,7 +94,7 @@
         ["test_isolation_outdir==''", {
           'action': [
             'python',
-            '<(DEPTH)/tools/swarm_client/isolate.py',
+            '<(DEPTH)/tools/swarming_client/isolate.py',
             '<(test_isolation_mode)',
             # GYP will eliminate duplicate arguments so '<(PRODUCT_DIR)' cannot
             # be provided twice. To work around this behavior, append '/'.
@@ -114,7 +114,7 @@
         }, {
           'action': [
             'python',
-            '<(DEPTH)/tools/swarm_client/isolate.py',
+            '<(DEPTH)/tools/swarming_client/isolate.py',
             '<(test_isolation_mode)',
             '--outdir', '<(test_isolation_outdir)',
             # See comment above.
diff --git a/examples/android/project.properties b/examples/android/project.properties
index bc163b0..8459f9b 100644
--- a/examples/android/project.properties
+++ b/examples/android/project.properties
@@ -11,6 +11,6 @@
 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 
 # Project target.
-target=android-17
+target=android-19
 
 java.compilerargs=-Xlint:all -Werror
diff --git a/libjingle_media_unittest.isolate b/libjingle_media_unittest.isolate
index 4c4ee31..36b50b5 100644
--- a/libjingle_media_unittest.isolate
+++ b/libjingle_media_unittest.isolate
@@ -30,7 +30,6 @@
       'variables': {
         'command': [
           '../testing/test_env.py',
-          '../tools/swarm_client/googletest/run_test_cases.py',
           '<(PRODUCT_DIR)/libjingle_media_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_tracked': [
@@ -39,7 +38,7 @@
           '<(PRODUCT_DIR)/libjingle_media_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_untracked': [
-          '../tools/swarm_client/',
+          '../tools/swarming_client/',
         ],
       },
     }],
diff --git a/libjingle_p2p_unittest.isolate b/libjingle_p2p_unittest.isolate
index 848f234..b5ad4ff 100644
--- a/libjingle_p2p_unittest.isolate
+++ b/libjingle_p2p_unittest.isolate
@@ -30,7 +30,6 @@
       'variables': {
         'command': [
           '../testing/test_env.py',
-          '../tools/swarm_client/googletest/run_test_cases.py',
           '<(PRODUCT_DIR)/libjingle_p2p_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
           '<(PRODUCT_DIR)/libjingle_p2p_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_untracked': [
-          '../tools/swarm_client/',
+          '../tools/swarming_client/',
         ],
       },
     }],
diff --git a/libjingle_peerconnection_unittest.isolate b/libjingle_peerconnection_unittest.isolate
index 660ffd5..e7dd687 100644
--- a/libjingle_peerconnection_unittest.isolate
+++ b/libjingle_peerconnection_unittest.isolate
@@ -30,7 +30,6 @@
       'variables': {
         'command': [
           '../testing/test_env.py',
-          '../tools/swarm_client/googletest/run_test_cases.py',
           '<(PRODUCT_DIR)/libjingle_peerconnection_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
           '<(PRODUCT_DIR)/libjingle_peerconnection_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_untracked': [
-          '../tools/swarm_client/',
+          '../tools/swarming_client/',
         ],
       },
     }],
diff --git a/libjingle_sound_unittest.isolate b/libjingle_sound_unittest.isolate
index 6da7d88..7166337 100644
--- a/libjingle_sound_unittest.isolate
+++ b/libjingle_sound_unittest.isolate
@@ -30,7 +30,6 @@
       'variables': {
         'command': [
           '../testing/test_env.py',
-          '../tools/swarm_client/googletest/run_test_cases.py',
           '<(PRODUCT_DIR)/libjingle_sound_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
           '<(PRODUCT_DIR)/libjingle_sound_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_untracked': [
-          '../tools/swarm_client/',
+          '../tools/swarming_client/',
         ],
       },
     }],
diff --git a/libjingle_tests.gyp b/libjingle_tests.gyp
index a88942f..7bfea59 100755
--- a/libjingle_tests.gyp
+++ b/libjingle_tests.gyp
@@ -88,6 +88,7 @@
         'media/base/testutils.cc',
         'media/base/testutils.h',
         'media/devices/fakedevicemanager.h',
+        'media/webrtc/dummyinstantiation.cc',
         'media/webrtc/fakewebrtccommon.h',
         'media/webrtc/fakewebrtcdeviceinfo.h',
         'media/webrtc/fakewebrtcvcmfactory.h',
diff --git a/libjingle_unittest.isolate b/libjingle_unittest.isolate
index efb8625..e678af0 100644
--- a/libjingle_unittest.isolate
+++ b/libjingle_unittest.isolate
@@ -30,7 +30,6 @@
       'variables': {
         'command': [
           '../testing/test_env.py',
-          '../tools/swarm_client/googletest/run_test_cases.py',
           '<(PRODUCT_DIR)/libjingle_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_tracked': [
@@ -38,7 +37,7 @@
           '<(PRODUCT_DIR)/libjingle_unittest<(EXECUTABLE_SUFFIX)',
         ],
         'isolate_dependency_untracked': [
-          '../tools/swarm_client/',
+          '../tools/swarming_client/',
         ],
       },
     }],
diff --git a/media/base/filemediaengine.cc b/media/base/filemediaengine.cc
index e5183f6..80e9729 100644
--- a/media/base/filemediaengine.cc
+++ b/media/base/filemediaengine.cc
@@ -83,7 +83,8 @@
     }
   }
 
-  return new FileVoiceChannel(input_file_stream, output_file_stream);
+  return new FileVoiceChannel(input_file_stream, output_file_stream,
+                              rtp_sender_thread_);
 }
 
 VideoMediaChannel* FileMediaEngine::CreateVideoChannel(
@@ -113,18 +114,19 @@
     }
   }
 
-  return new FileVideoChannel(input_file_stream, output_file_stream);
+  return new FileVideoChannel(input_file_stream, output_file_stream,
+                              rtp_sender_thread_);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Definition of RtpSenderReceiver.
 ///////////////////////////////////////////////////////////////////////////
-class RtpSenderReceiver
-    : public talk_base::Thread, public talk_base::MessageHandler {
+class RtpSenderReceiver : public talk_base::MessageHandler {
  public:
   RtpSenderReceiver(MediaChannel* channel,
                     talk_base::StreamInterface* input_file_stream,
-                    talk_base::StreamInterface* output_file_stream);
+                    talk_base::StreamInterface* output_file_stream,
+                    talk_base::Thread* sender_thread);
   virtual ~RtpSenderReceiver();
 
   // Called by media channel. Context: media channel thread.
@@ -149,6 +151,8 @@
   talk_base::scoped_ptr<talk_base::StreamInterface> output_stream_;
   talk_base::scoped_ptr<RtpDumpLoopReader> rtp_dump_reader_;
   talk_base::scoped_ptr<RtpDumpWriter> rtp_dump_writer_;
+  talk_base::Thread* sender_thread_;
+  bool own_sender_thread_;
   // RTP dump packet read from the input stream.
   RtpDumpPacket rtp_dump_packet_;
   uint32 start_send_time_;
@@ -165,34 +169,48 @@
 RtpSenderReceiver::RtpSenderReceiver(
     MediaChannel* channel,
     talk_base::StreamInterface* input_file_stream,
-    talk_base::StreamInterface* output_file_stream)
+    talk_base::StreamInterface* output_file_stream,
+    talk_base::Thread* sender_thread)
     : media_channel_(channel),
+      input_stream_(input_file_stream),
+      output_stream_(output_file_stream),
       sending_(false),
       first_packet_(true) {
-  input_stream_.reset(input_file_stream);
+  if (sender_thread == NULL) {
+    sender_thread_ = new talk_base::Thread();
+    own_sender_thread_ = true;
+  } else {
+    sender_thread_ = sender_thread;
+    own_sender_thread_ = false;
+  }
+
   if (input_stream_) {
     rtp_dump_reader_.reset(new RtpDumpLoopReader(input_stream_.get()));
     // Start the sender thread, which reads rtp dump records, waits based on
     // the record timestamps, and sends the RTP packets to the network.
-    Thread::Start();
+    if (own_sender_thread_) {
+      sender_thread_->Start();
+    }
   }
 
   // Create a rtp dump writer for the output RTP dump stream.
-  output_stream_.reset(output_file_stream);
   if (output_stream_) {
     rtp_dump_writer_.reset(new RtpDumpWriter(output_stream_.get()));
   }
 }
 
 RtpSenderReceiver::~RtpSenderReceiver() {
-  Stop();
+  if (own_sender_thread_) {
+    sender_thread_->Stop();
+    delete sender_thread_;
+  }
 }
 
 bool RtpSenderReceiver::SetSend(bool send) {
   bool was_sending = sending_;
   sending_ = send;
   if (!was_sending && sending_) {
-    PostDelayed(0, this);  // Wake up the send thread.
+    sender_thread_->PostDelayed(0, this);  // Wake up the send thread.
     start_send_time_ = talk_base::Time();
   }
   return true;
@@ -216,7 +234,6 @@
     // to sleep until SetSend(true) wakes it up.
     return;
   }
-
   if (!first_packet_) {
     // Send the previously read packet.
     SendRtpPacket(&rtp_dump_packet_.data[0], rtp_dump_packet_.data.size());
@@ -226,9 +243,9 @@
     int wait = talk_base::TimeUntil(
         start_send_time_ + rtp_dump_packet_.elapsed_time);
     wait = talk_base::_max(0, wait);
-    PostDelayed(wait, this);
+    sender_thread_->PostDelayed(wait, this);
   } else {
-    Quit();
+    sender_thread_->Quit();
   }
 }
 
@@ -262,10 +279,12 @@
 ///////////////////////////////////////////////////////////////////////////
 FileVoiceChannel::FileVoiceChannel(
     talk_base::StreamInterface* input_file_stream,
-    talk_base::StreamInterface* output_file_stream)
+    talk_base::StreamInterface* output_file_stream,
+    talk_base::Thread* rtp_sender_thread)
     : send_ssrc_(0),
       rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
-                                                 output_file_stream)) {}
+                                                 output_file_stream,
+                                                 rtp_sender_thread)) {}
 
 FileVoiceChannel::~FileVoiceChannel() {}
 
@@ -305,10 +324,12 @@
 ///////////////////////////////////////////////////////////////////////////
 FileVideoChannel::FileVideoChannel(
     talk_base::StreamInterface* input_file_stream,
-    talk_base::StreamInterface* output_file_stream)
+    talk_base::StreamInterface* output_file_stream,
+    talk_base::Thread* rtp_sender_thread)
     : send_ssrc_(0),
       rtp_sender_receiver_(new RtpSenderReceiver(this, input_file_stream,
-                                                 output_file_stream)) {}
+                                                 output_file_stream,
+                                                 rtp_sender_thread)) {}
 
 FileVideoChannel::~FileVideoChannel() {}
 
diff --git a/media/base/filemediaengine.h b/media/base/filemediaengine.h
index 9cdfe83..129af9c 100644
--- a/media/base/filemediaengine.h
+++ b/media/base/filemediaengine.h
@@ -50,7 +50,7 @@
 // only the RTP dump packets. TODO(whyuan): Enable RTCP packets.
 class FileMediaEngine : public MediaEngineInterface {
  public:
-  FileMediaEngine() {}
+  FileMediaEngine() : rtp_sender_thread_(NULL) {}
   virtual ~FileMediaEngine() {}
 
   // Set the file name of the input or output RTP dump for voice or video.
@@ -159,6 +159,10 @@
     return signal_state_change_;
   }
 
+  void set_rtp_sender_thread(talk_base::Thread* thread) {
+    rtp_sender_thread_ = thread;
+  }
+
  private:
   std::string voice_input_filename_;
   std::string voice_output_filename_;
@@ -170,6 +174,7 @@
   std::vector<RtpHeaderExtension> video_rtp_header_extensions_;
   sigslot::repeater2<VideoCapturer*, CaptureState>
      signal_state_change_;
+  talk_base::Thread* rtp_sender_thread_;
 
   DISALLOW_COPY_AND_ASSIGN(FileMediaEngine);
 };
@@ -179,7 +184,8 @@
 class FileVoiceChannel : public VoiceMediaChannel {
  public:
   FileVoiceChannel(talk_base::StreamInterface* input_file_stream,
-      talk_base::StreamInterface* output_file_stream);
+      talk_base::StreamInterface* output_file_stream,
+      talk_base::Thread* rtp_sender_thread);
   virtual ~FileVoiceChannel();
 
   // Implement pure virtual methods of VoiceMediaChannel.
@@ -255,7 +261,8 @@
 class FileVideoChannel : public VideoMediaChannel {
  public:
   FileVideoChannel(talk_base::StreamInterface* input_file_stream,
-      talk_base::StreamInterface* output_file_stream);
+      talk_base::StreamInterface* output_file_stream,
+      talk_base::Thread* rtp_sender_thread);
   virtual ~FileVideoChannel();
 
   // Implement pure virtual methods of VideoMediaChannel.
diff --git a/media/base/filemediaengine_unittest.cc b/media/base/filemediaengine_unittest.cc
index a72e0dc..7ba96a2 100644
--- a/media/base/filemediaengine_unittest.cc
+++ b/media/base/filemediaengine_unittest.cc
@@ -136,6 +136,7 @@
     engine_->set_voice_output_filename(voice_out);
     engine_->set_video_input_filename(video_in);
     engine_->set_video_output_filename(video_out);
+    engine_->set_rtp_sender_thread(talk_base::Thread::Current());
 
     voice_channel_.reset(engine_->CreateChannel());
     video_channel_.reset(engine_->CreateVideoChannel(NULL));
diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h
index d7e7192..9e1ea9d 100644
--- a/media/base/mediachannel.h
+++ b/media/base/mediachannel.h
@@ -298,7 +298,6 @@
     adapt_view_switch.SetFrom(change.adapt_view_switch);
     video_adapt_third.SetFrom(change.video_adapt_third);
     video_noise_reduction.SetFrom(change.video_noise_reduction);
-    video_three_layers.SetFrom(change.video_three_layers);
     video_one_layer_screencast.SetFrom(change.video_one_layer_screencast);
     video_high_bitrate.SetFrom(change.video_high_bitrate);
     video_watermark.SetFrom(change.video_watermark);
@@ -327,7 +326,6 @@
         adapt_view_switch == o.adapt_view_switch &&
         video_adapt_third == o.video_adapt_third &&
         video_noise_reduction == o.video_noise_reduction &&
-        video_three_layers == o.video_three_layers &&
         video_one_layer_screencast == o.video_one_layer_screencast &&
         video_high_bitrate == o.video_high_bitrate &&
         video_watermark == o.video_watermark &&
@@ -356,7 +354,6 @@
     ost << ToStringIfSet("adapt view switch", adapt_view_switch);
     ost << ToStringIfSet("video adapt third", video_adapt_third);
     ost << ToStringIfSet("noise reduction", video_noise_reduction);
-    ost << ToStringIfSet("3 layers", video_three_layers);
     ost << ToStringIfSet("1 layer screencast", video_one_layer_screencast);
     ost << ToStringIfSet("high bitrate", video_high_bitrate);
     ost << ToStringIfSet("watermark", video_watermark);
@@ -391,8 +388,6 @@
   Settable<bool> video_adapt_third;
   // Enable denoising?
   Settable<bool> video_noise_reduction;
-  // Experimental: Enable multi layer?
-  Settable<bool> video_three_layers;
   // Experimental: Enable one layer screencast?
   Settable<bool> video_one_layer_screencast;
   // Experimental: Enable WebRtc higher bitrate?
@@ -776,7 +771,9 @@
         preferred_bitrate(0),
         adapt_reason(0),
         capture_jitter_ms(0),
-        avg_encode_ms(0) {
+        avg_encode_ms(0),
+        encode_usage_percent(0),
+        capture_queue_delay_ms_per_s(0) {
   }
 
   std::vector<SsrcGroup> ssrc_groups;
@@ -792,6 +789,8 @@
   int adapt_reason;
   int capture_jitter_ms;
   int avg_encode_ms;
+  int encode_usage_percent;
+  int capture_queue_delay_ms_per_s;
 };
 
 struct VideoReceiverInfo : public MediaReceiverInfo {
diff --git a/media/base/videoadapter.cc b/media/base/videoadapter.cc
index 20114fb..22b1f7d 100644
--- a/media/base/videoadapter.cc
+++ b/media/base/videoadapter.cc
@@ -165,8 +165,8 @@
       frames_(0),
       adapted_frames_(0),
       adaption_changes_(0),
-      previous_width(0),
-      previous_height(0),
+      previous_width_(0),
+      previous_height_(0),
       black_output_(false),
       is_black_(false),
       interval_next_frame_(0) {
@@ -240,11 +240,11 @@
 // TODO(fbarchard): Add AdaptFrameRate function that only drops frames but
 // not resolution.
 bool VideoAdapter::AdaptFrame(const VideoFrame* in_frame,
-                              const VideoFrame** out_frame) {
-  talk_base::CritScope cs(&critical_section_);
+                              VideoFrame** out_frame) {
   if (!in_frame || !out_frame) {
     return false;
   }
+  talk_base::CritScope cs(&critical_section_);
   ++frames_;
 
   // Update input to actual frame dimensions.
@@ -306,8 +306,8 @@
   // resolution changes as well.  Consider dropping the statistics into their
   // own class which could be queried publically.
   bool changed = false;
-  if (previous_width && (previous_width != (*out_frame)->GetWidth() ||
-      previous_height != (*out_frame)->GetHeight())) {
+  if (previous_width_ && (previous_width_ != (*out_frame)->GetWidth() ||
+      previous_height_ != (*out_frame)->GetHeight())) {
     show = true;
     ++adaption_changes_;
     changed = true;
@@ -325,8 +325,8 @@
                  << "x" << (*out_frame)->GetHeight()
                  << " Changed: " << (changed ? "true" : "false");
   }
-  previous_width = (*out_frame)->GetWidth();
-  previous_height = (*out_frame)->GetHeight();
+  previous_width_ = (*out_frame)->GetWidth();
+  previous_height_ = (*out_frame)->GetHeight();
 
   return true;
 }
@@ -376,7 +376,7 @@
 ///////////////////////////////////////////////////////////////////////
 // Implementation of CoordinatedVideoAdapter
 CoordinatedVideoAdapter::CoordinatedVideoAdapter()
-    : cpu_adaptation_(false),
+    : cpu_adaptation_(true),
       cpu_smoothing_(false),
       gd_adaptation_(true),
       view_adaptation_(true),
diff --git a/media/base/videoadapter.h b/media/base/videoadapter.h
index 38a8c9d..12be4fa 100644
--- a/media/base/videoadapter.h
+++ b/media/base/videoadapter.h
@@ -62,7 +62,7 @@
   // successfully. Return false otherwise.
   // output_frame_ is owned by the VideoAdapter that has the best knowledge on
   // the output frame.
-  bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame);
+  bool AdaptFrame(const VideoFrame* in_frame, VideoFrame** out_frame);
 
   void set_scale_third(bool enable) {
     LOG(LS_INFO) << "Video Adapter third scaling is now "
@@ -90,8 +90,8 @@
   int frames_;  // Number of input frames.
   int adapted_frames_;  // Number of frames scaled.
   int adaption_changes_;  // Number of changes in scale factor.
-  size_t previous_width;  // Previous adapter output width.
-  size_t previous_height;  // Previous adapter output height.
+  size_t previous_width_;  // Previous adapter output width.
+  size_t previous_height_;  // Previous adapter output height.
   bool black_output_;  // Flag to tell if we need to black output_frame_.
   bool is_black_;  // Flag to tell if output_frame_ is currently black.
   int64 interval_next_frame_;
diff --git a/media/base/videocapturer.cc b/media/base/videocapturer.cc
index 0d2a20f..26fcfa9 100644
--- a/media/base/videocapturer.cc
+++ b/media/base/videocapturer.cc
@@ -475,14 +475,25 @@
                   << desired_width << " x " << desired_height;
     return;
   }
-  if (!muted_ && !ApplyProcessors(&i420_frame)) {
+
+  VideoFrame* adapted_frame = &i420_frame;
+  if (!SignalAdaptFrame.is_empty() && !IsScreencast()) {
+    VideoFrame* out_frame = NULL;
+    SignalAdaptFrame(this, adapted_frame, &out_frame);
+    if (!out_frame) {
+      return;  // VideoAdapter dropped the frame.
+    }
+    adapted_frame = out_frame;
+  }
+
+  if (!muted_ && !ApplyProcessors(adapted_frame)) {
     // Processor dropped the frame.
     return;
   }
   if (muted_) {
-    i420_frame.SetToBlack();
+    adapted_frame->SetToBlack();
   }
-  SignalVideoFrame(this, &i420_frame);
+  SignalVideoFrame(this, adapted_frame);
 #endif  // VIDEO_FRAME_NAME
 }
 
diff --git a/media/base/videocapturer.h b/media/base/videocapturer.h
index 933fc82..2bd68bc 100644
--- a/media/base/videocapturer.h
+++ b/media/base/videocapturer.h
@@ -255,6 +255,11 @@
   // Signal the captured frame to downstream.
   sigslot::signal2<VideoCapturer*, const CapturedFrame*,
                    sigslot::multi_threaded_local> SignalFrameCaptured;
+  // If slots are connected to SignalAdaptFrame, this signals with parameters
+  // of this capturer instance, the input video frame and output frame
+  // pointer, respectively.
+  sigslot::signal3<VideoCapturer*, const VideoFrame*, VideoFrame**,
+                   sigslot::multi_threaded_local> SignalAdaptFrame;
   // Signal the captured frame converted to I420 to downstream.
   sigslot::signal2<VideoCapturer*, const VideoFrame*,
                    sigslot::multi_threaded_local> SignalVideoFrame;
diff --git a/media/base/videoengine_unittest.h b/media/base/videoengine_unittest.h
index f50a765..95d8f6c 100644
--- a/media/base/videoengine_unittest.h
+++ b/media/base/videoengine_unittest.h
@@ -54,6 +54,12 @@
   EXPECT_EQ((h), (r).height()); \
   EXPECT_EQ(0, (r).errors()); \
 
+#define EXPECT_GT_FRAME_ON_RENDERER_WAIT(r, c, w, h, t) \
+  EXPECT_TRUE_WAIT((r).num_rendered_frames() >= (c) && \
+                   (w) == (r).width() && \
+                   (h) == (r).height(), (t)); \
+  EXPECT_EQ(0, (r).errors()); \
+
 static const uint32 kTimeout = 5000U;
 static const uint32 kSsrc = 1234u;
 static const uint32 kRtxSsrc = 4321u;
@@ -1002,7 +1008,8 @@
     EXPECT_GE(2, NumRtpPackets());
     uint32 ssrc = 0;
     size_t last_packet = NumRtpPackets() - 1;
-    talk_base::scoped_ptr<const talk_base::Buffer> p(GetRtpPacket(last_packet));
+    talk_base::scoped_ptr<const talk_base::Buffer>
+        p(GetRtpPacket(static_cast<int>(last_packet)));
     ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
     EXPECT_EQ(kSsrc, ssrc);
 
@@ -1019,7 +1026,7 @@
     EXPECT_TRUE_WAIT(NumRtpPackets() > rtp_packets, kTimeout);
 
     last_packet = NumRtpPackets() - 1;
-    p.reset(GetRtpPacket(last_packet));
+    p.reset(GetRtpPacket(static_cast<int>(last_packet)));
     ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
     EXPECT_EQ(789u, ssrc);
   }
@@ -1167,7 +1174,11 @@
 
     EXPECT_TRUE(channel_->SetRenderer(kSsrc, &renderer1));
     EXPECT_TRUE(SendFrame());
-    EXPECT_FRAME_ON_RENDERER_WAIT(
+    // Because the default channel is used, RemoveRecvStream above is not going
+    // to delete the channel. As a result the engine will continue to receive
+    // and decode the 3 frames sent above. So it is possible we will receive
+    // some (e.g. 1) of these 3 frames after the renderer is set again.
+    EXPECT_GT_FRAME_ON_RENDERER_WAIT(
         renderer1, 2, DefaultCodec().width, DefaultCodec().height, kTimeout);
   }
 
@@ -1279,16 +1290,15 @@
     EXPECT_FRAME_WAIT(1, 640, 400, kTimeout);
     // Remove the capturer.
     EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
+    // Wait for one black frame for removing the capturer.
+    EXPECT_FRAME_WAIT(2, 640, 400, kTimeout);
+
     // No capturer was added, so this RemoveCapturer should
     // fail.
     EXPECT_FALSE(channel_->SetCapturer(kSsrc, NULL));
-    // Wait for frames to stop flowing.
     talk_base::Thread::Current()->ProcessMessages(300);
-    int num_frames = renderer_.num_rendered_frames();
-    // Wait to make sure no more frames are sent
-    WAIT(renderer_.num_rendered_frames() != num_frames, 300);
     // Verify no more frames were sent.
-    EXPECT_EQ(num_frames, renderer_.num_rendered_frames());
+    EXPECT_EQ(2, renderer_.num_rendered_frames());
   }
 
   // Tests that we can add and remove capturer as unique sources.
@@ -1375,10 +1385,8 @@
     EXPECT_EQ(0, renderer.num_rendered_frames());
 
     EXPECT_TRUE(SendFrame());
-    EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 1 &&
-                     codec.width == renderer.width() &&
-                     codec.height == renderer.height(), kTimeout);
-    EXPECT_EQ(0, renderer.errors());
+    EXPECT_GT_FRAME_ON_RENDERER_WAIT(
+        renderer, 1, codec.width, codec.height, kTimeout);
 
     // Registering an external capturer is currently the same as screen casting
     // (update the test when this changes).
@@ -1396,9 +1404,8 @@
     EXPECT_TRUE(capturer->CaptureCustomFrame(kWidth, kHeight,
                                              cricket::FOURCC_ARGB));
     EXPECT_TRUE(capturer->CaptureFrame());
-    EXPECT_TRUE_WAIT(renderer.num_rendered_frames() >= 2 &&
-                     kScaledWidth == renderer.width() &&
-                     kScaledHeight == renderer.height(), kTimeout);
+    EXPECT_GT_FRAME_ON_RENDERER_WAIT(
+        renderer, 2, kScaledWidth, kScaledHeight, kTimeout);
     EXPECT_TRUE(channel_->SetCapturer(kSsrc, NULL));
   }
 
diff --git a/media/base/videoframe_unittest.h b/media/base/videoframe_unittest.h
index 42485f1..d7be7e3 100644
--- a/media/base/videoframe_unittest.h
+++ b/media/base/videoframe_unittest.h
@@ -527,7 +527,7 @@
                                     kWidth, kHeight));
     EXPECT_TRUE(LoadFrame(y, buf_size, cricket::FOURCC_I422,
                           kWidth, kHeight, &frame2));
-    EXPECT_TRUE(IsEqual(frame1, frame2, 0));
+    EXPECT_TRUE(IsEqual(frame1, frame2, 1));
   }
 
   // Test constructing an image from a YUY2 buffer.
@@ -1861,7 +1861,7 @@
                             kWidth, kHeight, kWidth, kHeight,
                             y,
                             out_size,  1, 1, 0, 0, cricket::ROTATION_0));
-    EXPECT_TRUE(IsEqual(frame1, frame2, 0));
+    EXPECT_TRUE(IsEqual(frame1, frame2, 1));
   }
 
   #define TEST_TOBYR(NAME, BAYER)                                              \
diff --git a/media/webrtc/dummyinstantiation.cc b/media/webrtc/dummyinstantiation.cc
new file mode 100644
index 0000000..7d27967
--- /dev/null
+++ b/media/webrtc/dummyinstantiation.cc
@@ -0,0 +1,37 @@
+/*
+ * libjingle
+ * Copyright 2013 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright notice,
+ *     this list of conditions and the following disclaimer in the documentation
+ *     and/or other materials provided with the distribution.
+ *  3. The name of the author may not be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/media/webrtc/fakewebrtcvideoengine.h"
+#include "talk/media/webrtc/fakewebrtcvoiceengine.h"
+
+static void EnsureAPIMatch() {
+  new cricket::FakeWebRtcVoiceEngine(NULL, 0);
+  new cricket::FakeWebRtcVideoDecoder();
+  new cricket::FakeWebRtcVideoEncoder();
+  new cricket::FakeWebRtcVideoEngine(NULL, 0);
+  new cricket::FakeWebRtcVideoEngine::Capturer();
+}
diff --git a/media/webrtc/fakewebrtcvideoengine.h b/media/webrtc/fakewebrtcvideoengine.h
index b81d04b..850451b 100644
--- a/media/webrtc/fakewebrtcvideoengine.h
+++ b/media/webrtc/fakewebrtcvideoengine.h
@@ -33,6 +33,7 @@
 #include <vector>
 
 #include "talk/base/basictypes.h"
+#include "talk/base/gunit.h"
 #include "talk/base/stringutils.h"
 #include "talk/media/base/codec.h"
 #include "talk/media/webrtc/fakewebrtccommon.h"
@@ -338,12 +339,14 @@
   };
   class Capturer : public webrtc::ViEExternalCapture {
    public:
-    Capturer() : channel_id_(-1), denoising_(false), last_capture_time_(0) { }
+    Capturer() : channel_id_(-1), denoising_(false),
+                 last_capture_time_(0), incoming_frame_num_(0) { }
     int channel_id() const { return channel_id_; }
     void set_channel_id(int channel_id) { channel_id_ = channel_id; }
     bool denoising() const { return denoising_; }
     void set_denoising(bool denoising) { denoising_ = denoising; }
-    int64 last_capture_time() { return last_capture_time_; }
+    int64 last_capture_time() const { return last_capture_time_; }
+    int incoming_frame_num() const { return incoming_frame_num_; }
 
     // From ViEExternalCapture
     virtual int IncomingFrame(unsigned char* videoFrame,
@@ -358,6 +361,7 @@
         const webrtc::ViEVideoFrameI420& video_frame,
         unsigned long long captureTime) {
       last_capture_time_ = captureTime;
+      ++incoming_frame_num_;
       return 0;
     }
 
@@ -365,6 +369,7 @@
     int channel_id_;
     bool denoising_;
     int64 last_capture_time_;
+    int incoming_frame_num_;
   };
 
   FakeWebRtcVideoEngine(const cricket::VideoCodec* const* codecs,
@@ -407,6 +412,16 @@
 
   int GetLastCapturer() const { return last_capturer_; }
   int GetNumCapturers() const { return static_cast<int>(capturers_.size()); }
+  int GetIncomingFrameNum(int channel_id) const {
+    for (std::map<int, Capturer*>::const_iterator iter = capturers_.begin();
+         iter != capturers_.end(); ++iter) {
+      Capturer* capturer = iter->second;
+      if (capturer->channel_id() == channel_id) {
+        return capturer->incoming_frame_num();
+      }
+    }
+    return -1;
+  }
   void set_fail_alloc_capturer(bool fail_alloc_capturer) {
     fail_alloc_capturer_ = fail_alloc_capturer;
   }
@@ -626,7 +641,7 @@
   WEBRTC_STUB(RegisterCpuOveruseObserver,
       (int channel, webrtc::CpuOveruseObserver* observer));
 #ifdef USE_WEBRTC_DEV_BRANCH
-  WEBRTC_STUB(CpuOveruseMeasures, (int, int*, int*));
+  WEBRTC_STUB(CpuOveruseMeasures, (int, int*, int*, int*, int*));
 #endif
   WEBRTC_STUB(ConnectAudioChannel, (const int, const int));
   WEBRTC_STUB(DisconnectAudioChannel, (const int));
@@ -745,9 +760,7 @@
   WEBRTC_STUB(WaitForFirstKeyFrame, (const int, const bool));
   WEBRTC_STUB(StartDebugRecording, (int, const char*));
   WEBRTC_STUB(StopDebugRecording, (int));
-#ifdef USE_WEBRTC_DEV_BRANCH
   WEBRTC_VOID_STUB(SuspendBelowMinBitrate, (int));
-#endif
 
   // webrtc::ViECapture
   WEBRTC_STUB(NumberOfCaptureDevices, ());
@@ -1022,6 +1035,9 @@
     channels_[channel]->rtp_absolute_send_time_receive_id_ = (enable) ? id : 0;
     return 0;
   }
+#ifdef USE_WEBRTC_DEV_BRANCH
+  WEBRTC_STUB(SetRtcpXrRrtrStatus, (int, bool));
+#endif
   WEBRTC_FUNC(SetTransmissionSmoothingStatus, (int channel, bool enable)) {
     WEBRTC_CHECK_CHANNEL(channel);
     channels_[channel]->transmission_smoothing_ = enable;
@@ -1033,14 +1049,12 @@
       unsigned int&, unsigned int&, unsigned int&, int&));
   WEBRTC_STUB_CONST(GetRTPStatistics, (const int, unsigned int&, unsigned int&,
       unsigned int&, unsigned int&));
-#ifdef USE_WEBRTC_DEV_BRANCH
   WEBRTC_STUB_CONST(GetReceiveChannelRtcpStatistics, (const int,
       webrtc::RtcpStatistics&, int&));
   WEBRTC_STUB_CONST(GetSendChannelRtcpStatistics, (const int,
       webrtc::RtcpStatistics&, int&));
   WEBRTC_STUB_CONST(GetRtpStatistics, (const int, webrtc::StreamDataCounters&,
       webrtc::StreamDataCounters&));
-#endif
   WEBRTC_FUNC_CONST(GetBandwidthUsage, (const int channel,
       unsigned int& total_bitrate, unsigned int& video_bitrate,
       unsigned int& fec_bitrate, unsigned int& nack_bitrate)) {
@@ -1083,7 +1097,6 @@
     }
     return 0;
   }
-#ifdef USE_WEBRTC_DEV_BRANCH
   WEBRTC_STUB(RegisterSendChannelRtcpStatisticsCallback,
                     (int, webrtc::RtcpStatisticsCallback*));
   WEBRTC_STUB(DeregisterSendChannelRtcpStatisticsCallback,
@@ -1108,7 +1121,6 @@
                     (int, webrtc::FrameCountObserver*));
   WEBRTC_STUB(DeregisterSendFrameCountObserver,
                     (int, webrtc::FrameCountObserver*));
-#endif
 
   WEBRTC_STUB(StartRTPDump, (const int, const char*, webrtc::RTPDirections));
   WEBRTC_STUB(StopRTPDump, (const int, webrtc::RTPDirections));
diff --git a/media/webrtc/fakewebrtcvoiceengine.h b/media/webrtc/fakewebrtcvoiceengine.h
index ece0339..809816b 100644
--- a/media/webrtc/fakewebrtcvoiceengine.h
+++ b/media/webrtc/fakewebrtcvoiceengine.h
@@ -34,6 +34,7 @@
 
 
 #include "talk/base/basictypes.h"
+#include "talk/base/gunit.h"
 #include "talk/base/stringutils.h"
 #include "talk/media/base/codec.h"
 #include "talk/media/base/voiceprocessor.h"
@@ -181,7 +182,7 @@
     }
     return -1;
   }
-  int GetNumChannels() const { return channels_.size(); }
+  int GetNumChannels() const { return static_cast<int>(channels_.size()); }
   bool GetPlayout(int channel) {
     return channels_[channel]->playout;
   }
@@ -298,14 +299,12 @@
   WEBRTC_FUNC(CreateChannel, ()) {
     return AddChannel(false);
   }
-#ifdef USE_WEBRTC_DEV_BRANCH
   WEBRTC_FUNC(CreateChannel, (const webrtc::Config& config)) {
     talk_base::scoped_ptr<webrtc::AudioCodingModule> acm(
         config.Get<webrtc::AudioCodingModuleFactory>().Create(0));
     return AddChannel(strcmp(acm->Version(), webrtc::kExperimentalAcmVersion)
                       == 0);
   }
-#endif
   WEBRTC_FUNC(DeleteChannel, (int channel)) {
     WEBRTC_CHECK_CHANNEL(channel);
     delete channels_[channel];
@@ -917,6 +916,9 @@
   WEBRTC_STUB(GetEcDelayMetrics, (int& delay_median, int& delay_std));
 
   WEBRTC_STUB(StartDebugRecording, (const char* fileNameUTF8));
+#ifdef USE_WEBRTC_DEV_BRANCH
+  WEBRTC_STUB(StartDebugRecording, (FILE* handle));
+#endif
   WEBRTC_STUB(StopDebugRecording, ());
 
   WEBRTC_FUNC(SetTypingDetectionStatus, (bool enable)) {
diff --git a/media/webrtc/webrtcvideoengine.cc b/media/webrtc/webrtcvideoengine.cc
index 397deb0..d6fabdb 100644
--- a/media/webrtc/webrtcvideoengine.cc
+++ b/media/webrtc/webrtcvideoengine.cc
@@ -228,9 +228,8 @@
   }
 
   virtual int DeliverFrame(unsigned char* buffer, int buffer_size,
-                           uint32_t time_stamp, int64_t render_time
-                           , void* handle
-                          ) {
+                           uint32_t time_stamp, int64_t render_time,
+                           void* handle) {
     talk_base::CritScope cs(&crit_);
     frame_rate_tracker_.Update(1);
     if (renderer_ == NULL) {
@@ -633,10 +632,6 @@
     }
   }
 
-  bool AdaptFrame(const VideoFrame* in_frame, const VideoFrame** out_frame) {
-    *out_frame = NULL;
-    return video_adapter_->AdaptFrame(in_frame, out_frame);
-  }
   int CurrentAdaptReason() const {
     return video_adapter_->adapt_reason();
   }
@@ -677,9 +672,18 @@
         // video capturer.
         video_adapter_->SetInputFormat(*capture_format);
       }
+      // TODO(thorcarpenter): When the adapter supports "only frame dropping"
+      // mode, also hook it up to screencast capturers.
+      video_capturer->SignalAdaptFrame.connect(
+          this, &WebRtcVideoChannelSendInfo::AdaptFrame);
     }
   }
 
+  void AdaptFrame(VideoCapturer* capturer, const VideoFrame* input,
+                  VideoFrame** adapted) {
+    video_adapter_->AdaptFrame(input, adapted);
+  }
+
   void ApplyCpuOptions(const VideoOptions& options) {
     bool cpu_adapt, cpu_smoothing, adapt_third;
     float low, med, high;
@@ -2004,17 +2008,15 @@
   LOG(LS_INFO) << "Removing video stream " << ssrc
                << " with VideoEngine channel #"
                << channel_id;
+  bool ret = true;
   if (engine()->vie()->base()->DeleteChannel(channel_id) == -1) {
     LOG_RTCERR1(DeleteChannel, channel_id);
-    // Leak the WebRtcVideoChannelRecvInfo owned by |it| but remove the channel
-    // from recv_channels_.
-    recv_channels_.erase(it);
-    return false;
+    ret = false;
   }
   // Delete the WebRtcVideoChannelRecvInfo pointed to by it->second.
   delete info;
   recv_channels_.erase(it);
-  return true;
+  return ret;
 }
 
 bool WebRtcVideoMediaChannel::StartSend() {
@@ -2117,18 +2119,6 @@
 }
 
 WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
-    VideoCapturer* video_capturer) {
-  for (SendChannelMap::iterator iter = send_channels_.begin();
-       iter != send_channels_.end(); ++iter) {
-    WebRtcVideoChannelSendInfo* send_channel = iter->second;
-    if (send_channel->video_capturer() == video_capturer) {
-      return send_channel;
-    }
-  }
-  return NULL;
-}
-
-WebRtcVideoChannelSendInfo* WebRtcVideoMediaChannel::GetSendChannel(
     uint32 local_ssrc) {
   uint32 key;
   if (!GetSendChannelKey(local_ssrc, &key)) {
@@ -2301,18 +2291,27 @@
       sinfo.adapt_reason = send_channel->CurrentAdaptReason();
       sinfo.capture_jitter_ms = -1;
       sinfo.avg_encode_ms = -1;
+      sinfo.encode_usage_percent = -1;
+      sinfo.capture_queue_delay_ms_per_s = -1;
 
 #ifdef USE_WEBRTC_DEV_BRANCH
       int capture_jitter_ms = 0;
       int avg_encode_time_ms = 0;
+      int encode_usage_percent = 0;
+      int capture_queue_delay_ms_per_s = 0;
       if (engine()->vie()->base()->CpuOveruseMeasures(
-          channel_id, &capture_jitter_ms, &avg_encode_time_ms) == 0) {
+          channel_id,
+          &capture_jitter_ms,
+          &avg_encode_time_ms,
+          &encode_usage_percent,
+          &capture_queue_delay_ms_per_s) == 0) {
         sinfo.capture_jitter_ms = capture_jitter_ms;
         sinfo.avg_encode_ms = avg_encode_time_ms;
+        sinfo.encode_usage_percent = encode_usage_percent;
+        sinfo.capture_queue_delay_ms_per_s = capture_queue_delay_ms_per_s;
       }
 #endif
 
-#ifdef USE_WEBRTC_DEV_BRANCH
       // Get received RTCP statistics for the sender (reported by the remote
       // client in a RTCP packet), if available.
       // It's not a fatal error if we can't, since RTCP may not have arrived
@@ -2330,28 +2329,6 @@
             outgoing_stream_rtcp_stats.fraction_lost) / (1 << 8);
         sinfo.rtt_ms = outgoing_stream_rtt_ms;
       }
-#else
-      // Get received RTCP statistics for the sender, if available.
-      // It's not a fatal error if we can't, since RTCP may not have arrived
-      // yet.
-      uint16 r_fraction_lost;
-      unsigned int r_cumulative_lost;
-      unsigned int r_extended_max;
-      unsigned int r_jitter;
-      int r_rtt_ms;
-
-      if (engine_->vie()->rtp()->GetSentRTCPStatistics(
-              channel_id,
-              r_fraction_lost,
-              r_cumulative_lost,
-              r_extended_max,
-              r_jitter, r_rtt_ms) == 0) {
-        // Convert Q8 to float.
-        sinfo.packets_lost = r_cumulative_lost;
-        sinfo.fraction_lost = static_cast<float>(r_fraction_lost) / (1 << 8);
-        sinfo.rtt_ms = r_rtt_ms;
-      }
-#endif
       info->senders.push_back(sinfo);
 
       unsigned int channel_total_bitrate_sent = 0;
@@ -2406,7 +2383,6 @@
         ssrc == 0)
       continue;
 
-#ifdef USE_WEBRTC_DEV_BRANCH
     webrtc::StreamDataCounters sent;
     webrtc::StreamDataCounters received;
     if (engine_->vie()->rtp()->GetRtpStatistics(channel->channel_id(),
@@ -2418,19 +2394,6 @@
     rinfo.add_ssrc(ssrc);
     rinfo.bytes_rcvd = received.bytes;
     rinfo.packets_rcvd = received.packets;
-#else
-    unsigned int bytes_sent, packets_sent, bytes_recv, packets_recv;
-    if (engine_->vie()->rtp()->GetRTPStatistics(
-        channel->channel_id(), bytes_sent, packets_sent, bytes_recv,
-        packets_recv) != 0) {
-      LOG_RTCERR1(GetRTPStatistics, channel->channel_id());
-      return false;
-    }
-    VideoReceiverInfo rinfo;
-    rinfo.add_ssrc(ssrc);
-    rinfo.bytes_rcvd = bytes_recv;
-    rinfo.packets_rcvd = packets_recv;
-#endif
     rinfo.packets_lost = -1;
     rinfo.packets_concealed = -1;
     rinfo.fraction_lost = -1;  // from SentRTCP
@@ -2442,7 +2405,6 @@
     rinfo.framerate_output = fps;
     channel->decoder_observer()->ExportTo(&rinfo);
 
-#ifdef USE_WEBRTC_DEV_BRANCH
     // Get our locally created statistics of the received RTP stream.
     webrtc::RtcpStatistics incoming_stream_rtcp_stats;
     int incoming_stream_rtt_ms;
@@ -2455,21 +2417,6 @@
       rinfo.fraction_lost = static_cast<float>(
           incoming_stream_rtcp_stats.fraction_lost) / (1 << 8);
     }
-#else
-    // Get sent RTCP statistics.
-    uint16 s_fraction_lost;
-    unsigned int s_cumulative_lost;
-    unsigned int s_extended_max;
-    unsigned int s_jitter;
-    int s_rtt_ms;
-    if (engine_->vie()->rtp()->GetReceivedRTCPStatistics(channel->channel_id(),
-            s_fraction_lost, s_cumulative_lost, s_extended_max,
-            s_jitter, s_rtt_ms) == 0) {
-      // Convert Q8 to float.
-      rinfo.packets_lost = s_cumulative_lost;
-      rinfo.fraction_lost = static_cast<float>(s_fraction_lost) / (1 << 8);
-    }
-#endif
     info->receivers.push_back(rinfo);
 
     unsigned int estimated_recv_stream_bandwidth = 0;
@@ -2516,7 +2463,7 @@
   send_channel->set_video_capturer(capturer);
   capturer->SignalVideoFrame.connect(
       this,
-      &WebRtcVideoMediaChannel::AdaptAndSendFrame);
+      &WebRtcVideoMediaChannel::SendFrame);
   if (!capturer->IsScreencast() && ratio_w_ != 0 && ratio_h_ != 0) {
     capturer->UpdateAspectRatio(ratio_w_, ratio_h_);
   }
@@ -2835,7 +2782,6 @@
     }
   }
   if (suspend_below_min_bitrate_changed) {
-#ifdef USE_WEBRTC_DEV_BRANCH
     if (options_.suspend_below_min_bitrate.GetWithDefaultIfUnset(false)) {
       for (SendChannelMap::iterator it = send_channels_.begin();
            it != send_channels_.end(); ++it) {
@@ -2845,7 +2791,6 @@
     } else {
       LOG(LS_WARNING) << "Cannot disable video suspension once it is enabled";
     }
-#endif
   }
   return true;
 }
@@ -2901,39 +2846,23 @@
   return true;
 }
 
-void WebRtcVideoMediaChannel::AdaptAndSendFrame(VideoCapturer* capturer,
-                                                const VideoFrame* frame) {
-  if (capturer->IsScreencast()) {
-    // Do not adapt frames that are screencast.
-    SendFrame(capturer, frame);
-    return;
-  }
-  // TODO(thorcarpenter): This is broken. One capturer registered on two ssrc
-  // will not send any video to the second ssrc send channel. We should remove
-  // GetSendChannel(capturer) and pass in an ssrc here.
-  WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
-  if (!send_channel) {
-    SendFrame(capturer, frame);
-    return;
-  }
-  const VideoFrame* output_frame = NULL;
-  send_channel->AdaptFrame(frame, &output_frame);
-  if (output_frame) {
-    SendFrame(send_channel, output_frame, capturer->IsScreencast());
-  }
-}
-
-// TODO(zhurunz): Add unittests to test this function.
 void WebRtcVideoMediaChannel::SendFrame(VideoCapturer* capturer,
                                         const VideoFrame* frame) {
-  // If there's send channel registers to the |capturer|, then only send the
-  // frame to that channel and return. Otherwise send the frame to the default
-  // channel, which currently taking frames from the engine.
-  WebRtcVideoChannelSendInfo* send_channel = GetSendChannel(capturer);
-  if (send_channel) {
-    SendFrame(send_channel, frame, capturer->IsScreencast());
+  // If the |capturer| is registered to any send channel, then send the frame
+  // to those send channels.
+  bool capturer_is_channel_owned = false;
+  for (SendChannelMap::iterator iter = send_channels_.begin();
+       iter != send_channels_.end(); ++iter) {
+    WebRtcVideoChannelSendInfo* send_channel = iter->second;
+    if (send_channel->video_capturer() == capturer) {
+      SendFrame(send_channel, frame, capturer->IsScreencast());
+      capturer_is_channel_owned = true;
+    }
+  }
+  if (capturer_is_channel_owned) {
     return;
   }
+
   // TODO(hellner): Remove below for loop once the captured frame no longer
   // come from the engine, i.e. the engine no longer owns a capturer.
   for (SendChannelMap::iterator iter = send_channels_.begin();
diff --git a/media/webrtc/webrtcvideoengine.h b/media/webrtc/webrtcvideoengine.h
index af4d627..d5f0e57 100644
--- a/media/webrtc/webrtcvideoengine.h
+++ b/media/webrtc/webrtcvideoengine.h
@@ -290,8 +290,6 @@
   bool SendFrame(WebRtcVideoChannelSendInfo* channel_info,
                  const VideoFrame* frame, bool is_screencast);
 
-  void AdaptAndSendFrame(VideoCapturer* capturer, const VideoFrame* frame);
-
   // Thunk functions for use with HybridVideoEngine
   void OnLocalFrame(VideoCapturer* capturer, const VideoFrame* frame) {
     SendFrame(0u, frame, capturer->IsScreencast());
@@ -366,7 +364,6 @@
   // If the local ssrc correspond to that of the default channel the key is 0.
   // For all other channels the returned key will be the same as the local ssrc.
   bool GetSendChannelKey(uint32 local_ssrc, uint32* key);
-  WebRtcVideoChannelSendInfo* GetSendChannel(VideoCapturer* video_capturer);
   WebRtcVideoChannelSendInfo* GetSendChannel(uint32 local_ssrc);
   // Creates a new unique key that can be used for inserting a new send channel
   // into |send_channels_|
diff --git a/media/webrtc/webrtcvideoengine_unittest.cc b/media/webrtc/webrtcvideoengine_unittest.cc
index e37bc3c..93ca9ad 100644
--- a/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/media/webrtc/webrtcvideoengine_unittest.cc
@@ -69,6 +69,12 @@
 
 static const unsigned int kNumberOfTemporalLayers = 1;
 
+static const uint32 kSsrcs1[] = {1};
+static const uint32 kSsrcs2[] = {1, 2};
+static const uint32 kSsrcs3[] = {1, 2, 3};
+static const uint32 kRtxSsrc1[] = {4};
+static const uint32 kRtxSsrcs3[] = {4, 5, 6};
+
 
 class FakeViEWrapper : public cricket::ViEWrapper {
  public:
@@ -117,11 +123,7 @@
       return false;
     }
     cricket::WebRtcVideoFrame frame;
-    size_t size = width * height * 3 / 2;  // I420
-    talk_base::scoped_ptr<uint8[]> pixel(new uint8[size]);
-    if (!frame.Init(cricket::FOURCC_I420,
-                    width, height, width, height,
-                    pixel.get(), size, 1, 1, 0, 0, 0)) {
+    if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) {
       return false;
     }
     cricket::FakeVideoCapturer capturer;
@@ -137,11 +139,7 @@
       return false;
     }
     cricket::WebRtcVideoFrame frame;
-    size_t size = width * height * 3 / 2;  // I420
-    talk_base::scoped_ptr<uint8[]> pixel(new uint8[size]);
-    if (!frame.Init(cricket::FOURCC_I420,
-                    width, height, width, height,
-                    pixel.get(), size, 1, 1, 0, timestamp, 0)) {
+    if (!frame.InitToBlack(width, height, 1, 1, 0, 0)) {
       return false;
     }
     cricket::FakeVideoCapturer capturer;
@@ -1218,6 +1216,41 @@
   EXPECT_FALSE(vie_.GetCaptureDenoising(capture_id));
 }
 
+TEST_F(WebRtcVideoEngineTestFake, MultipleSendStreamsWithOneCapturer) {
+  EXPECT_TRUE(SetupEngine());
+  cricket::FakeVideoCapturer capturer;
+  for (unsigned int i = 0; i < sizeof(kSsrcs2)/sizeof(kSsrcs2[0]); ++i) {
+    EXPECT_TRUE(channel_->AddSendStream(
+        cricket::StreamParams::CreateLegacy(kSsrcs2[i])));
+    // Register the capturer to the ssrc.
+    EXPECT_TRUE(channel_->SetCapturer(kSsrcs2[i], &capturer));
+  }
+
+  const int channel0 = vie_.GetChannelFromLocalSsrc(kSsrcs2[0]);
+  ASSERT_NE(-1, channel0);
+  const int channel1 = vie_.GetChannelFromLocalSsrc(kSsrcs2[1]);
+  ASSERT_NE(-1, channel1);
+  ASSERT_NE(channel0, channel1);
+
+  std::vector<cricket::VideoCodec> codecs;
+  codecs.push_back(kVP8Codec);
+  EXPECT_TRUE(channel_->SetSendCodecs(codecs));
+
+  cricket::WebRtcVideoFrame frame;
+  const size_t pixel_width = 1;
+  const size_t pixel_height = 1;
+  const int64 elapsed_time = 0;
+  const int64 time_stamp = 0;
+  EXPECT_TRUE(frame.InitToBlack(kVP8Codec.width, kVP8Codec.height,
+                                pixel_width, pixel_height,
+                                elapsed_time, time_stamp));
+  channel_->SendFrame(&capturer, &frame);
+
+  // Both channels should have received the frame.
+  EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel0));
+  EXPECT_EQ(1, vie_.GetIncomingFrameNum(channel1));
+}
+
 
 // Disabled since its flaky: b/11288120
 TEST_F(WebRtcVideoEngineTestFake, DISABLED_SendReceiveBitratesStats) {
@@ -1764,8 +1797,14 @@
   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) {
@@ -1778,6 +1817,9 @@
   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());
@@ -1785,6 +1827,9 @@
   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) {
@@ -1916,9 +1961,15 @@
   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.
diff --git a/media/webrtc/webrtcvoiceengine.cc b/media/webrtc/webrtcvoiceengine.cc
index 1b77671..745a1e0 100644
--- a/media/webrtc/webrtcvoiceengine.cc
+++ b/media/webrtc/webrtcvoiceengine.cc
@@ -1609,11 +1609,7 @@
 }
 
 int WebRtcVoiceEngine::CreateVoiceChannel(VoEWrapper* voice_engine_wrapper) {
-#ifdef USE_WEBRTC_DEV_BRANCH
   return voice_engine_wrapper->base()->CreateChannel(voe_config_);
-#else
-  return voice_engine_wrapper->base()->CreateChannel();
-#endif
 }
 
 int WebRtcVoiceEngine::CreateMediaVoiceChannel() {
diff --git a/media/webrtc/webrtcvoiceengine_unittest.cc b/media/webrtc/webrtcvoiceengine_unittest.cc
index cf8a54f..4c3ba2a 100644
--- a/media/webrtc/webrtcvoiceengine_unittest.cc
+++ b/media/webrtc/webrtcvoiceengine_unittest.cc
@@ -2060,7 +2060,7 @@
   char packets[4][sizeof(kPcmuFrame)];
   for (size_t i = 0; i < ARRAY_SIZE(packets); ++i) {
     memcpy(packets[i], kPcmuFrame, sizeof(kPcmuFrame));
-    talk_base::SetBE32(packets[i] + 8, i);
+    talk_base::SetBE32(packets[i] + 8, static_cast<uint32>(i));
   }
   EXPECT_TRUE(voe_.CheckNoPacket(channel_num1));
   EXPECT_TRUE(voe_.CheckNoPacket(channel_num2));
@@ -2192,7 +2192,8 @@
   EXPECT_FALSE(channel_->PlayRingbackTone(0, true, true));
   EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
   // Check we can set and play a ringback tone.
-  EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
+  EXPECT_TRUE(channel_->SetRingbackTone(
+                  kRingbackTone, static_cast<int>(strlen(kRingbackTone))));
   EXPECT_TRUE(channel_->PlayRingbackTone(0, true, true));
   EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
   // Check we can stop the tone manually.
@@ -2217,7 +2218,8 @@
   EXPECT_FALSE(channel_->PlayRingbackTone(2, true, true));
   EXPECT_EQ(0, voe_.IsPlayingFileLocally(channel_num));
   // Check we can set and play a ringback tone on the correct ssrc.
-  EXPECT_TRUE(channel_->SetRingbackTone(kRingbackTone, strlen(kRingbackTone)));
+  EXPECT_TRUE(channel_->SetRingbackTone(
+                  kRingbackTone, static_cast<int>(strlen(kRingbackTone))));
   EXPECT_FALSE(channel_->PlayRingbackTone(77, true, true));
   EXPECT_TRUE(channel_->PlayRingbackTone(2, true, true));
   EXPECT_EQ(1, voe_.IsPlayingFileLocally(channel_num));
@@ -2836,7 +2838,7 @@
   size_t size = 0;
   EXPECT_TRUE(stream->GetSize(&size));
   EXPECT_GT(size, 0U);
-  const std::string logs(stream->GetBuffer());
+  const std::string logs(stream->GetBuffer(), size);
   EXPECT_NE(std::string::npos, logs.find("ProcessThread"));
 }
 
@@ -2910,9 +2912,9 @@
       EXPECT_EQ(127, it->id);
     } else if (it->name == "opus") {
       EXPECT_EQ(111, it->id);
-      ASSERT_NE(it->params.find("minptime"), it->params.end());
+      ASSERT_TRUE(it->params.find("minptime") != it->params.end());
       EXPECT_EQ("10", it->params.find("minptime")->second);
-      ASSERT_NE(it->params.find("maxptime"), it->params.end());
+      ASSERT_TRUE(it->params.find("maxptime") != it->params.end());
       EXPECT_EQ("60", it->params.find("maxptime")->second);
     }
   }
@@ -2994,7 +2996,6 @@
   ASSERT_GE(soundclip_channel, 0);
   EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
 
-#ifdef USE_WEBRTC_DEV_BRANCH
   // Set options to use experimental ACM.
   cricket::AudioOptions options;
   options.experimental_acm.Set(true);
@@ -3017,5 +3018,4 @@
   soundclip_channel = engine_.CreateSoundclipVoiceChannel();
   ASSERT_GE(soundclip_channel, 0);
   EXPECT_FALSE(voe_sc_.IsUsingExperimentalAcm(soundclip_channel));
-#endif
 }
diff --git a/session/media/channel.cc b/session/media/channel.cc
index e0aff89..8579db2 100644
--- a/session/media/channel.cc
+++ b/session/media/channel.cc
@@ -587,11 +587,16 @@
 
 int BaseChannel::SetOption(SocketType type, talk_base::Socket::Option opt,
                            int value) {
+  TransportChannel* channel = NULL;
   switch (type) {
-    case ST_RTP: return transport_channel_->SetOption(opt, value);
-    case ST_RTCP: return rtcp_transport_channel_->SetOption(opt, value);
-    default: return -1;
+    case ST_RTP:
+      channel = transport_channel_;
+      break;
+    case ST_RTCP:
+      channel = rtcp_transport_channel_;
+      break;
   }
+  return channel ? channel->SetOption(opt, value) : -1;
 }
 
 void BaseChannel::OnWritableState(TransportChannel* channel) {
@@ -2152,7 +2157,9 @@
     // Tweak our video processing settings, if needed.
     VideoOptions video_options;
     media_channel()->GetOptions(&video_options);
-    video_options.conference_mode.Set(video->conference_mode());
+    if (video->conference_mode()) {
+      video_options.conference_mode.Set(true);
+    }
     video_options.buffered_mode_latency.Set(video->buffered_mode_latency());
 
     if (!media_channel()->SetOptions(video_options)) {