Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add packetLoss stats to transport #648

Merged
merged 5 commits into from
Sep 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rust/src/router/direct_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ pub struct DirectTransportStat {
pub available_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_received: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_sent: Option<f64>,
}

#[derive(Default)]
Expand Down
4 changes: 4 additions & 0 deletions rust/src/router/pipe_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ pub struct PipeTransportStat {
pub available_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_received: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_sent: Option<f64>,
// PipeTransport specific.
pub tuple: Option<TransportTuple>,
}
Expand Down
4 changes: 4 additions & 0 deletions rust/src/router/plain_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ pub struct PlainTransportStat {
pub available_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_received: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_sent: Option<f64>,
// PlainTransport specific.
pub rtcp_mux: bool,
pub comedia: bool,
Expand Down
4 changes: 4 additions & 0 deletions rust/src/router/webrtc_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ pub struct WebRtcTransportStat {
pub available_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_incoming_bitrate: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_received: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rtp_packet_loss_sent: Option<f64>,
// WebRtcTransport specific.
pub ice_role: IceRole,
pub ice_state: IceState,
Expand Down
2 changes: 2 additions & 0 deletions rust/tests/integration/direct_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ fn get_stats_succeeds() {
assert_eq!(stats[0].rtx_send_bitrate, 0);
assert_eq!(stats[0].probation_bytes_sent, 0);
assert_eq!(stats[0].probation_send_bitrate, 0);
assert_eq!(stats[0].rtp_packet_loss_received, None);
assert_eq!(stats[0].rtp_packet_loss_sent, None);
});
}

Expand Down
2 changes: 2 additions & 0 deletions rust/tests/integration/plain_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ fn get_stats_succeeds() {
assert_eq!(stats[0].rtx_send_bitrate, 0);
assert_eq!(stats[0].probation_bytes_sent, 0);
assert_eq!(stats[0].probation_send_bitrate, 0);
assert_eq!(stats[0].rtp_packet_loss_received, None);
assert_eq!(stats[0].rtp_packet_loss_sent, None);
assert!(matches!(
stats[0].tuple,
Some(TransportTuple::LocalOnly { .. }),
Expand Down
2 changes: 2 additions & 0 deletions rust/tests/integration/webrtc_transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@ fn get_stats_succeeds() {
assert_eq!(stats[0].probation_send_bitrate, 0);
assert_eq!(stats[0].ice_selected_tuple, None);
assert_eq!(stats[0].max_incoming_bitrate, None);
assert_eq!(stats[0].rtp_packet_loss_received, None);
assert_eq!(stats[0].rtp_packet_loss_sent, None);
});
}

Expand Down
5 changes: 5 additions & 0 deletions worker/include/RTC/TransportCongestionControlClient.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <libwebrtc/api/transport/network_types.h>
#include <libwebrtc/call/rtp_transport_controller_send.h>
#include <libwebrtc/modules/pacing/packet_router.h>
#include <deque>

namespace RTC
{
Expand Down Expand Up @@ -76,10 +77,12 @@ namespace RTC
return this->bitrates;
}
uint32_t GetAvailableBitrate() const;
double GetPacketLoss() const;
void RescheduleNextAvailableBitrateEvent();

private:
void MayEmitAvailableBitrateEvent(uint32_t previousAvailableBitrate);
void UpdatePacketLoss(double packetLoss);

// jmillan: missing.
// void OnRemoteNetworkEstimate(NetworkStateEstimate estimate) override;
Expand Down Expand Up @@ -113,6 +116,8 @@ namespace RTC
bool availableBitrateEventCalled{ false };
uint64_t lastAvailableBitrateEventAtMs{ 0u };
RTC::TrendCalculator desiredBitrateTrend;
std::deque<double> packetLossHistory;
double packetLoss{ 0 };
};
} // namespace RTC

Expand Down
5 changes: 5 additions & 0 deletions worker/include/RTC/TransportCongestionControlServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "RTC/RtpPacket.hpp"
#include "handles/Timer.hpp"
#include <libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.h>
#include <deque>

namespace RTC
{
Expand Down Expand Up @@ -50,12 +51,14 @@ namespace RTC
return 0u;
}
}
double GetPacketLoss() const;
void IncomingPacket(uint64_t nowMs, const RTC::RtpPacket* packet);
void SetMaxIncomingBitrate(uint32_t bitrate);

private:
void SendTransportCcFeedback();
void MaySendLimitationRembFeedback();
void UpdatePacketLoss(double packetLoss);

/* Pure virtual methods inherited from webrtc::RemoteBitrateEstimator::Listener. */
public:
Expand Down Expand Up @@ -84,6 +87,8 @@ namespace RTC
uint32_t maxIncomingBitrate{ 0u };
uint64_t limitationRembSentAtMs{ 0u };
uint8_t unlimitedRembCounter{ 0u };
std::deque<double> packetLossHistory;
double packetLoss{ 0 };
};
} // namespace RTC

Expand Down
8 changes: 8 additions & 0 deletions worker/src/RTC/Transport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,14 @@ namespace RTC
// Add maxIncomingBitrate.
if (this->maxIncomingBitrate != 0u)
jsonObject["maxIncomingBitrate"] = this->maxIncomingBitrate;

// Add packetLossReceived.
if (this->tccServer)
jsonObject["rtpPacketLossReceived"] = this->tccServer->GetPacketLoss();

// Add packetLossSent.
if (this->tccClient)
jsonObject["rtpPacketLossSent"] = this->tccClient->GetPacketLoss();
nazar-pc marked this conversation as resolved.
Show resolved Hide resolved
}

