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
This commit is contained in:
@@ -181,29 +181,11 @@ bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
|
||||
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 @@ bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
|
||||
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 @@ int32_t PacedSender::Process() {
|
||||
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;
|
||||
|
@@ -62,6 +62,15 @@ class PacedSenderTest : public ::testing::Test {
|
||||
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 @@ TEST_F(PacedSenderTest, QueuePacket) {
|
||||
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 @@ TEST_F(PacedSenderTest, PaceQueuedPackets) {
|
||||
|
||||
// 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 @@ TEST_F(PacedSenderTest, PaceQueuedPackets) {
|
||||
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 @@ TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) {
|
||||
|
||||
// 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 @@ TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) {
|
||||
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 @@ TEST_F(PacedSenderTest, PaceQueuedPacketsWithDuplicates) {
|
||||
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 @@ TEST_F(PacedSenderTest, Padding) {
|
||||
|
||||
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 @@ TEST_F(PacedSenderTest, VerifyPaddingUpToBitrate) {
|
||||
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 @@ TEST_F(PacedSenderTest, VerifyMaxPaddingBitrate) {
|
||||
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 @@ TEST_F(PacedSenderTest, VerifyAverageBitrateVaryingMediaPayload) {
|
||||
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 @@ TEST_F(PacedSenderTest, Priority) {
|
||||
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 @@ TEST_F(PacedSenderTest, Pause) {
|
||||
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));
|
||||
|
||||
|
@@ -980,7 +980,7 @@ void ModuleRtpRtcpImpl::TimeToSendPacket(uint32_t ssrc,
|
||||
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.
|
||||
|
@@ -59,7 +59,8 @@ RTPSender::RTPSender(const int32_t id, const bool audio, Clock *clock,
|
||||
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 @@ int32_t RTPSender::SendOutgoingData(
|
||||
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 @@ bool RTPSender::SendPaddingAccordingToBitrate(
|
||||
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 @@ int RTPSender::BuildPaddingPacket(uint8_t* packet, int header_length,
|
||||
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 @@ int RTPSender::BuildPaddingPacket(uint8_t* packet, int header_length,
|
||||
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 @@ int RTPSender::TimeToSendPadding(int bytes) {
|
||||
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 @@ int RTPSender::CreateRTPHeader(
|
||||
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 @@ int32_t RTPSender::BuildRTPheader(
|
||||
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_;
|
||||
|
@@ -44,6 +44,7 @@ class RTPSenderInterface {
|
||||
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 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
|
||||
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 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
|
||||
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 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
|
||||
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_;
|
||||
|
@@ -353,12 +353,14 @@ int32_t RTPSenderAudio::SendAudio(
|
||||
// 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 @@ RTPSenderAudio::SendTelephoneEventPacket(const bool ended,
|
||||
_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;
|
||||
|
@@ -165,7 +165,8 @@ TEST_F(RtpSenderTest, BuildRTPPacket) {
|
||||
int32_t length = rtp_sender_->BuildRTPheader(packet_,
|
||||
kPayload,
|
||||
kMarkerBit,
|
||||
kTimestamp);
|
||||
kTimestamp,
|
||||
0);
|
||||
EXPECT_EQ(12, length);
|
||||
|
||||
// Verify
|
||||
@@ -193,7 +194,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithTransmissionOffsetExtension) {
|
||||
int32_t length = rtp_sender_->BuildRTPheader(packet_,
|
||||
kPayload,
|
||||
kMarkerBit,
|
||||
kTimestamp);
|
||||
kTimestamp,
|
||||
0);
|
||||
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
|
||||
|
||||
// Verify
|
||||
@@ -230,7 +232,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithNegativeTransmissionOffsetExtension) {
|
||||
int32_t length = rtp_sender_->BuildRTPheader(packet_,
|
||||
kPayload,
|
||||
kMarkerBit,
|
||||
kTimestamp);
|
||||
kTimestamp,
|
||||
0);
|
||||
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
|
||||
|
||||
// Verify
|
||||
@@ -257,7 +260,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithAbsoluteSendTimeExtension) {
|
||||
int32_t length = rtp_sender_->BuildRTPheader(packet_,
|
||||
kPayload,
|
||||
kMarkerBit,
|
||||
kTimestamp);
|
||||
kTimestamp,
|
||||
0);
|
||||
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
|
||||
|
||||
// Verify
|
||||
@@ -295,7 +299,8 @@ TEST_F(RtpSenderTest, BuildRTPPacketWithHeaderExtensions) {
|
||||
int32_t length = rtp_sender_->BuildRTPheader(packet_,
|
||||
kPayload,
|
||||
kMarkerBit,
|
||||
kTimestamp);
|
||||
kTimestamp,
|
||||
0);
|
||||
EXPECT_EQ(12 + rtp_sender_->RtpHeaderExtensionTotalLength(), length);
|
||||
|
||||
// Verify
|
||||
@@ -337,12 +342,12 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
|
||||
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 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
|
||||
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 @@ TEST_F(RtpSenderAudioTest, BuildRTPPacketWithAudioLevelExtension) {
|
||||
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().
|
||||
|
@@ -361,7 +361,8 @@ int32_t RTPSenderVideo::SendGeneric(const FrameType frame_type,
|
||||
|
||||
// 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 @@ RTPSenderVideo::SendVP8(const FrameType frameType,
|
||||
// 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))
|
||||
|
@@ -160,8 +160,9 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
EXPECT_STRCASEEQ(sendCName, remoteCName);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RTX
|
||||
// Pacing
|
||||
//
|
||||
unsigned short recFractionsLost = 0;
|
||||
unsigned int recCumulativeLost = 0;
|
||||
@@ -173,6 +174,48 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
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 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
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 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
// 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 @@ void ViEAutoTest::ViERtpRtcpStandardTest()
|
||||
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);
|
||||
|
Reference in New Issue
Block a user