Reserve RTP/RTCP modules in SetSSRC.

Allows setting SSRCs for future simulcast layers even though no set send
codec uses them.

Also re-enabling CanSwitchToUseAllSsrcs as an end-to-end test, required
for bitrate ramp-up, instead of send-side only (resolving issue 3078).
This test was used to verify reserved modules' SSRCs are preserved
correctly.

To enable a multiple-stream end-to-end test test::CallTest was modified
to work on a vector of receive streams instead of just one.

BUG=3078
R=kjellander@webrtc.org, stefan@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6565 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc
index ad2416f..5d8b8e6 100644
--- a/webrtc/test/call_test.cc
+++ b/webrtc/test/call_test.cc
@@ -16,7 +16,6 @@
 
 CallTest::CallTest()
     : send_stream_(NULL),
-      receive_stream_(NULL),
       fake_encoder_(Clock::GetRealTimeClock()) {
 }
 CallTest::~CallTest() {
@@ -39,9 +38,9 @@
   if (test->ShouldCreateReceivers()) {
     CreateMatchingReceiveConfigs();
   }
-  test->ModifyConfigs(&send_config_, &receive_config_, &video_streams_);
+  test->ModifyConfigs(&send_config_, &receive_configs_, &video_streams_);
   CreateStreams();
-  test->OnStreamsCreated(send_stream_, receive_stream_);
+  test->OnStreamsCreated(send_stream_, receive_streams_);
 
   CreateFrameGeneratorCapturer();
   test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
@@ -56,15 +55,17 @@
 
 void CallTest::Start() {
   send_stream_->Start();
-  if (receive_stream_ != NULL)
-    receive_stream_->Start();
-  frame_generator_capturer_->Start();
+  for (size_t i = 0; i < receive_streams_.size(); ++i)
+    receive_streams_[i]->Start();
+  if (frame_generator_capturer_.get() != NULL)
+    frame_generator_capturer_->Start();
 }
 
 void CallTest::Stop() {
-  frame_generator_capturer_->Stop();
-  if (receive_stream_ != NULL)
-    receive_stream_->Stop();
+  if (frame_generator_capturer_.get() != NULL)
+    frame_generator_capturer_->Stop();
+  for (size_t i = 0; i < receive_streams_.size(); ++i)
+    receive_streams_[i]->Stop();
   send_stream_->Stop();
 }
 
@@ -93,21 +94,24 @@
     send_config_.rtp.ssrcs.push_back(kSendSsrcs[i]);
 }
 
-// TODO(pbos): Make receive configs into a vector.
 void CallTest::CreateMatchingReceiveConfigs() {
-  assert(send_config_.rtp.ssrcs.size() == 1);
-  receive_config_ = receiver_call_->GetDefaultReceiveConfig();
+  assert(!send_config_.rtp.ssrcs.empty());
+  assert(receive_configs_.empty());
+  VideoReceiveStream::Config config = receiver_call_->GetDefaultReceiveConfig();
   VideoCodec codec =
       test::CreateDecoderVideoCodec(send_config_.encoder_settings);
-  receive_config_.codecs.push_back(codec);
+  config.codecs.push_back(codec);
   if (send_config_.encoder_settings.encoder == &fake_encoder_) {
     ExternalVideoDecoder decoder;
     decoder.decoder = &fake_decoder_;
     decoder.payload_type = send_config_.encoder_settings.payload_type;
-    receive_config_.external_decoders.push_back(decoder);
+    config.external_decoders.push_back(decoder);
   }
-  receive_config_.rtp.remote_ssrc = send_config_.rtp.ssrcs[0];
-  receive_config_.rtp.local_ssrc = kReceiverLocalSsrc;
+  config.rtp.local_ssrc = kReceiverLocalSsrc;
+  for (size_t i = 0; i < send_config_.rtp.ssrcs.size(); ++i) {
+    config.rtp.remote_ssrc = send_config_.rtp.ssrcs[i];
+    receive_configs_.push_back(config);
+  }
 }
 
 void CallTest::CreateFrameGeneratorCapturer() {
@@ -121,22 +125,24 @@
 }
 void CallTest::CreateStreams() {
   assert(send_stream_ == NULL);
-  assert(receive_stream_ == NULL);
+  assert(receive_streams_.empty());
 
   send_stream_ =
       sender_call_->CreateVideoSendStream(send_config_, video_streams_, NULL);
 
-  if (receiver_call_.get() != NULL)
-    receive_stream_ = receiver_call_->CreateVideoReceiveStream(receive_config_);
+  for (size_t i = 0; i < receive_configs_.size(); ++i) {
+    receive_streams_.push_back(
+        receiver_call_->CreateVideoReceiveStream(receive_configs_[i]));
+  }
 }
 
 void CallTest::DestroyStreams() {
   if (send_stream_ != NULL)
     sender_call_->DestroyVideoSendStream(send_stream_);
-  if (receive_stream_ != NULL)
-    receiver_call_->DestroyVideoReceiveStream(receive_stream_);
   send_stream_ = NULL;
-  receive_stream_ = NULL;
+  for (size_t i = 0; i < receive_streams_.size(); ++i)
+    receiver_call_->DestroyVideoReceiveStream(receive_streams_[i]);
+  receive_streams_.clear();
 }
 
 const unsigned int CallTest::kDefaultTimeoutMs = 30 * 1000;
