From b50599b7b50c3ac84c22e1e183da427553ffd428 Mon Sep 17 00:00:00 2001 From: Tomas Lundqvist Date: Mon, 17 Oct 2022 14:44:52 +0000 Subject: [PATCH] Expose jitter in time in addition to in samples. RFC 3550 specifies samples to be the unit while https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict* specifies time. This avoids the need to convert to time in code that reads the jitter value from RtpReceiveStats. Bug: webrtc:13757 Change-Id: I972996971c58b686babd621ff4e0f5790fdf2cb1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/279281 Reviewed-by: Danil Chapovalov Commit-Queue: Tomas Lundqvist Cr-Commit-Position: refs/heads/main@{#38419} --- modules/rtp_rtcp/include/rtp_rtcp_defines.h | 4 +++ .../source/receive_statistics_impl.cc | 14 +++++++-- .../rtp_rtcp/source/receive_statistics_impl.h | 3 ++ .../source/receive_statistics_unittest.cc | 29 +++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 79626255ed..dec3e3cd7e 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -25,6 +25,7 @@ #include "api/audio_codecs/audio_format.h" #include "api/rtp_headers.h" #include "api/transport/network_types.h" +#include "api/units/time_delta.h" #include "modules/rtp_rtcp/source/rtcp_packet/remote_estimate.h" #include "system_wrappers/include/clock.h" @@ -442,7 +443,10 @@ struct RtpReceiveStats { // RTCReceivedRtpStreamStats dictionary, see // https://w3c.github.io/webrtc-stats/#receivedrtpstats-dict* int32_t packets_lost = 0; + // Interarrival jitter in samples. uint32_t jitter = 0; + // Interarrival jitter in time. + webrtc::TimeDelta interarrival_jitter = webrtc::TimeDelta::Zero(); // Timestamp and counters exposed in RTCInboundRtpStreamStats, see // https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict* diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc index 1e8e399f4d..e8b99ced10 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -16,6 +16,7 @@ #include #include +#include "api/units/time_delta.h" #include "modules/remote_bitrate_estimator/test/bwe_test_logging.h" #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" @@ -33,8 +34,7 @@ constexpr int64_t kStatisticsProcessIntervalMs = 1000; StreamStatistician::~StreamStatistician() {} -StreamStatisticianImpl::StreamStatisticianImpl(uint32_t ssrc, - Clock* clock, +StreamStatisticianImpl::StreamStatisticianImpl(uint32_t ssrc, Clock* clock, int max_reordering_threshold) : ssrc_(ssrc), clock_(clock), @@ -54,7 +54,8 @@ StreamStatisticianImpl::StreamStatisticianImpl(uint32_t ssrc, received_seq_first_(-1), received_seq_max_(-1), last_report_cumulative_loss_(0), - last_report_seq_max_(-1) {} + last_report_seq_max_(-1), + last_payload_type_frequency_(0) {} StreamStatisticianImpl::~StreamStatisticianImpl() = default; @@ -141,6 +142,7 @@ void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) { } last_received_timestamp_ = packet.Timestamp(); last_receive_time_ms_ = now_ms; + last_payload_type_frequency_ = packet.payload_type_frequency(); } void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet, @@ -178,6 +180,12 @@ RtpReceiveStats StreamStatisticianImpl::GetStats() const { stats.packets_lost = cumulative_loss_; // Note: internal jitter value is in Q4 and needs to be scaled by 1/16. stats.jitter = jitter_q4_ >> 4; + if (last_payload_type_frequency_ > 0) { + // Divide value in fractional seconds by frequency to get jitter in + // fractional seconds. + stats.interarrival_jitter = + webrtc::TimeDelta::Seconds(stats.jitter) / last_payload_type_frequency_; + } if (receive_counters_.last_packet_received_timestamp_ms.has_value()) { stats.last_packet_received_timestamp_ms = *receive_counters_.last_packet_received_timestamp_ms + diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h index 1a70fe4ad7..c6f2d8468e 100644 --- a/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -108,6 +108,9 @@ class StreamStatisticianImpl : public StreamStatisticianImplInterface { // Counter values when we sent the last report. int32_t last_report_cumulative_loss_; int64_t last_report_seq_max_; + + // The sample frequency of the last received packet. + int last_payload_type_frequency_; }; // Thread-safe implementation of StreamStatisticianImplInterface. diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc index d40a743469..d8f2df1fdf 100644 --- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc +++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc @@ -10,9 +10,11 @@ #include "modules/rtp_rtcp/include/receive_statistics.h" +#include #include #include +#include "api/units/time_delta.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "rtc_base/random.h" #include "system_wrappers/include/clock.h" @@ -578,5 +580,32 @@ TEST_P(ReceiveStatisticsTest, LastPacketReceivedTimestamp) { EXPECT_EQ(45, counters.last_packet_received_timestamp_ms); } +TEST_P(ReceiveStatisticsTest, SimpleJitterComputation) { + const int kMsPerPacket = 20; + const int kCodecSampleRate = 48'000; + const int kSamplesPerPacket = kMsPerPacket * kCodecSampleRate / 1'000; + const int kLateArrivalDeltaMs = 100; + const int kLateArrivalDeltaSamples = + kLateArrivalDeltaMs * kCodecSampleRate / 1'000; + + packet1_.set_payload_type_frequency(kCodecSampleRate); + packet1_.SetSequenceNumber(1); + packet1_.SetTimestamp(0); + receive_statistics_->OnRtpPacket(packet1_); + packet1_.SetSequenceNumber(2); + packet1_.SetTimestamp(kSamplesPerPacket); + // Arrives 100 ms late. + clock_.AdvanceTimeMilliseconds(kMsPerPacket + kLateArrivalDeltaMs); + receive_statistics_->OnRtpPacket(packet1_); + + StreamStatistician* statistician = + receive_statistics_->GetStatistician(kSsrc1); + // See jitter caluculation in https://www.rfc-editor.org/rfc/rfc3550 6.4.1. + const uint32_t expected_jitter = (kLateArrivalDeltaSamples) / 16; + EXPECT_EQ(expected_jitter, statistician->GetStats().jitter); + EXPECT_EQ(webrtc::TimeDelta::Seconds(expected_jitter) / kCodecSampleRate, + statistician->GetStats().interarrival_jitter); +} + } // namespace } // namespace webrtc