Update ReceiveStatistics to use Timestamp/TimeDelta to represent time
Bug: webrtc:13757
Change-Id: I1606a14ecf8ccb520428b84eed2f9a8ba746162f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/307181
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40188}
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index 48a1fe8..d52de41 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -27,8 +27,16 @@
namespace webrtc {
namespace {
-constexpr int64_t kStatisticsTimeoutMs = 8000;
-constexpr int64_t kStatisticsProcessIntervalMs = 1000;
+constexpr TimeDelta kStatisticsTimeout = TimeDelta::Seconds(8);
+constexpr TimeDelta kStatisticsProcessInterval = TimeDelta::Seconds(1);
+
+TimeDelta UnixEpochDelta(Clock& clock) {
+ Timestamp now = clock.CurrentTime();
+ NtpTime ntp_now = clock.ConvertTimestampToNtpTime(now);
+ return TimeDelta::Millis(ntp_now.ToMs() - now.ms() -
+ rtc::kNtpJan1970Millisecs);
+}
+
} // namespace
StreamStatistician::~StreamStatistician() {}
@@ -38,10 +46,8 @@
int max_reordering_threshold)
: ssrc_(ssrc),
clock_(clock),
- delta_internal_unix_epoch_ms_(clock_->CurrentNtpInMilliseconds() -
- clock_->TimeInMilliseconds() -
- rtc::kNtpJan1970Millisecs),
- incoming_bitrate_(kStatisticsProcessIntervalMs,
+ delta_internal_unix_epoch_(UnixEpochDelta(*clock_)),
+ incoming_bitrate_(kStatisticsProcessInterval.ms(),
RateStatistics::kBpsScale),
max_reordering_threshold_(max_reordering_threshold),
enable_retransmit_detection_(false),
@@ -49,7 +55,6 @@
jitter_q4_(0),
cumulative_loss_(0),
cumulative_loss_rtcp_offset_(0),
- last_receive_time_ms_(0),
last_received_timestamp_(0),
received_seq_first_(-1),
received_seq_max_(-1),
@@ -61,7 +66,7 @@
bool StreamStatisticianImpl::UpdateOutOfOrder(const RtpPacketReceived& packet,
int64_t sequence_number,
- int64_t now_ms) {
+ Timestamp now) {
// Check if `packet` is second packet of a stream restart.
if (received_seq_out_of_order_) {
// Count the previous packet as a received; it was postponed below.
@@ -103,7 +108,7 @@
return false;
// Old out of order packet, may be retransmit.
- if (enable_retransmit_detection_ && IsRetransmitOfOldPacket(packet, now_ms))
+ if (enable_retransmit_detection_ && IsRetransmitOfOldPacket(packet, now))
receive_counters_.retransmitted.AddPacket(packet);
return true;
}
@@ -111,9 +116,8 @@
void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) {
RTC_DCHECK_EQ(ssrc_, packet.Ssrc());
Timestamp now = clock_->CurrentTime();
- int64_t now_ms = now.ms();
- incoming_bitrate_.Update(packet.size(), now_ms);
+ incoming_bitrate_.Update(packet.size(), now.ms());
receive_counters_.transmitted.AddPacket(packet);
--cumulative_loss_;
@@ -126,7 +130,7 @@
last_report_seq_max_ = sequence_number - 1;
received_seq_max_ = sequence_number - 1;
receive_counters_.first_packet_time = now;
- } else if (UpdateOutOfOrder(packet, sequence_number, now_ms)) {
+ } else if (UpdateOutOfOrder(packet, sequence_number, now)) {
return;
}
// In order packet.
@@ -140,18 +144,19 @@
if (packet.Timestamp() != last_received_timestamp_ &&
(receive_counters_.transmitted.packets -
receive_counters_.retransmitted.packets) > 1) {
- UpdateJitter(packet, now_ms);
+ UpdateJitter(packet, now);
}
last_received_timestamp_ = packet.Timestamp();
- last_receive_time_ms_ = now_ms;
+ last_receive_time_ = now;
}
void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet,
- int64_t receive_time_ms) {
- int64_t receive_diff_ms = receive_time_ms - last_receive_time_ms_;
- RTC_DCHECK_GE(receive_diff_ms, 0);
- uint32_t receive_diff_rtp = static_cast<uint32_t>(
- (receive_diff_ms * packet.payload_type_frequency()) / 1000);
+ Timestamp receive_time) {
+ RTC_DCHECK(last_receive_time_.has_value());
+ TimeDelta receive_diff = receive_time - *last_receive_time_;
+ RTC_DCHECK_GE(receive_diff, TimeDelta::Zero());
+ uint32_t receive_diff_rtp =
+ (receive_diff * packet.payload_type_frequency()).seconds<uint32_t>();
int32_t time_diff_samples =
receive_diff_rtp - (packet.Timestamp() - last_received_timestamp_);
@@ -178,13 +183,13 @@
if (payload_type_frequency != 0) {
if (last_payload_type_frequency_ != 0) {
// Value in "jitter_q4_" variable is a number of samples.
- // I.e. jitter = timestamp (ms) * frequency (kHz).
+ // I.e. jitter = timestamp (s) * frequency (Hz).
// Since the frequency has changed we have to update the number of samples
// accordingly. The new value should rely on a new frequency.
// If we don't do such procedure we end up with the number of samples that
- // cannot be converted into milliseconds correctly
- // (i.e. jitter_ms = jitter_q4_ >> 4 / (payload_type_frequency / 1000)).
+ // cannot be converted into TimeDelta correctly
+ // (i.e. jitter = jitter_q4_ >> 4 / payload_type_frequency).
// In such case, the number of samples has a "mix".
// Doing so we pretend that everything prior and including the current
@@ -219,11 +224,11 @@
// 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_;
+ TimeDelta::Seconds(stats.jitter) / last_payload_type_frequency_;
}
- if (last_receive_time_ms_ > 0) {
+ if (last_receive_time_.has_value()) {
stats.last_packet_received_timestamp_ms =
- last_receive_time_ms_ + delta_internal_unix_epoch_ms_;
+ (*last_receive_time_ + delta_internal_unix_epoch_).ms();
}
stats.packet_counter = receive_counters_.transmitted;
return stats;
@@ -231,12 +236,12 @@
void StreamStatisticianImpl::MaybeAppendReportBlockAndReset(
std::vector<rtcp::ReportBlock>& report_blocks) {
- int64_t now_ms = clock_->TimeInMilliseconds();
- if (now_ms - last_receive_time_ms_ >= kStatisticsTimeoutMs) {
- // Not active.
+ if (!ReceivedRtpPacket()) {
return;
}
- if (!ReceivedRtpPacket()) {
+ Timestamp now = clock_->CurrentTime();
+ if (now - *last_receive_time_ >= kStatisticsTimeout) {
+ // Not active.
return;
}
@@ -278,9 +283,9 @@
// Only for report blocks in RTCP SR and RR.
last_report_cumulative_loss_ = cumulative_loss_;
last_report_seq_max_ = received_seq_max_;
- BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "cumulative_loss_pkts", now_ms,
+ BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "cumulative_loss_pkts", now.ms(),
cumulative_loss_, ssrc_);
- BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "received_seq_max_pkts", now_ms,
+ BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "received_seq_max_pkts", now.ms(),
(received_seq_max_ - received_seq_first_),
ssrc_);
}
@@ -310,30 +315,26 @@
bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
const RtpPacketReceived& packet,
- int64_t now_ms) const {
- uint32_t frequency_khz = packet.payload_type_frequency() / 1000;
- RTC_DCHECK_GT(frequency_khz, 0);
-
- int64_t time_diff_ms = now_ms - last_receive_time_ms_;
+ Timestamp now) const {
+ int frequency_hz = packet.payload_type_frequency();
+ RTC_DCHECK(last_receive_time_.has_value());
+ RTC_DCHECK_GT(frequency_hz, 0);
+ TimeDelta time_diff = now - *last_receive_time_;
// Diff in time stamp since last received in order.
uint32_t timestamp_diff = packet.Timestamp() - last_received_timestamp_;
- uint32_t rtp_time_stamp_diff_ms = timestamp_diff / frequency_khz;
-
- int64_t max_delay_ms = 0;
+ TimeDelta rtp_time_stamp_diff =
+ TimeDelta::Seconds(timestamp_diff) / frequency_hz;
// Jitter standard deviation in samples.
float jitter_std = std::sqrt(static_cast<float>(jitter_q4_ >> 4));
// 2 times the standard deviation => 95% confidence.
- // And transform to milliseconds by dividing by the frequency in kHz.
- max_delay_ms = static_cast<int64_t>((2 * jitter_std) / frequency_khz);
+ // Min max_delay is 1ms.
+ TimeDelta max_delay = std::max(
+ TimeDelta::Seconds(2 * jitter_std / frequency_hz), TimeDelta::Millis(1));
- // Min max_delay_ms is 1.
- if (max_delay_ms == 0) {
- max_delay_ms = 1;
- }
- return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms;
+ return time_diff > rtp_time_stamp_diff + max_delay;
}
std::unique_ptr<ReceiveStatistics> ReceiveStatistics::Create(Clock* clock) {
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 11853b3..8ec7c96 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -18,6 +18,8 @@
#include <vector>
#include "absl/types/optional.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "modules/rtp_rtcp/include/receive_statistics.h"
#include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
#include "rtc_base/containers/flat_map.h"
@@ -63,21 +65,21 @@
private:
bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet,
- int64_t now_ms) const;
- void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms);
+ Timestamp now) const;
+ void UpdateJitter(const RtpPacketReceived& packet, Timestamp receive_time);
void ReviseFrequencyAndJitter(int payload_type_frequency);
// Updates StreamStatistician for out of order packets.
// Returns true if packet considered to be out of order.
bool UpdateOutOfOrder(const RtpPacketReceived& packet,
int64_t sequence_number,
- int64_t now_ms);
+ Timestamp now);
// Checks if this StreamStatistician received any rtp packets.
- bool ReceivedRtpPacket() const { return received_seq_first_ >= 0; }
+ bool ReceivedRtpPacket() const { return last_receive_time_.has_value(); }
const uint32_t ssrc_;
Clock* const clock_;
// Delta used to map internal timestamps to Unix epoch ones.
- const int64_t delta_internal_unix_epoch_ms_;
+ const TimeDelta delta_internal_unix_epoch_;
RateStatistics incoming_bitrate_;
// In number of packets or sequence numbers.
int max_reordering_threshold_;
@@ -94,7 +96,7 @@
// senders, in particular, our own loss-based bandwidth estimator.
int32_t cumulative_loss_rtcp_offset_;
- int64_t last_receive_time_ms_;
+ absl::optional<Timestamp> last_receive_time_;
uint32_t last_received_timestamp_;
RtpSequenceNumberUnwrapper seq_unwrapper_;
int64_t received_seq_first_;