@@ -175,13 +181,15 @@
   return 1;
 }
 
-void BaseTest::ModifyConfigs(VideoSendStream::Config* send_config,
-                             VideoReceiveStream::Config* receive_config,
-                             std::vector<VideoStream>* video_streams) {
+void BaseTest::ModifyConfigs(
+    VideoSendStream::Config* send_config,
+    std::vector<VideoReceiveStream::Config>* receive_configs,
+    std::vector<VideoStream>* video_streams) {
 }
 
-void BaseTest::OnStreamsCreated(VideoSendStream* send_stream,
-                                VideoReceiveStream* receive_stream) {
+void BaseTest::OnStreamsCreated(
+    VideoSendStream* send_stream,
+    const std::vector<VideoReceiveStream*>& receive_streams) {
 }
 
 void BaseTest::OnFrameGeneratorCapturerCreated(
diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h
index 94ac2fa..37a883d 100644
--- a/webrtc/test/call_test.h
+++ b/webrtc/test/call_test.h
@@ -64,8 +64,8 @@
   VideoSendStream* send_stream_;
 
   scoped_ptr<Call> receiver_call_;
-  VideoReceiveStream::Config receive_config_;
-  VideoReceiveStream* receive_stream_;
+  std::vector<VideoReceiveStream::Config> receive_configs_;
+  std::vector<VideoReceiveStream*> receive_streams_;
 
   scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
   test::FakeEncoder fake_encoder_;
@@ -87,11 +87,13 @@
   virtual Call::Config GetReceiverCallConfig();
   virtual void OnCallsCreated(Call* sender_call, Call* receiver_call);
 
-  virtual void ModifyConfigs(VideoSendStream::Config* send_config,
-                             VideoReceiveStream::Config* receive_config,
-                             std::vector<VideoStream>* video_streams);
-  virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                VideoReceiveStream* receive_stream);
+  virtual void ModifyConfigs(
+      VideoSendStream::Config* send_config,
+      std::vector<VideoReceiveStream::Config>* receive_configs,
+      std::vector<VideoStream>* video_streams);
+  virtual void OnStreamsCreated(
+      VideoSendStream* send_stream,
+      const std::vector<VideoReceiveStream*>& receive_streams);
 
   virtual void OnFrameGeneratorCapturerCreated(
       FrameGeneratorCapturer* frame_generator_capturer);
diff --git a/webrtc/video/call_perf_tests.cc b/webrtc/video/call_perf_tests.cc
index b6e2b34..1824616 100644
--- a/webrtc/video/call_perf_tests.cc
+++ b/webrtc/video/call_perf_tests.cc
@@ -254,8 +254,8 @@
   CreateSendConfig(1);
   CreateMatchingReceiveConfigs();
 
-  receive_config_.renderer = &observer;
-  receive_config_.audio_channel_id = channel;
+  receive_configs_[0].renderer = &observer;
+  receive_configs_[0].audio_channel_id = channel;
 
   CreateStreams();
 
@@ -379,11 +379,11 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
-      receive_config->renderer = this;
+      (*receive_configs)[0].renderer = this;
       // Enable the receiver side rtt calculation.
-      receive_config->rtp.rtcp_xr.receiver_reference_time_report = true;
+      (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -518,14 +518,15 @@
       return send_transport_receiver_->DeliverPacket(packet, length);
     }
 
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) {
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
       send_stream_ = send_stream;
     }
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       if (pad_to_min_bitrate_) {
         send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index 0f6f2dc..fa3d3cf 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -49,39 +49,15 @@
 
   virtual ~EndToEndTest() {
     EXPECT_EQ(NULL, send_stream_);
-    EXPECT_EQ(NULL, receive_stream_);
+    EXPECT_TRUE(receive_streams_.empty());
   }
 
  protected:
-  void CreateFrameGenerator() {
-    frame_generator_capturer_.reset(
-        test::FrameGeneratorCapturer::Create(send_stream_->Input(),
-                                             video_streams_[0].width,
-                                             video_streams_[0].height,
-                                             30,
-                                             Clock::GetRealTimeClock()));
-  }
-
-  void StartSending() {
-    receive_stream_->Start();
-    send_stream_->Start();
-    if (frame_generator_capturer_.get() != NULL)
-      frame_generator_capturer_->Start();
-  }
-
-  void StopSending() {
-    if (frame_generator_capturer_.get() != NULL)
-      frame_generator_capturer_->Stop();
-    if (send_stream_ != NULL)
-      send_stream_->Stop();
-    if (receive_stream_ != NULL)
-      receive_stream_->Stop();
-  }
-
   void DecodesRetransmittedFrame(bool retransmit_over_rtx);
   void ReceivesPliAndRecovers(int rtp_history_ms);
   void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
   void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
+  void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
 };
 
 TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
@@ -93,8 +69,8 @@
 
   CreateStreams();
 
-  receive_stream_->Start();
-  receive_stream_->Start();
+  receive_streams_[0]->Start();
+  receive_streams_[0]->Start();
 
   DestroyStreams();
 }
