[fix] fix loss rate calculation

This commit is contained in:
dijunkun
2024-12-04 23:33:11 +08:00
parent 6e3c8c488d
commit 348df6a4bf
2 changed files with 123 additions and 125 deletions

View File

@@ -2,12 +2,13 @@
#include "log.h"
#define STATISTICAL_PERIOD 1000
#define RTP_SEQ_NUM_MAX 65535
IOStatistics::IOStatistics(
std::function<void(const NetTrafficStats&)> io_report_callback)
: io_report_callback_(io_report_callback) {
interval_ = 1000;
interval_ = STATISTICAL_PERIOD;
}
IOStatistics::~IOStatistics() {}
@@ -18,111 +19,120 @@ void IOStatistics::Process() {
cond_var_.wait_for(lock, std::chrono::milliseconds(interval_),
[this] { return !running_; });
video_inbound_bitrate_ = video_inbound_bytes_ * 1000 * 8 / interval_;
video_outbound_bitrate_ = video_outbound_bytes_ * 1000 * 8 / interval_;
audio_inbound_bitrate_ = audio_inbound_bytes_ * 1000 * 8 / interval_;
audio_outbound_bitrate_ = audio_outbound_bytes_ * 1000 * 8 / interval_;
data_inbound_bitrate_ = data_inbound_bytes_ * 1000 * 8 / interval_;
data_outbound_bitrate_ = data_outbound_bytes_ * 1000 * 8 / interval_;
video_inbound_bitrate_ = video_inbound_bytes_.load() * 1000 * 8 / interval_;
video_outbound_bitrate_ =
video_outbound_bytes_.load() * 1000 * 8 / interval_;
audio_inbound_bitrate_ = audio_inbound_bytes_.load() * 1000 * 8 / interval_;
audio_outbound_bitrate_ =
audio_outbound_bytes_.load() * 1000 * 8 / interval_;
data_inbound_bitrate_ = data_inbound_bytes_.load() * 1000 * 8 / interval_;
data_outbound_bitrate_ = data_outbound_bytes_.load() * 1000 * 8 / interval_;
total_inbound_bitrate_ =
video_inbound_bitrate_ + audio_inbound_bitrate_ + data_inbound_bitrate_;
total_outbound_bitrate_ = video_outbound_bitrate_ +
audio_outbound_bitrate_ + data_outbound_bitrate_;
video_inbound_bytes_ = 0;
video_outbound_bytes_ = 0;
audio_inbound_bytes_ = 0;
audio_outbound_bytes_ = 0;
data_inbound_bytes_ = 0;
data_outbound_bytes_ = 0;
// packet loss rate
{
video_rtp_pkt_loss_cnt_ =
expected_video_inbound_rtp_pkt_cnt_ - video_inbound_rtp_pkt_cnt_tmp_;
audio_rtp_pkt_loss_cnt_ =
expected_audio_inbound_rtp_pkt_cnt_ - audio_inbound_rtp_pkt_cnt_tmp_;
data_rtp_pkt_loss_cnt_ =
expected_data_inbound_rtp_pkt_cnt_ - data_inbound_rtp_pkt_cnt_tmp_;
if (expected_video_inbound_rtp_pkt_cnt_ > 0 &&
video_rtp_pkt_loss_cnt_ >= 0) {
video_rtp_pkt_loss_rate_ = video_rtp_pkt_loss_cnt_ /
current_period_last_received_video_rtp_pkt_seq_ =
last_received_video_rtp_pkt_seq_.load();
expected_video_inbound_rtp_pkt_cnt_ =
current_period_last_received_video_rtp_pkt_seq_ -
previous_period_last_received_video_rtp_pkt_seq_ - 1;
previous_period_last_received_video_rtp_pkt_seq_ =
current_period_last_received_video_rtp_pkt_seq_;
if (current_period_last_received_video_rtp_pkt_seq_ > 0 &&
expected_video_inbound_rtp_pkt_cnt_ >= 0) {
video_rtp_pkt_loss_rate_ = video_rtp_pkt_loss_cnt_.load() /
(float)expected_video_inbound_rtp_pkt_cnt_;
} else {
video_rtp_pkt_loss_rate_ = 0;
}
if (expected_audio_inbound_rtp_pkt_cnt_ > 0 &&
audio_inbound_rtp_pkt_cnt_tmp_ >= 0) {
audio_rtp_pkt_loss_rate_ =
audio_rtp_pkt_loss_cnt_ / (float)audio_inbound_rtp_pkt_cnt_;
current_period_last_received_audio_rtp_pkt_seq_ =
last_received_audio_rtp_pkt_seq_.load();
expected_audio_inbound_rtp_pkt_cnt_ =
current_period_last_received_audio_rtp_pkt_seq_ -
previous_period_last_received_audio_rtp_pkt_seq_ - 1;
previous_period_last_received_audio_rtp_pkt_seq_ =
current_period_last_received_audio_rtp_pkt_seq_;
if (current_period_last_received_audio_rtp_pkt_seq_ > 0 &&
expected_audio_inbound_rtp_pkt_cnt_ >= 0) {
audio_rtp_pkt_loss_rate_ = audio_rtp_pkt_loss_cnt_.load() /
(float)expected_audio_inbound_rtp_pkt_cnt_;
} else {
audio_rtp_pkt_loss_rate_ = 0;
}
if (expected_data_inbound_rtp_pkt_cnt_ > 0 &&
data_inbound_rtp_pkt_cnt_ >= 0) {
data_rtp_pkt_loss_rate_ =
data_rtp_pkt_loss_cnt_ / (float)data_inbound_rtp_pkt_cnt_;
current_period_last_received_data_rtp_pkt_seq_ =
last_received_data_rtp_pkt_seq_.load();
expected_data_inbound_rtp_pkt_cnt_ =
current_period_last_received_data_rtp_pkt_seq_ -
previous_period_last_received_data_rtp_pkt_seq_ - 1;
previous_period_last_received_data_rtp_pkt_seq_ =
current_period_last_received_data_rtp_pkt_seq_;
if (current_period_last_received_data_rtp_pkt_seq_ > 0 &&
expected_data_inbound_rtp_pkt_cnt_ >= 0) {
data_rtp_pkt_loss_rate_ = data_rtp_pkt_loss_cnt_.load() /
(float)expected_data_inbound_rtp_pkt_cnt_;
} else {
data_rtp_pkt_loss_rate_ = 0;
}
expected_video_inbound_rtp_pkt_cnt_ = 0;
expected_audio_inbound_rtp_pkt_cnt_ = 0;
expected_data_inbound_rtp_pkt_cnt_ = 0;
video_inbound_rtp_pkt_cnt_tmp_ = 0;
audio_inbound_rtp_pkt_cnt_tmp_ = 0;
data_inbound_rtp_pkt_cnt_tmp_ = 0;
video_rtp_pkt_loss_cnt_ = 0;
audio_rtp_pkt_loss_cnt_ = 0;
data_rtp_pkt_loss_cnt_ = 0;
}
video_inbound_bytes_.store(0);
video_outbound_bytes_.store(0);
audio_inbound_bytes_.store(0);
audio_outbound_bytes_.store(0);
data_inbound_bytes_.store(0);
data_outbound_bytes_.store(0);
video_rtp_pkt_loss_cnt_.store(0);
audio_rtp_pkt_loss_cnt_.store(0);
data_rtp_pkt_loss_cnt_.store(0);
if (io_report_callback_) {
NetTrafficStats net_traffic_stats;
net_traffic_stats.video_inbound_stats.bitrate = video_inbound_bitrate_;
net_traffic_stats.video_inbound_stats.rtp_packet_count =
video_inbound_rtp_pkt_cnt_;
video_inbound_rtp_pkt_cnt_.load();
net_traffic_stats.video_inbound_stats.loss_rate =
video_rtp_pkt_loss_rate_;
net_traffic_stats.video_outbound_stats.bitrate = video_outbound_bitrate_;
net_traffic_stats.video_outbound_stats.rtp_packet_count =
video_outbound_rtp_pkt_cnt_;
video_outbound_rtp_pkt_cnt_.load();
net_traffic_stats.audio_inbound_stats.bitrate = audio_inbound_bitrate_;
net_traffic_stats.audio_inbound_stats.rtp_packet_count =
audio_inbound_rtp_pkt_cnt_;
audio_inbound_rtp_pkt_cnt_.load();
net_traffic_stats.audio_inbound_stats.loss_rate =
audio_rtp_pkt_loss_rate_;
net_traffic_stats.audio_outbound_stats.bitrate = audio_outbound_bitrate_;
net_traffic_stats.audio_outbound_stats.rtp_packet_count =
audio_outbound_rtp_pkt_cnt_;
audio_outbound_rtp_pkt_cnt_.load();
net_traffic_stats.data_inbound_stats.bitrate = data_inbound_bitrate_;
net_traffic_stats.data_inbound_stats.rtp_packet_count =
data_inbound_rtp_pkt_cnt_;
data_inbound_rtp_pkt_cnt_.load();
net_traffic_stats.data_inbound_stats.loss_rate = data_rtp_pkt_loss_rate_;
net_traffic_stats.data_outbound_stats.bitrate = data_outbound_bitrate_;
net_traffic_stats.data_outbound_stats.rtp_packet_count =
data_outbound_rtp_pkt_cnt_;
data_outbound_rtp_pkt_cnt_.load();
net_traffic_stats.total_inbound_stats.bitrate = total_inbound_bitrate_;
net_traffic_stats.total_inbound_stats.loss_rate =
video_rtp_pkt_loss_rate_ + audio_rtp_pkt_loss_rate_ +
data_rtp_pkt_loss_rate_;
net_traffic_stats.total_inbound_stats.rtp_packet_count =
video_inbound_rtp_pkt_cnt_ + audio_inbound_rtp_pkt_cnt_ +
data_inbound_rtp_pkt_cnt_;
net_traffic_stats.video_inbound_stats.rtp_packet_count +
net_traffic_stats.audio_inbound_stats.rtp_packet_count +
net_traffic_stats.data_inbound_stats.rtp_packet_count;
net_traffic_stats.total_outbound_stats.bitrate = total_outbound_bitrate_;
net_traffic_stats.total_outbound_stats.rtp_packet_count =
video_outbound_rtp_pkt_cnt_ + audio_outbound_rtp_pkt_cnt_ +
data_outbound_rtp_pkt_cnt_;
net_traffic_stats.video_outbound_stats.rtp_packet_count +
net_traffic_stats.audio_outbound_stats.rtp_packet_count +
net_traffic_stats.data_outbound_stats.rtp_packet_count;
io_report_callback_(net_traffic_stats);
}
@@ -153,26 +163,21 @@ void IOStatistics::UpdateVideoOutboundBytes(uint32_t bytes) {
}
void IOStatistics::UpdateVideoPacketLossCount(uint16_t seq_num) {
if (last_received_video_rtp_pkt_seq_ != 0) {
if (last_received_video_rtp_pkt_seq_ < seq_num) {
if (seq_num - last_received_video_rtp_pkt_seq_ > 0x8000) {
expected_video_inbound_rtp_pkt_cnt_.fetch_add(
0xffff - last_received_video_rtp_pkt_seq_ + seq_num + 1,
std::memory_order_relaxed);
} else {
expected_video_inbound_rtp_pkt_cnt_.fetch_add(
seq_num - last_received_video_rtp_pkt_seq_,
std::memory_order_relaxed);
}
} else if (last_received_video_rtp_pkt_seq_ > seq_num) {
expected_video_inbound_rtp_pkt_cnt_.fetch_add(
0xffff - last_received_video_rtp_pkt_seq_ + seq_num + 1,
uint16_t last_v_seq = last_received_video_rtp_pkt_seq_.load();
if (last_v_seq != 0) {
if (seq_num > last_v_seq) {
if (seq_num - last_v_seq != 1) {
video_rtp_pkt_loss_cnt_.fetch_add(seq_num - last_v_seq - 1,
std::memory_order_relaxed);
}
} else {
expected_video_inbound_rtp_pkt_cnt_.fetch_add(1, std::memory_order_relaxed);
video_rtp_pkt_loss_cnt_.fetch_add(
seq_num + (std::numeric_limits<uint16_t>::max() - last_v_seq) - 1,
std::memory_order_relaxed);
}
last_received_video_rtp_pkt_seq_ = seq_num;
}
last_received_video_rtp_pkt_seq_.store(seq_num);
}
void IOStatistics::UpdateAudioInboundBytes(uint32_t bytes) {
@@ -184,24 +189,21 @@ void IOStatistics::UpdateAudioOutboundBytes(uint32_t bytes) {
}
void IOStatistics::UpdateAudioPacketLossCount(uint16_t seq_num) {
if (last_received_audio_rtp_pkt_seq_ != 0) {
if (last_received_audio_rtp_pkt_seq_ < seq_num) {
if (seq_num - last_received_audio_rtp_pkt_seq_ > 0x8000) {
expected_audio_inbound_rtp_pkt_cnt_.fetch_add(
0xffff - last_received_audio_rtp_pkt_seq_ + seq_num + 1,
uint16_t last_a_seq = last_received_audio_rtp_pkt_seq_.load();
if (last_a_seq != 0) {
if (seq_num > last_a_seq) {
if (seq_num - last_a_seq != 1) {
audio_rtp_pkt_loss_cnt_.fetch_add(seq_num - last_a_seq - 1,
std::memory_order_relaxed);
}
} else {
expected_audio_inbound_rtp_pkt_cnt_.fetch_add(
seq_num - last_received_audio_rtp_pkt_seq_,
std::memory_order_relaxed);
}
} else if (last_received_audio_rtp_pkt_seq_ > seq_num) {
expected_audio_inbound_rtp_pkt_cnt_.fetch_add(
0xffff - last_received_audio_rtp_pkt_seq_ + seq_num + 1,
audio_rtp_pkt_loss_cnt_.fetch_add(
seq_num + (std::numeric_limits<uint16_t>::max() - last_a_seq) - 1,
std::memory_order_relaxed);
}
}
last_received_audio_rtp_pkt_seq_ = seq_num;
last_received_audio_rtp_pkt_seq_.store(seq_num);
}
void IOStatistics::UpdateDataInboundBytes(uint32_t bytes) {
@@ -213,29 +215,25 @@ void IOStatistics::UpdateDataOutboundBytes(uint32_t bytes) {
}
void IOStatistics::UpdateDataPacketLossCount(uint16_t seq_num) {
if (last_received_data_rtp_pkt_seq_ != 0) {
if (last_received_data_rtp_pkt_seq_ < seq_num) {
if (seq_num - last_received_data_rtp_pkt_seq_ > 0x8000) {
expected_data_inbound_rtp_pkt_cnt_.fetch_add(
0xffff - last_received_data_rtp_pkt_seq_ + seq_num + 1,
uint16_t last_d_seq = last_received_data_rtp_pkt_seq_.load();
if (last_d_seq != 0) {
if (seq_num > last_d_seq) {
if (seq_num - last_d_seq != 1) {
data_rtp_pkt_loss_cnt_.fetch_add(seq_num - last_d_seq - 1,
std::memory_order_relaxed);
}
} else {
expected_data_inbound_rtp_pkt_cnt_.fetch_add(
seq_num - last_received_data_rtp_pkt_seq_,
std::memory_order_relaxed);
}
} else if (last_received_data_rtp_pkt_seq_ > seq_num) {
expected_data_inbound_rtp_pkt_cnt_.fetch_add(
0xffff - last_received_data_rtp_pkt_seq_ + seq_num + 1,
data_rtp_pkt_loss_cnt_.fetch_add(
seq_num + (std::numeric_limits<uint16_t>::max() - last_d_seq) - 1,
std::memory_order_relaxed);
}
}
last_received_data_rtp_pkt_seq_ = seq_num;
last_received_data_rtp_pkt_seq_.store(seq_num);
}
void IOStatistics::IncrementVideoInboundRtpPacketCount() {
++video_inbound_rtp_pkt_cnt_;
++video_inbound_rtp_pkt_cnt_tmp_;
}
void IOStatistics::IncrementVideoOutboundRtpPacketCount() {
@@ -244,7 +242,6 @@ void IOStatistics::IncrementVideoOutboundRtpPacketCount() {
void IOStatistics::IncrementAudioInboundRtpPacketCount() {
++audio_inbound_rtp_pkt_cnt_;
++audio_inbound_rtp_pkt_cnt_tmp_;
}
void IOStatistics::IncrementAudioOutboundRtpPacketCount() {
@@ -253,7 +250,6 @@ void IOStatistics::IncrementAudioOutboundRtpPacketCount() {
void IOStatistics::IncrementDataInboundRtpPacketCount() {
++data_inbound_rtp_pkt_cnt_;
++data_inbound_rtp_pkt_cnt_tmp_;
}
void IOStatistics::IncrementDataOutboundRtpPacketCount() {

View File

@@ -79,13 +79,22 @@ class IOStatistics {
std::atomic<uint32_t> video_inbound_bytes_ = 0;
std::atomic<uint32_t> video_outbound_bytes_ = 0;
uint16_t last_received_video_rtp_pkt_seq_ = 0;
std::atomic<uint16_t> last_received_video_rtp_pkt_seq_ = 0;
uint16_t current_period_last_received_video_rtp_pkt_seq_ = 0;
uint16_t previous_period_last_received_video_rtp_pkt_seq_ = 0;
uint16_t expected_video_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> audio_inbound_bytes_ = 0;
std::atomic<uint32_t> audio_outbound_bytes_ = 0;
uint16_t last_received_audio_rtp_pkt_seq_ = 0;
std::atomic<uint16_t> last_received_audio_rtp_pkt_seq_ = 0;
uint16_t current_period_last_received_audio_rtp_pkt_seq_ = 0;
uint16_t previous_period_last_received_audio_rtp_pkt_seq_ = 0;
uint16_t expected_audio_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> data_inbound_bytes_ = 0;
std::atomic<uint32_t> data_outbound_bytes_ = 0;
uint16_t last_received_data_rtp_pkt_seq_ = 0;
std::atomic<uint16_t> last_received_data_rtp_pkt_seq_ = 0;
uint16_t current_period_last_received_data_rtp_pkt_seq_ = 0;
uint16_t previous_period_last_received_data_rtp_pkt_seq_ = 0;
uint16_t expected_data_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> total_inbound_bytes_ = 0;
std::atomic<uint32_t> total_outbound_bytes_ = 0;
@@ -93,20 +102,13 @@ class IOStatistics {
std::atomic<uint32_t> audio_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> data_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> video_inbound_rtp_pkt_cnt_tmp_ = 0;
std::atomic<uint32_t> audio_inbound_rtp_pkt_cnt_tmp_ = 0;
std::atomic<uint32_t> data_inbound_rtp_pkt_cnt_tmp_ = 0;
std::atomic<uint32_t> data_outbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> video_outbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> audio_outbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> expected_video_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> expected_audio_inbound_rtp_pkt_cnt_ = 0;
std::atomic<uint32_t> expected_data_inbound_rtp_pkt_cnt_ = 0;
int32_t video_rtp_pkt_loss_cnt_ = 0;
int32_t audio_rtp_pkt_loss_cnt_ = 0;
int32_t data_rtp_pkt_loss_cnt_ = 0;
std::atomic<uint32_t> video_rtp_pkt_loss_cnt_ = 0;
std::atomic<uint32_t> audio_rtp_pkt_loss_cnt_ = 0;
std::atomic<uint32_t> data_rtp_pkt_loss_cnt_ = 0;
uint32_t video_inbound_bitrate_ = 0;
uint32_t video_outbound_bitrate_ = 0;