[feat] use the io statistics module to collect network information

This commit is contained in:
dijunkun
2024-11-29 17:53:30 +08:00
parent 11d84068a4
commit daef6f19dc
34 changed files with 405 additions and 102 deletions

View File

@@ -47,14 +47,25 @@ typedef struct {
} XVideoFrame; } XVideoFrame;
typedef struct { typedef struct {
uint64_t video_in; uint32_t bitrate;
uint64_t video_out; uint32_t rtp_packet_count;
uint64_t audio_in; float loss_rate;
uint64_t audio_out; } XInboundStats;
uint64_t data_in;
uint64_t data_out; typedef struct {
uint64_t total_in; uint32_t bitrate;
uint64_t total_out; uint32_t rtp_packet_count;
} XOutboundStats;
typedef struct {
XInboundStats video_inbound_stats;
XOutboundStats video_outbound_stats;
XInboundStats audio_inbound_stats;
XOutboundStats audio_outbound_stats;
XInboundStats data_inbound_stats;
XOutboundStats data_outbound_stats;
XInboundStats total_inbound_stats;
XOutboundStats total_outbound_stats;
} XNetTrafficStats; } XNetTrafficStats;
typedef struct Peer PeerPtr; typedef struct Peer PeerPtr;

View File

@@ -399,14 +399,7 @@ void PeerConnection::ProcessSignal(const std::string &signal) {
user_id_ = j["user_id"].get<std::string>(); user_id_ = j["user_id"].get<std::string>();
XNetTrafficStats net_traffic_stats; XNetTrafficStats net_traffic_stats;
net_traffic_stats.video_in = 0; memset(&net_traffic_stats, 0, sizeof(net_traffic_stats));
net_traffic_stats.video_out = 0;
net_traffic_stats.audio_in = 0;
net_traffic_stats.audio_out = 0;
net_traffic_stats.data_in = 0;
net_traffic_stats.data_out = 0;
net_traffic_stats.total_in = 0;
net_traffic_stats.total_out = 0;
net_status_report_(user_id_.data(), user_id_.size(), net_status_report_(user_id_.data(), user_id_.size(),
TraversalMode::UnknownMode, &net_traffic_stats, TraversalMode::UnknownMode, &net_traffic_stats,

View File

@@ -4,6 +4,9 @@
RtpAudioReceiver::RtpAudioReceiver() {} RtpAudioReceiver::RtpAudioReceiver() {}
RtpAudioReceiver::RtpAudioReceiver(std::shared_ptr<IOStatistics> io_statistics)
: io_statistics_(io_statistics) {}
RtpAudioReceiver::~RtpAudioReceiver() { RtpAudioReceiver::~RtpAudioReceiver() {
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->Stop(); rtp_statistics_->Stop();
@@ -16,8 +19,17 @@ void RtpAudioReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
rtp_statistics_->Start(); rtp_statistics_->Start();
} }
last_recv_bytes_ = (uint32_t)rtp_packet.Size();
total_rtp_payload_recv_ += (uint32_t)rtp_packet.PayloadSize();
total_rtp_packets_recv_++;
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->UpdateReceiveBytes((uint32_t)rtp_packet.Size()); rtp_statistics_->UpdateReceiveBytes(last_recv_bytes_);
}
if (io_statistics_) {
io_statistics_->UpdateAudioInboundBytes(last_recv_bytes_);
io_statistics_->IncrementAudioInboundRtpPacketCount();
} }
if (CheckIsTimeSendRR()) { if (CheckIsTimeSendRR()) {

View File

@@ -9,6 +9,7 @@
#include <functional> #include <functional>
#include "io_statistics.h"
#include "rtcp_receiver_report.h" #include "rtcp_receiver_report.h"
#include "rtp_codec.h" #include "rtp_codec.h"
#include "rtp_statistics.h" #include "rtp_statistics.h"
@@ -16,6 +17,7 @@
class RtpAudioReceiver { class RtpAudioReceiver {
public: public:
RtpAudioReceiver(); RtpAudioReceiver();
RtpAudioReceiver(std::shared_ptr<IOStatistics> io_statistics);
~RtpAudioReceiver(); ~RtpAudioReceiver();
public: public:
@@ -38,6 +40,10 @@ class RtpAudioReceiver {
private: private:
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr; std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
std::shared_ptr<IOStatistics> io_statistics_ = nullptr;
uint32_t last_recv_bytes_ = 0;
uint32_t total_rtp_payload_recv_ = 0;
uint32_t total_rtp_packets_recv_ = 0;
uint32_t last_send_rtcp_rr_packet_ts_ = 0; uint32_t last_send_rtcp_rr_packet_ts_ = 0;
std::function<int(const char*, size_t)> data_send_func_ = nullptr; std::function<int(const char*, size_t)> data_send_func_ = nullptr;
}; };

View File

@@ -8,6 +8,9 @@
RtpAudioSender::RtpAudioSender() {} RtpAudioSender::RtpAudioSender() {}
RtpAudioSender::RtpAudioSender(std::shared_ptr<IOStatistics> io_statistics)
: io_statistics_(io_statistics) {}
RtpAudioSender::~RtpAudioSender() { RtpAudioSender::~RtpAudioSender() {
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->Stop(); rtp_statistics_->Stop();
@@ -43,8 +46,13 @@ int RtpAudioSender::SendRtpPacket(RtpPacket& rtp_packet) {
} }
last_send_bytes_ += (uint32_t)rtp_packet.Size(); last_send_bytes_ += (uint32_t)rtp_packet.Size();
total_rtp_packets_sent_++;
total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize(); total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize();
total_rtp_packets_sent_++;
if (io_statistics_) {
io_statistics_->UpdateAudioOutboundBytes(last_send_bytes_);
io_statistics_->IncrementAudioOutboundRtpPacketCount();
}
if (CheckIsTimeSendSR()) { if (CheckIsTimeSendSR()) {
RtcpSenderReport rtcp_sr; RtcpSenderReport rtcp_sr;

View File

@@ -9,6 +9,7 @@
#include <functional> #include <functional>
#include "io_statistics.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "rtcp_sender_report.h" #include "rtcp_sender_report.h"
#include "rtp_packet.h" #include "rtp_packet.h"
@@ -18,6 +19,7 @@
class RtpAudioSender : public ThreadBase { class RtpAudioSender : public ThreadBase {
public: public:
RtpAudioSender(); RtpAudioSender();
RtpAudioSender(std::shared_ptr<IOStatistics> io_statistics);
virtual ~RtpAudioSender(); virtual ~RtpAudioSender();
public: public:
@@ -38,10 +40,11 @@ class RtpAudioSender : public ThreadBase {
std::function<int(const char *, size_t)> data_send_func_ = nullptr; std::function<int(const char *, size_t)> data_send_func_ = nullptr;
RingBuffer<RtpPacket> rtp_packe_queue_; RingBuffer<RtpPacket> rtp_packe_queue_;
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr; std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
std::shared_ptr<IOStatistics> io_statistics_ = nullptr;
uint32_t last_send_bytes_ = 0; uint32_t last_send_bytes_ = 0;
uint32_t last_send_rtcp_sr_packet_ts_ = 0;
uint32_t total_rtp_packets_sent_ = 0;
uint32_t total_rtp_payload_sent_ = 0; uint32_t total_rtp_payload_sent_ = 0;
uint32_t total_rtp_packets_sent_ = 0;
uint32_t last_send_rtcp_sr_packet_ts_ = 0;
}; };
#endif #endif

View File

@@ -4,6 +4,9 @@
RtpDataReceiver::RtpDataReceiver() {} RtpDataReceiver::RtpDataReceiver() {}
RtpDataReceiver::RtpDataReceiver(std::shared_ptr<IOStatistics> io_statistics)
: io_statistics_(io_statistics) {}
RtpDataReceiver::~RtpDataReceiver() { RtpDataReceiver::~RtpDataReceiver() {
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->Stop(); rtp_statistics_->Stop();
@@ -16,8 +19,17 @@ void RtpDataReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
rtp_statistics_->Start(); rtp_statistics_->Start();
} }
last_recv_bytes_ = (uint32_t)rtp_packet.Size();
total_rtp_payload_recv_ += (uint32_t)rtp_packet.PayloadSize();
total_rtp_packets_recv_++;
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->UpdateReceiveBytes((uint32_t)rtp_packet.Size()); rtp_statistics_->UpdateReceiveBytes(last_recv_bytes_);
}
if (io_statistics_) {
io_statistics_->UpdateDataInboundBytes(last_recv_bytes_);
io_statistics_->IncrementDataInboundRtpPacketCount();
} }
if (CheckIsTimeSendRR()) { if (CheckIsTimeSendRR()) {

View File

@@ -3,6 +3,7 @@
#include <functional> #include <functional>
#include "io_statistics.h"
#include "rtcp_receiver_report.h" #include "rtcp_receiver_report.h"
#include "rtp_codec.h" #include "rtp_codec.h"
#include "rtp_statistics.h" #include "rtp_statistics.h"
@@ -10,6 +11,7 @@
class RtpDataReceiver { class RtpDataReceiver {
public: public:
RtpDataReceiver(); RtpDataReceiver();
RtpDataReceiver(std::shared_ptr<IOStatistics> io_statistics);
~RtpDataReceiver(); ~RtpDataReceiver();
public: public:
@@ -32,6 +34,11 @@ class RtpDataReceiver {
private: private:
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr; std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
std::shared_ptr<IOStatistics> io_statistics_ = nullptr;
uint32_t last_recv_bytes_ = 0;
uint32_t total_rtp_payload_recv_ = 0;
uint32_t total_rtp_packets_recv_ = 0;
uint32_t last_send_rtcp_rr_packet_ts_ = 0; uint32_t last_send_rtcp_rr_packet_ts_ = 0;
std::function<int(const char*, size_t)> data_send_func_ = nullptr; std::function<int(const char*, size_t)> data_send_func_ = nullptr;
}; };

View File

@@ -8,6 +8,9 @@
RtpDataSender::RtpDataSender() {} RtpDataSender::RtpDataSender() {}
RtpDataSender::RtpDataSender(std::shared_ptr<IOStatistics> io_statistics)
: io_statistics_(io_statistics) {}
RtpDataSender::~RtpDataSender() { RtpDataSender::~RtpDataSender() {
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->Stop(); rtp_statistics_->Stop();
@@ -43,8 +46,13 @@ int RtpDataSender::SendRtpPacket(RtpPacket& rtp_packet) {
} }
last_send_bytes_ += (uint32_t)rtp_packet.Size(); last_send_bytes_ += (uint32_t)rtp_packet.Size();
total_rtp_packets_sent_++;
total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize(); total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize();
total_rtp_packets_sent_++;
if (io_statistics_) {
io_statistics_->UpdateDataOutboundBytes(last_send_bytes_);
io_statistics_->IncrementDataOutboundRtpPacketCount();
}
if (CheckIsTimeSendSR()) { if (CheckIsTimeSendSR()) {
RtcpSenderReport rtcp_sr; RtcpSenderReport rtcp_sr;

View File

@@ -9,6 +9,7 @@
#include <functional> #include <functional>
#include "io_statistics.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "rtcp_sender_report.h" #include "rtcp_sender_report.h"
#include "rtp_packet.h" #include "rtp_packet.h"
@@ -18,6 +19,7 @@
class RtpDataSender : public ThreadBase { class RtpDataSender : public ThreadBase {
public: public:
RtpDataSender(); RtpDataSender();
RtpDataSender(std::shared_ptr<IOStatistics> io_statistics);
virtual ~RtpDataSender(); virtual ~RtpDataSender();
public: public:
@@ -37,11 +39,14 @@ class RtpDataSender : public ThreadBase {
private: private:
std::function<int(const char *, size_t)> data_send_func_ = nullptr; std::function<int(const char *, size_t)> data_send_func_ = nullptr;
RingBuffer<RtpPacket> rtp_packe_queue_; RingBuffer<RtpPacket> rtp_packe_queue_;
private:
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr; std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
std::shared_ptr<IOStatistics> io_statistics_ = nullptr;
uint32_t last_send_bytes_ = 0; uint32_t last_send_bytes_ = 0;
uint32_t last_send_rtcp_sr_packet_ts_ = 0;
uint32_t total_rtp_packets_sent_ = 0;
uint32_t total_rtp_payload_sent_ = 0; uint32_t total_rtp_payload_sent_ = 0;
uint32_t total_rtp_packets_sent_ = 0;
uint32_t last_send_rtcp_sr_packet_ts_ = 0;
}; };
#endif #endif

View File

@@ -7,6 +7,9 @@
RtpVideoReceiver::RtpVideoReceiver() {} RtpVideoReceiver::RtpVideoReceiver() {}
RtpVideoReceiver::RtpVideoReceiver(std::shared_ptr<IOStatistics> io_statistics)
: io_statistics_(io_statistics) {}
RtpVideoReceiver::~RtpVideoReceiver() { RtpVideoReceiver::~RtpVideoReceiver() {
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->Stop(); rtp_statistics_->Stop();
@@ -19,8 +22,17 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) {
rtp_statistics_->Start(); rtp_statistics_->Start();
} }
last_recv_bytes_ = (uint32_t)rtp_packet.PayloadSize();
total_rtp_payload_recv_ += (uint32_t)rtp_packet.PayloadSize();
total_rtp_packets_recv_++;
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->UpdateReceiveBytes((uint32_t)rtp_packet.Size()); rtp_statistics_->UpdateReceiveBytes(last_recv_bytes_);
}
if (io_statistics_) {
io_statistics_->UpdateVideoInboundBytes(last_recv_bytes_);
io_statistics_->IncrementVideoInboundRtpPacketCount();
} }
if (CheckIsTimeSendRR()) { if (CheckIsTimeSendRR()) {

View File

@@ -7,6 +7,7 @@
#include <set> #include <set>
#include "fec_decoder.h" #include "fec_decoder.h"
#include "io_statistics.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "rtcp_receiver_report.h" #include "rtcp_receiver_report.h"
#include "rtp_codec.h" #include "rtp_codec.h"
@@ -17,6 +18,7 @@
class RtpVideoReceiver : public ThreadBase { class RtpVideoReceiver : public ThreadBase {
public: public:
RtpVideoReceiver(); RtpVideoReceiver();
RtpVideoReceiver(std::shared_ptr<IOStatistics> io_statistics);
virtual ~RtpVideoReceiver(); virtual ~RtpVideoReceiver();
public: public:
@@ -53,6 +55,11 @@ class RtpVideoReceiver : public ThreadBase {
private: private:
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr; std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
std::shared_ptr<IOStatistics> io_statistics_ = nullptr;
uint32_t last_recv_bytes_ = 0;
uint32_t total_rtp_packets_recv_ = 0;
uint32_t total_rtp_payload_recv_ = 0;
uint32_t last_send_rtcp_rr_packet_ts_ = 0; uint32_t last_send_rtcp_rr_packet_ts_ = 0;
std::function<int(const char*, size_t)> data_send_func_ = nullptr; std::function<int(const char*, size_t)> data_send_func_ = nullptr;

View File

@@ -8,6 +8,9 @@
RtpVideoSender::RtpVideoSender() {} RtpVideoSender::RtpVideoSender() {}
RtpVideoSender::RtpVideoSender(std::shared_ptr<IOStatistics> io_statistics)
: io_statistics_(io_statistics) {}
RtpVideoSender::~RtpVideoSender() { RtpVideoSender::~RtpVideoSender() {
if (rtp_statistics_) { if (rtp_statistics_) {
rtp_statistics_->Stop(); rtp_statistics_->Stop();
@@ -43,8 +46,13 @@ int RtpVideoSender::SendRtpPacket(RtpPacket& rtp_packet) {
} }
last_send_bytes_ += (uint32_t)rtp_packet.Size(); last_send_bytes_ += (uint32_t)rtp_packet.Size();
total_rtp_packets_sent_++;
total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize(); total_rtp_payload_sent_ += (uint32_t)rtp_packet.PayloadSize();
total_rtp_packets_sent_++;
if (io_statistics_) {
io_statistics_->UpdateVideoOutboundBytes(last_send_bytes_);
io_statistics_->IncrementVideoOutboundRtpPacketCount();
}
if (CheckIsTimeSendSR()) { if (CheckIsTimeSendSR()) {
RtcpSenderReport rtcp_sr; RtcpSenderReport rtcp_sr;

View File

@@ -3,6 +3,7 @@
#include <functional> #include <functional>
#include "io_statistics.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "rtcp_sender_report.h" #include "rtcp_sender_report.h"
#include "rtp_packet.h" #include "rtp_packet.h"
@@ -12,6 +13,7 @@
class RtpVideoSender : public ThreadBase { class RtpVideoSender : public ThreadBase {
public: public:
RtpVideoSender(); RtpVideoSender();
RtpVideoSender(std::shared_ptr<IOStatistics> io_statistics);
virtual ~RtpVideoSender(); virtual ~RtpVideoSender();
public: public:
@@ -33,10 +35,11 @@ class RtpVideoSender : public ThreadBase {
private: private:
std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr; std::unique_ptr<RtpStatistics> rtp_statistics_ = nullptr;
std::shared_ptr<IOStatistics> io_statistics_ = nullptr;
uint32_t last_send_bytes_ = 0; uint32_t last_send_bytes_ = 0;
uint32_t last_send_rtcp_sr_packet_ts_ = 0; uint32_t last_send_rtcp_sr_packet_ts_ = 0;
uint32_t total_rtp_packets_sent_ = 0;
uint32_t total_rtp_payload_sent_ = 0; uint32_t total_rtp_payload_sent_ = 0;
uint32_t total_rtp_packets_sent_ = 0;
}; };
#endif #endif

View File

@@ -14,6 +14,22 @@ void RtpStatistics::UpdateReceiveBytes(uint32_t received_bytes) {
received_bytes_ += received_bytes; received_bytes_ += received_bytes;
} }
void RtpStatistics::UpdatePacketLossRate(uint16_t seq_num) {
if (last_received_seq_num_ != 0) {
if (last_received_seq_num_ < seq_num) {
// seq wrap
if (seq_num - last_received_seq_num_ > 0x8000) {
lost_packets_num_ += 0xffff - last_received_seq_num_ + seq_num + 1;
} else {
lost_packets_num_ += seq_num - last_received_seq_num_ - 1;
}
} else if (last_received_seq_num_ > seq_num) {
lost_packets_num_ += 0xffff - last_received_seq_num_ + seq_num + 1;
}
}
last_received_seq_num_ = seq_num;
}
bool RtpStatistics::Process() { bool RtpStatistics::Process() {
if (!sent_bytes_) { if (!sent_bytes_) {
// LOG_INFO("rtp statistics: Send [{} bps]", sent_bytes_); // LOG_INFO("rtp statistics: Send [{} bps]", sent_bytes_);

View File

@@ -9,8 +9,12 @@ class RtpStatistics : public ThreadBase {
virtual ~RtpStatistics(); virtual ~RtpStatistics();
public: public:
// send side
void UpdateSentBytes(uint32_t sent_bytes); void UpdateSentBytes(uint32_t sent_bytes);
// receive side
void UpdateReceiveBytes(uint32_t received_bytes); void UpdateReceiveBytes(uint32_t received_bytes);
void UpdatePacketLossRate(uint16_t seq_num);
private: private:
bool Process(); bool Process();
@@ -18,6 +22,8 @@ class RtpStatistics : public ThreadBase {
private: private:
uint32_t sent_bytes_ = 0; uint32_t sent_bytes_ = 0;
uint32_t received_bytes_ = 0; uint32_t received_bytes_ = 0;
uint16_t last_received_seq_num_ = 0;
uint32_t lost_packets_num_ = 0;
}; };
#endif #endif

View File

@@ -1,5 +0,0 @@
#include "rtp_transceiver.h"
RtpTransceiver::RtpTransceiver() {}
RtpTransceiver::~RtpTransceiver() {}

View File

@@ -1,19 +0,0 @@
#ifndef _RTP_TRANSCEIVER_H_
#define _RTP_TRANSCEIVER_H_
#include <cstddef>
#include <functional>
class RtpTransceiver {
public:
RtpTransceiver();
~RtpTransceiver();
public:
virtual void SetSendDataFunc(
std::function<int(const char *, size_t)> data_send_func) = 0;
virtual void OnReceiveData(const char *data, size_t size) = 0;
};
#endif

View File

@@ -3,9 +3,7 @@
#include "log.h" #include "log.h"
IOStatistics::IOStatistics( IOStatistics::IOStatistics(
std::function<void(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, std::function<void(const NetTrafficStats&)> io_report_callback)
uint32_t, uint32_t, uint32_t)>
io_report_callback)
: io_report_callback_(io_report_callback) { : io_report_callback_(io_report_callback) {
interval_ = 1000; interval_ = 1000;
} }
@@ -36,11 +34,95 @@ void IOStatistics::Process() {
data_inbound_bytes_ = 0; data_inbound_bytes_ = 0;
data_outbound_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_ /
(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_;
} 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_;
} 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;
}
if (io_report_callback_) { if (io_report_callback_) {
io_report_callback_(video_inbound_bitrate_, video_outbound_bitrate_, NetTrafficStats net_traffic_stats;
audio_inbound_bitrate_, audio_outbound_bitrate_, net_traffic_stats.video_inbound_stats.bitrate = video_inbound_bitrate_;
data_inbound_bitrate_, data_outbound_bitrate_, net_traffic_stats.video_inbound_stats.rtp_packet_count =
total_inbound_bitrate_, total_outbound_bitrate_); video_inbound_rtp_pkt_cnt_;
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_;
net_traffic_stats.audio_inbound_stats.bitrate = audio_inbound_bitrate_;
net_traffic_stats.audio_inbound_stats.rtp_packet_count =
audio_inbound_rtp_pkt_cnt_;
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_;
net_traffic_stats.data_inbound_stats.bitrate = data_inbound_bitrate_;
net_traffic_stats.data_inbound_stats.rtp_packet_count =
data_inbound_rtp_pkt_cnt_;
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_;
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.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_;
io_report_callback_(net_traffic_stats);
} }
} }
} }
@@ -68,6 +150,24 @@ void IOStatistics::UpdateVideoOutboundBytes(uint32_t bytes) {
video_outbound_bytes_ += bytes; video_outbound_bytes_ += 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_ +=
0xffff - last_received_video_rtp_pkt_seq_ + seq_num + 1;
} else {
expected_video_inbound_rtp_pkt_cnt_ +=
seq_num - last_received_video_rtp_pkt_seq_ - 1;
}
} else if (last_received_video_rtp_pkt_seq_ > seq_num) {
expected_video_inbound_rtp_pkt_cnt_ +=
0xffff - last_received_video_rtp_pkt_seq_ + seq_num + 1;
}
}
last_received_video_rtp_pkt_seq_ = seq_num;
}
void IOStatistics::UpdateAudioInboundBytes(uint32_t bytes) { void IOStatistics::UpdateAudioInboundBytes(uint32_t bytes) {
audio_inbound_bytes_ += bytes; audio_inbound_bytes_ += bytes;
} }
@@ -76,6 +176,24 @@ void IOStatistics::UpdateAudioOutboundBytes(uint32_t bytes) {
audio_outbound_bytes_ += bytes; audio_outbound_bytes_ += 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_ +=
0xffff - last_received_audio_rtp_pkt_seq_ + seq_num + 1;
} else {
expected_audio_inbound_rtp_pkt_cnt_ +=
seq_num - last_received_audio_rtp_pkt_seq_ - 1;
}
} else if (last_received_audio_rtp_pkt_seq_ > seq_num) {
expected_audio_inbound_rtp_pkt_cnt_ +=
0xffff - last_received_audio_rtp_pkt_seq_ + seq_num + 1;
}
}
last_received_audio_rtp_pkt_seq_ = seq_num;
}
void IOStatistics::UpdateDataInboundBytes(uint32_t bytes) { void IOStatistics::UpdateDataInboundBytes(uint32_t bytes) {
data_inbound_bytes_ += bytes; data_inbound_bytes_ += bytes;
} }
@@ -83,3 +201,48 @@ void IOStatistics::UpdateDataInboundBytes(uint32_t bytes) {
void IOStatistics::UpdateDataOutboundBytes(uint32_t bytes) { void IOStatistics::UpdateDataOutboundBytes(uint32_t bytes) {
data_outbound_bytes_ += bytes; data_outbound_bytes_ += 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_ +=
0xffff - last_received_data_rtp_pkt_seq_ + seq_num + 1;
} else {
expected_data_inbound_rtp_pkt_cnt_ +=
seq_num - last_received_data_rtp_pkt_seq_ - 1;
}
} else if (last_received_data_rtp_pkt_seq_ > seq_num) {
expected_data_inbound_rtp_pkt_cnt_ +=
0xffff - last_received_data_rtp_pkt_seq_ + seq_num + 1;
}
}
last_received_data_rtp_pkt_seq_ = seq_num;
}
void IOStatistics::IncrementVideoInboundRtpPacketCount() {
video_inbound_rtp_pkt_cnt_++;
video_inbound_rtp_pkt_cnt_tmp_++;
}
void IOStatistics::IncrementVideoOutboundRtpPacketCount() {
video_outbound_rtp_pkt_cnt_++;
}
void IOStatistics::IncrementAudioInboundRtpPacketCount() {
audio_inbound_rtp_pkt_cnt_++;
audio_inbound_rtp_pkt_cnt_tmp_++;
}
void IOStatistics::IncrementAudioOutboundRtpPacketCount() {
audio_outbound_rtp_pkt_cnt_++;
}
void IOStatistics::IncrementDataInboundRtpPacketCount() {
data_inbound_rtp_pkt_cnt_++;
data_inbound_rtp_pkt_cnt_tmp_++;
}
void IOStatistics::IncrementDataOutboundRtpPacketCount() {
data_outbound_rtp_pkt_cnt_++;
}

View File

@@ -15,9 +15,30 @@
class IOStatistics { class IOStatistics {
public: public:
IOStatistics(std::function<void(uint32_t, uint32_t, uint32_t, uint32_t, typedef struct {
uint32_t, uint32_t, uint32_t, uint32_t)> uint32_t bitrate;
io_report_callback); uint32_t rtp_packet_count;
float loss_rate;
} InboundStats;
typedef struct {
uint32_t bitrate;
uint32_t rtp_packet_count;
} OutboundStats;
typedef struct {
InboundStats video_inbound_stats;
OutboundStats video_outbound_stats;
InboundStats audio_inbound_stats;
OutboundStats audio_outbound_stats;
InboundStats data_inbound_stats;
OutboundStats data_outbound_stats;
InboundStats total_inbound_stats;
OutboundStats total_outbound_stats;
} NetTrafficStats;
public:
IOStatistics(std::function<void(const NetTrafficStats&)> io_report_callback);
~IOStatistics(); ~IOStatistics();
public: public:
@@ -26,20 +47,30 @@ class IOStatistics {
void UpdateVideoInboundBytes(uint32_t bytes); void UpdateVideoInboundBytes(uint32_t bytes);
void UpdateVideoOutboundBytes(uint32_t bytes); void UpdateVideoOutboundBytes(uint32_t bytes);
void UpdateVideoPacketLossCount(uint16_t seq_num);
void UpdateAudioInboundBytes(uint32_t bytes); void UpdateAudioInboundBytes(uint32_t bytes);
void UpdateAudioOutboundBytes(uint32_t bytes); void UpdateAudioOutboundBytes(uint32_t bytes);
void UpdateAudioPacketLossCount(uint16_t seq_num);
void UpdateDataInboundBytes(uint32_t bytes); void UpdateDataInboundBytes(uint32_t bytes);
void UpdateDataOutboundBytes(uint32_t bytes); void UpdateDataOutboundBytes(uint32_t bytes);
void UpdateDataPacketLossCount(uint16_t seq_num);
void IncrementVideoInboundRtpPacketCount();
void IncrementVideoOutboundRtpPacketCount();
void IncrementAudioInboundRtpPacketCount();
void IncrementAudioOutboundRtpPacketCount();
void IncrementDataInboundRtpPacketCount();
void IncrementDataOutboundRtpPacketCount();
private: private:
void Process(); void Process();
private: private:
std::function<void(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, std::function<void(const NetTrafficStats&)> io_report_callback_ = nullptr;
uint32_t, uint32_t)>
io_report_callback_ = nullptr;
std::thread statistics_thread_; std::thread statistics_thread_;
std::mutex mtx_; std::mutex mtx_;
uint32_t interval_ = 1000; uint32_t interval_ = 1000;
@@ -48,13 +79,35 @@ class IOStatistics {
std::atomic<uint32_t> video_inbound_bytes_ = 0; std::atomic<uint32_t> video_inbound_bytes_ = 0;
std::atomic<uint32_t> video_outbound_bytes_ = 0; std::atomic<uint32_t> video_outbound_bytes_ = 0;
std::atomic<uint16_t> last_received_video_rtp_pkt_seq_ = 0;
std::atomic<uint32_t> audio_inbound_bytes_ = 0; std::atomic<uint32_t> audio_inbound_bytes_ = 0;
std::atomic<uint32_t> audio_outbound_bytes_ = 0; std::atomic<uint32_t> audio_outbound_bytes_ = 0;
std::atomic<uint16_t> last_received_audio_rtp_pkt_seq_ = 0;
std::atomic<uint32_t> data_inbound_bytes_ = 0; std::atomic<uint32_t> data_inbound_bytes_ = 0;
std::atomic<uint32_t> data_outbound_bytes_ = 0; std::atomic<uint32_t> data_outbound_bytes_ = 0;
std::atomic<uint16_t> last_received_data_rtp_pkt_seq_ = 0;
std::atomic<uint32_t> total_inbound_bytes_ = 0; std::atomic<uint32_t> total_inbound_bytes_ = 0;
std::atomic<uint32_t> total_outbound_bytes_ = 0; std::atomic<uint32_t> total_outbound_bytes_ = 0;
std::atomic<uint32_t> video_inbound_rtp_pkt_cnt_ = 0;
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;
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;
std::atomic<uint32_t> video_inbound_bitrate_ = 0; std::atomic<uint32_t> video_inbound_bitrate_ = 0;
std::atomic<uint32_t> video_outbound_bitrate_ = 0; std::atomic<uint32_t> video_outbound_bitrate_ = 0;
std::atomic<uint32_t> audio_inbound_bitrate_ = 0; std::atomic<uint32_t> audio_inbound_bitrate_ = 0;
@@ -63,6 +116,10 @@ class IOStatistics {
std::atomic<uint32_t> data_outbound_bitrate_ = 0; std::atomic<uint32_t> data_outbound_bitrate_ = 0;
std::atomic<uint32_t> total_inbound_bitrate_ = 0; std::atomic<uint32_t> total_inbound_bitrate_ = 0;
std::atomic<uint32_t> total_outbound_bitrate_ = 0; std::atomic<uint32_t> total_outbound_bitrate_ = 0;
float video_rtp_pkt_loss_rate_ = 0;
float audio_rtp_pkt_loss_rate_ = 0;
float data_rtp_pkt_loss_rate_ = 0;
}; };
#endif #endif

View File

@@ -61,30 +61,21 @@ int IceTransmission::InitIceTransmission(
std::string &turn_username, std::string &turn_password, std::string &turn_username, std::string &turn_password,
RtpPacket::PAYLOAD_TYPE video_codec_payload_type) { RtpPacket::PAYLOAD_TYPE video_codec_payload_type) {
ice_io_statistics_ = std::make_unique<IOStatistics>( ice_io_statistics_ = std::make_unique<IOStatistics>(
[this](uint32_t video_inbound_bitrate, uint32_t video_outbound_bitrate, [this](const IOStatistics::NetTrafficStats &net_traffic_stats) {
uint32_t audio_inbound_bitrate, uint32_t audio_outbound_bitrate,
uint32_t data_inbound_bitrate, uint32_t data_outbound_bitrate,
uint32_t total_inbound_bitrate, uint32_t total_outbound_bitrate) {
if (on_receive_net_status_report_) { if (on_receive_net_status_report_) {
XNetTrafficStats net_traffic_stats; XNetTrafficStats xnet_traffic_stats;
net_traffic_stats.video_in = video_inbound_bitrate;
net_traffic_stats.video_out = video_outbound_bitrate;
net_traffic_stats.audio_in = audio_inbound_bitrate;
net_traffic_stats.audio_out = audio_outbound_bitrate;
net_traffic_stats.data_in = data_inbound_bitrate;
net_traffic_stats.data_out = data_outbound_bitrate;
net_traffic_stats.total_in = total_inbound_bitrate;
net_traffic_stats.total_out = total_outbound_bitrate;
memcpy(&xnet_traffic_stats, &net_traffic_stats,
sizeof(XNetTrafficStats));
on_receive_net_status_report_(user_id_.data(), user_id_.size(), on_receive_net_status_report_(user_id_.data(), user_id_.size(),
TraversalMode(traversal_type_), TraversalMode(traversal_type_),
&net_traffic_stats, user_data_); &xnet_traffic_stats, user_data_);
} }
}); });
video_codec_payload_type_ = video_codec_payload_type; video_codec_payload_type_ = video_codec_payload_type;
rtp_video_receiver_ = std::make_unique<RtpVideoReceiver>(); rtp_video_receiver_ = std::make_unique<RtpVideoReceiver>(ice_io_statistics_);
// rr sender // rr sender
rtp_video_receiver_->SetSendDataFunc( rtp_video_receiver_->SetSendDataFunc(
[this](const char *data, size_t size) -> int { [this](const char *data, size_t size) -> int {
@@ -123,7 +114,7 @@ int IceTransmission::InitIceTransmission(
rtp_video_receiver_->Start(); rtp_video_receiver_->Start();
rtp_video_sender_ = std::make_unique<RtpVideoSender>(); rtp_video_sender_ = std::make_unique<RtpVideoSender>(ice_io_statistics_);
rtp_video_sender_->SetSendDataFunc( rtp_video_sender_->SetSendDataFunc(
[this](const char *data, size_t size) -> int { [this](const char *data, size_t size) -> int {
if (!ice_agent_) { if (!ice_agent_) {
@@ -144,7 +135,7 @@ int IceTransmission::InitIceTransmission(
rtp_video_sender_->Start(); rtp_video_sender_->Start();
rtp_audio_receiver_ = std::make_unique<RtpAudioReceiver>(); rtp_audio_receiver_ = std::make_unique<RtpAudioReceiver>(ice_io_statistics_);
// rr sender // rr sender
rtp_audio_receiver_->SetSendDataFunc( rtp_audio_receiver_->SetSendDataFunc(
[this](const char *data, size_t size) -> int { [this](const char *data, size_t size) -> int {
@@ -175,7 +166,7 @@ int IceTransmission::InitIceTransmission(
}); });
}); });
rtp_audio_sender_ = std::make_unique<RtpAudioSender>(); rtp_audio_sender_ = std::make_unique<RtpAudioSender>(ice_io_statistics_);
rtp_audio_sender_->SetSendDataFunc( rtp_audio_sender_->SetSendDataFunc(
[this](const char *data, size_t size) -> int { [this](const char *data, size_t size) -> int {
if (!ice_agent_) { if (!ice_agent_) {
@@ -196,7 +187,7 @@ int IceTransmission::InitIceTransmission(
rtp_audio_sender_->Start(); rtp_audio_sender_->Start();
rtp_data_receiver_ = std::make_unique<RtpDataReceiver>(); rtp_data_receiver_ = std::make_unique<RtpDataReceiver>(ice_io_statistics_);
// rr sender // rr sender
rtp_data_receiver_->SetSendDataFunc( rtp_data_receiver_->SetSendDataFunc(
[this](const char *data, size_t size) -> int { [this](const char *data, size_t size) -> int {
@@ -224,7 +215,7 @@ int IceTransmission::InitIceTransmission(
} }
}); });
rtp_data_sender_ = std::make_unique<RtpDataSender>(); rtp_data_sender_ = std::make_unique<RtpDataSender>(ice_io_statistics_);
rtp_data_sender_->SetSendDataFunc( rtp_data_sender_->SetSendDataFunc(
[this](const char *data, size_t size) -> int { [this](const char *data, size_t size) -> int {
if (!ice_agent_) { if (!ice_agent_) {
@@ -349,14 +340,7 @@ int IceTransmission::InitIceTransmission(
ice_transmission_obj->traversal_type_ = TraversalType::TP2P; ice_transmission_obj->traversal_type_ = TraversalType::TP2P;
} }
XNetTrafficStats net_traffic_stats; XNetTrafficStats net_traffic_stats;
net_traffic_stats.video_in = 0; memset(&net_traffic_stats, 0, sizeof(net_traffic_stats));
net_traffic_stats.video_out = 0;
net_traffic_stats.audio_in = 0;
net_traffic_stats.audio_out = 0;
net_traffic_stats.data_in = 0;
net_traffic_stats.data_out = 0;
net_traffic_stats.total_in = 0;
net_traffic_stats.total_out = 0;
ice_transmission_obj->on_receive_net_status_report_( ice_transmission_obj->on_receive_net_status_report_(
ice_transmission_obj->user_id_.data(), ice_transmission_obj->user_id_.data(),

View File

@@ -182,6 +182,7 @@ class IceTransmission {
std::unique_ptr<RtpCodec> video_rtp_codec_ = nullptr; std::unique_ptr<RtpCodec> video_rtp_codec_ = nullptr;
std::unique_ptr<RtpCodec> audio_rtp_codec_ = nullptr; std::unique_ptr<RtpCodec> audio_rtp_codec_ = nullptr;
std::unique_ptr<RtpCodec> data_rtp_codec_ = nullptr; std::unique_ptr<RtpCodec> data_rtp_codec_ = nullptr;
std::unique_ptr<RtpVideoReceiver> rtp_video_receiver_ = nullptr; std::unique_ptr<RtpVideoReceiver> rtp_video_receiver_ = nullptr;
std::unique_ptr<RtpVideoSender> rtp_video_sender_ = nullptr; std::unique_ptr<RtpVideoSender> rtp_video_sender_ = nullptr;
std::unique_ptr<RtpAudioReceiver> rtp_audio_receiver_ = nullptr; std::unique_ptr<RtpAudioReceiver> rtp_audio_receiver_ = nullptr;
@@ -194,7 +195,7 @@ class IceTransmission {
uint32_t last_complete_frame_ts_ = 0; uint32_t last_complete_frame_ts_ = 0;
private: private:
std::unique_ptr<IOStatistics> ice_io_statistics_ = nullptr; std::shared_ptr<IOStatistics> ice_io_statistics_ = nullptr;
private: private:
RtpPacket::PAYLOAD_TYPE video_codec_payload_type_; RtpPacket::PAYLOAD_TYPE video_codec_payload_type_;

View File

@@ -22,7 +22,7 @@ includes("thirdparty")
if is_os("windows") then if is_os("windows") then
add_defines("_WEBSOCKETPP_CPP11_INTERNAL_") add_defines("_WEBSOCKETPP_CPP11_INTERNAL_")
add_cxflags("/W4", "/WX") add_cxflags("/WX")
elseif is_os("linux") then elseif is_os("linux") then
add_requires("glib", {system = true}) add_requires("glib", {system = true})
add_packages("glib") add_packages("glib")
@@ -70,6 +70,12 @@ target("fec")
add_files("src/fec/*.cpp") add_files("src/fec/*.cpp")
add_includedirs("src/fec", {public = true}) add_includedirs("src/fec", {public = true})
target("statistics")
set_kind("object")
add_deps("log")
add_files("src/statistics/*.cpp")
add_includedirs("src/statistics", {public = true})
target("rtcp") target("rtcp")
set_kind("object") set_kind("object")
add_deps("log") add_deps("log")
@@ -78,9 +84,13 @@ target("rtcp")
target("rtp") target("rtp")
set_kind("object") set_kind("object")
add_deps("log", "frame", "ringbuffer", "thread", "rtcp", "fec") add_deps("log", "frame", "ringbuffer", "thread", "rtcp", "fec", "statistics")
add_files("src/rtp/*.cpp") add_files("src/rtp/*.cpp",
add_includedirs("src/rtp", {public = true}) "src/rtp/rtp_endpoint/*.cpp",
"src/rtp/rtp_packet/*.cpp")
add_includedirs("src/rtp",
"src/rtp/rtp_endpoint",
"src/rtp/rtp_packet", {public = true})
target("ice") target("ice")
set_kind("object") set_kind("object")
@@ -178,11 +188,6 @@ target("qos")
add_files("src/qos/*.cpp") add_files("src/qos/*.cpp")
add_includedirs("src/qos", {public = true}) add_includedirs("src/qos", {public = true})
target("statistics")
set_kind("object")
add_deps("log")
add_files("src/statistics/*.cpp")
add_includedirs("src/statistics", {public = true})
target("transmission") target("transmission")
set_kind("object") set_kind("object")