@@ -108,8 +84,8 @@
 
   CreateStreams();
 
-  receive_stream_->Stop();
-  receive_stream_->Stop();
+  receive_streams_[0]->Stop();
+  receive_streams_[0]->Stop();
 
   DestroyStreams();
 }
@@ -163,11 +139,11 @@
   CreateMatchingReceiveConfigs();
 
   TestFrameCallback pre_render_callback;
-  receive_config_.pre_render_callback = &pre_render_callback;
-  receive_config_.renderer = &renderer;
+  receive_configs_[0].pre_render_callback = &pre_render_callback;
+  receive_configs_[0].renderer = &renderer;
 
   CreateStreams();
-  StartSending();
+  Start();
 
   // Create frames that are smaller than the send width/height, this is done to
   // check that the callbacks are done after processing video.
@@ -179,7 +155,7 @@
   EXPECT_EQ(kEventSignaled, renderer.Wait())
       << "Timed out while waiting for the frame to render.";
 
-  StopSending();
+  Stop();
 
   sender_transport.StopSending();
   receiver_transport.StopSending();
@@ -212,10 +188,10 @@
 
   CreateSendConfig(1);
   CreateMatchingReceiveConfigs();
-  receive_config_.renderer = &renderer;
+  receive_configs_[0].renderer = &renderer;
 
   CreateStreams();
-  StartSending();
+  Start();
 
   scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
       video_streams_[0].width, video_streams_[0].height));
@@ -224,7 +200,7 @@
   EXPECT_EQ(kEventSignaled, renderer.Wait())
       << "Timed out while waiting for the frame to render.";
 
-  StopSending();
+  Stop();
 
   sender_transport.StopSending();
   receiver_transport.StopSending();
@@ -328,10 +304,10 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
-      receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -422,18 +398,18 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
       // int rtp_history_ms = 1000;
-      // receive_config->rtp.nack.rtp_history_ms = rtp_history_ms;
+      // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
       // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
       send_config->rtp.fec.red_payload_type = kRedPayloadType;
       send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
 
