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};