diff --git a/webrtc/call/call_perf_tests.cc b/webrtc/call/call_perf_tests.cc index e03c26dae1..782b45c9f2 100644 --- a/webrtc/call/call_perf_tests.cc +++ b/webrtc/call/call_perf_tests.cc @@ -24,7 +24,6 @@ #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/system_wrappers/include/metrics_default.h" -#include "webrtc/system_wrappers/include/rtp_to_ntp.h" #include "webrtc/test/call_test.h" #include "webrtc/test/direct_transport.h" #include "webrtc/test/drifting_clock.h" diff --git a/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h b/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h index cab488f3ea..118df4c4cf 100644 --- a/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h +++ b/webrtc/modules/rtp_rtcp/include/remote_ntp_time_estimator.h @@ -14,7 +14,7 @@ #include #include "webrtc/base/constructormagic.h" -#include "webrtc/system_wrappers/include/rtp_to_ntp.h" +#include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h" namespace webrtc { @@ -43,7 +43,7 @@ class RemoteNtpTimeEstimator { private: Clock* clock_; std::unique_ptr ts_extrapolator_; - RtcpMeasurements rtcp_list_; + RtpToNtpEstimator rtp_to_ntp_; int64_t last_timing_log_ms_; RTC_DISALLOW_COPY_AND_ASSIGN(RemoteNtpTimeEstimator); }; diff --git a/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc b/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc index 69a8f2391f..c78a8bc844 100644 --- a/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc +++ b/webrtc/modules/rtp_rtcp/source/remote_ntp_time_estimator.cc @@ -33,8 +33,8 @@ bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(int64_t rtt, uint32_t ntp_frac, uint32_t rtcp_timestamp) { bool new_rtcp_sr = false; - if (!UpdateRtcpList( - ntp_secs, ntp_frac, rtcp_timestamp, &rtcp_list_, &new_rtcp_sr)) { + if (!rtp_to_ntp_.UpdateMeasurements(ntp_secs, ntp_frac, rtcp_timestamp, + &new_rtcp_sr)) { return false; } if (!new_rtcp_sr) { @@ -52,7 +52,7 @@ bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(int64_t rtt, int64_t RemoteNtpTimeEstimator::Estimate(uint32_t rtp_timestamp) { int64_t sender_capture_ntp_ms = 0; - if (!RtpToNtpMs(rtp_timestamp, rtcp_list_, &sender_capture_ntp_ms)) { + if (!rtp_to_ntp_.Estimate(rtp_timestamp, &sender_capture_ntp_ms)) { return -1; } uint32_t timestamp = sender_capture_ntp_ms * 90; diff --git a/webrtc/system_wrappers/BUILD.gn b/webrtc/system_wrappers/BUILD.gn index 7f56fd8dcb..745867bf91 100644 --- a/webrtc/system_wrappers/BUILD.gn +++ b/webrtc/system_wrappers/BUILD.gn @@ -28,7 +28,7 @@ rtc_static_library("system_wrappers") { "include/logging.h", "include/metrics.h", "include/ntp_time.h", - "include/rtp_to_ntp.h", + "include/rtp_to_ntp_estimator.h", "include/rw_lock_wrapper.h", "include/sleep.h", "include/static_instance.h", @@ -50,7 +50,7 @@ rtc_static_library("system_wrappers") { "source/event_timer_win.h", "source/file_impl.cc", "source/logging.cc", - "source/rtp_to_ntp.cc", + "source/rtp_to_ntp_estimator.cc", "source/rw_lock.cc", "source/rw_lock_posix.cc", "source/rw_lock_posix.h", @@ -179,7 +179,7 @@ if (rtc_include_tests) { "source/metrics_default_unittest.cc", "source/metrics_unittest.cc", "source/ntp_time_unittest.cc", - "source/rtp_to_ntp_unittest.cc", + "source/rtp_to_ntp_estimator_unittest.cc", "source/stringize_macros_unittest.cc", ] configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] diff --git a/webrtc/system_wrappers/include/rtp_to_ntp.h b/webrtc/system_wrappers/include/rtp_to_ntp.h deleted file mode 100644 index c1e7ab603e..0000000000 --- a/webrtc/system_wrappers/include/rtp_to_ntp.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_H_ -#define SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_H_ - -#include - -#include "webrtc/system_wrappers/include/ntp_time.h" -#include "webrtc/typedefs.h" - -namespace webrtc { - -struct RtcpMeasurement { - RtcpMeasurement(); - RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp); - bool IsEqual(const RtcpMeasurement& other) const; - - NtpTime ntp_time; - uint32_t rtp_timestamp; -}; - -struct RtcpMeasurements { - RtcpMeasurements(); - ~RtcpMeasurements(); - bool Contains(const RtcpMeasurement& other) const; - bool IsValid(const RtcpMeasurement& other) const; - void UpdateParameters(); - - // Estimated parameters from RTP and NTP timestamp pairs in |list|. - struct RtpToNtpParameters { - double frequency_khz = 0.0; - double offset_ms = 0.0; - bool calculated = false; - }; - - std::list list; - RtpToNtpParameters params; -}; - -// Updates |list| in |rtcp_measurements| with timestamps from the RTCP SR. -// |new_rtcp_sr| will be set to true if these are the timestamps which have -// never be added to |list|. -// |rtcp_measurements.params| are estimated from the RTP and NTP timestamp pairs -// in the |list| when a new RTCP SR is inserted. -bool UpdateRtcpList(uint32_t ntp_secs, - uint32_t ntp_frac, - uint32_t rtp_timestamp, - RtcpMeasurements* rtcp_measurements, - bool* new_rtcp_sr); - -// Converts an RTP timestamp to the NTP domain in milliseconds using the -// estimated |rtcp_measurements.params|. -bool RtpToNtpMs(int64_t rtp_timestamp, - const RtcpMeasurements& rtcp_measurements, - int64_t* rtp_timestamp_in_ms); - -// Returns 1 there has been a forward wrap around, 0 if there has been no wrap -// around and -1 if there has been a backwards wrap around (i.e. reordering). -int CheckForWrapArounds(uint32_t rtp_timestamp, uint32_t rtcp_rtp_timestamp); - -} // namespace webrtc - -#endif // SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_H_ diff --git a/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h b/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h new file mode 100644 index 0000000000..a17428bf27 --- /dev/null +++ b/webrtc/system_wrappers/include/rtp_to_ntp_estimator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_ + +#include + +#include "webrtc/system_wrappers/include/ntp_time.h" +#include "webrtc/typedefs.h" + +namespace webrtc { +// Class for converting an RTP timestamp to the NTP domain in milliseconds. +// The class needs to be trained with (at least 2) RTP/NTP timestamp pairs from +// RTCP sender reports before the convertion can be done. +class RtpToNtpEstimator { + public: + RtpToNtpEstimator(); + ~RtpToNtpEstimator(); + + // RTP and NTP timestamp pair from a RTCP SR report. + struct RtcpMeasurement { + RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp); + bool IsEqual(const RtcpMeasurement& other) const; + + NtpTime ntp_time; + uint32_t rtp_timestamp; + }; + + // Estimated parameters from RTP and NTP timestamp pairs in |measurements_|. + struct Parameters { + double frequency_khz = 0.0; + double offset_ms = 0.0; + bool calculated = false; + }; + + // Updates measurements with RTP/NTP timestamp pair from a RTCP sender report. + // |new_rtcp_sr| is set to true if a new report is added. + bool UpdateMeasurements(uint32_t ntp_secs, + uint32_t ntp_frac, + uint32_t rtp_timestamp, + bool* new_rtcp_sr); + + // Converts an RTP timestamp to the NTP domain in milliseconds. + // Returns true on success, false otherwise. + bool Estimate(int64_t rtp_timestamp, int64_t* rtp_timestamp_ms) const; + + const Parameters& params() const { return params_; } + + private: + void UpdateParameters(); + + std::list measurements_; + Parameters params_; +}; + +// Returns: +// 1: forward wrap around. +// 0: no wrap around. +// -1: backwards wrap around (i.e. reordering). +int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp); + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_RTP_TO_NTP_ESTIMATOR_H_ diff --git a/webrtc/system_wrappers/source/rtp_to_ntp.cc b/webrtc/system_wrappers/source/rtp_to_ntp_estimator.cc similarity index 55% rename from webrtc/system_wrappers/source/rtp_to_ntp.cc rename to webrtc/system_wrappers/source/rtp_to_ntp_estimator.cc index cbd5020a1f..339635e88d 100644 --- a/webrtc/system_wrappers/source/rtp_to_ntp.cc +++ b/webrtc/system_wrappers/source/rtp_to_ntp_estimator.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/system_wrappers/include/rtp_to_ntp.h" +#include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h" #include "webrtc/base/logging.h" #include "webrtc/system_wrappers/include/clock.h" @@ -19,16 +19,16 @@ namespace { const size_t kNumRtcpReportsToUse = 2; // Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps. -bool CalculateFrequency(int64_t rtcp_ntp_ms1, +bool CalculateFrequency(int64_t ntp_ms1, uint32_t rtp_timestamp1, - int64_t rtcp_ntp_ms2, + int64_t ntp_ms2, uint32_t rtp_timestamp2, double* frequency_khz) { - if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) { + if (ntp_ms1 <= ntp_ms2) return false; - } + *frequency_khz = static_cast(rtp_timestamp1 - rtp_timestamp2) / - static_cast(rtcp_ntp_ms1 - rtcp_ntp_ms2); + static_cast(ntp_ms1 - ntp_ms2); return true; } @@ -45,133 +45,126 @@ bool CompensateForWrapAround(uint32_t new_timestamp, *compensated_timestamp = new_timestamp + (wraps << 32); return true; } -} // namespace -// Class holding RTP and NTP timestamp from a RTCP SR report. -RtcpMeasurement::RtcpMeasurement() : ntp_time(0, 0), rtp_timestamp(0) {} - -RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, - uint32_t ntp_frac, - uint32_t timestamp) - : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {} - -bool RtcpMeasurement::IsEqual(const RtcpMeasurement& other) const { - // Use || since two equal timestamps will result in zero frequency and in - // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency. - return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp); -} - -// Class holding list of RTP and NTP timestamp pairs. -RtcpMeasurements::RtcpMeasurements() {} -RtcpMeasurements::~RtcpMeasurements() {} - -bool RtcpMeasurements::Contains(const RtcpMeasurement& other) const { - for (const auto& it : list) { - if (it.IsEqual(other)) +bool Contains(const std::list& measurements, + const RtpToNtpEstimator::RtcpMeasurement& other) { + for (const auto& measurement : measurements) { + if (measurement.IsEqual(other)) return true; } return false; } -bool RtcpMeasurements::IsValid(const RtcpMeasurement& other) const { +bool IsValid(const std::list& measurements, + const RtpToNtpEstimator::RtcpMeasurement& other) { if (!other.ntp_time.Valid()) return false; int64_t ntp_ms_new = other.ntp_time.ToMs(); - for (const auto& it : list) { - if (ntp_ms_new <= it.ntp_time.ToMs()) { + for (const auto& measurement : measurements) { + if (ntp_ms_new <= measurement.ntp_time.ToMs()) { // Old report. return false; } int64_t timestamp_new = other.rtp_timestamp; - if (!CompensateForWrapAround(timestamp_new, it.rtp_timestamp, + if (!CompensateForWrapAround(timestamp_new, measurement.rtp_timestamp, ×tamp_new)) { return false; } - if (timestamp_new <= it.rtp_timestamp) { + if (timestamp_new <= measurement.rtp_timestamp) { LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp."; return false; } } return true; } +} // namespace -void RtcpMeasurements::UpdateParameters() { - if (list.size() != kNumRtcpReportsToUse) +RtpToNtpEstimator::RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, + uint32_t ntp_frac, + uint32_t timestamp) + : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {} + +bool RtpToNtpEstimator::RtcpMeasurement::IsEqual( + const RtcpMeasurement& other) const { + // Use || since two equal timestamps will result in zero frequency and in + // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency. + return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp); +} + +// Class for converting an RTP timestamp to the NTP domain. +RtpToNtpEstimator::RtpToNtpEstimator() {} +RtpToNtpEstimator::~RtpToNtpEstimator() {} + +void RtpToNtpEstimator::UpdateParameters() { + if (measurements_.size() != kNumRtcpReportsToUse) return; - int64_t timestamp_new = list.front().rtp_timestamp; - int64_t timestamp_old = list.back().rtp_timestamp; + int64_t timestamp_new = measurements_.front().rtp_timestamp; + int64_t timestamp_old = measurements_.back().rtp_timestamp; if (!CompensateForWrapAround(timestamp_new, timestamp_old, ×tamp_new)) return; - int64_t ntp_ms_new = list.front().ntp_time.ToMs(); - int64_t ntp_ms_old = list.back().ntp_time.ToMs(); + int64_t ntp_ms_new = measurements_.front().ntp_time.ToMs(); + int64_t ntp_ms_old = measurements_.back().ntp_time.ToMs(); if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old, - ¶ms.frequency_khz)) { + ¶ms_.frequency_khz)) { return; } - params.offset_ms = timestamp_new - params.frequency_khz * ntp_ms_new; - params.calculated = true; + params_.offset_ms = timestamp_new - params_.frequency_khz * ntp_ms_new; + params_.calculated = true; } -// Updates list holding NTP and RTP timestamp pairs. -bool UpdateRtcpList(uint32_t ntp_secs, - uint32_t ntp_frac, - uint32_t rtp_timestamp, - RtcpMeasurements* rtcp_measurements, - bool* new_rtcp_sr) { +bool RtpToNtpEstimator::UpdateMeasurements(uint32_t ntp_secs, + uint32_t ntp_frac, + uint32_t rtp_timestamp, + bool* new_rtcp_sr) { *new_rtcp_sr = false; RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp); - if (rtcp_measurements->Contains(measurement)) { + if (Contains(measurements_, measurement)) { // RTCP SR report already added. return true; } - - if (!rtcp_measurements->IsValid(measurement)) { + if (!IsValid(measurements_, measurement)) { // Old report or invalid parameters. return false; } // Insert new RTCP SR report. - if (rtcp_measurements->list.size() == kNumRtcpReportsToUse) - rtcp_measurements->list.pop_back(); + if (measurements_.size() == kNumRtcpReportsToUse) + measurements_.pop_back(); - rtcp_measurements->list.push_front(measurement); + measurements_.push_front(measurement); *new_rtcp_sr = true; // List updated, calculate new parameters. - rtcp_measurements->UpdateParameters(); + UpdateParameters(); return true; } -// Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp -// pairs in |rtcp|. The converted timestamp is returned in -// |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP -// timestamps and returns false if it can't do the conversion due to reordering. -bool RtpToNtpMs(int64_t rtp_timestamp, - const RtcpMeasurements& rtcp, - int64_t* rtp_timestamp_in_ms) { - if (!rtcp.params.calculated || rtcp.list.empty()) +bool RtpToNtpEstimator::Estimate(int64_t rtp_timestamp, + int64_t* rtp_timestamp_ms) const { + if (!params_.calculated || measurements_.empty()) return false; - uint32_t rtcp_timestamp_old = rtcp.list.back().rtp_timestamp; + uint32_t rtp_timestamp_old = measurements_.back().rtp_timestamp; int64_t rtp_timestamp_unwrapped; - if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old, + if (!CompensateForWrapAround(rtp_timestamp, rtp_timestamp_old, &rtp_timestamp_unwrapped)) { return false; } - double rtp_timestamp_ms = - (static_cast(rtp_timestamp_unwrapped) - rtcp.params.offset_ms) / - rtcp.params.frequency_khz + + double rtp_ms = + (static_cast(rtp_timestamp_unwrapped) - params_.offset_ms) / + params_.frequency_khz + 0.5f; - if (rtp_timestamp_ms < 0) { + + if (rtp_ms < 0) return false; - } - *rtp_timestamp_in_ms = rtp_timestamp_ms; + + *rtp_timestamp_ms = rtp_ms; return true; } diff --git a/webrtc/system_wrappers/source/rtp_to_ntp_unittest.cc b/webrtc/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc similarity index 50% rename from webrtc/system_wrappers/source/rtp_to_ntp_unittest.cc rename to webrtc/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc index bdaaa7d32d..09b47b4873 100644 --- a/webrtc/system_wrappers/source/rtp_to_ntp_unittest.cc +++ b/webrtc/system_wrappers/source/rtp_to_ntp_estimator_unittest.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/system_wrappers/include/rtp_to_ntp.h" +#include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h" #include "webrtc/test/gtest.h" namespace webrtc { @@ -38,236 +38,215 @@ TEST(WrapAroundTests, BackwardWrap) { } TEST(WrapAroundTests, OldRtcpWrapped_OldRtpTimestamp) { - RtcpMeasurements rtcp; + RtpToNtpEstimator estimator; bool new_sr; uint32_t ntp_sec = 0; uint32_t ntp_frac = 1; uint32_t timestamp = 0; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); ntp_frac += kOneMsInNtpFrac; timestamp -= kTimestampTicksPerMs; // Expected to fail since the older RTCP has a smaller RTP timestamp than the // newer (old:0, new:4294967206). - EXPECT_FALSE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_FALSE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); } TEST(WrapAroundTests, NewRtcpWrapped) { - RtcpMeasurements rtcp; + RtpToNtpEstimator estimator; bool new_sr; uint32_t ntp_sec = 0; uint32_t ntp_frac = 1; uint32_t timestamp = 0xFFFFFFFF; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); ntp_frac += kOneMsInNtpFrac; timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); int64_t timestamp_ms = -1; - EXPECT_TRUE(RtpToNtpMs(rtcp.list.back().rtp_timestamp, rtcp, ×tamp_ms)); + EXPECT_TRUE(estimator.Estimate(0xFFFFFFFF, ×tamp_ms)); // Since this RTP packet has the same timestamp as the RTCP packet constructed // at time 0 it should be mapped to 0 as well. EXPECT_EQ(0, timestamp_ms); } TEST(WrapAroundTests, RtpWrapped) { - RtcpMeasurements rtcp; + RtpToNtpEstimator estimator; bool new_sr; uint32_t ntp_sec = 0; uint32_t ntp_frac = 1; uint32_t timestamp = 0xFFFFFFFF - 2 * kTimestampTicksPerMs; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); ntp_frac += kOneMsInNtpFrac; timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); int64_t timestamp_ms = -1; - EXPECT_TRUE(RtpToNtpMs(rtcp.list.back().rtp_timestamp, rtcp, ×tamp_ms)); + EXPECT_TRUE(estimator.Estimate(0xFFFFFFFF - 2 * kTimestampTicksPerMs, + ×tamp_ms)); // Since this RTP packet has the same timestamp as the RTCP packet constructed // at time 0 it should be mapped to 0 as well. EXPECT_EQ(0, timestamp_ms); // Two kTimestampTicksPerMs advanced. timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(RtpToNtpMs(timestamp, rtcp, ×tamp_ms)); + EXPECT_TRUE(estimator.Estimate(timestamp, ×tamp_ms)); EXPECT_EQ(2, timestamp_ms); // Wrapped rtp. timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(RtpToNtpMs(timestamp, rtcp, ×tamp_ms)); + EXPECT_TRUE(estimator.Estimate(timestamp, ×tamp_ms)); EXPECT_EQ(3, timestamp_ms); } TEST(WrapAroundTests, OldRtp_RtcpsWrapped) { - RtcpMeasurements rtcp; + RtpToNtpEstimator estimator; bool new_sr; uint32_t ntp_sec = 0; uint32_t ntp_frac = 1; uint32_t timestamp = 0; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); ntp_frac += kOneMsInNtpFrac; timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); - timestamp -= 2*kTimestampTicksPerMs; + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); + timestamp -= 2 * kTimestampTicksPerMs; int64_t timestamp_ms = -1; - EXPECT_FALSE(RtpToNtpMs(timestamp, rtcp, ×tamp_ms)); + EXPECT_FALSE(estimator.Estimate(timestamp, ×tamp_ms)); } TEST(WrapAroundTests, OldRtp_NewRtcpWrapped) { - RtcpMeasurements rtcp; + RtpToNtpEstimator estimator; bool new_sr; uint32_t ntp_sec = 0; uint32_t ntp_frac = 1; uint32_t timestamp = 0xFFFFFFFF; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); ntp_frac += kOneMsInNtpFrac; timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); timestamp -= kTimestampTicksPerMs; int64_t timestamp_ms = -1; - EXPECT_TRUE(RtpToNtpMs(timestamp, rtcp, ×tamp_ms)); + EXPECT_TRUE(estimator.Estimate(timestamp, ×tamp_ms)); // Constructed at the same time as the first RTCP and should therefore be // mapped to zero. EXPECT_EQ(0, timestamp_ms); } -TEST(UpdateRtcpListTests, InjectRtcpSr) { - const uint32_t kNtpSec = 10; - const uint32_t kNtpFrac = 12345; - const uint32_t kTs = 0x12345678; - bool new_sr; - RtcpMeasurements rtcp; - EXPECT_TRUE(UpdateRtcpList(kNtpSec, kNtpFrac, kTs, &rtcp, &new_sr)); - EXPECT_TRUE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); - EXPECT_EQ(kNtpSec, rtcp.list.front().ntp_time.seconds()); - EXPECT_EQ(kNtpFrac, rtcp.list.front().ntp_time.fractions()); - EXPECT_EQ(kTs, rtcp.list.front().rtp_timestamp); - // Add second report. - EXPECT_TRUE(UpdateRtcpList(kNtpSec, kNtpFrac + kOneMsInNtpFrac, kTs + 1, - &rtcp, &new_sr)); - EXPECT_EQ(2u, rtcp.list.size()); - EXPECT_EQ(kTs + 1, rtcp.list.front().rtp_timestamp); - EXPECT_EQ(kTs + 0, rtcp.list.back().rtp_timestamp); - // List should contain last two reports. - EXPECT_TRUE(UpdateRtcpList(kNtpSec, kNtpFrac + 2 * kOneMsInNtpFrac, kTs + 2, - &rtcp, &new_sr)); - EXPECT_EQ(2u, rtcp.list.size()); - EXPECT_EQ(kTs + 2, rtcp.list.front().rtp_timestamp); - EXPECT_EQ(kTs + 1, rtcp.list.back().rtp_timestamp); -} - -TEST(UpdateRtcpListTests, FailsForZeroNtp) { - RtcpMeasurements rtcp; +TEST(UpdateRtcpMeasurementTests, FailsForZeroNtp) { + RtpToNtpEstimator estimator; uint32_t ntp_sec = 0; uint32_t ntp_frac = 0; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_FALSE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_FALSE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_FALSE(new_sr); - EXPECT_EQ(0u, rtcp.list.size()); } -TEST(UpdateRtcpListTests, FailsForEqualNtp) { - RtcpMeasurements rtcp; +TEST(UpdateRtcpMeasurementTests, FailsForEqualNtp) { + RtpToNtpEstimator estimator; uint32_t ntp_sec = 0; uint32_t ntp_frac = 699925050; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_TRUE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); // Ntp time already added, list not updated. ++timestamp; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_FALSE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); } -TEST(UpdateRtcpListTests, FailsForOldNtp) { - RtcpMeasurements rtcp; +TEST(UpdateRtcpMeasurementTests, FailsForOldNtp) { + RtpToNtpEstimator estimator; uint32_t ntp_sec = 1; uint32_t ntp_frac = 699925050; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_TRUE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); // Old ntp time, list not updated. ntp_frac -= kOneMsInNtpFrac; timestamp += kTimestampTicksPerMs; - EXPECT_FALSE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); - EXPECT_EQ(1u, rtcp.list.size()); + EXPECT_FALSE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); } -TEST(UpdateRtcpListTests, FailsForEqualTimestamp) { - RtcpMeasurements rtcp; +TEST(UpdateRtcpMeasurementTests, FailsForEqualTimestamp) { + RtpToNtpEstimator estimator; uint32_t ntp_sec = 0; uint32_t ntp_frac = 2; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_TRUE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); // Timestamp already added, list not updated. ++ntp_frac; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_FALSE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); } -TEST(UpdateRtcpListTests, FailsForOldRtpTimestamp) { - RtcpMeasurements rtcp; +TEST(UpdateRtcpMeasurementTests, FailsForOldRtpTimestamp) { + RtpToNtpEstimator estimator; uint32_t ntp_sec = 0; uint32_t ntp_frac = 2; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_TRUE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); // Old timestamp, list not updated. ntp_frac += kOneMsInNtpFrac; timestamp -= kTimestampTicksPerMs; - EXPECT_FALSE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_FALSE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_FALSE(new_sr); - EXPECT_EQ(1u, rtcp.list.size()); } -TEST(UpdateRtcpListTests, VerifyParameters) { - RtcpMeasurements rtcp; +TEST(UpdateRtcpMeasurementTests, VerifyParameters) { + RtpToNtpEstimator estimator; uint32_t ntp_sec = 1; uint32_t ntp_frac = 2; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); EXPECT_TRUE(new_sr); - EXPECT_FALSE(rtcp.params.calculated); + EXPECT_FALSE(estimator.params().calculated); // Add second report, parameters should be calculated. ntp_frac += kOneMsInNtpFrac; timestamp += kTimestampTicksPerMs; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); - EXPECT_TRUE(rtcp.params.calculated); - EXPECT_DOUBLE_EQ(90.0, rtcp.params.frequency_khz); - EXPECT_NE(0.0, rtcp.params.offset_ms); -} - -TEST(RtpToNtpTests, FailsForEmptyList) { - RtcpMeasurements rtcp; - rtcp.params.calculated = true; - // List is empty, conversion of RTP to NTP time should fail. - EXPECT_EQ(0u, rtcp.list.size()); - int64_t timestamp_ms = -1; - EXPECT_FALSE(RtpToNtpMs(0, rtcp, ×tamp_ms)); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); + EXPECT_TRUE(estimator.params().calculated); + EXPECT_DOUBLE_EQ(90.0, estimator.params().frequency_khz); + EXPECT_NE(0.0, estimator.params().offset_ms); } TEST(RtpToNtpTests, FailsForNoParameters) { - RtcpMeasurements rtcp; + RtpToNtpEstimator estimator; uint32_t ntp_sec = 1; uint32_t ntp_frac = 2; uint32_t timestamp = 0x12345678; bool new_sr; - EXPECT_TRUE(UpdateRtcpList(ntp_sec, ntp_frac, timestamp, &rtcp, &new_sr)); - EXPECT_EQ(1u, rtcp.list.size()); + EXPECT_TRUE( + estimator.UpdateMeasurements(ntp_sec, ntp_frac, timestamp, &new_sr)); + EXPECT_TRUE(new_sr); // Parameters are not calculated, conversion of RTP to NTP time should fail. - EXPECT_FALSE(rtcp.params.calculated); + EXPECT_FALSE(estimator.params().calculated); int64_t timestamp_ms = -1; - EXPECT_FALSE(RtpToNtpMs(timestamp, rtcp, ×tamp_ms)); + EXPECT_FALSE(estimator.Estimate(timestamp, ×tamp_ms)); } }; // namespace webrtc diff --git a/webrtc/video/rtp_streams_synchronizer.cc b/webrtc/video/rtp_streams_synchronizer.cc index d7fd949fff..0d026b310a 100644 --- a/webrtc/video/rtp_streams_synchronizer.cc +++ b/webrtc/video/rtp_streams_synchronizer.cc @@ -41,8 +41,8 @@ bool UpdateMeasurements(StreamSynchronization::Measurements* stream, } bool new_rtcp_sr = false; - if (!UpdateRtcpList(ntp_secs, ntp_frac, rtp_timestamp, &stream->rtcp, - &new_rtcp_sr)) { + if (!stream->rtp_to_ntp.UpdateMeasurements(ntp_secs, ntp_frac, rtp_timestamp, + &new_rtcp_sr)) { return false; } @@ -183,14 +183,14 @@ bool RtpStreamsSynchronizer::GetStreamSyncOffsetInMs( } int64_t latest_audio_ntp; - if (!RtpToNtpMs(playout_timestamp, audio_measurement_.rtcp, - &latest_audio_ntp)) { + if (!audio_measurement_.rtp_to_ntp.Estimate(playout_timestamp, + &latest_audio_ntp)) { return false; } int64_t latest_video_ntp; - if (!RtpToNtpMs(frame.timestamp(), video_measurement_.rtcp, - &latest_video_ntp)) { + if (!video_measurement_.rtp_to_ntp.Estimate(frame.timestamp(), + &latest_video_ntp)) { return false; } @@ -200,7 +200,7 @@ bool RtpStreamsSynchronizer::GetStreamSyncOffsetInMs( latest_video_ntp += time_to_render_ms; *stream_offset_ms = latest_audio_ntp - latest_video_ntp; - *estimated_freq_khz = video_measurement_.rtcp.params.frequency_khz; + *estimated_freq_khz = video_measurement_.rtp_to_ntp.params().frequency_khz; return true; } diff --git a/webrtc/video/stream_synchronization.cc b/webrtc/video/stream_synchronization.cc index ff389736f4..145922c3a0 100644 --- a/webrtc/video/stream_synchronization.cc +++ b/webrtc/video/stream_synchronization.cc @@ -40,15 +40,13 @@ bool StreamSynchronization::ComputeRelativeDelay( int* relative_delay_ms) { assert(relative_delay_ms); int64_t audio_last_capture_time_ms; - if (!RtpToNtpMs(audio_measurement.latest_timestamp, - audio_measurement.rtcp, - &audio_last_capture_time_ms)) { + if (!audio_measurement.rtp_to_ntp.Estimate(audio_measurement.latest_timestamp, + &audio_last_capture_time_ms)) { return false; } int64_t video_last_capture_time_ms; - if (!RtpToNtpMs(video_measurement.latest_timestamp, - video_measurement.rtcp, - &video_last_capture_time_ms)) { + if (!video_measurement.rtp_to_ntp.Estimate(video_measurement.latest_timestamp, + &video_last_capture_time_ms)) { return false; } if (video_last_capture_time_ms < 0) { diff --git a/webrtc/video/stream_synchronization.h b/webrtc/video/stream_synchronization.h index c700ee3bf7..0b1ad4fd3a 100644 --- a/webrtc/video/stream_synchronization.h +++ b/webrtc/video/stream_synchronization.h @@ -13,7 +13,7 @@ #include -#include "webrtc/system_wrappers/include/rtp_to_ntp.h" +#include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h" #include "webrtc/typedefs.h" namespace webrtc { @@ -21,8 +21,8 @@ namespace webrtc { class StreamSynchronization { public: struct Measurements { - Measurements() : rtcp(), latest_receive_time_ms(0), latest_timestamp(0) {} - RtcpMeasurements rtcp; + Measurements() : latest_receive_time_ms(0), latest_timestamp(0) {} + RtpToNtpEstimator rtp_to_ntp; int64_t latest_receive_time_ms; uint32_t latest_timestamp; }; diff --git a/webrtc/video/stream_synchronization_unittest.cc b/webrtc/video/stream_synchronization_unittest.cc index 770bbf6eeb..d5607a8c87 100644 --- a/webrtc/video/stream_synchronization_unittest.cc +++ b/webrtc/video/stream_synchronization_unittest.cc @@ -34,13 +34,6 @@ class Time { : kNtpJan1970(2208988800UL), time_now_ms_(offset) {} - RtcpMeasurement GenerateRtcp(int frequency, uint32_t offset) const { - RtcpMeasurement rtcp; - rtcp.ntp_time = GetNowNtp(); - rtcp.rtp_timestamp = GetNowRtp(frequency, offset); - return rtcp; - } - NtpTime GetNowNtp() const { uint32_t ntp_secs = time_now_ms_ / 1000 + kNtpJan1970; int64_t remainder_ms = time_now_ms_ % 1000; @@ -104,29 +97,29 @@ class StreamSynchronizationTest : public ::testing::Test { StreamSynchronization::Measurements audio; StreamSynchronization::Measurements video; // Generate NTP/RTP timestamp pair for both streams corresponding to RTCP. - RtcpMeasurement rtcp = - send_time_->GenerateRtcp(audio_frequency, audio_offset); - EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(), - rtcp.ntp_time.fractions(), rtcp.rtp_timestamp, - &audio.rtcp, &new_sr)); + NtpTime ntp_time = send_time_->GetNowNtp(); + uint32_t rtp_timestamp = + send_time_->GetNowRtp(audio_frequency, audio_offset); + EXPECT_TRUE(audio.rtp_to_ntp.UpdateMeasurements( + ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr)); send_time_->IncreaseTimeMs(100); receive_time_->IncreaseTimeMs(100); - rtcp = send_time_->GenerateRtcp(video_frequency, video_offset); - EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(), - rtcp.ntp_time.fractions(), rtcp.rtp_timestamp, - &video.rtcp, &new_sr)); + ntp_time = send_time_->GetNowNtp(); + rtp_timestamp = send_time_->GetNowRtp(video_frequency, video_offset); + EXPECT_TRUE(video.rtp_to_ntp.UpdateMeasurements( + ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr)); send_time_->IncreaseTimeMs(900); receive_time_->IncreaseTimeMs(900); - rtcp = send_time_->GenerateRtcp(audio_frequency, audio_offset); - EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(), - rtcp.ntp_time.fractions(), rtcp.rtp_timestamp, - &audio.rtcp, &new_sr)); + ntp_time = send_time_->GetNowNtp(); + rtp_timestamp = send_time_->GetNowRtp(audio_frequency, audio_offset); + EXPECT_TRUE(audio.rtp_to_ntp.UpdateMeasurements( + ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr)); send_time_->IncreaseTimeMs(100); receive_time_->IncreaseTimeMs(100); - rtcp = send_time_->GenerateRtcp(video_frequency, video_offset); - EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(), - rtcp.ntp_time.fractions(), rtcp.rtp_timestamp, - &video.rtcp, &new_sr)); + ntp_time = send_time_->GetNowNtp(); + rtp_timestamp = send_time_->GetNowRtp(video_frequency, video_offset); + EXPECT_TRUE(video.rtp_to_ntp.UpdateMeasurements( + ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr)); send_time_->IncreaseTimeMs(900); receive_time_->IncreaseTimeMs(900);