-      receive_config->rtp.fec.red_payload_type = kRedPayloadType;
-      receive_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
-      receive_config->renderer = this;
+      (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
+      (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+      (*receive_configs)[0].renderer = this;
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -500,16 +476,16 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
-      receive_config->pre_render_callback = this;
-      receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      (*receive_configs)[0].pre_render_callback = this;
+      (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
       if (retransmission_ssrc_ == kSendRtxSsrc) {
         send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
         send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
-        receive_config->rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc;
-        receive_config->rtp.rtx[kSendRtxPayloadType].payload_type =
+        (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].ssrc = kSendRtxSsrc;
+        (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].payload_type =
             kSendRtxPayloadType;
       }
     }
@@ -611,11 +587,11 @@
   send_config_.pre_encode_callback = &pre_encode_callback;
 
   CreateMatchingReceiveConfigs();
-  receive_config_.pre_render_callback = &pre_render_callback;
-  receive_config_.renderer = &renderer;
+  receive_configs_[0].pre_render_callback = &pre_render_callback;
+  receive_configs_[0].renderer = &renderer;
 
   CreateStreams();
-  StartSending();
+  Start();
 
   // Create frames that are smaller than the send width/height, this is done to
   // check that the callbacks are done after processing video.
@@ -630,7 +606,7 @@
   EXPECT_EQ(kEventSignaled, renderer.Wait())
       << "Timed out while waiting for the frame to render.";
 
-  StopSending();
+  Stop();
 
   sender_transport.StopSending();
   receiver_transport.StopSending();
@@ -701,11 +677,11 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
-      receive_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
-      receive_config->renderer = this;
+      (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
+      (*receive_configs)[0].renderer = this;
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -773,16 +749,16 @@
   CreateMatchingReceiveConfigs();
 
   CreateStreams();
-  CreateFrameGenerator();
-  StartSending();
+  CreateFrameGeneratorCapturer();
+  Start();
 
-  receiver_call_->DestroyVideoReceiveStream(receive_stream_);
-  receive_stream_ = NULL;
+  receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]);
+  receive_streams_.clear();
 
   // Wait() waits for a received packet.
   EXPECT_EQ(kEventSignaled, input_observer.Wait());
 
-  StopSending();
+  Stop();
 
   DestroyStreams();
 
@@ -848,11 +824,11 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
-      receive_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
-      receive_config->rtp.rtcp_mode = rtcp_mode_;
+      (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -1040,10 +1016,10 @@
   CreateSendConfig(1);
   CreateMatchingReceiveConfigs();
   send_config_.post_encode_callback = &post_encode_observer;
-  receive_config_.pre_decode_callback = &pre_decode_observer;
+  receive_configs_[0].pre_decode_callback = &pre_decode_observer;
 
   CreateStreams();
-  StartSending();
+  Start();
 
   scoped_ptr<test::FrameGenerator> frame_generator(test::FrameGenerator::Create(
       video_streams_[0].width, video_streams_[0].height));
@@ -1057,7 +1033,7 @@
 
   post_encode_observer.ExpectEqualFrames(pre_decode_observer);
 
-  StopSending();
+  Stop();
 
   sender_transport.StopSending();
   receiver_transport.StopSending();
@@ -1170,10 +1146,11 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
-      receive_config->rtp.rtcp_mode = newapi::kRtcpReducedSize;
-      receive_config->rtp.rtcp_xr.receiver_reference_time_report = enable_rrtr_;
+      (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize;
+      (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
+          enable_rrtr_;
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -1191,6 +1168,104 @@
   RunBaseTest(&test);
 }
 
+void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
+                                     bool send_single_ssrc_first) {
+  class SendsSetSsrcs : public test::EndToEndTest {
+   public:
+    SendsSetSsrcs(const uint32_t* ssrcs,
+                  size_t num_ssrcs,
+                  bool send_single_ssrc_first)
+        : EndToEndTest(kDefaultTimeoutMs),
+          num_ssrcs_(num_ssrcs),
+          send_single_ssrc_first_(send_single_ssrc_first),
+          ssrcs_to_observe_(num_ssrcs),
+          expect_single_ssrc_(send_single_ssrc_first) {
+      for (size_t i = 0; i < num_ssrcs; ++i)
+        valid_ssrcs_[ssrcs[i]] = true;
+    }
+
+   private:
+    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
+      RTPHeader header;
+      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
+
+      EXPECT_TRUE(valid_ssrcs_[header.ssrc])
+          << "Received unknown SSRC: " << header.ssrc;
+
+      if (!valid_ssrcs_[header.ssrc])
+        observation_complete_->Set();
+
+      if (!is_observed_[header.ssrc]) {
+        is_observed_[header.ssrc] = true;
+        --ssrcs_to_observe_;
+        if (expect_single_ssrc_) {
+          expect_single_ssrc_ = false;
+          observation_complete_->Set();
+        }
+      }
+
+      if (ssrcs_to_observe_ == 0)
+        observation_complete_->Set();
+
+      return SEND_PACKET;
+    }
+
+    virtual size_t GetNumStreams() const OVERRIDE { return num_ssrcs_; }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
+        std::vector<VideoStream>* video_streams) OVERRIDE {
+      if (num_ssrcs_ > 1) {
+        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
+        for (size_t i = 0; i < video_streams->size(); ++i) {
+          (*video_streams)[i].min_bitrate_bps = 10000;
+          (*video_streams)[i].target_bitrate_bps = 15000;
+          (*video_streams)[i].max_bitrate_bps = 20000;
+        }
+      }
+
+      all_streams_ = *video_streams;
+      if (send_single_ssrc_first_)
+        video_streams->resize(1);
+    }
+
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
+      send_stream_ = send_stream;
+    }
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for "
+          << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
+
+      if (send_single_ssrc_first_) {
+        // Set full simulcast and continue with the rest of the SSRCs.
+        send_stream_->ReconfigureVideoEncoder(all_streams_, NULL);
+        EXPECT_EQ(kEventSignaled, Wait())
+            << "Timed out while waiting on additional SSRCs.";
+      }
+    }
+
+   private:
+    std::map<uint32_t, bool> valid_ssrcs_;
+    std::map<uint32_t, bool> is_observed_;
+
+    const size_t num_ssrcs_;
+    const bool send_single_ssrc_first_;
+
+    size_t ssrcs_to_observe_;
+    bool expect_single_ssrc_;
+
+    VideoSendStream* send_stream_;
+    std::vector<VideoStream> all_streams_;
+  } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
+
+  RunBaseTest(&test);
+}
+
 TEST_F(EndToEndTest, GetStats) {
   class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
    public:
@@ -1332,12 +1407,12 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->pre_encode_callback = this;  // Used to inject delay.
       send_config->rtp.c_name = "SomeCName";
 
-      expected_receive_ssrc_ = receive_config->rtp.local_ssrc;
+      expected_receive_ssrc_ = (*receive_configs)[0].rtp.local_ssrc;
       const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
       for (size_t i = 0; i < ssrcs.size(); ++i)
         expected_send_ssrcs_.insert(ssrcs[i]);
@@ -1345,10 +1420,11 @@
       expected_cname_ = send_config->rtp.c_name;
     }
 
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) OVERRIDE {
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
       send_stream_ = send_stream;
-      receive_stream_ = receive_stream;
+      receive_stream_ = receive_streams[0];
     }
 
     virtual void PerformTest() OVERRIDE {
@@ -1427,9 +1503,10 @@
           sent_rtp_(0) {}
 
    private:
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) OVERRIDE {
-      receive_stream_ = receive_stream;
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
+      receive_stream_ = receive_streams[0];
     }
 
     virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
