Improving padding rules and breaking out bw allocation to ViEEncoder.

BUG=1837
TESTS=vie_auto_test --automated, trybots
R=mflodman@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4693 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org
2013-09-06 13:58:01 +00:00
parent 7bb8f02274
commit b2c8a952a7
8 changed files with 85 additions and 35 deletions

View File

@ -70,7 +70,9 @@ class PacedSender : public Module {
// pad. We will send padding packets to increase the total bitrate until we
// reach |pad_up_to_bitrate_kbps|. If the media bitrate is above
// |pad_up_to_bitrate_kbps| no padding will be sent.
void UpdateBitrate(int target_bitrate_kbps, int pad_up_to_bitrate_kbps);
void UpdateBitrate(int target_bitrate_kbps,
int max_padding_bitrate_kbps,
int pad_up_to_bitrate_kbps);
// Returns true if we send the packet now, else it will add the packet
// information to the queue and call TimeToSendPacket when it's time to send.

View File

@ -29,9 +29,6 @@ const int kMaxIntervalTimeMs = 30;
// low bitrates (less than 320 kbits/s).
const int kMaxQueueTimeWithoutSendingMs = 30;
// Max padding bytes per second.
const int kMaxPaddingKbps = 800;
} // namespace
namespace webrtc {
@ -128,7 +125,7 @@ PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
media_budget_(new paced_sender::IntervalBudget(
pace_multiplier_ * target_bitrate_kbps)),
padding_budget_(new paced_sender::IntervalBudget(kMaxPaddingKbps)),
padding_budget_(new paced_sender::IntervalBudget(0)),
// No padding until UpdateBitrate is called.
pad_up_to_bitrate_budget_(new paced_sender::IntervalBudget(0)),
time_last_update_(TickTime::Now()),
@ -164,9 +161,11 @@ bool PacedSender::Enabled() const {
}
void PacedSender::UpdateBitrate(int target_bitrate_kbps,
int max_padding_bitrate_kbps,
int pad_up_to_bitrate_kbps) {
CriticalSectionScoped cs(critsect_.get());
media_budget_->set_target_rate_kbps(pace_multiplier_ * target_bitrate_kbps);
padding_budget_->set_target_rate_kbps(max_padding_bitrate_kbps);
pad_up_to_bitrate_budget_->set_target_rate_kbps(pad_up_to_bitrate_kbps);
}

View File

@ -211,7 +211,7 @@ TEST_F(PacedSenderTest, Padding) {
uint16_t sequence_number = 1234;
int64_t capture_time_ms = 56789;
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
// Due to the multiplicative factor we can send 3 packets not 2 packets.
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
capture_time_ms, 250);
@ -237,7 +237,7 @@ TEST_F(PacedSenderTest, Padding) {
TEST_F(PacedSenderTest, NoPaddingWhenDisabled) {
send_bucket_->SetStatus(false);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
// No padding is expected since the pacer is disabled.
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
@ -257,7 +257,7 @@ TEST_F(PacedSenderTest, VerifyPaddingUpToBitrate) {
int64_t capture_time_ms = 56789;
const int kTimeStep = 5;
const int64_t kBitrateWindow = 100;
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
int64_t start_time = TickTime::MillisecondTimestamp();
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
@ -276,7 +276,9 @@ TEST_F(PacedSenderTest, VerifyMaxPaddingBitrate) {
const int kTimeStep = 5;
const int64_t kBitrateWindow = 100;
const int kTargetBitrate = 1500;
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
const int kMaxPaddingBitrate = 800;
send_bucket_->UpdateBitrate(kTargetBitrate, kMaxPaddingBitrate,
kTargetBitrate);
int64_t start_time = TickTime::MillisecondTimestamp();
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
@ -298,7 +300,7 @@ TEST_F(PacedSenderTest, VerifyAverageBitrateVaryingMediaPayload) {
send_bucket_.reset(new PacedSender(&callback, kTargetBitrate,
kPaceMultiplier));
send_bucket_->SetStatus(true);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
int64_t start_time = TickTime::MillisecondTimestamp();
int media_bytes = 0;
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {

View File

@ -679,7 +679,8 @@ class RtpRtcp : public Module {
/*
* Set the target send bitrate
*/
virtual void SetTargetSendBitrate(const uint32_t bitrate) = 0;
virtual void SetTargetSendBitrate(
const std::vector<uint32_t>& stream_bitrates) = 0;
/*
* Turn on/off generic FEC

View File

@ -218,7 +218,7 @@ class MockRtpRtcp : public RtpRtcp {
MOCK_METHOD1(SetCameraDelay,
int32_t(const int32_t delayMS));
MOCK_METHOD1(SetTargetSendBitrate,
void(const uint32_t bitrate));
void(const std::vector<uint32_t>& stream_bitrates));
MOCK_METHOD3(SetGenericFECStatus,
int32_t(const bool enable, const uint8_t payloadTypeRED, const uint8_t payloadTypeFEC));
MOCK_METHOD3(GenericFECStatus,

View File

@ -1254,42 +1254,35 @@ RtpVideoCodecTypes ModuleRtpRtcpImpl::SendVideoCodec() const {
return rtp_sender_.VideoCodecType();
}
void ModuleRtpRtcpImpl::SetTargetSendBitrate(const uint32_t bitrate) {
void ModuleRtpRtcpImpl::SetTargetSendBitrate(
const std::vector<uint32_t>& stream_bitrates) {
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_,
"SetTargetSendBitrate: %ubit", bitrate);
"SetTargetSendBitrate: %ld streams", stream_bitrates.size());
const bool have_child_modules(child_modules_.empty() ? false : true);
if (have_child_modules) {
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
if (simulcast_) {
uint32_t bitrate_remainder = bitrate;
std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
for (int i = 0; it != child_modules_.end() &&
i < send_video_codec_.numberOfSimulcastStreams; ++it) {
for (size_t i = 0;
it != child_modules_.end() && i < stream_bitrates.size(); ++it) {
if ((*it)->SendingMedia()) {
RTPSender& rtp_sender = (*it)->rtp_sender_;
if (send_video_codec_.simulcastStream[i].maxBitrate * 1000 >
bitrate_remainder) {
rtp_sender.SetTargetSendBitrate(bitrate_remainder);
bitrate_remainder = 0;
} else {
rtp_sender.SetTargetSendBitrate(
send_video_codec_.simulcastStream[i].maxBitrate * 1000);
bitrate_remainder -=
send_video_codec_.simulcastStream[i].maxBitrate * 1000;
}
rtp_sender.SetTargetSendBitrate(stream_bitrates[i]);
++i;
}
}
} else {
assert(stream_bitrates.size() == 1);
std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
for (; it != child_modules_.end(); ++it) {
RTPSender& rtp_sender = (*it)->rtp_sender_;
rtp_sender.SetTargetSendBitrate(bitrate);
rtp_sender.SetTargetSendBitrate(stream_bitrates[0]);
}
}
} else {
rtp_sender_.SetTargetSendBitrate(bitrate);
assert(stream_bitrates.size() == 1);
rtp_sender_.SetTargetSendBitrate(stream_bitrates[0]);
}
}

View File

@ -303,7 +303,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
virtual int32_t SetCameraDelay(const int32_t delay_ms) OVERRIDE;
virtual void SetTargetSendBitrate(const uint32_t bitrate) OVERRIDE;
virtual void SetTargetSendBitrate(
const std::vector<uint32_t>& stream_bitrates) OVERRIDE;
virtual int32_t SetGenericFECStatus(
const bool enable,

View File

@ -55,6 +55,28 @@ static const int kMinPacingDelayMs = 200;
// VideoEngine API and remove the kTransmissionMaxBitrateMultiplier.
static const int kTransmissionMaxBitrateMultiplier = 2;
std::vector<uint32_t> AllocateStreamBitrates(
uint32_t total_bitrate,
const SimulcastStream* stream_configs,
size_t number_of_streams) {
if (number_of_streams == 0) {
std::vector<uint32_t> stream_bitrates(1, 0);
stream_bitrates[0] = total_bitrate;
return stream_bitrates;
}
std::vector<uint32_t> stream_bitrates(number_of_streams, 0);
uint32_t bitrate_remainder = total_bitrate;
for (size_t i = 0; i < stream_bitrates.size() && bitrate_remainder > 0; ++i) {
if (stream_configs[i].maxBitrate * 1000 > bitrate_remainder) {
stream_bitrates[i] = bitrate_remainder;
} else {
stream_bitrates[i] = stream_configs[i].maxBitrate * 1000;
}
bitrate_remainder -= stream_bitrates[i];
}
return stream_bitrates;
}
class QMVideoSettingsCallback : public VCMQMSettingsCallback {
public:
explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
@ -401,7 +423,11 @@ int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
return -1;
}
// Convert from kbps to bps.
default_rtp_rtcp_->SetTargetSendBitrate(video_codec.startBitrate * 1000);
std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
video_codec.startBitrate * 1000,
video_codec.simulcastStream,
video_codec.numberOfSimulcastStreams);
default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
uint16_t max_data_payload_length =
default_rtp_rtcp_->MaxDataPayloadLength();
@ -1013,10 +1039,36 @@ void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps,
if (vcm_.SendCodec(&send_codec) != 0) {
return;
}
int pad_up_to_bitrate = std::min(bitrate_kbps,
static_cast<int>(send_codec.maxBitrate));
paced_sender_->UpdateBitrate(bitrate_kbps, pad_up_to_bitrate);
default_rtp_rtcp_->SetTargetSendBitrate(bitrate_bps);
SimulcastStream* stream_configs = send_codec.simulcastStream;
// Allocate the bandwidth between the streams.
std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
bitrate_bps,
stream_configs,
send_codec.numberOfSimulcastStreams);
// Find the max amount of padding we can allow ourselves to send at this
// point, based on which streams are currently active and what our current
// available bandwidth is.
int max_padding_bitrate_kbps = 0;
int i = send_codec.numberOfSimulcastStreams - 1;
for (std::vector<uint32_t>::reverse_iterator it = stream_bitrates.rbegin();
it != stream_bitrates.rend(); ++it) {
if (*it > 0) {
max_padding_bitrate_kbps = std::min((*it + 500) / 1000,
stream_configs[i].minBitrate);
break;
}
--i;
}
int pad_up_to_bitrate_kbps =
stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate;
for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) {
pad_up_to_bitrate_kbps += stream_configs[i].targetBitrate;
}
pad_up_to_bitrate_kbps = std::min(bitrate_kbps, pad_up_to_bitrate_kbps);
paced_sender_->UpdateBitrate(bitrate_kbps,
max_padding_bitrate_kbps,
pad_up_to_bitrate_kbps);
default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
}
PacedSender* ViEEncoder::GetPacedSender() {