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:
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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() {
|
||||
|
Reference in New Issue
Block a user