@@ -1456,4 +1533,14 @@
   RunBaseTest(&test);
 }
 
+TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
+
+TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
+  TestSendsSetSsrcs(kNumSsrcs, false);
+}
+
+TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
+  TestSendsSetSsrcs(kNumSsrcs, true);
+}
+
 }  // namespace webrtc
diff --git a/webrtc/video/full_stack.cc b/webrtc/video/full_stack.cc
index 1c03042..e2a8e86 100644
--- a/webrtc/video/full_stack.cc
+++ b/webrtc/video/full_stack.cc
@@ -396,7 +396,7 @@
   stream->max_framerate = params.clip.fps;
 
   CreateMatchingReceiveConfigs();
-  receive_config_.renderer = &analyzer;
+  receive_configs_[0].renderer = &analyzer;
 
   CreateStreams();
   analyzer.input_ = send_stream_->Input();
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index f9bbd57..4d32ab4 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -173,6 +173,8 @@
     rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
   }
 
+  ConfigureSsrcs();
+
   char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength];
   assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength);
   strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1);
@@ -373,38 +375,7 @@
   assert(streams[0].max_framerate > 0);
   video_codec.maxFramerate = streams[0].max_framerate;
 
-  if (codec_->SetSendCodec(channel_, video_codec) != 0)
-    return false;
-
-  for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
-    rtp_rtcp_->SetLocalSSRC(channel_,
-                            config_.rtp.ssrcs[i],
-                            kViEStreamTypeNormal,
-                            static_cast<unsigned char>(i));
-  }
-
-  if (config_.rtp.rtx.ssrcs.empty()) {
-    assert(!config_.rtp.rtx.pad_with_redundant_payloads);
-    return true;
-  }
-
-  // Set up RTX.
-  assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size());
-  for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
-    rtp_rtcp_->SetLocalSSRC(channel_,
-                            config_.rtp.rtx.ssrcs[i],
-                            kViEStreamTypeRtx,
-                            static_cast<unsigned char>(i));
-  }
-
-  if (config_.rtp.rtx.pad_with_redundant_payloads) {
-    rtp_rtcp_->SetPadWithRedundantPayloads(channel_, true);
-  }
-
-  assert(config_.rtp.rtx.payload_type >= 0);
-  rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
-
-  return true;
+  return codec_->SetSendCodec(channel_, video_codec) == 0;
 }
 
 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
@@ -427,5 +398,34 @@
   return rtcp_cname;
 }
 
+void VideoSendStream::ConfigureSsrcs() {
+  for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
+    uint32_t ssrc = config_.rtp.ssrcs[i];
+    rtp_rtcp_->SetLocalSSRC(
+        channel_, ssrc, kViEStreamTypeNormal, static_cast<unsigned char>(i));
+  }
+
+  if (config_.rtp.rtx.ssrcs.empty()) {
+    assert(!config_.rtp.rtx.pad_with_redundant_payloads);
+    return;
+  }
+
+  // Set up RTX.
+  assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size());
+  for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
+    rtp_rtcp_->SetLocalSSRC(channel_,
+                            config_.rtp.rtx.ssrcs[i],
+                            kViEStreamTypeRtx,
+                            static_cast<unsigned char>(i));
+  }
+
+  if (config_.rtp.rtx.pad_with_redundant_payloads) {
+    rtp_rtcp_->SetPadWithRedundantPayloads(channel_, true);
+  }
+
+  assert(config_.rtp.rtx.payload_type >= 0);
+  rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
+}
+
 }  // namespace internal
 }  // namespace webrtc
diff --git a/webrtc/video/video_send_stream.h b/webrtc/video/video_send_stream.h
index ed77665..df65b74 100644
--- a/webrtc/video/video_send_stream.h
+++ b/webrtc/video/video_send_stream.h
@@ -71,6 +71,7 @@
   virtual std::string GetCName() OVERRIDE;
 
  private:
+  void ConfigureSsrcs();
   TransportAdapter transport_adapter_;
   EncodedFrameCallbackAdapter encoded_frame_proxy_;
   const VideoSendStream::Config config_;
diff --git a/webrtc/video/video_send_stream_tests.cc b/webrtc/video/video_send_stream_tests.cc
index 2d9bf5b..b1197ef 100644
--- a/webrtc/video/video_send_stream_tests.cc
+++ b/webrtc/video/video_send_stream_tests.cc
@@ -60,113 +60,8 @@
   void TestNackRetransmission(uint32_t retransmit_ssrc,
                               uint8_t retransmit_payload_type);
   void TestPacketFragmentationSize(VideoFormat format, bool with_fec);
-  void SendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
-
 };
 
