LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/system_wrappers/source - rtp_to_ntp_estimator.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 84 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/system_wrappers/include/rtp_to_ntp_estimator.h"
      12             : 
      13             : #include "webrtc/base/logging.h"
      14             : #include "webrtc/system_wrappers/include/clock.h"
      15             : 
      16             : namespace webrtc {
      17             : namespace {
      18             : // Number of RTCP SR reports to use to map between RTP and NTP.
      19             : const size_t kNumRtcpReportsToUse = 2;
      20             : 
      21             : // Calculates the RTP timestamp frequency from two pairs of NTP/RTP timestamps.
      22           0 : bool CalculateFrequency(int64_t ntp_ms1,
      23             :                         uint32_t rtp_timestamp1,
      24             :                         int64_t ntp_ms2,
      25             :                         uint32_t rtp_timestamp2,
      26             :                         double* frequency_khz) {
      27           0 :   if (ntp_ms1 <= ntp_ms2)
      28           0 :     return false;
      29             : 
      30           0 :   *frequency_khz = static_cast<double>(rtp_timestamp1 - rtp_timestamp2) /
      31           0 :                    static_cast<double>(ntp_ms1 - ntp_ms2);
      32           0 :   return true;
      33             : }
      34             : 
      35             : // Detects if there has been a wraparound between |old_timestamp| and
      36             : // |new_timestamp|, and compensates by adding 2^32 if that is the case.
      37           0 : bool CompensateForWrapAround(uint32_t new_timestamp,
      38             :                              uint32_t old_timestamp,
      39             :                              int64_t* compensated_timestamp) {
      40           0 :   int64_t wraps = CheckForWrapArounds(new_timestamp, old_timestamp);
      41           0 :   if (wraps < 0) {
      42             :     // Reordering, don't use this packet.
      43           0 :     return false;
      44             :   }
      45           0 :   *compensated_timestamp = new_timestamp + (wraps << 32);
      46           0 :   return true;
      47             : }
      48             : 
      49           0 : bool Contains(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements,
      50             :               const RtpToNtpEstimator::RtcpMeasurement& other) {
      51           0 :   for (const auto& measurement : measurements) {
      52           0 :     if (measurement.IsEqual(other))
      53           0 :       return true;
      54             :   }
      55           0 :   return false;
      56             : }
      57             : 
      58           0 : bool IsValid(const std::list<RtpToNtpEstimator::RtcpMeasurement>& measurements,
      59             :              const RtpToNtpEstimator::RtcpMeasurement& other) {
      60           0 :   if (!other.ntp_time.Valid())
      61           0 :     return false;
      62             : 
      63           0 :   int64_t ntp_ms_new = other.ntp_time.ToMs();
      64           0 :   for (const auto& measurement : measurements) {
      65           0 :     if (ntp_ms_new <= measurement.ntp_time.ToMs()) {
      66             :       // Old report.
      67           0 :       return false;
      68             :     }
      69           0 :     int64_t timestamp_new = other.rtp_timestamp;
      70           0 :     if (!CompensateForWrapAround(timestamp_new, measurement.rtp_timestamp,
      71             :                                  &timestamp_new)) {
      72           0 :       return false;
      73             :     }
      74           0 :     if (timestamp_new <= measurement.rtp_timestamp) {
      75           0 :       LOG(LS_WARNING) << "Newer RTCP SR report with older RTP timestamp.";
      76           0 :       return false;
      77             :     }
      78             :   }
      79           0 :   return true;
      80             : }
      81             : }  // namespace
      82             : 
      83           0 : RtpToNtpEstimator::RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs,
      84             :                                                     uint32_t ntp_frac,
      85           0 :                                                     uint32_t timestamp)
      86           0 :     : ntp_time(ntp_secs, ntp_frac), rtp_timestamp(timestamp) {}
      87             : 
      88           0 : bool RtpToNtpEstimator::RtcpMeasurement::IsEqual(
      89             :     const RtcpMeasurement& other) const {
      90             :   // Use || since two equal timestamps will result in zero frequency and in
      91             :   // RtpToNtpMs, |rtp_timestamp_ms| is estimated by dividing by the frequency.
      92           0 :   return (ntp_time == other.ntp_time) || (rtp_timestamp == other.rtp_timestamp);
      93             : }
      94             : 
      95             : // Class for converting an RTP timestamp to the NTP domain.
      96           0 : RtpToNtpEstimator::RtpToNtpEstimator() {}
      97           0 : RtpToNtpEstimator::~RtpToNtpEstimator() {}
      98             : 
      99           0 : void RtpToNtpEstimator::UpdateParameters() {
     100           0 :   if (measurements_.size() != kNumRtcpReportsToUse)
     101           0 :     return;
     102             : 
     103           0 :   int64_t timestamp_new = measurements_.front().rtp_timestamp;
     104           0 :   int64_t timestamp_old = measurements_.back().rtp_timestamp;
     105           0 :   if (!CompensateForWrapAround(timestamp_new, timestamp_old, &timestamp_new))
     106           0 :     return;
     107             : 
     108           0 :   int64_t ntp_ms_new = measurements_.front().ntp_time.ToMs();
     109           0 :   int64_t ntp_ms_old = measurements_.back().ntp_time.ToMs();
     110             : 
     111           0 :   if (!CalculateFrequency(ntp_ms_new, timestamp_new, ntp_ms_old, timestamp_old,
     112             :                           &params_.frequency_khz)) {
     113           0 :     return;
     114             :   }
     115           0 :   params_.offset_ms = timestamp_new - params_.frequency_khz * ntp_ms_new;
     116           0 :   params_.calculated = true;
     117             : }
     118             : 
     119           0 : bool RtpToNtpEstimator::UpdateMeasurements(uint32_t ntp_secs,
     120             :                                            uint32_t ntp_frac,
     121             :                                            uint32_t rtp_timestamp,
     122             :                                            bool* new_rtcp_sr) {
     123           0 :   *new_rtcp_sr = false;
     124             : 
     125           0 :   RtcpMeasurement measurement(ntp_secs, ntp_frac, rtp_timestamp);
     126           0 :   if (Contains(measurements_, measurement)) {
     127             :     // RTCP SR report already added.
     128           0 :     return true;
     129             :   }
     130           0 :   if (!IsValid(measurements_, measurement)) {
     131             :     // Old report or invalid parameters.
     132           0 :     return false;
     133             :   }
     134             : 
     135             :   // Insert new RTCP SR report.
     136           0 :   if (measurements_.size() == kNumRtcpReportsToUse)
     137           0 :     measurements_.pop_back();
     138             : 
     139           0 :   measurements_.push_front(measurement);
     140           0 :   *new_rtcp_sr = true;
     141             : 
     142             :   // List updated, calculate new parameters.
     143           0 :   UpdateParameters();
     144           0 :   return true;
     145             : }
     146             : 
     147           0 : bool RtpToNtpEstimator::Estimate(int64_t rtp_timestamp,
     148             :                                  int64_t* rtp_timestamp_ms) const {
     149           0 :   if (!params_.calculated || measurements_.empty())
     150           0 :     return false;
     151             : 
     152           0 :   uint32_t rtp_timestamp_old = measurements_.back().rtp_timestamp;
     153             :   int64_t rtp_timestamp_unwrapped;
     154           0 :   if (!CompensateForWrapAround(rtp_timestamp, rtp_timestamp_old,
     155             :                                &rtp_timestamp_unwrapped)) {
     156           0 :     return false;
     157             :   }
     158             : 
     159             :   double rtp_ms =
     160           0 :       (static_cast<double>(rtp_timestamp_unwrapped) - params_.offset_ms) /
     161           0 :           params_.frequency_khz +
     162           0 :       0.5f;
     163             : 
     164           0 :   if (rtp_ms < 0)
     165           0 :     return false;
     166             : 
     167           0 :   *rtp_timestamp_ms = rtp_ms;
     168           0 :   return true;
     169             : }
     170             : 
     171           0 : int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) {
     172           0 :   if (new_timestamp < old_timestamp) {
     173             :     // This difference should be less than -2^31 if we have had a wrap around
     174             :     // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is
     175             :     // cast to a int32_t, it should be positive.
     176           0 :     if (static_cast<int32_t>(new_timestamp - old_timestamp) > 0) {
     177             :       // Forward wrap around.
     178           0 :       return 1;
     179             :     }
     180           0 :   } else if (static_cast<int32_t>(old_timestamp - new_timestamp) > 0) {
     181             :     // This difference should be less than -2^31 if we have had a backward wrap
     182             :     // around. Since it is cast to a int32_t, it should be positive.
     183           0 :     return -1;
     184             :   }
     185           0 :   return 0;
     186             : }
     187             : 
     188             : }  // namespace webrtc

Generated by: LCOV version 1.13