diff --git a/src/interface/x.h b/src/interface/x.h index ad27494..3b479b9 100644 --- a/src/interface/x.h +++ b/src/interface/x.h @@ -47,14 +47,25 @@ typedef struct { } XVideoFrame; typedef struct { - uint64_t video_in; - uint64_t video_out; - uint64_t audio_in; - uint64_t audio_out; - uint64_t data_in; - uint64_t data_out; - uint64_t total_in; - uint64_t total_out; + uint32_t bitrate; + uint32_t rtp_packet_count; + float loss_rate; +} XInboundStats; + +typedef struct { + uint32_t bitrate; + 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; typedef struct Peer PeerPtr; diff --git a/src/pc/peer_connection.cpp b/src/pc/peer_connection.cpp index c2dc0cc..cf92f53 100644 --- a/src/pc/peer_connection.cpp +++ b/src/pc/peer_connection.cpp @@ -399,14 +399,7 @@ void PeerConnection::ProcessSignal(const std::string &signal) { user_id_ = j["user_id"].get(); XNetTrafficStats net_traffic_stats; - net_traffic_stats.video_in = 0; - 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; + memset(&net_traffic_stats, 0, sizeof(net_traffic_stats)); net_status_report_(user_id_.data(), user_id_.size(), TraversalMode::UnknownMode, &net_traffic_stats, diff --git a/src/rtp/rtp_audio_receiver.cpp b/src/rtp/rtp_endpoint/rtp_audio_receiver.cpp similarity index 82% rename from src/rtp/rtp_audio_receiver.cpp rename to src/rtp/rtp_endpoint/rtp_audio_receiver.cpp index 0c2b222..da62da7 100644 --- a/src/rtp/rtp_audio_receiver.cpp +++ b/src/rtp/rtp_endpoint/rtp_audio_receiver.cpp @@ -4,6 +4,9 @@ RtpAudioReceiver::RtpAudioReceiver() {} +RtpAudioReceiver::RtpAudioReceiver(std::shared_ptr io_statistics) + : io_statistics_(io_statistics) {} + RtpAudioReceiver::~RtpAudioReceiver() { if (rtp_statistics_) { rtp_statistics_->Stop(); @@ -16,8 +19,17 @@ void RtpAudioReceiver::InsertRtpPacket(RtpPacket& rtp_packet) { 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_) { - 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()) { diff --git a/src/rtp/rtp_audio_receiver.h b/src/rtp/rtp_endpoint/rtp_audio_receiver.h similarity index 79% rename from src/rtp/rtp_audio_receiver.h rename to src/rtp/rtp_endpoint/rtp_audio_receiver.h index 28afe89..3167f6a 100644 --- a/src/rtp/rtp_audio_receiver.h +++ b/src/rtp/rtp_endpoint/rtp_audio_receiver.h @@ -9,6 +9,7 @@ #include +#include "io_statistics.h" #include "rtcp_receiver_report.h" #include "rtp_codec.h" #include "rtp_statistics.h" @@ -16,6 +17,7 @@ class RtpAudioReceiver { public: RtpAudioReceiver(); + RtpAudioReceiver(std::shared_ptr io_statistics); ~RtpAudioReceiver(); public: @@ -38,6 +40,10 @@ class RtpAudioReceiver { private: std::unique_ptr rtp_statistics_ = nullptr; + std::shared_ptr 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; std::function data_send_func_ = nullptr; }; diff --git a/src/rtp/rtp_audio_sender.cpp b/src/rtp/rtp_endpoint/rtp_audio_sender.cpp similarity index 92% rename from src/rtp/rtp_audio_sender.cpp rename to src/rtp/rtp_endpoint/rtp_audio_sender.cpp index 9abffaf..2e37954 100644 --- a/src/rtp/rtp_audio_sender.cpp +++ b/src/rtp/rtp_endpoint/rtp_audio_sender.cpp @@ -8,6 +8,9 @@ RtpAudioSender::RtpAudioSender() {} +RtpAudioSender::RtpAudioSender(std::shared_ptr io_statistics) + : io_statistics_(io_statistics) {} + RtpAudioSender::~RtpAudioSender() { if (rtp_statistics_) { rtp_statistics_->Stop(); @@ -43,8 +46,13 @@ int RtpAudioSender::SendRtpPacket(RtpPacket& rtp_packet) { } last_send_bytes_ += (uint32_t)rtp_packet.Size(); - total_rtp_packets_sent_++; 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()) { RtcpSenderReport rtcp_sr; diff --git a/src/rtp/rtp_audio_sender.h b/src/rtp/rtp_endpoint/rtp_audio_sender.h similarity index 87% rename from src/rtp/rtp_audio_sender.h rename to src/rtp/rtp_endpoint/rtp_audio_sender.h index 3f58868..7d624d6 100644 --- a/src/rtp/rtp_audio_sender.h +++ b/src/rtp/rtp_endpoint/rtp_audio_sender.h @@ -9,6 +9,7 @@ #include +#include "io_statistics.h" #include "ringbuffer.h" #include "rtcp_sender_report.h" #include "rtp_packet.h" @@ -18,6 +19,7 @@ class RtpAudioSender : public ThreadBase { public: RtpAudioSender(); + RtpAudioSender(std::shared_ptr io_statistics); virtual ~RtpAudioSender(); public: @@ -38,10 +40,11 @@ class RtpAudioSender : public ThreadBase { std::function data_send_func_ = nullptr; RingBuffer rtp_packe_queue_; std::unique_ptr rtp_statistics_ = nullptr; + std::shared_ptr io_statistics_ = nullptr; 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_packets_sent_ = 0; + uint32_t last_send_rtcp_sr_packet_ts_ = 0; }; #endif \ No newline at end of file diff --git a/src/rtp/rtp_data_receiver.cpp b/src/rtp/rtp_endpoint/rtp_data_receiver.cpp similarity index 82% rename from src/rtp/rtp_data_receiver.cpp rename to src/rtp/rtp_endpoint/rtp_data_receiver.cpp index c1de99c..fe99e67 100644 --- a/src/rtp/rtp_data_receiver.cpp +++ b/src/rtp/rtp_endpoint/rtp_data_receiver.cpp @@ -4,6 +4,9 @@ RtpDataReceiver::RtpDataReceiver() {} +RtpDataReceiver::RtpDataReceiver(std::shared_ptr io_statistics) + : io_statistics_(io_statistics) {} + RtpDataReceiver::~RtpDataReceiver() { if (rtp_statistics_) { rtp_statistics_->Stop(); @@ -16,8 +19,17 @@ void RtpDataReceiver::InsertRtpPacket(RtpPacket& rtp_packet) { 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_) { - 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()) { diff --git a/src/rtp/rtp_data_receiver.h b/src/rtp/rtp_endpoint/rtp_data_receiver.h similarity index 77% rename from src/rtp/rtp_data_receiver.h rename to src/rtp/rtp_endpoint/rtp_data_receiver.h index d3c925d..f9ed875 100644 --- a/src/rtp/rtp_data_receiver.h +++ b/src/rtp/rtp_endpoint/rtp_data_receiver.h @@ -3,6 +3,7 @@ #include +#include "io_statistics.h" #include "rtcp_receiver_report.h" #include "rtp_codec.h" #include "rtp_statistics.h" @@ -10,6 +11,7 @@ class RtpDataReceiver { public: RtpDataReceiver(); + RtpDataReceiver(std::shared_ptr io_statistics); ~RtpDataReceiver(); public: @@ -32,6 +34,11 @@ class RtpDataReceiver { private: std::unique_ptr rtp_statistics_ = nullptr; + std::shared_ptr 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; std::function data_send_func_ = nullptr; }; diff --git a/src/rtp/rtp_data_sender.cpp b/src/rtp/rtp_endpoint/rtp_data_sender.cpp similarity index 92% rename from src/rtp/rtp_data_sender.cpp rename to src/rtp/rtp_endpoint/rtp_data_sender.cpp index f0aa68a..e0063cf 100644 --- a/src/rtp/rtp_data_sender.cpp +++ b/src/rtp/rtp_endpoint/rtp_data_sender.cpp @@ -8,6 +8,9 @@ RtpDataSender::RtpDataSender() {} +RtpDataSender::RtpDataSender(std::shared_ptr io_statistics) + : io_statistics_(io_statistics) {} + RtpDataSender::~RtpDataSender() { if (rtp_statistics_) { rtp_statistics_->Stop(); @@ -43,8 +46,13 @@ int RtpDataSender::SendRtpPacket(RtpPacket& rtp_packet) { } last_send_bytes_ += (uint32_t)rtp_packet.Size(); - total_rtp_packets_sent_++; 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()) { RtcpSenderReport rtcp_sr; diff --git a/src/rtp/rtp_data_sender.h b/src/rtp/rtp_endpoint/rtp_data_sender.h similarity index 86% rename from src/rtp/rtp_data_sender.h rename to src/rtp/rtp_endpoint/rtp_data_sender.h index 7b8dc39..e41f81d 100644 --- a/src/rtp/rtp_data_sender.h +++ b/src/rtp/rtp_endpoint/rtp_data_sender.h @@ -9,6 +9,7 @@ #include +#include "io_statistics.h" #include "ringbuffer.h" #include "rtcp_sender_report.h" #include "rtp_packet.h" @@ -18,6 +19,7 @@ class RtpDataSender : public ThreadBase { public: RtpDataSender(); + RtpDataSender(std::shared_ptr io_statistics); virtual ~RtpDataSender(); public: @@ -37,11 +39,14 @@ class RtpDataSender : public ThreadBase { private: std::function data_send_func_ = nullptr; RingBuffer rtp_packe_queue_; + + private: std::unique_ptr rtp_statistics_ = nullptr; + std::shared_ptr io_statistics_ = nullptr; 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_packets_sent_ = 0; + uint32_t last_send_rtcp_sr_packet_ts_ = 0; }; #endif \ No newline at end of file diff --git a/src/rtp/rtp_video_receiver.cpp b/src/rtp/rtp_endpoint/rtp_video_receiver.cpp similarity index 95% rename from src/rtp/rtp_video_receiver.cpp rename to src/rtp/rtp_endpoint/rtp_video_receiver.cpp index f436768..8a4d35c 100644 --- a/src/rtp/rtp_video_receiver.cpp +++ b/src/rtp/rtp_endpoint/rtp_video_receiver.cpp @@ -7,6 +7,9 @@ RtpVideoReceiver::RtpVideoReceiver() {} +RtpVideoReceiver::RtpVideoReceiver(std::shared_ptr io_statistics) + : io_statistics_(io_statistics) {} + RtpVideoReceiver::~RtpVideoReceiver() { if (rtp_statistics_) { rtp_statistics_->Stop(); @@ -19,8 +22,17 @@ void RtpVideoReceiver::InsertRtpPacket(RtpPacket& rtp_packet) { 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_) { - 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()) { diff --git a/src/rtp/rtp_video_receiver.h b/src/rtp/rtp_endpoint/rtp_video_receiver.h similarity index 88% rename from src/rtp/rtp_video_receiver.h rename to src/rtp/rtp_endpoint/rtp_video_receiver.h index 7ca7035..e1bb7a3 100644 --- a/src/rtp/rtp_video_receiver.h +++ b/src/rtp/rtp_endpoint/rtp_video_receiver.h @@ -7,6 +7,7 @@ #include #include "fec_decoder.h" +#include "io_statistics.h" #include "ringbuffer.h" #include "rtcp_receiver_report.h" #include "rtp_codec.h" @@ -17,6 +18,7 @@ class RtpVideoReceiver : public ThreadBase { public: RtpVideoReceiver(); + RtpVideoReceiver(std::shared_ptr io_statistics); virtual ~RtpVideoReceiver(); public: @@ -53,6 +55,11 @@ class RtpVideoReceiver : public ThreadBase { private: std::unique_ptr rtp_statistics_ = nullptr; + std::shared_ptr 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; std::function data_send_func_ = nullptr; diff --git a/src/rtp/rtp_video_sender.cpp b/src/rtp/rtp_endpoint/rtp_video_sender.cpp similarity index 92% rename from src/rtp/rtp_video_sender.cpp rename to src/rtp/rtp_endpoint/rtp_video_sender.cpp index df2b3e0..7e3e20f 100644 --- a/src/rtp/rtp_video_sender.cpp +++ b/src/rtp/rtp_endpoint/rtp_video_sender.cpp @@ -8,6 +8,9 @@ RtpVideoSender::RtpVideoSender() {} +RtpVideoSender::RtpVideoSender(std::shared_ptr io_statistics) + : io_statistics_(io_statistics) {} + RtpVideoSender::~RtpVideoSender() { if (rtp_statistics_) { rtp_statistics_->Stop(); @@ -43,8 +46,13 @@ int RtpVideoSender::SendRtpPacket(RtpPacket& rtp_packet) { } last_send_bytes_ += (uint32_t)rtp_packet.Size(); - total_rtp_packets_sent_++; 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()) { RtcpSenderReport rtcp_sr; diff --git a/src/rtp/rtp_video_sender.h b/src/rtp/rtp_endpoint/rtp_video_sender.h similarity index 86% rename from src/rtp/rtp_video_sender.h rename to src/rtp/rtp_endpoint/rtp_video_sender.h index dd24c3e..8b3f077 100644 --- a/src/rtp/rtp_video_sender.h +++ b/src/rtp/rtp_endpoint/rtp_video_sender.h @@ -3,6 +3,7 @@ #include +#include "io_statistics.h" #include "ringbuffer.h" #include "rtcp_sender_report.h" #include "rtp_packet.h" @@ -12,6 +13,7 @@ class RtpVideoSender : public ThreadBase { public: RtpVideoSender(); + RtpVideoSender(std::shared_ptr io_statistics); virtual ~RtpVideoSender(); public: @@ -33,10 +35,11 @@ class RtpVideoSender : public ThreadBase { private: std::unique_ptr rtp_statistics_ = nullptr; + std::shared_ptr io_statistics_ = nullptr; 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_packets_sent_ = 0; }; #endif \ No newline at end of file diff --git a/src/rtp/byte_buffer.cpp b/src/rtp/rtp_packet/byte_buffer.cpp similarity index 100% rename from src/rtp/byte_buffer.cpp rename to src/rtp/rtp_packet/byte_buffer.cpp diff --git a/src/rtp/byte_buffer.h b/src/rtp/rtp_packet/byte_buffer.h similarity index 100% rename from src/rtp/byte_buffer.h rename to src/rtp/rtp_packet/byte_buffer.h diff --git a/src/rtp/obu.cpp b/src/rtp/rtp_packet/obu.cpp similarity index 100% rename from src/rtp/obu.cpp rename to src/rtp/rtp_packet/obu.cpp diff --git a/src/rtp/obu.h b/src/rtp/rtp_packet/obu.h similarity index 100% rename from src/rtp/obu.h rename to src/rtp/rtp_packet/obu.h diff --git a/src/rtp/obu_parser.cpp b/src/rtp/rtp_packet/obu_parser.cpp similarity index 100% rename from src/rtp/obu_parser.cpp rename to src/rtp/rtp_packet/obu_parser.cpp diff --git a/src/rtp/obu_parser.h b/src/rtp/rtp_packet/obu_parser.h similarity index 100% rename from src/rtp/obu_parser.h rename to src/rtp/rtp_packet/obu_parser.h diff --git a/src/rtp/rtp_codec.cpp b/src/rtp/rtp_packet/rtp_codec.cpp similarity index 100% rename from src/rtp/rtp_codec.cpp rename to src/rtp/rtp_packet/rtp_codec.cpp diff --git a/src/rtp/rtp_codec.h b/src/rtp/rtp_packet/rtp_codec.h similarity index 100% rename from src/rtp/rtp_codec.h rename to src/rtp/rtp_packet/rtp_codec.h diff --git a/src/rtp/rtp_codec_av1.cpp b/src/rtp/rtp_packet/rtp_codec_av1.cpp similarity index 100% rename from src/rtp/rtp_codec_av1.cpp rename to src/rtp/rtp_packet/rtp_codec_av1.cpp diff --git a/src/rtp/rtp_packet.cpp b/src/rtp/rtp_packet/rtp_packet.cpp similarity index 100% rename from src/rtp/rtp_packet.cpp rename to src/rtp/rtp_packet/rtp_packet.cpp diff --git a/src/rtp/rtp_packet.h b/src/rtp/rtp_packet/rtp_packet.h similarity index 100% rename from src/rtp/rtp_packet.h rename to src/rtp/rtp_packet/rtp_packet.h diff --git a/src/rtp/rtp_statistics.cpp b/src/rtp/rtp_statistics.cpp index 96afce3..36c0880 100644 --- a/src/rtp/rtp_statistics.cpp +++ b/src/rtp/rtp_statistics.cpp @@ -14,6 +14,22 @@ void RtpStatistics::UpdateReceiveBytes(uint32_t 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() { if (!sent_bytes_) { // LOG_INFO("rtp statistics: Send [{} bps]", sent_bytes_); diff --git a/src/rtp/rtp_statistics.h b/src/rtp/rtp_statistics.h index 05dd41c..e0efdb6 100644 --- a/src/rtp/rtp_statistics.h +++ b/src/rtp/rtp_statistics.h @@ -9,8 +9,12 @@ class RtpStatistics : public ThreadBase { virtual ~RtpStatistics(); public: + // send side void UpdateSentBytes(uint32_t sent_bytes); + + // receive side void UpdateReceiveBytes(uint32_t received_bytes); + void UpdatePacketLossRate(uint16_t seq_num); private: bool Process(); @@ -18,6 +22,8 @@ class RtpStatistics : public ThreadBase { private: uint32_t sent_bytes_ = 0; uint32_t received_bytes_ = 0; + uint16_t last_received_seq_num_ = 0; + uint32_t lost_packets_num_ = 0; }; #endif \ No newline at end of file diff --git a/src/rtp/rtp_transceiver.cpp b/src/rtp/rtp_transceiver.cpp deleted file mode 100644 index 923eac6..0000000 --- a/src/rtp/rtp_transceiver.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "rtp_transceiver.h" - -RtpTransceiver::RtpTransceiver() {} - -RtpTransceiver::~RtpTransceiver() {} \ No newline at end of file diff --git a/src/rtp/rtp_transceiver.h b/src/rtp/rtp_transceiver.h deleted file mode 100644 index 154644d..0000000 --- a/src/rtp/rtp_transceiver.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _RTP_TRANSCEIVER_H_ -#define _RTP_TRANSCEIVER_H_ - -#include -#include - -class RtpTransceiver { - public: - RtpTransceiver(); - ~RtpTransceiver(); - - public: - virtual void SetSendDataFunc( - std::function data_send_func) = 0; - - virtual void OnReceiveData(const char *data, size_t size) = 0; -}; - -#endif \ No newline at end of file diff --git a/src/statistics/io_statistics.cpp b/src/statistics/io_statistics.cpp index 8530aa4..59ce67f 100644 --- a/src/statistics/io_statistics.cpp +++ b/src/statistics/io_statistics.cpp @@ -3,9 +3,7 @@ #include "log.h" IOStatistics::IOStatistics( - std::function - io_report_callback) + std::function io_report_callback) : io_report_callback_(io_report_callback) { interval_ = 1000; } @@ -36,11 +34,95 @@ void IOStatistics::Process() { 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_ / + (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_) { - io_report_callback_(video_inbound_bitrate_, video_outbound_bitrate_, - audio_inbound_bitrate_, audio_outbound_bitrate_, - data_inbound_bitrate_, data_outbound_bitrate_, - total_inbound_bitrate_, total_outbound_bitrate_); + 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_; + 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; } +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) { audio_inbound_bytes_ += bytes; } @@ -76,10 +176,73 @@ void IOStatistics::UpdateAudioOutboundBytes(uint32_t 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) { data_inbound_bytes_ += bytes; } void IOStatistics::UpdateDataOutboundBytes(uint32_t 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_++; } \ No newline at end of file diff --git a/src/statistics/io_statistics.h b/src/statistics/io_statistics.h index fb6fcd6..660078e 100644 --- a/src/statistics/io_statistics.h +++ b/src/statistics/io_statistics.h @@ -15,9 +15,30 @@ class IOStatistics { public: - IOStatistics(std::function - io_report_callback); + typedef struct { + uint32_t bitrate; + 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 io_report_callback); ~IOStatistics(); public: @@ -26,20 +47,30 @@ class IOStatistics { void UpdateVideoInboundBytes(uint32_t bytes); void UpdateVideoOutboundBytes(uint32_t bytes); + void UpdateVideoPacketLossCount(uint16_t seq_num); void UpdateAudioInboundBytes(uint32_t bytes); void UpdateAudioOutboundBytes(uint32_t bytes); + void UpdateAudioPacketLossCount(uint16_t seq_num); void UpdateDataInboundBytes(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: void Process(); private: - std::function - io_report_callback_ = nullptr; + std::function io_report_callback_ = nullptr; std::thread statistics_thread_; std::mutex mtx_; uint32_t interval_ = 1000; @@ -48,13 +79,35 @@ class IOStatistics { std::atomic video_inbound_bytes_ = 0; std::atomic video_outbound_bytes_ = 0; + std::atomic last_received_video_rtp_pkt_seq_ = 0; std::atomic audio_inbound_bytes_ = 0; std::atomic audio_outbound_bytes_ = 0; + std::atomic last_received_audio_rtp_pkt_seq_ = 0; std::atomic data_inbound_bytes_ = 0; std::atomic data_outbound_bytes_ = 0; + std::atomic last_received_data_rtp_pkt_seq_ = 0; std::atomic total_inbound_bytes_ = 0; std::atomic total_outbound_bytes_ = 0; + std::atomic video_inbound_rtp_pkt_cnt_ = 0; + std::atomic audio_inbound_rtp_pkt_cnt_ = 0; + std::atomic data_inbound_rtp_pkt_cnt_ = 0; + + std::atomic video_inbound_rtp_pkt_cnt_tmp_ = 0; + std::atomic audio_inbound_rtp_pkt_cnt_tmp_ = 0; + std::atomic data_inbound_rtp_pkt_cnt_tmp_ = 0; + + std::atomic data_outbound_rtp_pkt_cnt_ = 0; + std::atomic video_outbound_rtp_pkt_cnt_ = 0; + std::atomic audio_outbound_rtp_pkt_cnt_ = 0; + + std::atomic expected_video_inbound_rtp_pkt_cnt_ = 0; + std::atomic expected_audio_inbound_rtp_pkt_cnt_ = 0; + std::atomic expected_data_inbound_rtp_pkt_cnt_ = 0; + std::atomic video_rtp_pkt_loss_cnt_ = 0; + std::atomic audio_rtp_pkt_loss_cnt_ = 0; + std::atomic data_rtp_pkt_loss_cnt_ = 0; + std::atomic video_inbound_bitrate_ = 0; std::atomic video_outbound_bitrate_ = 0; std::atomic audio_inbound_bitrate_ = 0; @@ -63,6 +116,10 @@ class IOStatistics { std::atomic data_outbound_bitrate_ = 0; std::atomic total_inbound_bitrate_ = 0; std::atomic 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 \ No newline at end of file diff --git a/src/transmission/ice_transmission.cpp b/src/transmission/ice_transmission.cpp index 9187ab3..8c15ee4 100644 --- a/src/transmission/ice_transmission.cpp +++ b/src/transmission/ice_transmission.cpp @@ -61,30 +61,21 @@ int IceTransmission::InitIceTransmission( std::string &turn_username, std::string &turn_password, RtpPacket::PAYLOAD_TYPE video_codec_payload_type) { ice_io_statistics_ = std::make_unique( - [this](uint32_t video_inbound_bitrate, uint32_t video_outbound_bitrate, - 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) { + [this](const IOStatistics::NetTrafficStats &net_traffic_stats) { if (on_receive_net_status_report_) { - XNetTrafficStats net_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; + XNetTrafficStats xnet_traffic_stats; + memcpy(&xnet_traffic_stats, &net_traffic_stats, + sizeof(XNetTrafficStats)); on_receive_net_status_report_(user_id_.data(), user_id_.size(), TraversalMode(traversal_type_), - &net_traffic_stats, user_data_); + &xnet_traffic_stats, user_data_); } }); video_codec_payload_type_ = video_codec_payload_type; - rtp_video_receiver_ = std::make_unique(); + rtp_video_receiver_ = std::make_unique(ice_io_statistics_); // rr sender rtp_video_receiver_->SetSendDataFunc( [this](const char *data, size_t size) -> int { @@ -123,7 +114,7 @@ int IceTransmission::InitIceTransmission( rtp_video_receiver_->Start(); - rtp_video_sender_ = std::make_unique(); + rtp_video_sender_ = std::make_unique(ice_io_statistics_); rtp_video_sender_->SetSendDataFunc( [this](const char *data, size_t size) -> int { if (!ice_agent_) { @@ -144,7 +135,7 @@ int IceTransmission::InitIceTransmission( rtp_video_sender_->Start(); - rtp_audio_receiver_ = std::make_unique(); + rtp_audio_receiver_ = std::make_unique(ice_io_statistics_); // rr sender rtp_audio_receiver_->SetSendDataFunc( [this](const char *data, size_t size) -> int { @@ -175,7 +166,7 @@ int IceTransmission::InitIceTransmission( }); }); - rtp_audio_sender_ = std::make_unique(); + rtp_audio_sender_ = std::make_unique(ice_io_statistics_); rtp_audio_sender_->SetSendDataFunc( [this](const char *data, size_t size) -> int { if (!ice_agent_) { @@ -196,7 +187,7 @@ int IceTransmission::InitIceTransmission( rtp_audio_sender_->Start(); - rtp_data_receiver_ = std::make_unique(); + rtp_data_receiver_ = std::make_unique(ice_io_statistics_); // rr sender rtp_data_receiver_->SetSendDataFunc( [this](const char *data, size_t size) -> int { @@ -224,7 +215,7 @@ int IceTransmission::InitIceTransmission( } }); - rtp_data_sender_ = std::make_unique(); + rtp_data_sender_ = std::make_unique(ice_io_statistics_); rtp_data_sender_->SetSendDataFunc( [this](const char *data, size_t size) -> int { if (!ice_agent_) { @@ -349,14 +340,7 @@ int IceTransmission::InitIceTransmission( ice_transmission_obj->traversal_type_ = TraversalType::TP2P; } XNetTrafficStats net_traffic_stats; - net_traffic_stats.video_in = 0; - 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; + memset(&net_traffic_stats, 0, sizeof(net_traffic_stats)); ice_transmission_obj->on_receive_net_status_report_( ice_transmission_obj->user_id_.data(), diff --git a/src/transmission/ice_transmission.h b/src/transmission/ice_transmission.h index 6e199df..308ab42 100644 --- a/src/transmission/ice_transmission.h +++ b/src/transmission/ice_transmission.h @@ -182,6 +182,7 @@ class IceTransmission { std::unique_ptr video_rtp_codec_ = nullptr; std::unique_ptr audio_rtp_codec_ = nullptr; std::unique_ptr data_rtp_codec_ = nullptr; + std::unique_ptr rtp_video_receiver_ = nullptr; std::unique_ptr rtp_video_sender_ = nullptr; std::unique_ptr rtp_audio_receiver_ = nullptr; @@ -194,7 +195,7 @@ class IceTransmission { uint32_t last_complete_frame_ts_ = 0; private: - std::unique_ptr ice_io_statistics_ = nullptr; + std::shared_ptr ice_io_statistics_ = nullptr; private: RtpPacket::PAYLOAD_TYPE video_codec_payload_type_; diff --git a/xmake.lua b/xmake.lua index 041667e..315113d 100644 --- a/xmake.lua +++ b/xmake.lua @@ -22,7 +22,7 @@ includes("thirdparty") if is_os("windows") then add_defines("_WEBSOCKETPP_CPP11_INTERNAL_") - add_cxflags("/W4", "/WX") + add_cxflags("/WX") elseif is_os("linux") then add_requires("glib", {system = true}) add_packages("glib") @@ -70,6 +70,12 @@ target("fec") add_files("src/fec/*.cpp") 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") set_kind("object") add_deps("log") @@ -78,9 +84,13 @@ target("rtcp") target("rtp") set_kind("object") - add_deps("log", "frame", "ringbuffer", "thread", "rtcp", "fec") - add_files("src/rtp/*.cpp") - add_includedirs("src/rtp", {public = true}) + add_deps("log", "frame", "ringbuffer", "thread", "rtcp", "fec", "statistics") + add_files("src/rtp/*.cpp", + "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") set_kind("object") @@ -178,11 +188,6 @@ target("qos") add_files("src/qos/*.cpp") 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") set_kind("object")