-void VideoSendStreamTest::SendsSetSsrcs(size_t num_ssrcs,
-                                        bool send_single_ssrc_first) {
-  class SendsSetSsrcs : public test::SendTest {
-   public:
-    SendsSetSsrcs(const uint32_t* ssrcs,
-                  size_t num_ssrcs,
-                  bool send_single_ssrc_first)
-        : SendTest(kDefaultTimeoutMs),
-          num_ssrcs_(num_ssrcs),
-          send_single_ssrc_first_(send_single_ssrc_first),
-          ssrcs_to_observe_(num_ssrcs),
-          expect_single_ssrc_(send_single_ssrc_first) {
-      for (size_t i = 0; i < num_ssrcs; ++i)
-        valid_ssrcs_[ssrcs[i]] = true;
-    }
-
-   private:
-    virtual Action OnSendRtp(const uint8_t* packet, size_t length) OVERRIDE {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, static_cast<int>(length), &header));
-
-      // TODO(pbos): Reenable this part of the test when #1695 is resolved and
-      //             all SSRCs are allocated on startup. This test was
-      //             observed
-      //             to fail on TSan as the codec gets set before the SSRCs
-      //             are
-      //             set up and some frames are sent on a random-generated
-      //             SSRC
-      //             before the correct SSRC gets set.
-      // EXPECT_TRUE(valid_ssrcs_[header.ssrc])
-      //    << "Received unknown SSRC: " << header.ssrc;
-      //
-      // if (!valid_ssrcs_[header.ssrc])
-      //  observation_complete_->Set();
-
-      if (!is_observed_[header.ssrc]) {
-        is_observed_[header.ssrc] = true;
-        --ssrcs_to_observe_;
-        if (expect_single_ssrc_) {
-          expect_single_ssrc_ = false;
-          observation_complete_->Set();
-        }
-      }
-
-      if (ssrcs_to_observe_ == 0)
-        observation_complete_->Set();
-
-      return SEND_PACKET;
-    }
-
-    virtual void ModifyConfigs(
-        VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
-        std::vector<VideoStream>* video_streams) OVERRIDE {
-      if (num_ssrcs_ > 1) {
-        // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
-        for (size_t i = 0; i < video_streams->size(); ++i) {
-          (*video_streams)[i].min_bitrate_bps = 10000;
-          (*video_streams)[i].target_bitrate_bps = 10000;
-          (*video_streams)[i].max_bitrate_bps = 10000;
-        }
-      }
-
-      all_streams_ = *video_streams;
-      if (send_single_ssrc_first_)
-        video_streams->resize(1);
-    }
-
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) OVERRIDE {
-      send_stream_ = send_stream;
-    }
-
-    virtual void PerformTest() OVERRIDE {
-      EXPECT_EQ(kEventSignaled, Wait())
-          << "Timed out while waiting for "
-          << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
-
-      if (send_single_ssrc_first_) {
-        // Set full simulcast and continue with the rest of the SSRCs.
-        send_stream_->ReconfigureVideoEncoder(all_streams_, NULL);
-        EXPECT_EQ(kEventSignaled, Wait())
-            << "Timed out while waiting on additional SSRCs.";
-      }
-    }
-
-   private:
-    std::map<uint32_t, bool> valid_ssrcs_;
-    std::map<uint32_t, bool> is_observed_;
-
-    const size_t num_ssrcs_;
-    const bool send_single_ssrc_first_;
-
-    size_t ssrcs_to_observe_;
-    bool expect_single_ssrc_;
-
-    VideoSendStream* send_stream_;
-    std::vector<VideoStream> all_streams_;
-  } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
-
-  RunBaseTest(&test);
-}
-
 TEST_F(VideoSendStreamTest, CanStartStartedStream) {
   test::NullTransport transport;
   Call::Config call_config(&transport);
@@ -191,16 +86,6 @@
   DestroyStreams();
 }
 
-TEST_F(VideoSendStreamTest, SendsSetSsrc) { SendsSetSsrcs(1, false); }
-
-TEST_F(VideoSendStreamTest, DISABLED_SendsSetSimulcastSsrcs) {
-  SendsSetSsrcs(kNumSsrcs, false);
-}
-
-TEST_F(VideoSendStreamTest, DISABLED_CanSwitchToUseAllSsrcs) {
-  SendsSetSsrcs(kNumSsrcs, true);
-}
-
 TEST_F(VideoSendStreamTest, SupportsCName) {
   static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
   class CNameObserver : public test::SendTest {
@@ -227,7 +112,7 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.c_name = kCName;
     }
@@ -265,7 +150,7 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.extensions.push_back(
           RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
@@ -306,7 +191,7 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->encoder_settings.encoder = &encoder_;
       send_config->rtp.extensions.push_back(
@@ -475,7 +360,7 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.fec.red_payload_type = kRedPayloadType;
       send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
@@ -555,9 +440,9 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
-      send_config->rtp.nack.rtp_history_ms = 1000;
+      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
       send_config->rtp.rtx.payload_type = retransmit_payload_type_;
       if (retransmit_ssrc_ != kSendSsrcs[0])
         send_config->rtp.rtx.ssrcs.push_back(retransmit_ssrc_);
@@ -730,7 +615,7 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       if (use_fec_) {
         send_config->rtp.fec.red_payload_type = kRedPayloadType;
@@ -897,16 +782,17 @@
       transport_.SetReceiver(send_transport_receiver);
     }
 
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) OVERRIDE {
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
       stream_ = send_stream;
     }
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
-      send_config->rtp.nack.rtp_history_ms = 1000;
+      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
       send_config->pre_encode_callback = this;
       send_config->suspend_below_min_bitrate = true;
       int min_bitrate_bps = (*video_streams)[0].min_bitrate_bps;
@@ -1095,14 +981,15 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.c_name = kCName;
       SetConfig(*send_config);
     }
 
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) OVERRIDE {
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
       stream_ = send_stream;
     }
 
