1 /*
2 * Copyright (c) 2016 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 "modules/rtp_rtcp/source/time_util.h"
12
13 #include <algorithm>
14
15 #include "rtc_base/checks.h"
16 #include "rtc_base/numerics/divide_round.h"
17 #include "rtc_base/time_utils.h"
18
19 namespace webrtc {
20
SaturatedToCompactNtp(TimeDelta delta)21 uint32_t SaturatedToCompactNtp(TimeDelta delta) {
22 constexpr uint32_t kMaxCompactNtp = 0xFFFFFFFF;
23 constexpr int kCompactNtpInSecond = 0x10000;
24 if (delta <= TimeDelta::Zero())
25 return 0;
26 if (delta.us() >=
27 kMaxCompactNtp * rtc::kNumMicrosecsPerSec / kCompactNtpInSecond)
28 return kMaxCompactNtp;
29 // To convert to compact ntp need to divide by 1e6 to get seconds,
30 // then multiply by 0x10000 to get the final result.
31 // To avoid float operations, multiplication and division swapped.
32 return DivideRoundToNearest(delta.us() * kCompactNtpInSecond,
33 rtc::kNumMicrosecsPerSec);
34 }
35
CompactNtpRttToTimeDelta(uint32_t compact_ntp_interval)36 TimeDelta CompactNtpRttToTimeDelta(uint32_t compact_ntp_interval) {
37 static constexpr TimeDelta kMinRtt = TimeDelta::Millis(1);
38 // Interval to convert expected to be positive, e.g. RTT or delay.
39 // Because interval can be derived from non-monotonic ntp clock,
40 // it might become negative that is indistinguishable from very large values.
41 // Since very large RTT/delay is less likely than non-monotonic ntp clock,
42 // such value is considered negative and converted to minimum value of 1ms.
43 if (compact_ntp_interval > 0x80000000)
44 return kMinRtt;
45 // Convert to 64bit value to avoid multiplication overflow.
46 int64_t value = static_cast<int64_t>(compact_ntp_interval);
47 // To convert to TimeDelta need to divide by 2^16 to get seconds,
48 // then multiply by 1'000'000 to get microseconds. To avoid float operations,
49 // multiplication and division are swapped.
50 int64_t us = DivideRoundToNearest(value * rtc::kNumMicrosecsPerSec, 1 << 16);
51 // Small RTT value is considered too good to be true and increased to 1ms.
52 return std::max(TimeDelta::Micros(us), kMinRtt);
53 }
54 } // namespace webrtc
55