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 <danilchap@webrtc.org> Commit-Queue: Tomas Lundqvist <tomasl@google.com> Cr-Commit-Position: refs/heads/main@{#38419}
This commit is contained in:
committed by
WebRTC LUCI CQ
parent
f0e65bab0e
commit
b50599b7b5
@ -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*
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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 +
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -10,9 +10,11 @@
|
||||
|
||||
#include "modules/rtp_rtcp/include/receive_statistics.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user