@@ -1145,8 +1032,9 @@
       rtp_rtcp_->SetRTCPStatus(kRtcpNonCompound);
     }
 
-    virtual void OnStreamsCreated(VideoSendStream* send_stream,
-                                  VideoReceiveStream* receive_stream) OVERRIDE {
+    virtual void OnStreamsCreated(
+        VideoSendStream* send_stream,
+        const std::vector<VideoReceiveStream*>& receive_streams) OVERRIDE {
       stream_ = send_stream;
     }
 
@@ -1191,7 +1079,7 @@
 
     virtual void ModifyConfigs(
         VideoSendStream::Config* send_config,
-        VideoReceiveStream::Config* receive_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
         std::vector<VideoStream>* video_streams) OVERRIDE {
       send_config->rtp.min_transmit_bitrate_bps = kMinTransmitBitrateBps;
     }
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 62bb095..80d3065 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -244,31 +244,25 @@
       num_modules_to_add = 0;
     }
 
-    while (removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0) {
-      RtpRtcp* rtp_rtcp = removed_rtp_rtcp_.front();
+    // Add back removed rtp modules. Order is important (allocate from front of
+    // removed modules) to preserve RTP settings such as SSRCs for simulcast
+    // streams.
+    std::list<RtpRtcp*> new_rtp_modules;
+    for (; removed_rtp_rtcp_.size() > 0 && num_modules_to_add > 0;
+         --num_modules_to_add) {
+      new_rtp_modules.push_back(removed_rtp_rtcp_.front());
       removed_rtp_rtcp_.pop_front();
-      simulcast_rtp_rtcp_.push_back(rtp_rtcp);
-      rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
-      rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
-      module_process_thread_.RegisterModule(rtp_rtcp);
-      --num_modules_to_add;
     }
 
-    for (int i = 0; i < num_modules_to_add; ++i) {
-      RtpRtcp::Configuration configuration;
-      configuration.id = ViEModuleId(engine_id_, channel_id_);
-      configuration.audio = false;  // Video.
-      configuration.default_module = default_rtp_rtcp_;
-      configuration.outgoing_transport = &vie_sender_;
-      configuration.intra_frame_callback = intra_frame_observer_;
-      configuration.bandwidth_callback = bandwidth_observer_.get();
-      configuration.rtt_stats = rtt_stats_;
-      configuration.paced_sender = paced_sender_;
+    for (int i = 0; i < num_modules_to_add; ++i)
+      new_rtp_modules.push_back(CreateRtpRtcpModule());
 
-      RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
+    // Initialize newly added modules.
+    for (std::list<RtpRtcp*>::iterator it = new_rtp_modules.begin();
+         it != new_rtp_modules.end();
+         ++it) {
+      RtpRtcp* rtp_rtcp = *it;
 
-      // Silently ignore error.
-      module_process_thread_.RegisterModule(rtp_rtcp);
       rtp_rtcp->SetRTCPStatus(rtp_rtcp_->RTCP());
 
       if (rtp_rtcp_->StorePackets()) {
@@ -278,13 +272,18 @@
       }
 
       if (fec_enabled) {
-        rtp_rtcp->SetGenericFECStatus(fec_enabled, payload_type_red,
-            payload_type_fec);
+        rtp_rtcp->SetGenericFECStatus(
+            fec_enabled, payload_type_red, payload_type_fec);
       }
       rtp_rtcp->SetSendingStatus(rtp_rtcp_->Sending());
       rtp_rtcp->SetSendingMediaStatus(rtp_rtcp_->SendingMedia());
+
       simulcast_rtp_rtcp_.push_back(rtp_rtcp);
+
+      // Silently ignore error.
+      module_process_thread_.RegisterModule(rtp_rtcp);
     }
+
     // Remove last in list if we have too many.
     for (int j = simulcast_rtp_rtcp_.size();
          j > (video_codec.numberOfSimulcastStreams - 1);
@@ -792,29 +791,15 @@
 int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
                             const StreamType usage,
                             const uint8_t simulcast_idx) {
-  if (simulcast_idx == 0) {
-    if (usage == kViEStreamTypeRtx) {
-      rtp_rtcp_->SetRtxSsrc(SSRC);
-    } else {
-      rtp_rtcp_->SetSSRC(SSRC);
-    }
-    return 0;
-  }
   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-  if (simulcast_idx > simulcast_rtp_rtcp_.size()) {
-      return -1;
-  }
-  std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
-  for (int i = 1; i < simulcast_idx; ++i, ++it) {
-    if (it ==  simulcast_rtp_rtcp_.end()) {
-      return -1;
-    }
-  }
-  RtpRtcp* rtp_rtcp_module = *it;
+  ReserveRtpRtcpModules(simulcast_idx + 1);
+  RtpRtcp* rtp_rtcp = GetRtpRtcpModule(simulcast_idx);
+  if (rtp_rtcp == NULL)
+    return -1;
   if (usage == kViEStreamTypeRtx) {
-    rtp_rtcp_module->SetRtxSsrc(SSRC);
+    rtp_rtcp->SetRtxSsrc(SSRC);
   } else {
-    rtp_rtcp_module->SetSSRC(SSRC);
+    rtp_rtcp->SetSSRC(SSRC);
   }
   return 0;
 }
@@ -826,21 +811,11 @@
 }
 
 int32_t ViEChannel::GetLocalSSRC(uint8_t idx, unsigned int* ssrc) {
-  if (idx == 0) {
-    *ssrc = rtp_rtcp_->SSRC();
-    return 0;
-  }
   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
-  if (idx > simulcast_rtp_rtcp_.size()) {
+  RtpRtcp* rtp_rtcp = GetRtpRtcpModule(idx);
+  if (rtp_rtcp == NULL)
     return -1;
-  }
-  std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
-  for (int i = 1; i < idx; ++i, ++it) {
-    if (it ==  simulcast_rtp_rtcp_.end()) {
-      return -1;
-    }
-  }
-  *ssrc = (*it)->SSRC();
+  *ssrc = rtp_rtcp->SSRC();
   return 0;
 }
 
@@ -1530,6 +1505,61 @@
   vcm_->SetReceiveChannelParameters(rtt);
 }
 
