Refactors send rate statistics in RtpSenderEgress

When FEC generation is moved to egress, we'll need to poll bitrates from
there instead of the RtpVideoSender. In preparation, refactoring some
getter methods.

For context, see https://webrtc-review.googlesource.com/c/src/+/173708

Bug: webrtc:11340
Change-Id: Ibc27362361ee9640d9fce676fc8e1093a579344f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174202
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31214}
This commit is contained in:
Erik Språng
2020-05-11 18:22:02 +02:00
committed by Commit Bot
parent 8e321cd690
commit bf46cfef22
8 changed files with 94 additions and 46 deletions

View File

@ -836,16 +836,14 @@ int RtpVideoSender::ProtectionRequest(const FecProtectionParams* delta_params,
*sent_nack_rate_bps = 0;
*sent_fec_rate_bps = 0;
for (const RtpStreamSender& stream : rtp_streams_) {
uint32_t not_used = 0;
uint32_t module_nack_rate = 0;
if (stream.fec_generator) {
stream.fec_generator->SetProtectionParameters(*delta_params, *key_params);
*sent_fec_rate_bps += stream.fec_generator->CurrentFecRate().bps();
}
*sent_video_rate_bps += stream.sender_video->VideoBitrateSent();
stream.rtp_rtcp->BitrateSent(&not_used, /*video_rate=*/nullptr,
/*fec_rate=*/nullptr, &module_nack_rate);
*sent_nack_rate_bps += module_nack_rate;
*sent_nack_rate_bps +=
stream.rtp_rtcp->GetSendRates()[RtpPacketMediaType::kRetransmission]
.bps<uint32_t>();
}
return 0;
}

View File

@ -285,12 +285,16 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
// bitrate estimate since the stream participates in the bitrate allocation.
virtual void SetAsPartOfAllocation(bool part_of_allocation) = 0;
// Fetches the current send bitrates in bits/s.
// TODO(sprang): Remove when all call sites have been moved to
// GetSendRates(). 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 bitrate sent (post-pacing) per packet type.
virtual RtpSendRates GetSendRates() const = 0;
virtual RTPSender* RtpSender() = 0;
virtual const RTPSender* RtpSender() const = 0;

View File

