Add round-robin selection of send stream to pad on.

BUG=1812
R=pbos@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6472 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index fe33e1b..70fe717 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -17,11 +17,6 @@
 #include "webrtc/system_wrappers/interface/logging.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 
-#ifdef MATLAB
-#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h"
-extern MatlabEngine eng;  // Global variable defined elsewhere.
-#endif
-
 #ifdef _WIN32
 // Disable warning C4355: 'this' : used in base member initializer list.
 #pragma warning(disable : 4355)
@@ -66,7 +61,9 @@
                   configuration.outgoing_transport,
                   configuration.audio_messages,
                   configuration.paced_sender),
-      rtcp_sender_(configuration.id, configuration.audio, configuration.clock,
+      rtcp_sender_(configuration.id,
+                   configuration.audio,
+                   configuration.clock,
                    configuration.receive_statistics),
       rtcp_receiver_(configuration.id, configuration.clock, this),
       clock_(configuration.clock),
@@ -83,15 +80,13 @@
           CriticalSectionWrapper::CreateCriticalSection()),
       default_module_(
           static_cast<ModuleRtpRtcpImpl*>(configuration.default_module)),
+      padding_index_(-1),  // Start padding at the first child module.
       nack_method_(kNackOff),
       nack_last_time_sent_full_(0),
       nack_last_seq_number_sent_(0),
       simulcast_(false),
       key_frame_req_method_(kKeyFrameReqFirRtp),
       remote_bitrate_(configuration.remote_bitrate_estimator),
