| Index: webrtc/system_wrappers/source/rtp_to_ntp.cc
|
| diff --git a/webrtc/system_wrappers/source/rtp_to_ntp.cc b/webrtc/system_wrappers/source/rtp_to_ntp.cc
|
| index 05091461d4123ff9bfbea041bd18187a0c411e02..8290749f132390e0de9ad409030daf79957b9c33 100644
|
| --- a/webrtc/system_wrappers/source/rtp_to_ntp.cc
|
| +++ b/webrtc/system_wrappers/source/rtp_to_ntp.cc
|
| @@ -10,27 +10,17 @@
|
|
|
| #include "webrtc/system_wrappers/include/rtp_to_ntp.h"
|
|
|
| +#include "webrtc/base/logging.h"
|
| #include "webrtc/system_wrappers/include/clock.h"
|
|
|
| -#include <assert.h>
|
| -
|
| namespace webrtc {
|
| -
|
| -RtcpMeasurement::RtcpMeasurement()
|
| - : ntp_secs(0), ntp_frac(0), rtp_timestamp(0) {}
|
| -
|
| -RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac,
|
| - uint32_t timestamp)
|
| - : ntp_secs(ntp_secs), ntp_frac(ntp_frac), rtp_timestamp(timestamp) {}
|
| -
|
| -// Calculates the RTP timestamp frequency from two pairs of NTP and RTP
|
| -// timestamps.
|
| -bool CalculateFrequency(
|
| - int64_t rtcp_ntp_ms1,
|
| - uint32_t rtp_timestamp1,
|
| - int64_t rtcp_ntp_ms2,
|
| - uint32_t rtp_timestamp2,
|
| - double* frequency_khz) {
|
| +namespace {
|
| +// Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps.
|
| +bool CalculateFrequency(int64_t rtcp_ntp_ms1,
|
| + uint32_t rtp_timestamp1,
|
| + int64_t rtcp_ntp_ms2,
|
| + uint32_t rtp_timestamp2,
|
| + double* frequency_khz) {
|
| if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) {
|
| return false;
|
| }
|
| @@ -44,7 +34,6 @@ bool CalculateFrequency(
|
| bool CompensateForWrapAround(uint32_t new_timestamp,
|
| uint32_t old_timestamp,
|
| int64_t* compensated_timestamp) {
|
| - assert(compensated_timestamp);
|
| int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp);
|
| if (wraps < 0) {
|
| // Reordering, don't use this packet.
|
| @@ -53,39 +42,111 @@ 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_secs(0), ntp_frac(0), rtp_timestamp(0) {}
|
| +
|
| +RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs,
|
| + uint32_t ntp_frac,
|
| + uint32_t timestamp)
|
| + : ntp_secs(ntp_secs), ntp_frac(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_secs == other.ntp_secs && ntp_frac == other.ntp_frac) ||
|
| + (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))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool RtcpMeasurements::IsValid(const RtcpMeasurement& other) const {
|
| + if (other.ntp_secs == 0 && other.ntp_frac == 0) {
|
| + // Invalid or not defined.
|
| + return false;
|
| + }
|
| + int64_t ntp_ms_new = Clock::NtpToMs(other.ntp_secs, other.ntp_frac);
|
| + for (const auto& it : list) {
|
| + if (ntp_ms_new <= Clock::NtpToMs(it.ntp_secs, it.ntp_frac)) {
|
| + // Old report.
|
| + return false;
|
| + }
|
| + int64_t timestamp_new = other.rtp_timestamp;
|
| + if (!CompensateForWrapAround(timestamp_new, it.rtp_timestamp,
|
| + ×tamp_new)) {
|
| + return false;
|
| + }
|
| + if (timestamp_new <= it.rtp_timestamp) {
|
| + LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp.";
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void RtcpMeasurements::UpdateParameters() {
|
| + if (list.size() != 2)
|
| + return;
|
| +
|
| + int64_t timestamp_new = list.front().rtp_timestamp;
|
| + int64_t timestamp_old = list.back().rtp_timestamp;
|
| + if (!CompensateForWrapAround(timestamp_new, timestamp_old, ×tamp_new))
|
| + return;
|
| +
|
| + int64_t ntp_ms_new =
|
| + Clock::NtpToMs(list.front().ntp_secs, list.front().ntp_frac);
|
| + int64_t ntp_ms_old =
|
| + Clock::NtpToMs(list.back().ntp_secs, list.back().ntp_frac);
|
| +
|
| + if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old,
|
| + ¶ms.frequency_khz)) {
|
| + return;
|
| + }
|
| + 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,
|
| - RtcpList* rtcp_list,
|
| + RtcpMeasurements* rtcp_measurements,
|
| bool* new_rtcp_sr) {
|
| *new_rtcp_sr = false;
|
| - if (ntp_secs == 0 && ntp_frac == 0) {
|
| - return false;
|
| - }
|
|
|
| - RtcpMeasurement measurement;
|
| - measurement.ntp_secs = ntp_secs;
|
| - measurement.ntp_frac = ntp_frac;
|
| - measurement.rtp_timestamp = rtp_timestamp;
|
| -
|
| - for (RtcpList::iterator it = rtcp_list->begin();
|
| - it != rtcp_list->end(); ++it) {
|
| - if ((measurement.ntp_secs == (*it).ntp_secs &&
|
| - measurement.ntp_frac == (*it).ntp_frac) ||
|
| - (measurement.rtp_timestamp == (*it).rtp_timestamp)) {
|
| - // This RTCP has already been added to the list.
|
| - return true;
|
| - }
|
| + RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp);
|
| + if (rtcp_measurements->Contains(measurement)) {
|
| + // RTCP SR report already added.
|
| + return true;
|
| }
|
|
|
| - // We need two RTCP SR reports to map between RTP and NTP. More than two will
|
| - // not improve the mapping.
|
| - if (rtcp_list->size() == 2) {
|
| - rtcp_list->pop_back();
|
| + if (!rtcp_measurements->IsValid(measurement)) {
|
| + // Old report or invalid parameters.
|
| + return false;
|
| }
|
| - rtcp_list->push_front(measurement);
|
| +
|
| + // Two RTCP SR reports are needed to map between RTP and NTP.
|
| + // More than two will not improve the mapping.
|
| + if (rtcp_measurements->list.size() == 2)
|
| + rtcp_measurements->list.pop_back();
|
| +
|
| + rtcp_measurements->list.push_front(measurement);
|
| *new_rtcp_sr = true;
|
| +
|
| + // List updated, calculate new parameters.
|
| + rtcp_measurements->UpdateParameters();
|
| return true;
|
| }
|
|
|
| @@ -94,45 +155,26 @@ bool UpdateRtcpList(uint32_t ntp_secs,
|
| // |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 RtcpList& rtcp,
|
| + const RtcpMeasurements& rtcp,
|
| int64_t* rtp_timestamp_in_ms) {
|
| - if (rtcp.size() != 2)
|
| - return false;
|
| -
|
| - int64_t rtcp_ntp_ms_new = Clock::NtpToMs(rtcp.front().ntp_secs,
|
| - rtcp.front().ntp_frac);
|
| - int64_t rtcp_ntp_ms_old = Clock::NtpToMs(rtcp.back().ntp_secs,
|
| - rtcp.back().ntp_frac);
|
| - int64_t rtcp_timestamp_new = rtcp.front().rtp_timestamp;
|
| - int64_t rtcp_timestamp_old = rtcp.back().rtp_timestamp;
|
| - if (!CompensateForWrapAround(rtcp_timestamp_new,
|
| - rtcp_timestamp_old,
|
| - &rtcp_timestamp_new)) {
|
| - return false;
|
| - }
|
| - if (rtcp_timestamp_new < rtcp_timestamp_old)
|
| + if (!rtcp.params.calculated || rtcp.list.empty())
|
| return false;
|
|
|
| - double freq_khz;
|
| - if (!CalculateFrequency(rtcp_ntp_ms_new,
|
| - rtcp_timestamp_new,
|
| - rtcp_ntp_ms_old,
|
| - rtcp_timestamp_old,
|
| - &freq_khz)) {
|
| - return false;
|
| - }
|
| - double offset = rtcp_timestamp_new - freq_khz * rtcp_ntp_ms_new;
|
| + uint32_t rtcp_timestamp_old = rtcp.list.back().rtp_timestamp;
|
| int64_t rtp_timestamp_unwrapped;
|
| if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old,
|
| &rtp_timestamp_unwrapped)) {
|
| return false;
|
| }
|
| - double rtp_timestamp_ntp_ms = (static_cast<double>(rtp_timestamp_unwrapped) -
|
| - offset) / freq_khz + 0.5f;
|
| - if (rtp_timestamp_ntp_ms < 0) {
|
| +
|
| + double rtp_timestamp_ms =
|
| + (static_cast<double>(rtp_timestamp_unwrapped) - rtcp.params.offset_ms) /
|
| + rtcp.params.frequency_khz +
|
| + 0.5f;
|
| + if (rtp_timestamp_ms < 0) {
|
| return false;
|
| }
|
| - *rtp_timestamp_in_ms = rtp_timestamp_ntp_ms;
|
| + *rtp_timestamp_in_ms = rtp_timestamp_ms;
|
| return true;
|
| }
|
|
|
|
|