@ -17,6 +17,7 @@
#include <memory>
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h"
@ -211,12 +212,15 @@ class RtcpBandwidthObserver {
virtual ~RtcpBandwidthObserver() {}
};
enum class RtpPacketMediaType {
kAudio, // Audio media packets.
kVideo, // Video media packets.
kRetransmission, // RTX (usually) packets send as response to NACK.
kForwardErrorCorrection, // FEC packets.
kPadding // RTX or plain padding sent to maintain BWE.
// NOTE! |kNumMediaTypes| must be kept in sync with RtpPacketMediaType!
static constexpr size_t kNumMediaTypes = 5;
enum class RtpPacketMediaType : size_t {
kAudio, // Audio media packets.
kVideo, // Video media packets.
kRetransmission, // Retransmisions, sent as response to NACK.
kForwardErrorCorrection, // FEC packets.
kPadding = kNumMediaTypes - 1, // RTX or plain padding sent to maintain BWE.
// Again, don't forget to udate |kNumMediaTypes| if you add another value!
};
struct RtpPacketSendInfo {
@ -382,6 +386,34 @@ struct StreamDataCounters {
RtpPacketCounter fec; // Number of redundancy packets/bytes.
};
class RtpSendRates {
template <std::size_t... Is>
constexpr std::array<DataRate, sizeof...(Is)> make_zero_array(
std::index_sequence<Is...>) {
return {{(static_cast<void>(Is), DataRate::Zero())...}};
}
public:
RtpSendRates()
: send_rates_(
make_zero_array(std::make_index_sequence<kNumMediaTypes>())) {}
RtpSendRates(const RtpSendRates& rhs) = default;
RtpSendRates& operator=(const RtpSendRates&) = default;
DataRate& operator[](RtpPacketMediaType type) {
return send_rates_[static_cast<size_t>(type)];
}
const DataRate& operator[](RtpPacketMediaType type) const {
return send_rates_[static_cast<size_t>(type)];
}
DataRate Sum() const {
return absl::c_accumulate(send_rates_, DataRate::Zero());
}
private:
std::array<DataRate, kNumMediaTypes> send_rates_;
};
// Callback, called whenever byte/packet counts have been updated.
class StreamDataCountersCallback {
public:

View File

@ -95,6 +95,7 @@ class MockRtpRtcp : public RtpRtcp {
uint32_t* fec_rate,
uint32_t* nack_rate),
(const override));
MOCK_METHOD(RtpSendRates, GetSendRates, (), (const override));
MOCK_METHOD(int,
EstimatedReceiveBandwidth,
(uint32_t * available_bandwidth),

View File

@ -290,7 +290,7 @@ RTCPSender::FeedbackState ModuleRtpRtcpImpl::GetFeedbackState() {
state.media_bytes_sent = rtp_stats.transmitted.payload_bytes +
rtx_stats.transmitted.payload_bytes;
state.send_bitrate =
rtp_sender_->packet_sender.SendBitrate().bps<uint32_t>();
rtp_sender_->packet_sender.GetSendRates().Sum().bps<uint32_t>();
}
state.module = this;
@ -702,12 +702,17 @@ void ModuleRtpRtcpImpl::BitrateSent(uint32_t* total_rate,
uint32_t* video_rate,
uint32_t* fec_rate,
uint32_t* nack_rate) const {
*total_rate = rtp_sender_->packet_sender.SendBitrate().bps<uint32_t>();
RtpSendRates send_rates = rtp_sender_->packet_sender.GetSendRates();
*total_rate = send_rates.Sum().bps<uint32_t>();
if (video_rate)
*video_rate = 0;
if (fec_rate)
*fec_rate = 0;
*nack_rate = rtp_sender_->packet_sender.NackOverheadRate().bps<uint32_t>();
*nack_rate = send_rates[RtpPacketMediaType::kRetransmission].bps<uint32_t>();
}
RtpSendRates ModuleRtpRtcpImpl::GetSendRates() const {
return rtp_sender_->packet_sender.GetSendRates();
}
void ModuleRtpRtcpImpl::OnRequestSendReport() {
@ -803,12 +808,13 @@ const RTPSender* ModuleRtpRtcpImpl::RtpSender() const {
DataRate ModuleRtpRtcpImpl::SendRate() const {
RTC_DCHECK(rtp_sender_);
return rtp_sender_->packet_sender.SendBitrate();
return rtp_sender_->packet_sender.GetSendRates().Sum();
}
DataRate ModuleRtpRtcpImpl::NackOverheadRate() const {
RTC_DCHECK(rtp_sender_);
return rtp_sender_->packet_sender.NackOverheadRate();
return rtp_sender_->packet_sender
.GetSendRates()[RtpPacketMediaType::kRetransmission];
}
} // namespace webrtc

View File

@ -264,6 +264,8 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {
uint32_t* fec_rate,
uint32_t* nackRate) const override;
RtpSendRates GetSendRates() const override;
void OnReceivedNack(
const std::vector<uint16_t>& nack_sequence_numbers) override;
void OnReceivedRtcpReportBlocks(
@ -294,6 +296,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp, public RTCPReceiver::ModuleRtpRtcp {
Clock* clock() const { return clock_; }
// TODO(sprang): Remove when usage is gone.
DataRate SendRate() const;
DataRate NackOverheadRate() const;

View File

@ -79,9 +79,8 @@ RtpSenderEgress::RtpSenderEgress(const RtpRtcp::Configuration& config,
max_delay_it_(send_delays_.end()),
sum_delays_ms_(0),
total_packet_send_delay_ms_(0),
total_bitrate_sent_(kBitrateStatisticsWindowMs,
RateStatistics::kBpsScale),
nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
send_rates_(kNumMediaTypes,
{kBitrateStatisticsWindowMs, RateStatistics::kBpsScale}),
rtp_sequence_number_map_(need_rtp_packet_infos_
? std::make_unique<RtpSequenceNumberMap>(
kRtpSequenceNumberMapMaxEntries)
@ -99,16 +98,20 @@ void RtpSenderEgress::SendPacket(RtpPacketToSend* packet,
if (is_audio_) {
#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "AudioTotBitrate_kbps", now_ms,
SendBitrate().kbps(), packet_ssrc);
BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "AudioNackBitrate_kbps", now_ms,
NackOverheadRate().kbps(), packet_ssrc);
GetSendRates().Sum().kbps(), packet_ssrc);
BWE_TEST_LOGGING_PLOT_WITH_SSRC(
1, "AudioNackBitrate_kbps", now_ms,
GetSendRates()[RtpPacketMediaType::kRetransmission].kbps(),
packet_ssrc);
#endif
} else {
#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoTotBitrate_kbps", now_ms,
SendBitrate().kbps(), packet_ssrc);
BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoNackBitrate_kbps", now_ms,
NackOverheadRate().kbps(), packet_ssrc);
GetSendRates().Sum().kbps(), packet_ssrc);
BWE_TEST_LOGGING_PLOT_WITH_SSRC(
1, "VideoNackBitrate_kbps", now_ms,
GetSendRates()[RtpPacketMediaType::kRetransmission].kbps(),
packet_ssrc);
#endif
}
@ -203,21 +206,22 @@ void RtpSenderEgress::ProcessBitrateAndNotifyObservers() {
return;
rtc::CritScope lock(&lock_);
int64_t now_ms = clock_->TimeInMilliseconds();
bitrate_callback_->Notify(total_bitrate_sent_.Rate(now_ms).value_or(0),
nack_bitrate_sent_.Rate(now_ms).value_or(0), ssrc_);
RtpSendRates send_rates = GetSendRates();
bitrate_callback_->Notify(
send_rates.Sum().bps(),
send_rates[RtpPacketMediaType::kRetransmission].bps(), ssrc_);
}
DataRate RtpSenderEgress::SendBitrate() const {
rtc::CritScope cs(&lock_);
return DataRate::BitsPerSec(
total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0));
}
DataRate RtpSenderEgress::NackOverheadRate() const {
rtc::CritScope cs(&lock_);
return DataRate::BitsPerSec(
nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0));
RtpSendRates RtpSenderEgress::GetSendRates() const {
rtc::CritScope lock(&lock_);
const int64_t now_ms = clock_->TimeInMilliseconds();
RtpSendRates current_rates;
for (size_t i = 0; i < kNumMediaTypes; ++i) {
RtpPacketMediaType type = static_cast<RtpPacketMediaType>(i);
current_rates[type] =
DataRate::BitsPerSec(send_rates_[i].Rate(now_ms).value_or(0));
}
return current_rates;
}
void RtpSenderEgress::GetDataCounters(StreamDataCounters* rtp_stats,
@ -432,8 +436,6 @@ void RtpSenderEgress::UpdateRtpStats(const RtpPacketToSend& packet) {
StreamDataCounters* counters =
packet.Ssrc() == rtx_ssrc_ ? &rtx_rtp_stats_ : &rtp_stats_;
total_bitrate_sent_.Update(packet.size(), now_ms);
if (counters->first_packet_time_ms == -1) {
counters->first_packet_time_ms = now_ms;
}
@ -444,10 +446,13 @@ void RtpSenderEgress::UpdateRtpStats(const RtpPacketToSend& packet) {
if (packet.packet_type() == RtpPacketMediaType::kRetransmission) {
counters->retransmitted.AddPacket(packet);
nack_bitrate_sent_.Update(packet.size(), now_ms);
}
counters->transmitted.AddPacket(packet);
RTC_DCHECK(packet.packet_type().has_value());
send_rates_[static_cast<size_t>(*packet.packet_type())].Update(packet.size(),
now_ms);
if (rtp_stats_callback_) {
rtp_stats_callback_->DataCountersUpdated(*counters, packet.Ssrc());
}

View File

@ -57,8 +57,7 @@ class RtpSenderEgress {
absl::optional<uint32_t> FlexFecSsrc() const { return flexfec_ssrc_; }
void ProcessBitrateAndNotifyObservers();
DataRate SendBitrate() const;
DataRate NackOverheadRate() const;
RtpSendRates GetSendRates() const;
void GetDataCounters(StreamDataCounters* rtp_stats,
StreamDataCounters* rtx_stats) const;
@ -129,8 +128,8 @@ class RtpSenderEgress {
uint64_t total_packet_send_delay_ms_ RTC_GUARDED_BY(lock_);
StreamDataCounters rtp_stats_ RTC_GUARDED_BY(lock_);
StreamDataCounters rtx_rtp_stats_ RTC_GUARDED_BY(lock_);
RateStatistics total_bitrate_sent_ RTC_GUARDED_BY(lock_);
RateStatistics nack_bitrate_sent_ RTC_GUARDED_BY(lock_);
// One element per value in RtpPacketMediaType, with index matching value.
std::vector<RateStatistics> send_rates_ RTC_GUARDED_BY(lock_);
// Maps sent packets' sequence numbers to a tuple consisting of:
// 1. The timestamp, without the randomizing offset mandated by the RFC.