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
|
// 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
|
// reach |pad_up_to_bitrate_kbps|. If the media bitrate is above
|
||||||
// |pad_up_to_bitrate_kbps| no padding will be sent.
|
// |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
|
// 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.
|
// 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).
|
// low bitrates (less than 320 kbits/s).
|
||||||
const int kMaxQueueTimeWithoutSendingMs = 30;
|
const int kMaxQueueTimeWithoutSendingMs = 30;
|
||||||
|
|
||||||
// Max padding bytes per second.
|
|
||||||
const int kMaxPaddingKbps = 800;
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -128,7 +125,7 @@ PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
|
|||||||
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
media_budget_(new paced_sender::IntervalBudget(
|
media_budget_(new paced_sender::IntervalBudget(
|
||||||
pace_multiplier_ * target_bitrate_kbps)),
|
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.
|
// No padding until UpdateBitrate is called.
|
||||||
pad_up_to_bitrate_budget_(new paced_sender::IntervalBudget(0)),
|
pad_up_to_bitrate_budget_(new paced_sender::IntervalBudget(0)),
|
||||||
time_last_update_(TickTime::Now()),
|
time_last_update_(TickTime::Now()),
|
||||||
@ -164,9 +161,11 @@ bool PacedSender::Enabled() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PacedSender::UpdateBitrate(int target_bitrate_kbps,
|
void PacedSender::UpdateBitrate(int target_bitrate_kbps,
|
||||||
|
int max_padding_bitrate_kbps,
|
||||||
int pad_up_to_bitrate_kbps) {
|
int pad_up_to_bitrate_kbps) {
|
||||||
CriticalSectionScoped cs(critsect_.get());
|
CriticalSectionScoped cs(critsect_.get());
|
||||||
media_budget_->set_target_rate_kbps(pace_multiplier_ * target_bitrate_kbps);
|
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);
|
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;
|
uint16_t sequence_number = 1234;
|
||||||
int64_t capture_time_ms = 56789;
|
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.
|
// Due to the multiplicative factor we can send 3 packets not 2 packets.
|
||||||
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
|
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
|
||||||
capture_time_ms, 250);
|
capture_time_ms, 250);
|
||||||
@ -237,7 +237,7 @@ TEST_F(PacedSenderTest, Padding) {
|
|||||||
|
|
||||||
TEST_F(PacedSenderTest, NoPaddingWhenDisabled) {
|
TEST_F(PacedSenderTest, NoPaddingWhenDisabled) {
|
||||||
send_bucket_->SetStatus(false);
|
send_bucket_->SetStatus(false);
|
||||||
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
|
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
|
||||||
// No padding is expected since the pacer is disabled.
|
// No padding is expected since the pacer is disabled.
|
||||||
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
|
EXPECT_CALL(callback_, TimeToSendPadding(_)).Times(0);
|
||||||
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
|
EXPECT_EQ(5, send_bucket_->TimeUntilNextProcess());
|
||||||
@ -257,7 +257,7 @@ TEST_F(PacedSenderTest, VerifyPaddingUpToBitrate) {
|
|||||||
int64_t capture_time_ms = 56789;
|
int64_t capture_time_ms = 56789;
|
||||||
const int kTimeStep = 5;
|
const int kTimeStep = 5;
|
||||||
const int64_t kBitrateWindow = 100;
|
const int64_t kBitrateWindow = 100;
|
||||||
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
|
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
|
||||||
int64_t start_time = TickTime::MillisecondTimestamp();
|
int64_t start_time = TickTime::MillisecondTimestamp();
|
||||||
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
|
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
|
||||||
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
|
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
|
||||||
@ -276,7 +276,9 @@ TEST_F(PacedSenderTest, VerifyMaxPaddingBitrate) {
|
|||||||
const int kTimeStep = 5;
|
const int kTimeStep = 5;
|
||||||
const int64_t kBitrateWindow = 100;
|
const int64_t kBitrateWindow = 100;
|
||||||
const int kTargetBitrate = 1500;
|
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();
|
int64_t start_time = TickTime::MillisecondTimestamp();
|
||||||
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
|
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
|
||||||
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
|
SendAndExpectPacket(PacedSender::kNormalPriority, ssrc, sequence_number++,
|
||||||
@ -298,7 +300,7 @@ TEST_F(PacedSenderTest, VerifyAverageBitrateVaryingMediaPayload) {
|
|||||||
send_bucket_.reset(new PacedSender(&callback, kTargetBitrate,
|
send_bucket_.reset(new PacedSender(&callback, kTargetBitrate,
|
||||||
kPaceMultiplier));
|
kPaceMultiplier));
|
||||||
send_bucket_->SetStatus(true);
|
send_bucket_->SetStatus(true);
|
||||||
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate);
|
send_bucket_->UpdateBitrate(kTargetBitrate, kTargetBitrate, kTargetBitrate);
|
||||||
int64_t start_time = TickTime::MillisecondTimestamp();
|
int64_t start_time = TickTime::MillisecondTimestamp();
|
||||||
int media_bytes = 0;
|
int media_bytes = 0;
|
||||||
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
|
while (TickTime::MillisecondTimestamp() - start_time < kBitrateWindow) {
|
||||||
|
@ -679,7 +679,8 @@ class RtpRtcp : public Module {
|
|||||||
/*
|
/*
|
||||||
* Set the target send bitrate
|
* 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
|
* Turn on/off generic FEC
|
||||||
|
@ -218,7 +218,7 @@ class MockRtpRtcp : public RtpRtcp {
|
|||||||
MOCK_METHOD1(SetCameraDelay,
|
MOCK_METHOD1(SetCameraDelay,
|
||||||
int32_t(const int32_t delayMS));
|
int32_t(const int32_t delayMS));
|
||||||
MOCK_METHOD1(SetTargetSendBitrate,
|
MOCK_METHOD1(SetTargetSendBitrate,
|
||||||
void(const uint32_t bitrate));
|
void(const std::vector<uint32_t>& stream_bitrates));
|
||||||
MOCK_METHOD3(SetGenericFECStatus,
|
MOCK_METHOD3(SetGenericFECStatus,
|
||||||
int32_t(const bool enable, const uint8_t payloadTypeRED, const uint8_t payloadTypeFEC));
|
int32_t(const bool enable, const uint8_t payloadTypeRED, const uint8_t payloadTypeFEC));
|
||||||
MOCK_METHOD3(GenericFECStatus,
|
MOCK_METHOD3(GenericFECStatus,
|
||||||
|
@ -1254,42 +1254,35 @@ RtpVideoCodecTypes ModuleRtpRtcpImpl::SendVideoCodec() const {
|
|||||||
return rtp_sender_.VideoCodecType();
|
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_,
|
WEBRTC_TRACE(kTraceModuleCall, kTraceRtpRtcp, id_,
|
||||||
"SetTargetSendBitrate: %ubit", bitrate);
|
"SetTargetSendBitrate: %ld streams", stream_bitrates.size());
|
||||||
|
|
||||||
const bool have_child_modules(child_modules_.empty() ? false : true);
|
const bool have_child_modules(child_modules_.empty() ? false : true);
|
||||||
if (have_child_modules) {
|
if (have_child_modules) {
|
||||||
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
|
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
|
||||||
if (simulcast_) {
|
if (simulcast_) {
|
||||||
uint32_t bitrate_remainder = bitrate;
|
|
||||||
std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
|
std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
|
||||||
for (int i = 0; it != child_modules_.end() &&
|
for (size_t i = 0;
|
||||||
i < send_video_codec_.numberOfSimulcastStreams; ++it) {
|
it != child_modules_.end() && i < stream_bitrates.size(); ++it) {
|
||||||
if ((*it)->SendingMedia()) {
|
if ((*it)->SendingMedia()) {
|
||||||
RTPSender& rtp_sender = (*it)->rtp_sender_;
|
RTPSender& rtp_sender = (*it)->rtp_sender_;
|
||||||
if (send_video_codec_.simulcastStream[i].maxBitrate * 1000 >
|
rtp_sender.SetTargetSendBitrate(stream_bitrates[i]);
|
||||||
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;
|
|
||||||
}
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
assert(stream_bitrates.size() == 1);
|
||||||
std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
|
std::list<ModuleRtpRtcpImpl*>::iterator it = child_modules_.begin();
|
||||||
for (; it != child_modules_.end(); ++it) {
|
for (; it != child_modules_.end(); ++it) {
|
||||||
RTPSender& rtp_sender = (*it)->rtp_sender_;
|
RTPSender& rtp_sender = (*it)->rtp_sender_;
|
||||||
rtp_sender.SetTargetSendBitrate(bitrate);
|
rtp_sender.SetTargetSendBitrate(stream_bitrates[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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 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(
|
virtual int32_t SetGenericFECStatus(
|
||||||
const bool enable,
|
const bool enable,
|
||||||
|
@ -55,6 +55,28 @@ static const int kMinPacingDelayMs = 200;
|
|||||||
// VideoEngine API and remove the kTransmissionMaxBitrateMultiplier.
|
// VideoEngine API and remove the kTransmissionMaxBitrateMultiplier.
|
||||||
static const int kTransmissionMaxBitrateMultiplier = 2;
|
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 {
|
class QMVideoSettingsCallback : public VCMQMSettingsCallback {
|
||||||
public:
|
public:
|
||||||
explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
|
explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
|
||||||
@ -401,7 +423,11 @@ int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Convert from kbps to bps.
|
// 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 =
|
uint16_t max_data_payload_length =
|
||||||
default_rtp_rtcp_->MaxDataPayloadLength();
|
default_rtp_rtcp_->MaxDataPayloadLength();
|
||||||
@ -1013,10 +1039,36 @@ void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps,
|
|||||||
if (vcm_.SendCodec(&send_codec) != 0) {
|
if (vcm_.SendCodec(&send_codec) != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int pad_up_to_bitrate = std::min(bitrate_kbps,
|
SimulcastStream* stream_configs = send_codec.simulcastStream;
|
||||||
static_cast<int>(send_codec.maxBitrate));
|
// Allocate the bandwidth between the streams.
|
||||||
paced_sender_->UpdateBitrate(bitrate_kbps, pad_up_to_bitrate);
|
std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
|
||||||
default_rtp_rtcp_->SetTargetSendBitrate(bitrate_bps);
|
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() {
|
PacedSender* ViEEncoder::GetPacedSender() {
|
||||||
|
Reference in New Issue
Block a user