Fixes some pacer/padding issues found while testing.
- A bug was introduced in r4234 causing no paced packets to be sent.
- Only update the sequence number counter if a padding packet is actually going to be sent, to avoid packet loss.
- Have all packets go through the pacer if pacing is enabled to avoid reordering.
- Fix race condition on reading capture_time_ms_/timestamp_ in rtp_sender.cc.
BUG=1837
TEST=trybots and vie_auto_test --automated
R=mflodman@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/1682004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@4246 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/pacing/paced_sender.cc b/webrtc/modules/pacing/paced_sender.cc
index d672913..3e50275 100644
--- a/webrtc/modules/pacing/paced_sender.cc
+++ b/webrtc/modules/pacing/paced_sender.cc
@@ -181,29 +181,11 @@
if (capture_time_ms < 0) {
capture_time_ms = TickTime::MillisecondTimestamp();
}
- if (paused_) {
- // Queue all packets when we are paused.
- switch (priority) {
- case kHighPriority:
- high_priority_packets_->push_back(paced_sender::Packet(ssrc,
- sequence_number,
- capture_time_ms,
- bytes));
- break;
- case kNormalPriority:
- if (capture_time_ms > capture_time_ms_last_queued_) {
- capture_time_ms_last_queued_ = capture_time_ms;
- TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
- "capture_time_ms", capture_time_ms);
- }
- case kLowPriority:
- // Queue the low priority packets in the normal priority queue when we
- // are paused to avoid starvation.
- normal_priority_packets_->push_back(paced_sender::Packet(
- ssrc, sequence_number, capture_time_ms, bytes));
- break;
- }
- return false;
+ if (paused_ && priority == kNormalPriority &&
+ capture_time_ms > capture_time_ms_last_queued_) {
+ capture_time_ms_last_queued_ = capture_time_ms;
+ TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
+ "capture_time_ms", capture_time_ms);
}
paced_sender::PacketList* packet_list = NULL;
switch (priority) {
@@ -217,11 +199,6 @@
packet_list = low_priority_packets_.get();
break;
}
- if (packet_list->empty() &&
- media_budget_->bytes_remaining() > 0) {
- UpdateMediaBytesSent(bytes);
- return true; // We can send now.
- }
packet_list->push_back(paced_sender::Packet(ssrc, sequence_number,
capture_time_ms, bytes));
return false;
@@ -267,9 +244,11 @@
CriticalSectionScoped cs(critsect_.get());
int elapsed_time_ms = (now - time_last_update_).Milliseconds();
time_last_update_ = now;
- if (!paused_ && elapsed_time_ms > 0) {
- uint32_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
- UpdateBytesPerInterval(delta_time_ms);
+ if (!paused_) {
+ if (elapsed_time_ms > 0) {
+ uint32_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
+ UpdateBytesPerInterval(delta_time_ms);
+ }
uint32_t ssrc;
uint16_t sequence_number;
int64_t capture_time_ms;
diff --git a/webrtc/modules/pacing/paced_sender_unittest.cc b/webrtc/modules/pacing/paced_sender_unittest.cc
index 49d18ee..c8dcd97 100644
--- a/webrtc/modules/pacing/paced_sender_unittest.cc
+++ b/webrtc/modules/pacing/paced_sender_unittest.cc
@@ -62,6 +62,15 @@
send_bucket_->SetStatus(true);
}
+ void SendAndExpectPacket(PacedSender::Priority priority,
+ uint32_t ssrc, uint16_t sequence_number,
+ int64_t capture_time_ms, int size) {
+ EXPECT_FALSE(send_bucket_->SendPacket(priority, ssrc,
+ sequence_number, capture_time_ms, size));
+ EXPECT_CALL(callback_, TimeToSendPacket(
+ ssrc, sequence_number, capture_time_ms)).Times(1);
+ }
+
MockPacedSenderCallback callback_;
scoped_ptr<PacedSender> send_bucket_;
};
@@ -70,34 +79,35 @@
uint32_t ssrc = 12345;
uint16_t sequence_number = 1234;
int64_t capture_time_ms = 56789;
-
// Due to the multiplicative factor we can send 3 packets not 2 packets.
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
sequence_number, capture_time_ms, 250));
+ send_bucket_->Process();
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
EXPECT_CALL(callback_,
TimeToSendPacket(ssrc, sequence_number, capture_time_ms)).Times(0);
TickTime::AdvanceFakeClock(4);
EXPECT_EQ(1, send_bucket_->TimeUntilNextProcess());
- EXPECT_CALL(callback_,
- TimeToSendPacket(ssrc, sequence_number, capture_time_ms)).Times(1);
TickTime::AdvanceFakeClock(1);
EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
- EXPECT_EQ(0, send_bucket_->Process());
+ EXPECT_CALL(callback_, TimeToSendPacket(
+ ssrc, sequence_number++, capture_time_ms)).Times(1);
+ send_bucket_->Process();
sequence_number++;
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
sequence_number++, capture_time_ms, 250));
+ send_bucket_->Process();
}
TEST_F(PacedSenderTest, PaceQueuedPackets) {
@@ -107,13 +117,14 @@
// Due to the multiplicative factor we can send 3 packets not 2 packets.
for (int i = 0; i < 3; ++i) {
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
}
for (int j = 0; j < 30; ++j) {
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
sequence_number++, capture_time_ms, 250));
}
+ send_bucket_->Process();
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
for (int k = 0; k < 10; ++k) {
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
@@ -127,14 +138,15 @@
TickTime::AdvanceFakeClock(5);
EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
EXPECT_EQ(0, send_bucket_->Process());
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ sequence_number, capture_time_ms, 250));
+ send_bucket_->Process();
}
TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) {
@@ -145,8 +157,8 @@
// Due to the multiplicative factor we can send 3 packets not 2 packets.
for (int i = 0; i < 3; ++i) {
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
}
queued_sequence_number = sequence_number;
@@ -158,6 +170,7 @@
sequence_number++, capture_time_ms, 250));
}
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
+ send_bucket_->Process();
for (int k = 0; k < 10; ++k) {
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
TickTime::AdvanceFakeClock(5);
@@ -173,14 +186,15 @@
TickTime::AdvanceFakeClock(5);
EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
EXPECT_EQ(0, send_bucket_->Process());
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
sequence_number++, capture_time_ms, 250));
+ send_bucket_->Process();
}
TEST_F(PacedSenderTest, Padding) {
@@ -190,16 +204,14 @@
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
// Due to the multiplicative factor we can send 3 packets not 2 packets.
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
// No padding is expected since we have sent too much already.
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
- EXPECT_CALL(callback_,
- TimeToSendPacket(ssrc, sequence_number, capture_time_ms)).Times(0);
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
TickTime::AdvanceFakeClock(5);
EXPECT_EQ(0, send_bucket_->TimeUntilNextProcess());
@@ -223,9 +235,8 @@
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
int64_t start_time = TickTime::MillisecondTimestamp();
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms,
- 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
TickTime::AdvanceFakeClock(kTimeStep);
EXPECT_CALL(callback_, TimeToSendPadding(250)).Times(1).
WillOnce(Return(250));
@@ -243,9 +254,8 @@
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
int64_t start_time = TickTime::MillisecondTimestamp();
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms,
- 250));
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
TickTime::AdvanceFakeClock(kTimeStep);
EXPECT_CALL(callback_, TimeToSendPadding(500)).Times(1).
WillOnce(Return(250));
@@ -262,14 +272,15 @@
PacedSenderPadding callback;
send_bucket_.reset(new PacedSender(&callback, kTargetBitrate,
kPaceMultiplier));
+ send_bucket_->SetStatus(true);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
int64_t start_time = TickTime::MillisecondTimestamp();
int media_bytes = 0;
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
int media_payload = rand() % 100 + 200; // [200, 300] bytes.
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
- sequence_number++, capture_time_ms,
- media_payload));
+ EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority, ssrc,
+ sequence_number++, capture_time_ms,
+ media_payload));
media_bytes += media_payload;
TickTime::AdvanceFakeClock(kTimeStep);
send_bucket_->Process();
@@ -286,12 +297,13 @@
int64_t capture_time_ms_low_priority = 1234567;
// Due to the multiplicative factor we can send 3 packets not 2 packets.
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kLowPriority,
- ssrc_low_priority, sequence_number++, capture_time_ms_low_priority, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
- ssrc, sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
- ssrc, sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kLowPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ send_bucket_->Process();
// Expect normal and low priority to be queued and high to pass through.
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kLowPriority,
@@ -332,22 +344,23 @@
EXPECT_EQ(0, send_bucket_->QueueInMs());
// Due to the multiplicative factor we can send 3 packets not 2 packets.
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kLowPriority,
- ssrc_low_priority, sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
- ssrc, sequence_number++, capture_time_ms, 250));
- EXPECT_TRUE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
- ssrc, sequence_number++, capture_time_ms, 250));
+ SendAndExpectPacket(PacedSender::kLowPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
+ capture_time_ms, 250);
+ send_bucket_->Process();
send_bucket_->Pause();
// Expect everything to be queued.
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kLowPriority,
- ssrc_low_priority, sequence_number++, capture_time_ms, 250));
+ ssrc_low_priority, sequence_number++, second_capture_time_ms, 250));
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
ssrc, sequence_number++, capture_time_ms, 250));
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kNormalPriority,
- ssrc, sequence_number++, second_capture_time_ms, 250));
+ ssrc, sequence_number++, capture_time_ms, 250));
EXPECT_FALSE(send_bucket_->SendPacket(PacedSender::kHighPriority,
ssrc, sequence_number++, capture_time_ms, 250));
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index b136783..c5defe8 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -980,7 +980,7 @@
bool no_child_modules = false;
{
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
- no_child_modules = !child_modules_.empty();
+ no_child_modules = child_modules_.empty();
}
if (no_child_modules) {
// Don't send from default module.
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
index 613efe7..07a3f1b 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -59,7 +59,8 @@
packets_sent_(0), payload_bytes_sent_(0), start_time_stamp_forced_(false),
start_time_stamp_(0), ssrc_db_(*SSRCDatabase::GetSSRCDatabase()),
remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false),
- timestamp_(0), num_csrcs_(0), csrcs_(), include_csrcs_(true),
+ timestamp_(0), capture_time_ms_(0), last_packet_marker_bit_(false),
+ num_csrcs_(0), csrcs_(), include_csrcs_(true),
rtx_(kRtxOff), payload_type_rtx_(-1) {
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
@@ -383,7 +384,6 @@
return SendPaddingAccordingToBitrate(payload_type, capture_timestamp,
capture_time_ms) ? 0 : -1;
}
- capture_time_ms_ = capture_time_ms;
return video_->SendVideo(video_type, frame_type, payload_type,
capture_timestamp, capture_time_ms, payload_data,
payload_size, fragmentation, codec_info,
@@ -413,8 +413,8 @@
bytes = bytes_cap;
}
}
- int bytes_sent = SendPadData(payload_type, capture_time_ms, bytes,
- kDontRetransmit, false);
+ int bytes_sent = SendPadData(payload_type, capture_timestamp, capture_time_ms,
+ bytes, kDontRetransmit, false);
// We did not manage to send all bytes. Comparing with 31 due to modulus 32.
return bytes - bytes_sent < 31;
}
@@ -423,12 +423,7 @@
int32_t bytes) {
int padding_bytes_in_packet = kMaxPaddingLength;
if (bytes < kMaxPaddingLength) {
- // Round to the nearest multiple of 32.
- padding_bytes_in_packet = (bytes + 16) & 0xffe0;
- }
- if (padding_bytes_in_packet < 32) {
- // Sanity don't send empty packets.
- return 0;
+ padding_bytes_in_packet = bytes;
}
packet[0] |= 0x20; // Set padding bit.
int32_t *data =
@@ -443,45 +438,55 @@
return padding_bytes_in_packet;
}
-int RTPSender::SendPadData(int payload_type, int64_t capture_time_ms,
- int32_t bytes, StorageType store,
- bool force_full_size_packets) {
+int RTPSender::SendPadData(int payload_type, uint32_t timestamp,
+ int64_t capture_time_ms, int32_t bytes,
+ StorageType store, bool force_full_size_packets) {
// Drop this packet if we're not sending media packets.
if (!sending_media_) {
return bytes;
}
- uint32_t ssrc;
- uint16_t sequence_number;
- uint32_t timestamp;
- {
- CriticalSectionScoped cs(send_critsect_);
- timestamp = timestamp_;
- if (rtx_ == kRtxOff) {
- ssrc = ssrc_;
- sequence_number = sequence_number_;
- ++sequence_number_;
- } else {
- ssrc = ssrc_rtx_;
- sequence_number = sequence_number_rtx_;
- ++sequence_number_rtx_;
- }
- }
int padding_bytes_in_packet = 0;
int bytes_sent = 0;
for (; bytes > 0; bytes -= padding_bytes_in_packet) {
- // Generate an RTX packet which only contains random padding data.
- uint8_t padding_packet[IP_PACKET_SIZE];
- int header_length = CreateRTPHeader(padding_packet, payload_type, ssrc,
- false, timestamp, sequence_number,
- NULL, 0);
// Always send full padding packets.
if (force_full_size_packets && bytes < kMaxPaddingLength)
bytes = kMaxPaddingLength;
- padding_bytes_in_packet = BuildPaddingPacket(padding_packet, header_length,
- bytes);
- if (padding_bytes_in_packet == 0) {
+ if (bytes < kMaxPaddingLength) {
+ if (force_full_size_packets) {
+ bytes = kMaxPaddingLength;
+ } else {
+ // Round to the nearest multiple of 32.
+ bytes = (bytes + 16) & 0xffe0;
+ }
+ }
+ if (padding_bytes_in_packet < 32) {
+ // Sanity don't send empty packets.
break;
}
+ uint32_t ssrc;
+ uint16_t sequence_number;
+ {
+ CriticalSectionScoped cs(send_critsect_);
+ // Only send padding packets following the last packet of a frame,
+ // indicated by the marker bit.
+ if (!last_packet_marker_bit_)
+ return bytes_sent;
+ if (rtx_ == kRtxOff) {
+ ssrc = ssrc_;
+ sequence_number = sequence_number_;
+ ++sequence_number_;
+ } else {
+ ssrc = ssrc_rtx_;
+ sequence_number = sequence_number_rtx_;
+ ++sequence_number_rtx_;
+ }
+ }
+ uint8_t padding_packet[IP_PACKET_SIZE];
+ int header_length = CreateRTPHeader(padding_packet, payload_type, ssrc,
+ false, timestamp, sequence_number, NULL,
+ 0);
+ padding_bytes_in_packet = BuildPaddingPacket(padding_packet, header_length,
+ bytes);
if (0 > SendToNetwork(padding_packet, padding_bytes_in_packet,
header_length, capture_time_ms, store,
PacedSender::kLowPriority)) {
@@ -739,12 +744,16 @@
return 0;
}
int payload_type;
+ int64_t capture_time_ms;
+ uint32_t timestamp;
{
CriticalSectionScoped cs(send_critsect_);
payload_type = (rtx_ == kRtxOff) ? payload_type_ : payload_type_rtx_;
+ timestamp = timestamp_;
+ capture_time_ms = capture_time_ms_;
}
- return SendPadData(payload_type, capture_time_ms_, bytes, kDontStore,
- true);
+ return SendPadData(payload_type, timestamp, capture_time_ms, bytes,
+ kDontStore, true);
}
// TODO(pwestin): send in the RTPHeaderParser to avoid parsing it again.
@@ -898,7 +907,8 @@
int32_t RTPSender::BuildRTPheader(
uint8_t *data_buffer, const int8_t payload_type,
const bool marker_bit, const uint32_t capture_timestamp,
- const bool time_stamp_provided, const bool inc_sequence_number) {
+ int64_t capture_time_ms, const bool time_stamp_provided,
+ const bool inc_sequence_number) {
assert(payload_type >= 0);
CriticalSectionScoped cs(send_critsect_);
@@ -911,6 +921,8 @@
timestamp_++;
}
uint32_t sequence_number = sequence_number_++;
+ capture_time_ms_ = capture_time_ms;
+ last_packet_marker_bit_ = marker_bit;
int csrcs_length = 0;
if (include_csrcs_)
csrcs_length = num_csrcs_;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
index 22ac3e8..1efba85 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
@@ -44,6 +44,7 @@
virtual int32_t BuildRTPheader(
uint8_t *data_buffer, const int8_t payload_type,
const bool marker_bit, const uint32_t capture_time_stamp,
+ int64_t capture_time_ms,
const bool time_stamp_provided = true,
const bool inc_sequence_number = true) = 0;
@@ -132,8 +133,9 @@
const RTPVideoTypeHeader * rtp_type_hdr = NULL);
int BuildPaddingPacket(uint8_t* packet, int header_length, int32_t bytes);
- int SendPadData(int payload_type, int64_t capture_time_ms, int32_t bytes,
- StorageType store, bool force_full_size_packets);
+ int SendPadData(int payload_type, uint32_t timestamp, int64_t capture_time_ms,
+ int32_t bytes, StorageType store,
+ bool force_full_size_packets);
// RTP header extension
int32_t SetTransmissionTimeOffset(
const int32_t transmission_time_offset);
@@ -192,6 +194,7 @@
virtual int32_t BuildRTPheader(
uint8_t *data_buffer, const int8_t payload_type,
const bool marker_bit, const uint32_t capture_time_stamp,
+ int64_t capture_time_ms,
const bool time_stamp_provided = true,
const bool inc_sequence_number = true);
@@ -324,6 +327,7 @@
uint32_t ssrc_;
uint32_t timestamp_;
int64_t capture_time_ms_;
+ bool last_packet_marker_bit_;
uint8_t num_csrcs_;
uint32_t csrcs_[kRtpCsrcSize];
bool include_csrcs_;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
index e1972e5..b5684aa 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_audio.cc
@@ -353,12 +353,14 @@
// we need to get the current timestamp to calc the diff
uint32_t oldTimeStamp = _rtpSender->Timestamp();
rtpHeaderLength = _rtpSender->BuildRTPheader(dataBuffer, _REDPayloadType,
- markerBit, captureTimeStamp);
+ markerBit, captureTimeStamp,
+ _clock->TimeInMilliseconds());
timestampOffset = uint16_t(_rtpSender->Timestamp() - oldTimeStamp);
} else {
rtpHeaderLength = _rtpSender->BuildRTPheader(dataBuffer, payloadType,
- markerBit, captureTimeStamp);
+ markerBit, captureTimeStamp,
+ _clock->TimeInMilliseconds());
}
if (rtpHeaderLength <= 0) {
return -1;
@@ -583,7 +585,8 @@
_sendAudioCritsect->Enter();
//Send DTMF data
- _rtpSender->BuildRTPheader(dtmfbuffer, _dtmfPayloadType, markerBit, dtmfTimeStamp);
+ _rtpSender->BuildRTPheader(dtmfbuffer, _dtmfPayloadType, markerBit,
+ dtmfTimeStamp, _clock->TimeInMilliseconds());
// reset CSRC and X bit
dtmfbuffer[0] &= 0xe0;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index b20231c..6c9131f 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -165,7 +165,8 @@
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
+ kTimestamp,
+ 0);
EXPECT_EQ(12, length);
// Verify
@@ -193,7 +194,8 @@
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
+ kTimestamp,
+ 0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
// Verify
@@ -230,7 +232,8 @@
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
+ kTimestamp,
+ 0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
// Verify
@@ -257,7 +260,8 @@
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
+ kTimestamp,
+ 0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
// Verify
@@ -295,7 +299,8 @@
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
+ kTimestamp,
+ 0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
// Verify
@@ -337,12 +342,12 @@
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
rtp_sender_->SetTargetSendBitrate(300000);
+ int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
-
- int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
+ kTimestamp,
+ capture_time_ms);
// Packet should be stored in a send bucket.
EXPECT_EQ(0, rtp_sender_->SendToNetwork(packet_,
@@ -391,12 +396,12 @@
EXPECT_EQ(0, rtp_sender_->RegisterRtpHeaderExtension(
kRtpExtensionAbsoluteSendTime, kAbsoluteSendTimeExtensionId));
rtp_sender_->SetTargetSendBitrate(300000);
+ int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int32_t rtp_length = rtp_sender_->BuildRTPheader(packet_,
kPayload,
kMarkerBit,
- kTimestamp);
-
- int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
+ kTimestamp,
+ capture_time_ms);
// Packet should be stored in a send bucket.
EXPECT_EQ(0, rtp_sender_->SendToNetwork(packet_,
@@ -521,7 +526,8 @@
int32_t length = rtp_sender_->BuildRTPheader(packet_,
kAudioPayload,
kMarkerBit,
- kTimestamp);
+ kTimestamp,
+ 0);
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
// Currently, no space is added by for header extension by BuildRTPHeader().
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
index a7abd8e..07ab310 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -361,7 +361,8 @@
// MarkerBit is 1 on final packet (bytes_to_send == 0)
if (_rtpSender.BuildRTPheader(buffer, payload_type, size == 0,
- capture_timestamp) != rtp_header_length) {
+ capture_timestamp,
+ capture_time_ms) != rtp_header_length) {
return -1;
}
@@ -465,7 +466,7 @@
// Write RTP header.
// Set marker bit true if this is the last packet in frame.
_rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
- captureTimeStamp);
+ captureTimeStamp, capture_time_ms);
if (-1 == SendVideoPacket(dataBuffer, payloadBytesInPacket,
rtpHeaderLength, captureTimeStamp,
capture_time_ms, storage, protect))
diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
index d823700..dbd3ac6 100644
--- a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
+++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
@@ -160,8 +160,9 @@
EXPECT_STRCASEEQ(sendCName, remoteCName);
}
+
//
- // RTX
+ // Pacing
//
unsigned short recFractionsLost = 0;
unsigned int recCumulativeLost = 0;
@@ -173,6 +174,48 @@
unsigned int sentFecBitrate = 0;
unsigned int sentNackBitrate = 0;
+ ViETest::Log("Testing Pacing\n");
+ EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel));
+ EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel));
+
+ myTransport.ClearStats();
+
+ EXPECT_EQ(0, ViE.rtp_rtcp->SetNACKStatus(tbChannel.videoChannel, true));
+ EXPECT_EQ(0, ViE.rtp_rtcp->SetTransmissionSmoothingStatus(
+ tbChannel.videoChannel, true));
+ EXPECT_EQ(0, ViE.base->StartReceive(tbChannel.videoChannel));
+ EXPECT_EQ(0, ViE.base->StartSend(tbChannel.videoChannel));
+
+ NetworkParameters network;
+ network.packet_loss_rate = 0;
+ network.loss_model = kUniformLoss;
+ myTransport.SetNetworkParameters(network);
+
+ AutoTestSleep(kAutoTestSleepTimeMs);
+
+ EXPECT_EQ(0, ViE.rtp_rtcp->GetReceivedRTCPStatistics(
+ tbChannel.videoChannel, recFractionsLost, recCumulativeLost,
+ recExtendedMax, recJitter, recRttMs));
+ EXPECT_EQ(0, ViE.rtp_rtcp->GetBandwidthUsage(
+ tbChannel.videoChannel, sentTotalBitrate, sentVideoBitrate,
+ sentFecBitrate, sentNackBitrate));
+
+ int num_rtp_packets = 0;
+ int num_dropped_packets = 0;
+ int num_rtcp_packets = 0;
+ std::map<uint8_t, int> packet_counters;
+ myTransport.GetStats(num_rtp_packets, num_dropped_packets, num_rtcp_packets,
+ &packet_counters);
+ EXPECT_GT(num_rtp_packets, 0);
+ EXPECT_EQ(num_dropped_packets, 0);
+ EXPECT_GT(num_rtcp_packets, 0);
+ EXPECT_GT(sentTotalBitrate, 0u);
+ EXPECT_EQ(sentNackBitrate, 0u);
+ EXPECT_EQ(recCumulativeLost, 0u);
+
+ //
+ // RTX
+ //
ViETest::Log("Testing NACK over RTX\n");
EXPECT_EQ(0, ViE.base->StopSend(tbChannel.videoChannel));
EXPECT_EQ(0, ViE.base->StopReceive(tbChannel.videoChannel));
@@ -180,6 +223,8 @@
myTransport.ClearStats();
const uint8_t kRtxPayloadType = 96;
+ EXPECT_EQ(0, ViE.rtp_rtcp->SetTransmissionSmoothingStatus(
+ tbChannel.videoChannel, false));
EXPECT_EQ(0, ViE.rtp_rtcp->SetNACKStatus(tbChannel.videoChannel, true));
EXPECT_EQ(0, ViE.rtp_rtcp->SetRtxSendPayloadType(tbChannel.videoChannel,
kRtxPayloadType));
@@ -198,7 +243,6 @@
// Make sure the first key frame gets through.
AutoTestSleep(100);
const int kPacketLossRate = 20;
- NetworkParameters network;
network.packet_loss_rate = kPacketLossRate;
network.loss_model = kUniformLoss;
myTransport.SetNetworkParameters(network);
@@ -211,10 +255,7 @@
tbChannel.videoChannel, sentTotalBitrate, sentVideoBitrate,
sentFecBitrate, sentNackBitrate));
- int num_rtp_packets = 0;
- int num_dropped_packets = 0;
- int num_rtcp_packets = 0;
- std::map<uint8_t, int> packet_counters;
+ packet_counters.clear();
myTransport.GetStats(num_rtp_packets, num_dropped_packets, num_rtcp_packets,
&packet_counters);
EXPECT_GT(num_rtp_packets, 0);