-#ifdef MATLAB
-      , plot1_(NULL),
-#endif
       rtt_stats_(configuration.rtt_stats),
       critical_section_rtt_(CriticalSectionWrapper::CreateCriticalSection()),
       rtt_ms_(0) {
@@ -121,12 +116,6 @@
   if (default_module_) {
     default_module_->DeRegisterChildModule(this);
   }
-#ifdef MATLAB
-  if (plot1_) {
-    eng.DeletePlot(plot1_);
-    plot1_ = NULL;
-  }
-#endif
 }
 
 void ModuleRtpRtcpImpl::RegisterChildModule(RtpRtcp* module) {
@@ -148,7 +137,7 @@
   CriticalSectionScoped double_lock(
       critical_section_module_ptrs_feedback_.get());
 
-  std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+  std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
   while (it != child_modules_.end()) {
     RtpRtcp* module = *it;
     if (module == remove_module) {
@@ -252,8 +241,9 @@
   rtp_sender_.SetRTXStatus(mode);
 }
 
-void ModuleRtpRtcpImpl::RTXSendStatus(int* mode, uint32_t* ssrc,
-                                         int* payload_type) const {
+void ModuleRtpRtcpImpl::RTXSendStatus(int* mode,
+                                      uint32_t* ssrc,
+                                      int* payload_type) const {
   rtp_sender_.RTXStatus(mode, ssrc, payload_type);
 }
 
@@ -372,7 +362,7 @@
     // For default we need to update all child modules too.
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
 
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       RtpRtcp* module = *it;
       if (module) {
@@ -443,7 +433,7 @@
   }
 
   CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-  std::list<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
+  std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
   while (it != child_modules_.end()) {
     RTPSender& rtp_sender = (*it)->rtp_sender_;
     if (rtp_sender.SendingMedia()) {
@@ -488,7 +478,7 @@
       return -1;
     }
     int idx = 0;
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     for (; idx < rtp_video_hdr->simulcastIdx; ++it) {
       if (it == child_modules_.end()) {
         return -1;
@@ -515,7 +505,7 @@
                                    fragmentation,
                                    rtp_video_hdr);
   } else {
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     // Send to all "child" modules
     while (it != child_modules_.end()) {
       if ((*it)->SendingMedia()) {
@@ -546,7 +536,7 @@
     }
   } else {
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       if ((*it)->SendingMedia() && ssrc == (*it)->rtp_sender_.SSRC()) {
         return (*it)->rtp_sender_.TimeToSendPacket(sequence_number,
@@ -568,13 +558,15 @@
     }
   } else {
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
-    while (it != child_modules_.end()) {
+    // Decide what media stream to pad on based on a round-robin scheme.
+    for (size_t i = 0; i < child_modules_.size(); ++i) {
+      padding_index_ = (padding_index_ + 1) % child_modules_.size();
       // Send padding on one of the modules sending media.
-      if ((*it)->SendingMedia()) {
-        return (*it)->rtp_sender_.TimeToSendPadding(bytes);
+      if (child_modules_[padding_index_]->SendingMedia() &&
+          child_modules_[padding_index_]->rtp_sender_.GetTargetBitrate() > 0) {
+        return child_modules_[padding_index_]->rtp_sender_.TimeToSendPadding(
+            bytes);
       }
-      ++it;
     }
   }
   return 0;
@@ -603,8 +595,7 @@
   if (IsDefaultModule()) {
     // For default we need to update all child modules too.
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-    std::list<ModuleRtpRtcpImpl*>::const_iterator it =
-      child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       RtpRtcp* module = *it;
       if (module) {
@@ -1001,28 +992,28 @@
   if (IsDefaultModule()) {
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
     if (simulcast_) {
-      std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+      std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
       for (size_t i = 0;
            it != child_modules_.end() && i < stream_bitrates.size(); ++it) {
         if ((*it)->SendingMedia()) {
           RTPSender& rtp_sender = (*it)->rtp_sender_;
-          rtp_sender.SetTargetSendBitrate(stream_bitrates[i]);
+          rtp_sender.SetTargetBitrate(stream_bitrates[i]);
           ++i;
         }
       }
     } else {
       if (stream_bitrates.size() > 1)
         return;
-      std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+      std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
       for (; it != child_modules_.end(); ++it) {
         RTPSender& rtp_sender = (*it)->rtp_sender_;
-        rtp_sender.SetTargetSendBitrate(stream_bitrates[0]);
+        rtp_sender.SetTargetBitrate(stream_bitrates[0]);
       }
     }
   } else {
     if (stream_bitrates.size() > 1)
       return;
-    rtp_sender_.SetTargetSendBitrate(stream_bitrates[0]);
+    rtp_sender_.SetTargetBitrate(stream_bitrates[0]);
   }
 }
 
@@ -1054,7 +1045,7 @@
 int32_t ModuleRtpRtcpImpl::SetCameraDelay(const int32_t delay_ms) {
   if (IsDefaultModule()) {
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       RtpRtcp* module = *it;
       if (module) {
@@ -1084,7 +1075,7 @@
   if (IsDefaultModule()) {
     // For default we need to check all child modules too.
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       RtpRtcp* module = *it;
       if (module)  {
@@ -1118,7 +1109,7 @@
     // For default we need to update all child modules too.
     CriticalSectionScoped lock(critical_section_module_ptrs_.get());
 
-    std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       RtpRtcp* module = *it;
       if (module) {
@@ -1172,8 +1163,7 @@
     if (nack_rate != NULL)
       *nack_rate = 0;
 
-    std::list<ModuleRtpRtcpImpl*>::const_iterator it =
-      child_modules_.begin();
+    std::vector<ModuleRtpRtcpImpl*>::const_iterator it = child_modules_.begin();
     while (it != child_modules_.end()) {
       RtpRtcp* module = *it;
       if (module) {
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index ef00a46..55826b6 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -21,10 +21,6 @@
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
 #include "webrtc/test/testsupport/gtest_prod_util.h"
 
-#ifdef MATLAB
-class MatlabPlot;
-#endif
-
 namespace webrtc {
 
 class ModuleRtpRtcpImpl : public RtpRtcp {
@@ -426,7 +422,8 @@
   scoped_ptr<CriticalSectionWrapper> critical_section_module_ptrs_;
   scoped_ptr<CriticalSectionWrapper> critical_section_module_ptrs_feedback_;
   ModuleRtpRtcpImpl*            default_module_;
-  std::list<ModuleRtpRtcpImpl*> child_modules_;
+  std::vector<ModuleRtpRtcpImpl*> child_modules_;
+  size_t padding_index_;
 
   // Send side
   NACKMethod            nack_method_;
@@ -439,10 +436,6 @@
 
   RemoteBitrateEstimator* remote_bitrate_;
 
-#ifdef MATLAB
-  MatlabPlot*           plot1_;
-#endif
-
   RtcpRttStats* rtt_stats_;
 
   // The processed RTT from RtcpRttStats.
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 4b6fa32..eb76cfe 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -12,13 +12,22 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #include "webrtc/common_types.h"
+#include "webrtc/modules/pacing/include/mock/mock_paced_sender.h"
+#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
+#include "webrtc/system_wrappers/interface/scoped_vector.h"
+
+using ::testing::_;
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::SaveArg;
 
 namespace webrtc {
 namespace {
 const uint32_t kSenderSsrc = 0x12345;
 const uint32_t kReceiverSsrc = 0x23456;
+const uint32_t kSenderRtxSsrc = 0x32345;
 const uint32_t kOneWayNetworkDelayMs = 100;
 
 class RtcpRttStatsTestImpl : public RtcpRttStats {
@@ -215,4 +224,245 @@
   EXPECT_EQ(2U, sender_.RtcpReceived().fir_packets);
   EXPECT_EQ(1U, sender_.RtcpReceived().pli_packets);
 }
+
+class RtpSendingTestTransport : public Transport {
+ public:
+  void ResetCounters() { bytes_received_.clear(); }
+
+  virtual int SendPacket(int channel, const void* data, int length) {
+    RTPHeader header;
+    scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
+    EXPECT_TRUE(
+        parser->Parse(static_cast<const uint8_t*>(data), length, &header));
+    bytes_received_[header.ssrc] += length;
+    ++packets_received_[header.ssrc];
+    return length;
+  }
+
+  virtual int SendRTCPPacket(int channel, const void* data, int length) {
+    return length;
+  }
+
+  int GetPacketsReceived(uint32_t ssrc) const {
+    std::map<uint32_t, int>::const_iterator it = packets_received_.find(ssrc);
+    if (it == packets_received_.end())
+      return 0;
+    return it->second;
+  }
+
+  int GetBytesReceived(uint32_t ssrc) const {
+    std::map<uint32_t, int>::const_iterator it = bytes_received_.find(ssrc);
+    if (it == bytes_received_.end())
+      return 0;
+    return it->second;
+  }
+
+  int GetTotalBytesReceived() const {
+    int sum = 0;
+    for (std::map<uint32_t, int>::const_iterator it = bytes_received_.begin();
+         it != bytes_received_.end();
+         ++it) {
+      sum += it->second;
+    }
+    return sum;
+  }
+
+ private:
+  std::map<uint32_t, int> bytes_received_;
+  std::map<uint32_t, int> packets_received_;
+};
+
+class RtpSendingTest : public ::testing::Test {
+ protected:
+  // Map from SSRC to number of received packets and bytes.
+  typedef std::map<uint32_t, std::pair<int, int> > PaddingMap;
+
+  RtpSendingTest() {
+    // Send module.
+    RtpRtcp::Configuration config;
+    config.audio = false;
+    config.clock = Clock::GetRealTimeClock();
+    config.outgoing_transport = &transport_;
+    config.receive_statistics = receive_statistics_.get();
+    config.rtt_stats = &rtt_stats_;
+    config.paced_sender = &pacer_;
+    memset(&codec_, 0, sizeof(VideoCodec));
+    codec_.plType = 100;
+    strncpy(codec_.plName, "VP8", 3);
+    codec_.numberOfSimulcastStreams = 3;
+    codec_.simulcastStream[0].width = 320;
+    codec_.simulcastStream[0].height = 180;
+    codec_.simulcastStream[0].maxBitrate = 300;
+    codec_.simulcastStream[1].width = 640;
+    codec_.simulcastStream[1].height = 360;
+    codec_.simulcastStream[1].maxBitrate = 600;
+    codec_.simulcastStream[2].width = 1280;
+    codec_.simulcastStream[2].height = 720;
+    codec_.simulcastStream[2].maxBitrate = 1200;
+    // We need numberOfSimulcastStreams + 1 RTP modules since we need one
+    // default module.
+    for (int i = 0; i < codec_.numberOfSimulcastStreams + 1; ++i) {
+      RtpRtcp* sender = RtpRtcp::CreateRtpRtcp(config);
+      EXPECT_EQ(0, sender->RegisterSendPayload(codec_));
+      EXPECT_EQ(0, sender->SetSendingStatus(true));
+      EXPECT_EQ(0, sender->SetSendingMediaStatus(true));
+      sender->SetSSRC(kSenderSsrc + i);
+      sender->SetRemoteSSRC(kReceiverSsrc + i);
+      senders_.push_back(sender);
+      config.default_module = senders_[0];
+    }
+    std::vector<uint32_t> bitrates;
+    bitrates.push_back(codec_.simulcastStream[0].maxBitrate);
+    bitrates.push_back(codec_.simulcastStream[1].maxBitrate);
+    bitrates.push_back(codec_.simulcastStream[2].maxBitrate);
+    senders_[0]->SetTargetSendBitrate(bitrates);
+  }
+
+  ~RtpSendingTest() {
+    for (int i = senders_.size() - 1; i >= 0; --i) {
+      delete senders_[i];
+    }
+  }
+
+  void SendFrameOnSender(int sender_index,
+                         const uint8_t* payload,
+                         size_t length) {
+    RTPVideoHeader rtp_video_header = {
+        codec_.simulcastStream[sender_index].width,
+        codec_.simulcastStream[sender_index].height,
+        true,
+        0,
+        kRtpVideoVp8,
+        {}};
+    uint32_t seq_num = 0;
+    uint32_t ssrc = 0;
+    int64_t capture_time_ms = 0;
+    bool retransmission = false;
+    EXPECT_CALL(pacer_, SendPacket(_, _, _, _, _, _))
+        .WillRepeatedly(DoAll(SaveArg<1>(&ssrc),
+                              SaveArg<2>(&seq_num),
+                              SaveArg<3>(&capture_time_ms),
+                              SaveArg<5>(&retransmission),
+                              Return(true)));
+    EXPECT_EQ(0,
+              senders_[sender_index]->SendOutgoingData(kVideoFrameKey,
+                                                       codec_.plType,
+                                                       0,
+                                                       0,
+                                                       payload,
+                                                       length,
+                                                       NULL,
+                                                       &rtp_video_header));
+    EXPECT_TRUE(senders_[sender_index]->TimeToSendPacket(
+        ssrc, seq_num, capture_time_ms, retransmission));
+  }
+
+  void ExpectPadding(const PaddingMap& expected_padding) {
+    int expected_total_bytes = 0;
+    for (PaddingMap::const_iterator it = expected_padding.begin();
+         it != expected_padding.end();
+         ++it) {
+      int packets_received = transport_.GetBytesReceived(it->first);
+      if (it->second.first > 0) {
+        EXPECT_GE(packets_received, it->second.first)
+            << "On SSRC: " << it->first;
+      }
+      int bytes_received = transport_.GetBytesReceived(it->first);
+      expected_total_bytes += bytes_received;
+      if (it->second.second > 0) {
+        EXPECT_GE(bytes_received, it->second.second)
+            << "On SSRC: " << it->first;
+      } else {
+        EXPECT_EQ(0, bytes_received) << "On SSRC: " << it->first;
+      }
+    }
+    EXPECT_EQ(expected_total_bytes, transport_.GetTotalBytesReceived());
+  }
+
+  scoped_ptr<ReceiveStatistics> receive_statistics_;
+  RtcpRttStatsTestImpl rtt_stats_;
+  std::vector<RtpRtcp*> senders_;
+  RtpSendingTestTransport transport_;
+  NiceMock<MockPacedSender> pacer_;
+  VideoCodec codec_;
+};
+
+TEST_F(RtpSendingTest, RoundRobinPadding) {
+  // We have to send on an SSRC to be allowed to pad, since a marker bit must
+  // be sent prior to padding packets.
+  const uint8_t payload[200] = {0};
+  for (int i = 0; i < codec_.numberOfSimulcastStreams; ++i) {
+    SendFrameOnSender(i + 1, payload, sizeof(payload));
+  }
+  transport_.ResetCounters();
+  senders_[0]->TimeToSendPadding(500);
+  PaddingMap expected_padding;
+  expected_padding[kSenderSsrc + 1] = std::make_pair(2, 500);
+  expected_padding[kSenderSsrc + 2] = std::make_pair(0, 0);
+  expected_padding[kSenderSsrc + 3] = std::make_pair(0, 0);
+  ExpectPadding(expected_padding);
+  senders_[0]->TimeToSendPadding(1000);
+  expected_padding[kSenderSsrc + 2] = std::make_pair(4, 1000);
+  ExpectPadding(expected_padding);
+  senders_[0]->TimeToSendPadding(1500);
+  expected_padding[kSenderSsrc + 3] = std::make_pair(6, 1500);
+  ExpectPadding(expected_padding);
+}
+
+TEST_F(RtpSendingTest, RoundRobinPaddingRtx) {
+  // Enable RTX to allow padding to be sent prior to media.
+  for (int i = 1; i < codec_.numberOfSimulcastStreams + 1; ++i) {
+    senders_[i]->SetRtxSendPayloadType(96);
+    senders_[i]->SetRtxSsrc(kSenderRtxSsrc + i);
+    senders_[i]->SetRTXSendStatus(kRtxRetransmitted);
+  }
+  transport_.ResetCounters();
+  senders_[0]->TimeToSendPadding(500);
+  PaddingMap expected_padding;
+  expected_padding[kSenderSsrc + 1] = std::make_pair(0, 0);
+  expected_padding[kSenderSsrc + 2] = std::make_pair(0, 0);
+  expected_padding[kSenderSsrc + 3] = std::make_pair(0, 0);
+  expected_padding[kSenderRtxSsrc + 1] = std::make_pair(2, 500);
+  expected_padding[kSenderRtxSsrc + 2] = std::make_pair(0, 0);
+  expected_padding[kSenderRtxSsrc + 3] = std::make_pair(0, 0);
+  ExpectPadding(expected_padding);
+  senders_[0]->TimeToSendPadding(1000);
+  expected_padding[kSenderRtxSsrc + 2] = std::make_pair(4, 500);
+  ExpectPadding(expected_padding);
+  senders_[0]->TimeToSendPadding(1500);
+
+  expected_padding[kSenderRtxSsrc + 3] = std::make_pair(6, 500);
+  ExpectPadding(expected_padding);
+}
+
+TEST_F(RtpSendingTest, RoundRobinPaddingRtxRedundantPayloads) {
+  for (int i = 1; i < codec_.numberOfSimulcastStreams + 1; ++i) {
+    senders_[i]->SetRtxSendPayloadType(96);
+    senders_[i]->SetRtxSsrc(kSenderRtxSsrc + i);
+    senders_[i]->SetRTXSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
+    senders_[i]->SetStorePacketsStatus(true, 100);
+  }
+  // First send payloads so that we have something to retransmit.
+  const size_t kPayloadSize = 500;
+  const uint8_t payload[kPayloadSize] = {0};
+  for (int i = 0; i < codec_.numberOfSimulcastStreams; ++i) {
+    SendFrameOnSender(i + 1, payload, sizeof(payload));
+  }
+  transport_.ResetCounters();
+  senders_[0]->TimeToSendPadding(500);
+  PaddingMap expected_padding;
+  expected_padding[kSenderSsrc + 1] = std::make_pair<int, int>(0, 0);
+  expected_padding[kSenderSsrc + 2] = std::make_pair<int, int>(0, 0);
+  expected_padding[kSenderSsrc + 3] = std::make_pair<int, int>(0, 0);
+  expected_padding[kSenderRtxSsrc + 1] = std::make_pair<int, int>(1, 500);
+  expected_padding[kSenderRtxSsrc + 2] = std::make_pair<int, int>(0, 0);
+  expected_padding[kSenderRtxSsrc + 3] = std::make_pair<int, int>(0, 0);
+  ExpectPadding(expected_padding);
+  senders_[0]->TimeToSendPadding(1000);
+  expected_padding[kSenderRtxSsrc + 2] = std::make_pair<int, int>(2, 1000);
+  ExpectPadding(expected_padding);
+  senders_[0]->TimeToSendPadding(1500);
+  expected_padding[kSenderRtxSsrc + 3] = std::make_pair<int, int>(3, 1500);
+  ExpectPadding(expected_padding);
+}
 }  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
index 6e59a2d..7cfcd72 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -89,7 +89,7 @@
       rtx_(kRtxOff),
       payload_type_rtx_(-1),
       target_bitrate_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
-      target_bitrate_kbps_(0) {
+      target_bitrate_(0) {
   memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
   memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
   memset(csrcs_, 0, sizeof(csrcs_));
@@ -127,8 +127,14 @@
   delete video_;
 }
 
-void RTPSender::SetTargetSendBitrate(const uint32_t bits) {
-  SetTargetBitrateKbps(static_cast<uint16_t>(bits / 1000));
+void RTPSender::SetTargetBitrate(uint32_t bitrate) {
+  CriticalSectionScoped cs(target_bitrate_critsect_.get());
+  target_bitrate_ = bitrate;
+}
+
+uint32_t RTPSender::GetTargetBitrate() {
+  CriticalSectionScoped cs(target_bitrate_critsect_.get());
+  return target_bitrate_;
 }
 
 uint16_t RTPSender::ActualSendBitrateKbit() const {
@@ -330,7 +336,6 @@
   *payload_type = payload_type_rtx_;
 }
 
-
 void RTPSender::SetRtxPayloadType(int payload_type) {
   CriticalSectionScoped cs(send_critsect_);
   payload_type_rtx_ = payload_type;
@@ -465,8 +470,8 @@
   // Current bitrate since last estimate(1 second) averaged with the
   // estimate since then, to get the most up to date bitrate.
   uint32_t current_bitrate = bitrate_sent_.BitrateNow();
-  uint16_t target_bitrate_kbps = GetTargetBitrateKbps();
-  int bitrate_diff = target_bitrate_kbps * 1000 - current_bitrate;
+  uint32_t target_bitrate = GetTargetBitrate();
+  int bitrate_diff = target_bitrate - current_bitrate;
   if (bitrate_diff <= 0) {
     return true;
   }
@@ -477,7 +482,7 @@
   } else {
     bytes = (bitrate_diff / 8);
     // Cap at 200 ms of target send data.
-    int bytes_cap = target_bitrate_kbps * 25;  // 1000 / 8 / 5.
+    int bytes_cap = target_bitrate / 1000 * 25;  // 1000 / 8 / 5.
     if (bytes > bytes_cap) {
       bytes = bytes_cap;
     }
@@ -656,12 +661,12 @@
                "num_seqnum", nack_sequence_numbers.size(), "avg_rtt", avg_rtt);
   const int64_t now = clock_->TimeInMilliseconds();
   uint32_t bytes_re_sent = 0;
-  uint16_t target_bitrate_kbps = GetTargetBitrateKbps();
+  uint32_t target_bitrate = GetTargetBitrate();
 
   // Enough bandwidth to send NACK?
   if (!ProcessNACKBitRate(now)) {
     LOG(LS_INFO) << "NACK bitrate reached. Skip sending NACK response. Target "
-                 << target_bitrate_kbps;
+                 << target_bitrate;
     return;
   }
 
@@ -681,10 +686,10 @@
       break;
     }
     // Delay bandwidth estimate (RTT * BW).
-    if (target_bitrate_kbps != 0 && avg_rtt) {
+    if (target_bitrate != 0 && avg_rtt) {
       // kbits/s * ms = bits => bits/8 = bytes
       uint32_t target_bytes =
-          (static_cast<uint32_t>(target_bitrate_kbps) * avg_rtt) >> 3;
+          (static_cast<uint32_t>(target_bitrate / 1000) * avg_rtt) >> 3;
       if (bytes_re_sent > target_bytes) {
         break;  // Ignore the rest of the packets in the list.
       }
@@ -699,33 +704,34 @@
 
 bool RTPSender::ProcessNACKBitRate(const uint32_t now) {
   uint32_t num = 0;
-  int32_t byte_count = 0;
-  const uint32_t avg_interval = 1000;
-  uint16_t target_bitrate_kbps = GetTargetBitrateKbps();
+  int byte_count = 0;
+  const int kAvgIntervalMs = 1000;
+  uint32_t target_bitrate = GetTargetBitrate();
 
   CriticalSectionScoped cs(send_critsect_);
 
-  if (target_bitrate_kbps == 0) {
+  if (target_bitrate == 0) {
     return true;
   }
   for (num = 0; num < NACK_BYTECOUNT_SIZE; ++num) {
-    if ((now - nack_byte_count_times_[num]) > avg_interval) {
+    if ((now - nack_byte_count_times_[num]) > kAvgIntervalMs) {
       // Don't use data older than 1sec.
       break;
     } else {
       byte_count += nack_byte_count_[num];
     }
   }
-  int32_t time_interval = avg_interval;
+  int time_interval = kAvgIntervalMs;
   if (num == NACK_BYTECOUNT_SIZE) {
     // More than NACK_BYTECOUNT_SIZE nack messages has been received
     // during the last msg_interval.
     time_interval = now - nack_byte_count_times_[num - 1];
     if (time_interval < 0) {
-      time_interval = avg_interval;
+      time_interval = kAvgIntervalMs;
     }
   }
-  return (byte_count * 8) < (target_bitrate_kbps * time_interval);
+  return (byte_count * 8) <
+         static_cast<int>(target_bitrate / 1000 * time_interval);
 }
 
 void RTPSender::UpdateNACKBitRate(const uint32_t bytes,
@@ -882,8 +888,13 @@
   int bytes_sent = SendRedundantPayloads(payload_type, bytes);
   bytes -= bytes_sent;
   if (bytes > 0) {
-    int padding_sent = SendPadData(payload_type, timestamp, capture_time_ms,
-                                   bytes, kDontStore, true, true);
+    int padding_sent = SendPadData(payload_type,
+                                   timestamp,
+                                   capture_time_ms,
+                                   bytes,
+                                   kDontStore,
+                                   true,
+                                   rtx_ == kRtxOff);
     bytes_sent += padding_sent;
   }
   return bytes_sent;
@@ -1659,14 +1670,4 @@
     bitrate_callback_->Notify(stats, ssrc_);
   }
 }
-
-void RTPSender::SetTargetBitrateKbps(uint16_t bitrate_kbps) {
-  CriticalSectionScoped cs(target_bitrate_critsect_.get());
-  target_bitrate_kbps_ = bitrate_kbps;
-}
-
-uint16_t RTPSender::GetTargetBitrateKbps() {
-  CriticalSectionScoped cs(target_bitrate_critsect_.get());
-  return target_bitrate_kbps_;
-}
 }  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
index 17457ff..17b026c 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
@@ -83,7 +83,8 @@
   // was sent within the statistics window.
   bool GetSendSideDelay(int* avg_send_delay_ms, int* max_send_delay_ms) const;
 
-  void SetTargetSendBitrate(const uint32_t bits);
+  void SetTargetBitrate(uint32_t bitrate);
+  uint32_t GetTargetBitrate();
 
   virtual uint16_t MaxDataPayloadLength() const
       OVERRIDE;  // with RTP and FEC headers.
@@ -329,9 +330,6 @@
                       bool is_retransmit);
   bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const;
 
-  void SetTargetBitrateKbps(uint16_t bitrate_kbps);
-  uint16_t GetTargetBitrateKbps();
-
   Clock* clock_;
   Bitrate bitrate_sent_;
 
@@ -399,7 +397,7 @@
   // that by the time the function returns there is no guarantee
   // that the target bitrate is still valid.
   scoped_ptr<CriticalSectionWrapper> target_bitrate_critsect_;
-  uint16_t target_bitrate_kbps_ GUARDED_BY(target_bitrate_critsect_);
+  uint16_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_);
 };
 
 }  // namespace webrtc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 67a4a57..1848289 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -444,7 +444,7 @@
       kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
   EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
       kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
-  rtp_sender_->SetTargetSendBitrate(300000);
+  rtp_sender_->SetTargetBitrate(300000);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
                                                    kPayload,
@@ -498,7 +498,7 @@
       kRtpExtensionTransmissionTimeOffset, kTransmissionTimeOffsetExtensionId));
   EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
       kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
-  rtp_sender_->SetTargetSendBitrate(300000);
+  rtp_sender_->SetTargetBitrate(300000);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
                                                    kPayload,
@@ -580,7 +580,7 @@
                                          kAbsoluteSendTimeExtensionId);
   webrtc::RTPHeader rtp_header;
 
-  rtp_sender_->SetTargetSendBitrate(300000);
+  rtp_sender_->SetTargetBitrate(300000);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
                                                    kPayload,
@@ -698,7 +698,7 @@
                                          kTransmissionTimeOffsetExtensionId);
   rtp_parser->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
                                          kAbsoluteSendTimeExtensionId);
-  rtp_sender_->SetTargetSendBitrate(300000);
+  rtp_sender_->SetTargetBitrate(300000);
   const size_t kNumPayloadSizes = 10;
   const int kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700, 750,
       800, 850, 900, 950};