Account for packetization overhead when setting target bitrate.

That is, the payload packetization overhead (eg. vp8 payload header),
not the RTP headers, extensions, etc.
The encoder and pacer both look at payload rate, but are currently not
aware of the bytes that are added in between them.

Bug: webrtc:10155
Change-Id: I4cdb04849d762360374d47a496983c8c6df191d2
Reviewed-on: https://webrtc-review.googlesource.com/c/115410
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26163}
This commit is contained in:
Erik Språng 2019-01-08 16:19:11 +01:00 committed by Commit Bot
parent 791d43c4b1
commit 482b3ef2ac
11 changed files with 72 additions and 6 deletions

View File

@ -480,6 +480,16 @@ bool RtpVideoSender::NackEnabled() const {
return nack_enabled;
}
uint32_t RtpVideoSender::GetPacketizationOverheadRate() const {
uint32_t packetization_overhead_bps = 0;
for (auto& rtp_rtcp : rtp_modules_) {
if (rtp_rtcp->SendingMedia()) {
packetization_overhead_bps += rtp_rtcp->PacketizationOverheadBps();
}
}
return packetization_overhead_bps;
}
void RtpVideoSender::DeliverRtcp(const uint8_t* packet, size_t length) {
// Runs on a network thread.
for (auto& rtp_rtcp : rtp_modules_)
@ -622,6 +632,17 @@ void RtpVideoSender::OnBitrateUpdated(uint32_t bitrate_bps,
// protection overhead.
encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
payload_bitrate_bps, framerate, fraction_loss, loss_mask_vector_, rtt);
// Subtract packetization overhead from the encoder target. If rate is really
// low, cap the overhead at 50%. Since packetization is measured over an
// averaging window, it might intermittently be higher than encoder target
// (eg encoder pause event), so cap it to target.
const uint32_t packetization_rate_bps =
std::min(GetPacketizationOverheadRate(), encoder_target_rate_bps_);
encoder_target_rate_bps_ =
std::max(encoder_target_rate_bps_ - packetization_rate_bps,
encoder_target_rate_bps_ / 2);
loss_mask_vector_.clear();
uint32_t encoder_overhead_rate_bps =

View File

@ -128,6 +128,7 @@ class RtpVideoSender : public RtpVideoSenderInterface,
void ConfigureRids(const RtpConfig& rtp_config);
bool FecEnabled() const;
bool NackEnabled() const;
uint32_t GetPacketizationOverheadRate() const;
const bool send_side_bwe_with_overhead_;

View File

@ -238,12 +238,17 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
// bitrate estimate since the stream participates in the bitrate allocation.
virtual void SetAsPartOfAllocation(bool part_of_allocation) = 0;
// Returns current bitrate in Kbit/s.
// Fetches the current send bitrates in bits/s.
virtual void BitrateSent(uint32_t* total_rate,
uint32_t* video_rate,
uint32_t* fec_rate,
uint32_t* nack_rate) const = 0;
// Returns the current packetization overhead rate, in bps. Note that this is
// the payload overhead, eg the VP8 payload headers, not the RTP headers
// or extension/
virtual uint32_t PacketizationOverheadBps() const = 0;
// Used by the codec module to deliver a video or audio frame for
// packetization.
// |frame_type| - type of frame to send

View File

@ -85,6 +85,7 @@ class MockRtpRtcp : public RtpRtcp {
uint32_t* video_rate,
uint32_t* fec_rate,
uint32_t* nack_rate));
MOCK_CONST_METHOD0(PacketizationOverheadBps, uint32_t());
MOCK_CONST_METHOD1(EstimatedReceiveBandwidth,
int(uint32_t* available_bandwidth));
MOCK_METHOD9(SendOutgoingData,

View File

@ -826,6 +826,10 @@ void ModuleRtpRtcpImpl::BitrateSent(uint32_t* total_rate,
*nack_rate = rtp_sender_->NackOverheadRate();
}
uint32_t ModuleRtpRtcpImpl::PacketizationOverheadBps() const {
return rtp_sender_->PacketizationOverheadBps();
}
void ModuleRtpRtcpImpl::OnRequestSendReport() {
SendRTCP(kRtcpSr);
}

View File

@ -299,6 +299,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {
uint32_t* video_rate,
uint32_t* fec_rate,
uint32_t* nackRate) const override;
uint32_t PacketizationOverheadBps() const override;
void RegisterSendChannelRtpStatisticsCallback(
StreamDataCountersCallback* callback) override;

View File

@ -246,6 +246,10 @@ uint32_t RTPSender::NackOverheadRate() const {
return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
uint32_t RTPSender::PacketizationOverheadBps() const {
return video_ ? video_->PacketizationOverheadBps() : 0;
}
void RTPSender::SetExtmapAllowMixed(bool extmap_allow_mixed) {
rtc::CritScope lock(&send_critsect_);
rtp_header_extension_map_.SetExtmapAllowMixed(extmap_allow_mixed);

View File

@ -78,6 +78,7 @@ class RTPSender {
uint32_t VideoBitrateSent() const;
uint32_t FecOverheadRate() const;
uint32_t NackOverheadRate() const;
uint32_t PacketizationOverheadBps() const;
int32_t RegisterPayload(absl::string_view payload_name,
const int8_t payload_type,

View File

@ -170,6 +170,7 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock,
key_fec_params_{0, 1, kFecMaskRandom},
fec_bitrate_(1000, RateStatistics::kBpsScale),
video_bitrate_(1000, RateStatistics::kBpsScale),
packetization_overhead_bitrate_(1000, RateStatistics::kBpsScale),
frame_encryptor_(frame_encryptor),
require_frame_encryption_(require_frame_encryption),
generic_descriptor_auth_experiment_(
@ -546,6 +547,17 @@ bool RTPSenderVideo::SendVideo(enum VideoCodecType video_type,
expected_retransmission_time_ms);
size_t num_packets = packetizer->NumPackets();
size_t unpacketized_payload_size;
if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
unpacketized_payload_size = 0;
for (uint16_t i = 0; i < fragmentation->fragmentationVectorSize; ++i) {
unpacketized_payload_size += fragmentation->fragmentationLength[i];
}
} else {
unpacketized_payload_size = payload_size;
}
size_t packetized_payload_size = 0;
if (num_packets == 0)
return false;
@ -576,6 +588,7 @@ bool RTPSenderVideo::SendVideo(enum VideoCodecType video_type,
RTC_DCHECK_LE(packet->payload_size(), expected_payload_capacity);
if (!rtp_sender_->AssignSequenceNumber(packet.get()))
return false;
packetized_payload_size += packet->payload_size();
// No FEC protection for upper temporal layers, if used.
bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx;
@ -615,6 +628,12 @@ bool RTPSenderVideo::SendVideo(enum VideoCodecType video_type,
}
}
rtc::CritScope cs(&stats_crit_);
RTC_DCHECK_GE(packetized_payload_size, unpacketized_payload_size);
packetization_overhead_bitrate_.Update(
packetized_payload_size - unpacketized_payload_size,
clock_->TimeInMilliseconds());
TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
rtp_timestamp);
return true;
@ -630,6 +649,12 @@ uint32_t RTPSenderVideo::FecOverheadRate() const {
return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
uint32_t RTPSenderVideo::PacketizationOverheadBps() const {
rtc::CritScope cs(&stats_crit_);
return packetization_overhead_bitrate_.Rate(clock_->TimeInMilliseconds())
.value_or(0);
}
int RTPSenderVideo::SelectiveRetransmissions() const {
rtc::CritScope cs(&crit_);
return retransmission_settings_;

View File

@ -77,6 +77,7 @@ class RTPSenderVideo {
uint32_t VideoBitrateSent() const;
uint32_t FecOverheadRate() const;
uint32_t PacketizationOverheadBps() const;
int SelectiveRetransmissions() const;
void SetSelectiveRetransmissions(uint8_t settings);
@ -159,6 +160,7 @@ class RTPSenderVideo {
RateStatistics fec_bitrate_ RTC_GUARDED_BY(stats_crit_);
// Bitrate used for video payload and RTP headers.
RateStatistics video_bitrate_ RTC_GUARDED_BY(stats_crit_);
RateStatistics packetization_overhead_bitrate_ RTC_GUARDED_BY(stats_crit_);
std::map<int, TemporalLayerStats> frame_stats_by_temporal_layer_
RTC_GUARDED_BY(stats_crit_);

View File

@ -259,11 +259,12 @@ class VideoStreamFactory
std::vector<VideoStream> streams =
test::CreateVideoStreams(width, height, encoder_config);
// Use the same total bitrates when sending a single stream to avoid
// lowering the bitrate estimate and requiring a subsequent rampup.
const int encoder_stream_bps =
kEncoderBitrateBps /
rtc::checked_cast<int>(encoder_config.number_of_streams);
// Always divide the same total bitrate across all streams so that sending a
// single stream avoids lowering the bitrate estimate and requiring a
// subsequent rampup. Also reduce the target by 10% to account for overhead
// that might sometimes otherwise cause streams to not be enabled.
const int encoder_stream_bps = rtc::checked_cast<int>(
0.9 * (kEncoderBitrateBps / encoder_config.number_of_streams));
for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
streams[i].min_bitrate_bps = encoder_stream_bps;