void Transport::HandleRequest(Channel::ChannelRequest* request)
Expand Down
55 changes: 55 additions & 0 deletions worker/src/RTC/TransportCongestionControlClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace RTC
static constexpr float MaxBitrateIncrementFactor{ 1.35f };
static constexpr float MaxPaddingBitrateFactor{ 0.85f };
static constexpr uint64_t AvailableBitrateEventInterval{ 2000u }; // In ms.
static constexpr size_t PacketLossHistogramLength{ 24 };

/* Instance methods. */

Expand Down Expand Up @@ -163,9 +164,56 @@ namespace RTC
{
MS_TRACE();

// Update packet loss history.
size_t expected_packets = feedback->GetPacketStatusCount();
size_t lost_packets = 0;
for (const auto& result : feedback->GetPacketResults())
{
if (!result.received)
lost_packets += 1;
}
this->UpdatePacketLoss(static_cast<double>(lost_packets) / expected_packets);

this->rtpTransportControllerSend->OnTransportFeedback(*feedback);
}

void TransportCongestionControlClient::UpdatePacketLoss(double packetLoss)
{
// Add the score into the histogram.
if (this->packetLossHistory.size() == PacketLossHistogramLength)
this->packetLossHistory.pop_front();

this->packetLossHistory.push_back(packetLoss);

/*
* Scoring mechanism is a weighted average.
*
* The more recent the score is, the more weight it has.
* The oldest score has a weight of 1 and subsequent scores weight is
* increased by one sequentially.
*
* Ie:
* - scores: [1,2,3,4]
* - this->scores = ((1) + (2+2) + (3+3+3) + (4+4+4+4)) / 10 = 2.8 => 3
*/

size_t weight{ 0 };
size_t samples{ 0 };
double totalPacketLoss{ 0 };

for (auto packetLossEntry : this->packetLossHistory)
{
weight++;
samples += weight;
totalPacketLoss += weight * packetLossEntry;
}

// clang-tidy "thinks" that this can lead to division by zero but we are
// smarter.
// NOLINTNEXTLINE(clang-analyzer-core.DivideZero)
this->packetLoss = totalPacketLoss / samples;
}

void TransportCongestionControlClient::SetMaxOutgoingBitrate(uint32_t maxBitrate)
{
if (maxBitrate < this->initialAvailableBitrate)
Expand Down Expand Up @@ -245,6 +293,13 @@ namespace RTC
return this->bitrates.availableBitrate;
}

double TransportCongestionControlClient::GetPacketLoss() const
{
MS_TRACE();

return this->packetLoss;
}

void TransportCongestionControlClient::RescheduleNextAvailableBitrateEvent()
{
MS_TRACE();
Expand Down
47 changes: 46 additions & 1 deletion worker/src/RTC/TransportCongestionControlServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace RTC
static constexpr uint64_t TransportCcFeedbackSendInterval{ 100u }; // In ms.
static constexpr uint64_t LimitationRembInterval{ 1500u }; // In ms.
static constexpr uint8_t UnlimitedRembNumPackets{ 4u };
static constexpr size_t PacketLossHistogramLength{ 24 };

/* Instance methods. */

Expand Down Expand Up @@ -101,6 +102,13 @@ namespace RTC
}
}

double TransportCongestionControlServer::GetPacketLoss() const
{
MS_TRACE();

return this->packetLoss;
}

void TransportCongestionControlServer::IncomingPacket(uint64_t nowMs, const RTC::RtpPacket* packet)
{
MS_TRACE();
Expand All @@ -119,7 +127,7 @@ namespace RTC
this->transportCcFeedbackMediaSsrc = packet->GetSsrc();

this->transportCcFeedbackPacket->SetSenderSsrc(0u);
this->transportCcFeedbackPacket->SetMediaSsrc(packet->GetSsrc());
this->transportCcFeedbackPacket->SetMediaSsrc(this->transportCcFeedbackMediaSsrc);

// Provide the feedback packet with the RTP packet info. If it fails,
// send current feedback and add the packet info to a new one.
Expand Down Expand Up @@ -223,6 +231,17 @@ namespace RTC
this->listener->OnTransportCongestionControlServerSendRtcpPacket(
this, this->transportCcFeedbackPacket.get());

// Update packet loss history.
size_t expected_packets = this->transportCcFeedbackPacket->GetPacketStatusCount();
size_t lost_packets = 0;
for (const auto& result : this->transportCcFeedbackPacket->GetPacketResults())
{
if (!result.received)
lost_packets += 1;
}

this->UpdatePacketLoss(static_cast<double>(lost_packets) / expected_packets);

// Create a new feedback packet.
this->transportCcFeedbackPacket.reset(new RTC::RTCP::FeedbackRtpTransportPacket(
this->transportCcFeedbackSenderSsrc, this->transportCcFeedbackMediaSsrc));
Expand Down Expand Up @@ -280,6 +299,32 @@ namespace RTC
}
}

void TransportCongestionControlServer::UpdatePacketLoss(double packetLoss)
{
// Add the score into the histogram.
if (this->packetLossHistory.size() == PacketLossHistogramLength)
this->packetLossHistory.pop_front();

this->packetLossHistory.push_back(packetLoss);

// Calculate a weighted average
size_t weight{ 0 };
size_t samples{ 0 };
double totalPacketLoss{ 0 };

for (auto packetLossEntry : this->packetLossHistory)
{
weight++;
samples += weight;
totalPacketLoss += weight * packetLossEntry;
}

// clang-tidy "thinks" that this can lead to division by zero but we are
// smarter.
// NOLINTNEXTLINE(clang-analyzer-core.DivideZero)
this->packetLoss = totalPacketLoss / samples;
}

inline void TransportCongestionControlServer::OnRembServerAvailableBitrate(
const webrtc::RemoteBitrateEstimator* /*rembServer*/,
const std::vector<uint32_t>& ssrcs,
Expand Down