From 7ab3ecd4c21c48380d7120ca500277fe1779ddb3 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Thu, 24 Mar 2022 18:59:40 +0100 Subject: [PATCH] Use TimeDelta to convert to to/from compact ntp time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: webrtc:13757 Change-Id: I1c5f0a666da8e6b30291763d110ff049df573490 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/256103 Reviewed-by: Åsa Persson Reviewed-by: Björn Terelius Commit-Queue: Danil Chapovalov Cr-Commit-Position: refs/heads/main@{#36333} --- modules/rtp_rtcp/source/rtcp_receiver.cc | 14 +-- .../rtp_rtcp/source/rtcp_receiver_unittest.cc | 118 +++++++++--------- .../rtp_rtcp/source/rtcp_transceiver_impl.cc | 10 +- .../source/rtcp_transceiver_impl_unittest.cc | 23 ++-- modules/rtp_rtcp/source/time_util.cc | 32 ++--- modules/rtp_rtcp/source/time_util.h | 12 +- modules/rtp_rtcp/source/time_util_unittest.cc | 63 +++++----- .../log_simulation.cc | 2 +- 8 files changed, 147 insertions(+), 127 deletions(-) diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc index d0f9596837..6eb8dee2d1 100644 --- a/modules/rtp_rtcp/source/rtcp_receiver.cc +++ b/modules/rtp_rtcp/source/rtcp_receiver.cc @@ -669,7 +669,6 @@ void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block, (clock_->CurrentNtpInMilliseconds() - rtc::kNtpJan1970Millisecs) * rtc::kNumMicrosecsPerMillisec); - int64_t rtt_ms = 0; uint32_t send_time_ntp = report_block.last_sr(); // RFC3550, section 6.4.1, LSR field discription states: // If no SR has been received yet, the field is set to zero. @@ -691,13 +690,13 @@ void RTCPReceiver::HandleReportBlock(const ReportBlock& report_block, // RTT in 1/(2^16) seconds. uint32_t rtt_ntp = receive_time_ntp - delay_ntp - send_time_ntp; // Convert to 1/1000 seconds (milliseconds). - rtt_ms = CompactNtpRttToMs(rtt_ntp); - report_block_data->AddRoundTripTimeSample(rtt_ms); + TimeDelta rtt = CompactNtpRttToTimeDelta(rtt_ntp); + report_block_data->AddRoundTripTimeSample(rtt.ms()); if (report_block.source_ssrc() == main_ssrc_) { - rtts_[remote_ssrc].AddRtt(TimeDelta::Millis(rtt_ms)); + rtts_[remote_ssrc].AddRtt(rtt); } - packet_information->rtt_ms = rtt_ms; + packet_information->rtt_ms = rtt.ms(); } packet_information->report_blocks.push_back( @@ -941,9 +940,10 @@ void RTCPReceiver::HandleXrDlrrReportBlock(uint32_t sender_ssrc, uint32_t now_ntp = CompactNtp(clock_->CurrentNtpTime()); uint32_t rtt_ntp = now_ntp - delay_ntp - send_time_ntp; - xr_rr_rtt_ms_ = CompactNtpRttToMs(rtt_ntp); + TimeDelta rtt = CompactNtpRttToTimeDelta(rtt_ntp); + xr_rr_rtt_ms_ = rtt.ms(); - non_sender_rtts_[sender_ssrc].Update(TimeDelta::Millis(xr_rr_rtt_ms_)); + non_sender_rtts_[sender_ssrc].Update(rtt); } void RTCPReceiver::HandleXrTargetBitrate( diff --git a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc index eb5d265c6a..95dc9df9ae 100644 --- a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc +++ b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc @@ -15,6 +15,7 @@ #include #include "api/array_view.h" +#include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/video/video_bitrate_allocation.h" #include "api/video/video_bitrate_allocator.h" @@ -244,15 +245,15 @@ TEST(RtcpReceiverTest, InjectSrPacketCalculatesRTT) { RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl); receiver.SetRemoteSSRC(kSenderSsrc); - const int64_t kRttMs = 123; + const TimeDelta kRtt = TimeDelta::Millis(123); const uint32_t kDelayNtp = 0x4321; - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); int64_t rtt_ms = 0; EXPECT_EQ(-1, receiver.RTT(kSenderSsrc, &rtt_ms, nullptr, nullptr, nullptr)); uint32_t sent_ntp = CompactNtp(mocks.clock.CurrentNtpTime()); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::SenderReport sr; sr.SetSenderSsrc(kSenderSsrc); @@ -267,7 +268,7 @@ TEST(RtcpReceiverTest, InjectSrPacketCalculatesRTT) { receiver.IncomingPacket(sr.Build()); EXPECT_EQ(0, receiver.RTT(kSenderSsrc, &rtt_ms, nullptr, nullptr, nullptr)); - EXPECT_NEAR(kRttMs, rtt_ms, 1); + EXPECT_NEAR(rtt_ms, kRtt.ms(), 1); } TEST(RtcpReceiverTest, InjectSrPacketCalculatesNegativeRTTAsOne) { @@ -275,15 +276,15 @@ TEST(RtcpReceiverTest, InjectSrPacketCalculatesNegativeRTTAsOne) { RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl); receiver.SetRemoteSSRC(kSenderSsrc); - const int64_t kRttMs = -13; + const TimeDelta kRtt = TimeDelta::Millis(-13); const uint32_t kDelayNtp = 0x4321; - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); int64_t rtt_ms = 0; EXPECT_EQ(-1, receiver.RTT(kSenderSsrc, &rtt_ms, nullptr, nullptr, nullptr)); uint32_t sent_ntp = CompactNtp(mocks.clock.CurrentNtpTime()); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::SenderReport sr; sr.SetSenderSsrc(kSenderSsrc); @@ -308,12 +309,12 @@ TEST(RtcpReceiverTest, RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl); receiver.SetRemoteSSRC(kSenderSsrc); - const int64_t kRttMs = 120; + const TimeDelta kRtt = TimeDelta::Millis(120); const uint32_t kDelayNtp = 123000; - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); uint32_t sent_ntp = CompactNtp(mocks.clock.CurrentNtpTime()); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::SenderReport sr; sr.SetSenderSsrc(kSenderSsrc); @@ -328,7 +329,7 @@ TEST(RtcpReceiverTest, EXPECT_CALL(mocks.rtp_rtcp_impl, OnReceivedRtcpReportBlocks(SizeIs(2))); EXPECT_CALL(mocks.bandwidth_observer, - OnReceivedRtcpReceiverReport(SizeIs(2), kRttMs, _)); + OnReceivedRtcpReceiverReport(SizeIs(2), kRtt.ms(), _)); receiver.IncomingPacket(sr.Build()); } @@ -830,7 +831,7 @@ TEST(RtcpReceiverTest, InjectExtendedReportsDlrrPacketWithSubBlock) { uint32_t compact_ntp_now = CompactNtp(mocks.clock.CurrentNtpTime()); EXPECT_TRUE(receiver.GetAndResetXrRrRtt(&rtt_ms)); uint32_t rtt_ntp = compact_ntp_now - kDelay - kLastRR; - EXPECT_NEAR(CompactNtpRttToMs(rtt_ntp), rtt_ms, 1); + EXPECT_NEAR(CompactNtpRttToTimeDelta(rtt_ntp).ms(), rtt_ms, 1); RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_GT(non_sender_rtt_stats.round_trip_time(), TimeDelta::Zero()); @@ -860,7 +861,7 @@ TEST(RtcpReceiverTest, InjectExtendedReportsDlrrPacketWithMultipleSubBlocks) { int64_t rtt_ms = 0; EXPECT_TRUE(receiver.GetAndResetXrRrRtt(&rtt_ms)); uint32_t rtt_ntp = compact_ntp_now - kDelay - kLastRR; - EXPECT_NEAR(CompactNtpRttToMs(rtt_ntp), rtt_ms, 1); + EXPECT_NEAR(CompactNtpRttToTimeDelta(rtt_ntp).ms(), rtt_ms, 1); RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_GT(non_sender_rtt_stats.round_trip_time(), TimeDelta::Zero()); @@ -947,12 +948,12 @@ TEST(RtcpReceiverTest, RttCalculatedAfterExtendedReportsDlrr) { receiver.SetRemoteSSRC(kSenderSsrc); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -962,7 +963,7 @@ TEST(RtcpReceiverTest, RttCalculatedAfterExtendedReportsDlrr) { int64_t rtt_ms = 0; EXPECT_TRUE(receiver.GetAndResetXrRrRtt(&rtt_ms)); - EXPECT_NEAR(kRttMs, rtt_ms, 1); + EXPECT_NEAR(kRtt.ms(), rtt_ms, 1); RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); @@ -982,12 +983,12 @@ TEST(RtcpReceiverTest, SetterEnablesReceiverRtt) { receiver.SetNonSenderRttMeasurement(true); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -997,7 +998,7 @@ TEST(RtcpReceiverTest, SetterEnablesReceiverRtt) { int64_t rtt_ms = 0; EXPECT_TRUE(receiver.GetAndResetXrRrRtt(&rtt_ms)); - EXPECT_NEAR(rtt_ms, kRttMs, 1); + EXPECT_NEAR(rtt_ms, kRtt.ms(), 1); RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); @@ -1017,12 +1018,12 @@ TEST(RtcpReceiverTest, DoesntCalculateRttOnReceivedDlrr) { receiver.SetNonSenderRttMeasurement(false); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -1048,12 +1049,12 @@ TEST(RtcpReceiverTest, XrDlrrCalculatesNegativeRttAsOne) { receiver.SetRemoteSSRC(kSenderSsrc); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(-3600 * 1000, -1); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(-3600 * 1000, -1)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -1081,12 +1082,12 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleMeasurements) { receiver.SetRemoteSSRC(kSenderSsrc); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -1099,7 +1100,7 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleMeasurements) { RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); - EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRttMs, 1); + EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRtt.ms(), 1); EXPECT_EQ(non_sender_rtt_stats.round_trip_time_measurements(), 1); EXPECT_EQ(non_sender_rtt_stats.total_round_trip_time().ms(), non_sender_rtt_stats.round_trip_time()->ms()); @@ -1107,7 +1108,7 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleMeasurements) { // Generate another XR report with the same RTT and delay. NtpTime now2 = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp2 = CompactNtp(now2); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr2; xr2.SetSenderSsrc(kSenderSsrc); @@ -1119,9 +1120,10 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleMeasurements) { // the values are as expected. non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); - EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRttMs, 1); + EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRtt.ms(), 1); EXPECT_EQ(non_sender_rtt_stats.round_trip_time_measurements(), 2); - EXPECT_NEAR(non_sender_rtt_stats.total_round_trip_time().ms(), 2 * kRttMs, 2); + EXPECT_NEAR(non_sender_rtt_stats.total_round_trip_time().ms(), 2 * kRtt.ms(), + 2); } // Test that the receiver RTT stat resets when receiving a SR without XR. This @@ -1135,12 +1137,12 @@ TEST(RtcpReceiverTest, ReceiverRttResetOnSrWithoutXr) { receiver.SetRemoteSSRC(kSenderSsrc); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -1151,7 +1153,7 @@ TEST(RtcpReceiverTest, ReceiverRttResetOnSrWithoutXr) { RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); - EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRttMs, 1); + EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRtt.ms(), 1); // Generate a SR without XR. rtcp::ReportBlock rb; @@ -1180,12 +1182,12 @@ TEST(RtcpReceiverTest, ReceiverRttResetOnDlrrWithZeroTimestamp) { receiver.SetRemoteSSRC(kSenderSsrc); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -1196,12 +1198,12 @@ TEST(RtcpReceiverTest, ReceiverRttResetOnDlrrWithZeroTimestamp) { RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); - EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRttMs, 1); + EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRtt.ms(), 1); // Generate an XR+DLRR with zero timestamp. rtcp::ExtendedReports xr2; xr2.SetSenderSsrc(kSenderSsrc); - xr2.AddDlrrItem(ReceiveTimeInfo(kReceiverMainSsrc, 0, kDelayMs)); + xr2.AddDlrrItem(ReceiveTimeInfo(kReceiverMainSsrc, 0, kDelayNtp)); receiver.IncomingPacket(xr2.Build()); @@ -1220,12 +1222,12 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleRemoteSsrcs) { receiver.SetNonSenderRttMeasurement(true); Random rand(0x0123456789abcdef); - const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); NtpTime now = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp = CompactNtp(now); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::ExtendedReports xr; xr.SetSenderSsrc(kSenderSsrc); @@ -1234,12 +1236,12 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleRemoteSsrcs) { receiver.IncomingPacket(xr.Build()); // Generate an XR report for another SSRC. - const int64_t kRttMs2 = rand.Rand(1, 9 * 3600 * 1000); + const TimeDelta kRtt2 = TimeDelta::Millis(rand.Rand(1, 9 * 3600 * 1000)); const uint32_t kDelayNtp2 = rand.Rand(0, 0x7fffffff); - const int64_t kDelayMs2 = CompactNtpRttToMs(kDelayNtp2); + const TimeDelta kDelay2 = CompactNtpRttToTimeDelta(kDelayNtp2); NtpTime now2 = mocks.clock.CurrentNtpTime(); uint32_t sent_ntp2 = CompactNtp(now2); - mocks.clock.AdvanceTimeMilliseconds(kRttMs2 + kDelayMs2); + mocks.clock.AdvanceTime(kRtt2 + kDelay2); rtcp::ExtendedReports xr2; xr2.SetSenderSsrc(kSenderSsrc + 1); @@ -1251,7 +1253,7 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleRemoteSsrcs) { RTCPReceiver::NonSenderRttStats non_sender_rtt_stats = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats.round_trip_time().has_value()); - EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRttMs, 1); + EXPECT_NEAR(non_sender_rtt_stats.round_trip_time()->ms(), kRtt.ms(), 1); EXPECT_FALSE(non_sender_rtt_stats.total_round_trip_time().IsZero()); EXPECT_GT(non_sender_rtt_stats.round_trip_time_measurements(), 0); @@ -1260,7 +1262,7 @@ TEST(RtcpReceiverTest, ReceiverRttWithMultipleRemoteSsrcs) { RTCPReceiver::NonSenderRttStats non_sender_rtt_stats2 = receiver.GetNonSenderRTT(); EXPECT_TRUE(non_sender_rtt_stats2.round_trip_time().has_value()); - EXPECT_NEAR(non_sender_rtt_stats2.round_trip_time()->ms(), kRttMs2, 1); + EXPECT_NEAR(non_sender_rtt_stats2.round_trip_time()->ms(), kRtt2.ms(), 1); EXPECT_FALSE(non_sender_rtt_stats2.total_round_trip_time().IsZero()); EXPECT_GT(non_sender_rtt_stats2.round_trip_time_measurements(), 0); } @@ -1615,12 +1617,12 @@ TEST(RtcpReceiverTest, VerifyRttObtainedFromReportBlockDataObserver) { RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl); receiver.SetRemoteSSRC(kSenderSsrc); - const int64_t kRttMs = 120; + const TimeDelta kRtt = TimeDelta::Millis(120); const uint32_t kDelayNtp = 123000; - const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp); + const TimeDelta kDelay = CompactNtpRttToTimeDelta(kDelayNtp); uint32_t sent_ntp = CompactNtp(mocks.clock.CurrentNtpTime()); - mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs); + mocks.clock.AdvanceTime(kRtt + kDelay); rtcp::SenderReport sr; sr.SetSenderSsrc(kSenderSsrc); @@ -1641,10 +1643,10 @@ TEST(RtcpReceiverTest, VerifyRttObtainedFromReportBlockDataObserver) { EXPECT_EQ(kReceiverMainSsrc, report_block_data.report_block().source_ssrc); EXPECT_EQ(1u, report_block_data.num_rtts()); - EXPECT_EQ(kRttMs, report_block_data.min_rtt_ms()); - EXPECT_EQ(kRttMs, report_block_data.max_rtt_ms()); - EXPECT_EQ(kRttMs, report_block_data.sum_rtt_ms()); - EXPECT_EQ(kRttMs, report_block_data.last_rtt_ms()); + EXPECT_EQ(kRtt.ms(), report_block_data.min_rtt_ms()); + EXPECT_EQ(kRtt.ms(), report_block_data.max_rtt_ms()); + EXPECT_EQ(kRtt.ms(), report_block_data.sum_rtt_ms()); + EXPECT_EQ(kRtt.ms(), report_block_data.last_rtt_ms()); }); EXPECT_CALL(observer, OnReportBlockDataUpdated) .WillOnce([](ReportBlockData report_block_data) { diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc index ccce613e45..967777f1f5 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc +++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc @@ -446,8 +446,8 @@ void RtcpTransceiverImpl::HandleDlrr(const rtcp::Dlrr& dlrr, Timestamp now) { if (rti.ssrc != config_.feedback_ssrc) continue; uint32_t rtt_ntp = receive_time_ntp - rti.delay_since_last_rr - rti.last_rr; - int64_t rtt_ms = CompactNtpRttToMs(rtt_ntp); - config_.network_link_observer->OnRttUpdate(now, TimeDelta::Millis(rtt_ms)); + TimeDelta rtt = CompactNtpRttToTimeDelta(rtt_ntp); + config_.network_link_observer->OnRttUpdate(now, rtt); } } @@ -472,7 +472,7 @@ void RtcpTransceiverImpl::ProcessReportBlocks( uint32_t rtt_ntp = receive_time_ntp - report_block.delay_since_last_sr() - report_block.last_sr(); - rtt_sum += TimeDelta::Millis(CompactNtpRttToMs(rtt_ntp)); + rtt_sum += CompactNtpRttToTimeDelta(rtt_ntp); ++num_rtts; } // For backward compatibility, do not report rtt based on report blocks to the @@ -788,8 +788,8 @@ std::vector RtcpTransceiverImpl::CreateReportBlocks( const SenderReportTimes& last_sender_report = *it->second.last_received_sender_report; last_sr = CompactNtp(last_sender_report.remote_sent_time); - last_delay = SaturatedUsToCompactNtp( - now.us() - last_sender_report.local_received_time.us()); + last_delay = + SaturatedToCompactNtp(now - last_sender_report.local_received_time); report_block.SetLastSr(last_sr); report_block.SetDelayLastSr(last_delay); } diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc index 5da10c898a..8161d74b21 100644 --- a/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc +++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl_unittest.cc @@ -123,6 +123,12 @@ constexpr TimeDelta kReportPeriod = TimeDelta::Millis(10); // Use finite timeout to fail tests rather than hang them. constexpr int kAlmostForeverMs = 1000; +constexpr TimeDelta kTimePrecision = TimeDelta::Millis(1); + +MATCHER_P(Near, value, "") { + return arg > value - kTimePrecision && arg < value + kTimePrecision; +} + // Helper to wait for an rtcp packet produced on a different thread/task queue. class FakeRtcpTransport : public webrtc::Transport { public: @@ -967,10 +973,12 @@ TEST(RtcpTransceiverImplTest, // match result of ReceiveStatisticsProvider::RtcpReportBlocks callback, // but for simplicity of the test asume it is the same. ASSERT_EQ(report_blocks[0].source_ssrc(), kRemoteSsrc1); - EXPECT_EQ(CompactNtpRttToMs(report_blocks[0].delay_since_last_sr()), 200); + EXPECT_THAT(CompactNtpRttToTimeDelta(report_blocks[0].delay_since_last_sr()), + Near(TimeDelta::Millis(200))); ASSERT_EQ(report_blocks[1].source_ssrc(), kRemoteSsrc2); - EXPECT_EQ(CompactNtpRttToMs(report_blocks[1].delay_since_last_sr()), 100); + EXPECT_THAT(CompactNtpRttToTimeDelta(report_blocks[1].delay_since_last_sr()), + Near(TimeDelta::Millis(100))); } TEST(RtcpTransceiverImplTest, MaySendMultipleReceiverReportInSinglePacket) { @@ -1330,11 +1338,12 @@ TEST(RtcpTransceiverImplTest, PassRttFromDlrrToLinkObserver) { rtcp::ReceiveTimeInfo rti; rti.ssrc = kSenderSsrc; rti.last_rr = CompactNtp(config.clock->ConvertTimestampToNtpTime(send_time)); - rti.delay_since_last_rr = SaturatedUsToCompactNtp(10'000); // 10ms + rti.delay_since_last_rr = SaturatedToCompactNtp(TimeDelta::Millis(10)); rtcp::ExtendedReports xr; xr.AddDlrrItem(rti); - EXPECT_CALL(link_observer, OnRttUpdate(receive_time, TimeDelta::Millis(100))); + EXPECT_CALL(link_observer, + OnRttUpdate(receive_time, Near(TimeDelta::Millis(100)))); rtcp_transceiver.ReceivePacket(xr.Build(), receive_time); } @@ -1351,15 +1360,15 @@ TEST(RtcpTransceiverImplTest, CalculatesRoundTripTimeFromReportBlocks) { rtcp::ReportBlock rb1; rb1.SetLastSr(CompactNtp(config.clock->ConvertTimestampToNtpTime( receive_time - rtt - TimeDelta::Millis(10)))); - rb1.SetDelayLastSr(SaturatedUsToCompactNtp(10'000)); // 10ms + rb1.SetDelayLastSr(SaturatedToCompactNtp(TimeDelta::Millis(10))); rr.AddReportBlock(rb1); rtcp::ReportBlock rb2; rb2.SetLastSr(CompactNtp(config.clock->ConvertTimestampToNtpTime( receive_time - rtt - TimeDelta::Millis(20)))); - rb2.SetDelayLastSr(SaturatedUsToCompactNtp(20'000)); // 20ms + rb2.SetDelayLastSr(SaturatedToCompactNtp(TimeDelta::Millis(20))); rr.AddReportBlock(rb2); - EXPECT_CALL(link_observer, OnRttUpdate(receive_time, rtt)); + EXPECT_CALL(link_observer, OnRttUpdate(receive_time, Near(rtt))); rtcp_transceiver.ReceivePacket(rr.Build(), receive_time); } diff --git a/modules/rtp_rtcp/source/time_util.cc b/modules/rtp_rtcp/source/time_util.cc index fe0cfea11f..44ca07dabe 100644 --- a/modules/rtp_rtcp/source/time_util.cc +++ b/modules/rtp_rtcp/source/time_util.cc @@ -18,35 +18,37 @@ namespace webrtc { -uint32_t SaturatedUsToCompactNtp(int64_t us) { +uint32_t SaturatedToCompactNtp(TimeDelta delta) { constexpr uint32_t kMaxCompactNtp = 0xFFFFFFFF; constexpr int kCompactNtpInSecond = 0x10000; - if (us <= 0) + if (delta <= TimeDelta::Zero()) return 0; - if (us >= kMaxCompactNtp * rtc::kNumMicrosecsPerSec / kCompactNtpInSecond) + if (delta.us() >= + kMaxCompactNtp * rtc::kNumMicrosecsPerSec / kCompactNtpInSecond) return kMaxCompactNtp; // To convert to compact ntp need to divide by 1e6 to get seconds, // then multiply by 0x10000 to get the final result. // To avoid float operations, multiplication and division swapped. - return DivideRoundToNearest(us * kCompactNtpInSecond, + return DivideRoundToNearest(delta.us() * kCompactNtpInSecond, rtc::kNumMicrosecsPerSec); } -int64_t CompactNtpRttToMs(uint32_t compact_ntp_interval) { - // Interval to convert expected to be positive, e.g. rtt or delay. +TimeDelta CompactNtpRttToTimeDelta(uint32_t compact_ntp_interval) { + static constexpr TimeDelta kMinRtt = TimeDelta::Millis(1); + // Interval to convert expected to be positive, e.g. RTT or delay. // Because interval can be derived from non-monotonic ntp clock, // it might become negative that is indistinguishable from very large values. - // Since very large rtt/delay are less likely than non-monotonic ntp clock, - // those values consider to be negative and convert to minimum value of 1ms. + // Since very large RTT/delay is less likely than non-monotonic ntp clock, + // such value is considered negative and converted to minimum value of 1ms. if (compact_ntp_interval > 0x80000000) - return 1; + return kMinRtt; // Convert to 64bit value to avoid multiplication overflow. int64_t value = static_cast(compact_ntp_interval); - // To convert to milliseconds need to divide by 2^16 to get seconds, - // then multiply by 1000 to get milliseconds. To avoid float operations, - // multiplication and division swapped. - int64_t ms = DivideRoundToNearest(value * 1000, 1 << 16); - // Rtt value 0 considered too good to be true and increases to 1. - return std::max(ms, 1); + // To convert to TimeDelta need to divide by 2^16 to get seconds, + // then multiply by 1'000'000 to get microseconds. To avoid float operations, + // multiplication and division are swapped. + int64_t us = DivideRoundToNearest(value * rtc::kNumMicrosecsPerSec, 1 << 16); + // Small RTT value is considered too good to be true and increased to 1ms. + return std::max(TimeDelta::Micros(us), kMinRtt); } } // namespace webrtc diff --git a/modules/rtp_rtcp/source/time_util.h b/modules/rtp_rtcp/source/time_util.h index c883e5ca38..fba2dd9ff4 100644 --- a/modules/rtp_rtcp/source/time_util.h +++ b/modules/rtp_rtcp/source/time_util.h @@ -13,6 +13,7 @@ #include +#include "api/units/time_delta.h" #include "system_wrappers/include/ntp_time.h" namespace webrtc { @@ -29,14 +30,15 @@ inline uint32_t CompactNtp(NtpTime ntp) { return (ntp.seconds() << 16) | (ntp.fractions() >> 16); } -// Converts interval in microseconds to compact ntp (1/2^16 seconds) resolution. +// Converts interval to compact ntp (1/2^16 seconds) resolution. // Negative values converted to 0, Overlarge values converted to max uint32_t. -uint32_t SaturatedUsToCompactNtp(int64_t us); +uint32_t SaturatedToCompactNtp(TimeDelta delta); -// Converts interval between compact ntp timestamps to milliseconds. +// Converts interval from compact ntp (1/2^16 seconds) resolution to TimeDelta. // This interval can be up to ~9.1 hours (2^15 seconds). -// Values close to 2^16 seconds consider negative and result in minimum rtt = 1. -int64_t CompactNtpRttToMs(uint32_t compact_ntp_interval); +// Values close to 2^16 seconds are considered negative and are converted to +// minimum value of 1ms. +TimeDelta CompactNtpRttToTimeDelta(uint32_t compact_ntp_interval); } // namespace webrtc #endif // MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ diff --git a/modules/rtp_rtcp/source/time_util_unittest.cc b/modules/rtp_rtcp/source/time_util_unittest.cc index 6ff55dda55..983155e8a3 100644 --- a/modules/rtp_rtcp/source/time_util_unittest.cc +++ b/modules/rtp_rtcp/source/time_util_unittest.cc @@ -21,18 +21,16 @@ TEST(TimeUtilTest, CompactNtp) { EXPECT_EQ(kNtpMid, CompactNtp(kNtp)); } -TEST(TimeUtilTest, CompactNtpRttToMs) { +TEST(TimeUtilTest, CompactNtpRttToTimeDelta) { const NtpTime ntp1(0x12345, 0x23456); const NtpTime ntp2(0x12654, 0x64335); int64_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); - int64_t ntp_to_ms_diff = CompactNtpRttToMs(ntp_diff); - - EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); + EXPECT_NEAR(CompactNtpRttToTimeDelta(ntp_diff).ms(), ms_diff, 1); } -TEST(TimeUtilTest, CompactNtpRttToMsWithWrap) { +TEST(TimeUtilTest, CompactNtpRttToTimeDeltaWithWrap) { const NtpTime ntp1(0x1ffff, 0x23456); const NtpTime ntp2(0x20000, 0x64335); int64_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); @@ -43,51 +41,58 @@ TEST(TimeUtilTest, CompactNtpRttToMsWithWrap) { ASSERT_LT(CompactNtp(ntp2), CompactNtp(ntp1)); uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); - int64_t ntp_to_ms_diff = CompactNtpRttToMs(ntp_diff); - - EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); + EXPECT_NEAR(CompactNtpRttToTimeDelta(ntp_diff).ms(), ms_diff, 1); } -TEST(TimeUtilTest, CompactNtpRttToMsLarge) { +TEST(TimeUtilTest, CompactNtpRttToTimeDeltaLarge) { const NtpTime ntp1(0x10000, 0x00006); const NtpTime ntp2(0x17fff, 0xffff5); int64_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); // Ntp difference close to 2^15 seconds should convert correctly too. ASSERT_NEAR(ms_diff, ((1 << 15) - 1) * 1000, 1); uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); - int64_t ntp_to_ms_diff = CompactNtpRttToMs(ntp_diff); - - EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); + EXPECT_NEAR(CompactNtpRttToTimeDelta(ntp_diff).ms(), ms_diff, 1); } -TEST(TimeUtilTest, CompactNtpRttToMsNegative) { +TEST(TimeUtilTest, CompactNtpRttToTimeDeltaNegative) { const NtpTime ntp1(0x20000, 0x23456); const NtpTime ntp2(0x1ffff, 0x64335); int64_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); ASSERT_GT(0, ms_diff); // Ntp difference close to 2^16 seconds should be treated as negative. uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); - int64_t ntp_to_ms_diff = CompactNtpRttToMs(ntp_diff); - EXPECT_EQ(1, ntp_to_ms_diff); + EXPECT_EQ(CompactNtpRttToTimeDelta(ntp_diff), TimeDelta::Millis(1)); } -TEST(TimeUtilTest, SaturatedUsToCompactNtp) { +TEST(TimeUtilTest, SaturatedToCompactNtp) { // Converts negative to zero. - EXPECT_EQ(SaturatedUsToCompactNtp(-1), 0u); - EXPECT_EQ(SaturatedUsToCompactNtp(0), 0u); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Micros(-1)), 0u); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Zero()), 0u); // Converts values just above and just below max uint32_t. - EXPECT_EQ(SaturatedUsToCompactNtp(65536000000), 0xffffffff); - EXPECT_EQ(SaturatedUsToCompactNtp(65535999985), 0xffffffff); - EXPECT_EQ(SaturatedUsToCompactNtp(65535999970), 0xfffffffe); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Micros(65536000000)), 0xffffffff); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Micros(65535999985)), 0xffffffff); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Micros(65535999970)), 0xfffffffe); // Converts half-seconds. - EXPECT_EQ(SaturatedUsToCompactNtp(500000), 0x8000u); - EXPECT_EQ(SaturatedUsToCompactNtp(1000000), 0x10000u); - EXPECT_EQ(SaturatedUsToCompactNtp(1500000), 0x18000u); - // Convert us -> compact_ntp -> ms. Compact ntp precision is ~15us. - EXPECT_EQ(CompactNtpRttToMs(SaturatedUsToCompactNtp(1516)), 2); - EXPECT_EQ(CompactNtpRttToMs(SaturatedUsToCompactNtp(15000)), 15); - EXPECT_EQ(CompactNtpRttToMs(SaturatedUsToCompactNtp(5485)), 5); - EXPECT_EQ(CompactNtpRttToMs(SaturatedUsToCompactNtp(5515)), 6); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Millis(500)), 0x8000u); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Seconds(1)), 0x10000u); + EXPECT_EQ(SaturatedToCompactNtp(TimeDelta::Millis(1'500)), 0x18000u); + // Convert us -> compact_ntp -> TimeDelta. Compact ntp precision is ~15us. + EXPECT_NEAR( + CompactNtpRttToTimeDelta(SaturatedToCompactNtp(TimeDelta::Micros(1'516))) + .us(), + 1'516, 16); + EXPECT_NEAR( + CompactNtpRttToTimeDelta(SaturatedToCompactNtp(TimeDelta::Millis(15))) + .us(), + 15'000, 16); + EXPECT_NEAR( + CompactNtpRttToTimeDelta(SaturatedToCompactNtp(TimeDelta::Micros(5'485))) + .us(), + 5'485, 16); + EXPECT_NEAR( + CompactNtpRttToTimeDelta(SaturatedToCompactNtp(TimeDelta::Micros(5'515))) + .us(), + 5'515, 16); } } // namespace webrtc diff --git a/rtc_tools/rtc_event_log_visualizer/log_simulation.cc b/rtc_tools/rtc_event_log_visualizer/log_simulation.cc index c0b418de4b..30c4de199a 100644 --- a/rtc_tools/rtc_event_log_visualizer/log_simulation.cc +++ b/rtc_tools/rtc_event_log_visualizer/log_simulation.cc @@ -152,7 +152,7 @@ void LogBasedNetworkControllerSimulation::OnReceiverReport( CompactNtp(clock->ConvertTimestampToNtpTime(report_log_time)); uint32_t rtt_ntp = receive_time_ntp - rb.delay_since_last_sr() - rb.last_sr(); - rtt = std::min(rtt, TimeDelta::Millis(CompactNtpRttToMs(rtt_ntp))); + rtt = std::min(rtt, CompactNtpRttToTimeDelta(rtt_ntp)); } } if (rtt.IsFinite()) {