Adding trace and changing pacing constants

BUG=1721,1722
R=mikhal@webrtc.org, niklas.enbom@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3940 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
pwestin@webrtc.org 2013-05-02 19:02:17 +00:00
parent a5961b855e
commit 52b4e8871a
7 changed files with 97 additions and 30 deletions

View File

@ -21,7 +21,7 @@ namespace webrtc {
class MockPacedSender : public PacedSender {
public:
MockPacedSender() : PacedSender(NULL, 0) {}
MockPacedSender() : PacedSender(NULL, 0, 0) {}
MOCK_METHOD5(SendPacket, bool(Priority priority,
uint32_t ssrc,
uint16_t sequence_number,

View File

@ -44,7 +44,8 @@ class PacedSender : public Module {
protected:
virtual ~Callback() {}
};
PacedSender(Callback* callback, int target_bitrate_kbps);
PacedSender(Callback* callback, int target_bitrate_kbps,
float pace_multiplier);
virtual ~PacedSender();
@ -110,11 +111,13 @@ class PacedSender : public Module {
// Checks if next packet in line can be transmitted. Returns true on success.
bool GetNextPacket(uint32_t* ssrc, uint16_t* sequence_number,
int64_t* capture_time_ms);
int64_t* capture_time_ms, Priority* priority,
bool* last_packet);
// Local helper function to GetNextPacket.
void GetNextPacketFromList(PacketList* list,
uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms);
uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms,
bool* last_packet);
// Updates the number of bytes that can be sent for the next time interval.
void UpdateBytesPerInterval(uint32_t delta_time_in_ms);
@ -123,6 +126,7 @@ class PacedSender : public Module {
void UpdateState(int num_bytes);
Callback* callback_;
const float pace_multiplier_;
bool enable_;
bool paused_;
scoped_ptr<CriticalSectionWrapper> critsect_;
@ -131,6 +135,8 @@ class PacedSender : public Module {
int padding_bytes_remaining_interval_;
TickTime time_last_update_;
TickTime time_last_send_;
int64_t capture_time_ms_last_queued_;
int64_t capture_time_ms_last_sent_;
PacketList high_priority_packets_;
PacketList normal_priority_packets_;

View File

@ -12,15 +12,11 @@
#include <assert.h>
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/trace_event.h"
namespace {
// Multiplicative factor that is applied to the target bitrate to calculate the
// number of bytes that can be transmitted per interval.
// Increasing this factor will result in lower delays in cases of bitrate
// overshoots from the encoder.
const float kBytesPerIntervalMargin = 1.5f;
// Time limit in milliseconds between packet bursts.
const int kMinPacketLimitMs = 5;
@ -59,15 +55,19 @@ void PacedSender::PacketList::push_back(const PacedSender::Packet& packet) {
}
}
PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps)
PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
float pace_multiplier)
: callback_(callback),
pace_multiplier_(pace_multiplier),
enable_(false),
paused_(false),
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
target_bitrate_kbytes_per_s_(target_bitrate_kbps >> 3), // Divide by 8.
bytes_remaining_interval_(0),
padding_bytes_remaining_interval_(0),
time_last_update_(TickTime::Now()) {
time_last_update_(TickTime::Now()),
capture_time_ms_last_queued_(0),
capture_time_ms_last_sent_(0) {
UpdateBytesPerInterval(kMinPacketLimitMs);
}
@ -113,6 +113,11 @@ bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
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.
@ -140,6 +145,11 @@ bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
UpdateState(bytes);
return true; // We can send now.
}
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);
}
normal_priority_packets_.push_back(
Packet(ssrc, sequence_number, capture_time_ms, bytes));
return false;
@ -204,7 +214,18 @@ int32_t PacedSender::Process() {
uint32_t ssrc;
uint16_t sequence_number;
int64_t capture_time_ms;
while (GetNextPacket(&ssrc, &sequence_number, &capture_time_ms)) {
Priority priority;
bool last_packet;
while (GetNextPacket(&ssrc, &sequence_number, &capture_time_ms,
&priority, &last_packet)) {
if (priority == kNormalPriority) {
if (capture_time_ms > capture_time_ms_last_sent_) {
capture_time_ms_last_sent_ = capture_time_ms;
} else if (capture_time_ms == capture_time_ms_last_sent_ &&
last_packet) {
TRACE_EVENT_ASYNC_END0("webrtc_rtp", "PacedSend", capture_time_ms);
}
}
critsect_->Leave();
callback_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms);
critsect_->Enter();
@ -229,10 +250,10 @@ void PacedSender::UpdateBytesPerInterval(uint32_t delta_time_ms) {
if (bytes_remaining_interval_ < 0) {
// We overused last interval, compensate this interval.
bytes_remaining_interval_ += kBytesPerIntervalMargin * bytes_per_interval;
bytes_remaining_interval_ += pace_multiplier_ * bytes_per_interval;
} else {
// If we underused last interval we can't use it this interval.
bytes_remaining_interval_ = kBytesPerIntervalMargin * bytes_per_interval;
bytes_remaining_interval_ = pace_multiplier_ * bytes_per_interval;
}
if (padding_bytes_remaining_interval_ < 0) {
// We overused last interval, compensate this interval.
@ -245,51 +266,60 @@ void PacedSender::UpdateBytesPerInterval(uint32_t delta_time_ms) {
// MUST have critsect_ when calling.
bool PacedSender::GetNextPacket(uint32_t* ssrc, uint16_t* sequence_number,
int64_t* capture_time_ms) {
int64_t* capture_time_ms, Priority* priority,
bool* last_packet) {
if (bytes_remaining_interval_ <= 0) {
// All bytes consumed for this interval.
// Check if we have not sent in a too long time.
if ((TickTime::Now() - time_last_send_).Milliseconds() >
kMaxQueueTimeWithoutSendingMs) {
if (!high_priority_packets_.empty()) {
*priority = kHighPriority;
GetNextPacketFromList(&high_priority_packets_, ssrc, sequence_number,
capture_time_ms);
capture_time_ms, last_packet);
return true;
}
if (!normal_priority_packets_.empty()) {
*priority = kNormalPriority;
GetNextPacketFromList(&normal_priority_packets_, ssrc, sequence_number,
capture_time_ms);
capture_time_ms, last_packet);
return true;
}
}
return false;
}
if (!high_priority_packets_.empty()) {
*priority = kHighPriority;
GetNextPacketFromList(&high_priority_packets_, ssrc, sequence_number,
capture_time_ms);
capture_time_ms, last_packet);
return true;
}
if (!normal_priority_packets_.empty()) {
*priority = kNormalPriority;
GetNextPacketFromList(&normal_priority_packets_, ssrc, sequence_number,
capture_time_ms);
capture_time_ms, last_packet);
return true;
}
if (!low_priority_packets_.empty()) {
*priority = kLowPriority;
GetNextPacketFromList(&low_priority_packets_, ssrc, sequence_number,
capture_time_ms);
capture_time_ms, last_packet);
return true;
}
return false;
}
void PacedSender::GetNextPacketFromList(PacketList* list,
uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms) {
uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms,
bool* last_packet) {
Packet packet = list->front();
UpdateState(packet.bytes_);
*sequence_number = packet.sequence_number_;
*ssrc = packet.ssrc_;
*capture_time_ms = packet.capture_time_ms_;
list->pop_front();
*last_packet = list->empty() ||
list->front().capture_time_ms_ > *capture_time_ms;
}
// MUST have critsect_ when calling.

View File

@ -19,6 +19,7 @@ namespace webrtc {
namespace test {
static const int kTargetBitrate = 800;
static const float kPaceMultiplier = 1.5f;
class MockPacedSenderCallback : public PacedSender::Callback {
public:
@ -33,7 +34,8 @@ class PacedSenderTest : public ::testing::Test {
PacedSenderTest() {
TickTime::UseFakeClock(123456);
// Need to initialize PacedSender after we initialize clock.
send_bucket_.reset(new PacedSender(&callback_, kTargetBitrate));
send_bucket_.reset(new PacedSender(&callback_, kTargetBitrate,
kPaceMultiplier));
send_bucket_->SetStatus(true);
}
MockPacedSenderCallback callback_;

View File

@ -491,6 +491,10 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
// re-transmit and not new payload data.
}
TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPSender::ReSendPacket",
"timestamp", rtp_header.header.timestamp,
"seqnum", rtp_header.header.sequenceNumber);
if (paced_sender_) {
if (!paced_sender_->SendPacket(PacedSender::kHighPriority,
rtp_header.header.ssrc,
@ -503,10 +507,6 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, uint32_t min_resend_time) {
}
}
TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPSender::ReSendPacket",
"timestamp", rtp_header.header.timestamp,
"seqnum", rtp_header.header.sequenceNumber);
if (SendPacketToNetwork(buffer_to_send_ptr, length)) {
return 0;
}
@ -518,6 +518,8 @@ bool RTPSender::SendPacketToNetwork(const uint8_t *packet, uint32_t size) {
if (transport_) {
bytes_sent = transport_->SendPacket(id_, packet, size);
}
TRACE_EVENT_INSTANT2("webrtc_rtp", "RTPSender::SendPacketToNetwork",
"size", size, "sent", bytes_sent);
// TODO(pwesin): Add a separate bitrate for sent bitrate after pacer.
if (bytes_sent <= 0) {
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, id_,

View File

@ -33,6 +33,17 @@ namespace webrtc {
// Pace in kbits/s until we receive first estimate.
static const int kInitialPace = 2000;
// Pacing-rate relative to our target send rate.
// Multiplicative factor that is applied to the target bitrate to calculate the
// number of bytes that can be transmitted per interval.
// Increasing this factor will result in lower delays in cases of bitrate
// overshoots from the encoder.
static const float kPaceMultiplier = 2.5f;
// Margin on when we pause the encoder when the pacing buffer overflows relative
// to the configured buffer delay.
static const float kEncoderPausePacerMargin = 2.0f;
// Don't stop the encoder unless the delay is above this configured value.
static const int kMinPacingDelayMs = 200;
@ -106,6 +117,7 @@ ViEEncoder::ViEEncoder(int32_t engine_id,
target_delay_ms_(0),
network_is_transmitting_(true),
encoder_paused_(false),
encoder_paused_and_dropped_frame_(false),
channels_dropping_delta_frames_(0),
drop_next_frame_(false),
fec_enabled_(false),
@ -131,7 +143,8 @@ ViEEncoder::ViEEncoder(int32_t engine_id,
default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
bitrate_observer_.reset(new ViEBitrateObserver(this));
pacing_callback_.reset(new ViEPacedSenderCallback(this));
paced_sender_.reset(new PacedSender(pacing_callback_.get(), kInitialPace));
paced_sender_.reset(
new PacedSender(pacing_callback_.get(), kInitialPace, kPaceMultiplier));
}
bool ViEEncoder::Init() {
@ -485,7 +498,8 @@ bool ViEEncoder::EncoderPaused() const {
// TODO(pwestin): Workaround until nack is configured as a time and not
// number of packets.
return paced_sender_->QueueInMs() >=
std::max(target_delay_ms_, kMinPacingDelayMs);
std::max(static_cast<int>(target_delay_ms_ * kEncoderPausePacerMargin),
kMinPacingDelayMs);
}
return !network_is_transmitting_;
}
@ -508,10 +522,22 @@ void ViEEncoder::DeliverFrame(int id,
video_frame->timestamp());
{
CriticalSectionScoped cs(data_cs_.get());
if (EncoderPaused() || default_rtp_rtcp_->SendingMedia() == false) {
if (default_rtp_rtcp_->SendingMedia() == false) {
// We've paused or we have no channels attached, don't encode.
return;
}
if (EncoderPaused()) {
if (!encoder_paused_and_dropped_frame_) {
TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this);
}
encoder_paused_and_dropped_frame_ = true;
return;
}
if (encoder_paused_and_dropped_frame_) {
TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this);
}
encoder_paused_and_dropped_frame_ = false;
if (drop_next_frame_) {
// Drop this frame.
WEBRTC_TRACE(webrtc::kTraceStream,

View File

@ -195,6 +195,7 @@ class ViEEncoder
int target_delay_ms_;
bool network_is_transmitting_;
bool encoder_paused_;
bool encoder_paused_and_dropped_frame_;
std::map<unsigned int, int64_t> time_last_intra_request_ms_;
int32_t channels_dropping_delta_frames_;
bool drop_next_frame_;