+void ViEChannel::ReserveRtpRtcpModules(size_t num_modules) {
+  for (size_t total_modules =
+           1 + simulcast_rtp_rtcp_.size() + removed_rtp_rtcp_.size();
+       total_modules < num_modules;
+       ++total_modules) {
+    RtpRtcp* rtp_rtcp = CreateRtpRtcpModule();
+    rtp_rtcp->SetSendingStatus(false);
+    rtp_rtcp->SetSendingMediaStatus(false);
+    rtp_rtcp->RegisterSendFrameCountObserver(NULL);
+    rtp_rtcp->RegisterSendChannelRtcpStatisticsCallback(NULL);
+    rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(NULL);
+    rtp_rtcp->RegisterVideoBitrateObserver(NULL);
+    removed_rtp_rtcp_.push_back(rtp_rtcp);
+  }
+}
+
+RtpRtcp* ViEChannel::GetRtpRtcpModule(size_t index) const {
+  if (index == 0)
+    return rtp_rtcp_.get();
+  if (index <= simulcast_rtp_rtcp_.size()) {
+    std::list<RtpRtcp*>::const_iterator it = simulcast_rtp_rtcp_.begin();
+    for (size_t i = 1; i < index; ++i) {
+      ++it;
+    }
+    return *it;
+  }
+
+  // If the requested module exists it must be in the removed list. Index
+  // translation to this list must remove the default module as well as all
+  // active simulcast modules.
+  size_t removed_idx = index - simulcast_rtp_rtcp_.size() - 1;
+  if (removed_idx >= removed_rtp_rtcp_.size())
+    return NULL;
+
+  std::list<RtpRtcp*>::const_iterator it = removed_rtp_rtcp_.begin();
+  while (removed_idx-- > 0)
+    ++it;
+
+  return *it;
+}
+
+RtpRtcp* ViEChannel::CreateRtpRtcpModule() {
+  RtpRtcp::Configuration configuration;
+  configuration.id = ViEModuleId(engine_id_, channel_id_);
+  configuration.audio = false;  // Video.
+  configuration.default_module = default_rtp_rtcp_;
+  configuration.outgoing_transport = &vie_sender_;
+  configuration.intra_frame_callback = intra_frame_observer_;
+  configuration.bandwidth_callback = bandwidth_observer_.get();
+  configuration.rtt_stats = rtt_stats_;
+  configuration.paced_sender = paced_sender_;
+
+  return RtpRtcp::CreateRtpRtcp(configuration);
+}
+
 int32_t ViEChannel::StartDecodeThread() {
   // Start the decode thread
   if (decode_thread_) {
diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h
index 23b7e5e..c76d129 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -362,6 +362,11 @@
   void OnRttUpdate(uint32_t rtt);
 
  private:
+  void ReserveRtpRtcpModules(size_t total_modules)
+      EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_);
+  RtpRtcp* GetRtpRtcpModule(size_t simulcast_idx) const
+      EXCLUSIVE_LOCKS_REQUIRED(rtp_rtcp_cs_);
+  RtpRtcp* CreateRtpRtcpModule();
   // Assumed to be protected.
   int32_t StartDecodeThread();
   int32_t StopDecodeThread();