diff --git a/modules/congestion_controller/bbr/BUILD.gn b/modules/congestion_controller/bbr/BUILD.gn index 61ae174afd..22ee7b7e87 100644 --- a/modules/congestion_controller/bbr/BUILD.gn +++ b/modules/congestion_controller/bbr/BUILD.gn @@ -36,6 +36,7 @@ rtc_source_set("bbr_controller") { "../../../rtc_base/experiments:congestion_controller_experiment", "../../../rtc_base/system:fallthrough", "../network_control", + "../network_control/units", ] } rtc_source_set("data_transfer_tracker") { @@ -47,7 +48,7 @@ rtc_source_set("data_transfer_tracker") { deps = [ "../../../rtc_base:checks", "../../../rtc_base:rtc_base_approved", - "../network_control", + "../network_control/units", ] } rtc_source_set("rtt_stats") { @@ -58,7 +59,7 @@ rtc_source_set("rtt_stats") { ] deps = [ "../../../rtc_base:rtc_base_approved", - "../network_control", + "../network_control/units", ] } rtc_source_set("windowed_filter") { @@ -83,8 +84,8 @@ if (rtc_include_tests) { ":rtt_stats", ":windowed_filter", "../../../test:test_support", - "../network_control", "../network_control:network_control_test", + "../network_control/units", ] if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). diff --git a/modules/congestion_controller/bbr/bbr_network_controller.cc b/modules/congestion_controller/bbr/bbr_network_controller.cc index 1659bcb0b3..dd9affd5e6 100644 --- a/modules/congestion_controller/bbr/bbr_network_controller.cc +++ b/modules/congestion_controller/bbr/bbr_network_controller.cc @@ -15,8 +15,7 @@ #include #include -#include "modules/congestion_controller/network_control/include/network_units.h" -#include "modules/congestion_controller/network_control/include/network_units_to_string.h" +#include "modules/congestion_controller/network_control/units/network_units.h" #include "rtc_base/checks.h" #include "rtc_base/experiments/congestion_controller_experiment.h" #include "rtc_base/logging.h" diff --git a/modules/congestion_controller/bbr/bbr_network_controller.h b/modules/congestion_controller/bbr/bbr_network_controller.h index dc2b13c902..e9321ca72e 100644 --- a/modules/congestion_controller/bbr/bbr_network_controller.h +++ b/modules/congestion_controller/bbr/bbr_network_controller.h @@ -23,7 +23,6 @@ #include "modules/congestion_controller/bbr/windowed_filter.h" #include "modules/congestion_controller/network_control/include/network_control.h" #include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/congestion_controller/network_control/include/network_units.h" #include "api/optional.h" #include "rtc_base/random.h" diff --git a/modules/congestion_controller/bbr/data_transfer_tracker.h b/modules/congestion_controller/bbr/data_transfer_tracker.h index fe80fa72a9..74d0f81777 100644 --- a/modules/congestion_controller/bbr/data_transfer_tracker.h +++ b/modules/congestion_controller/bbr/data_transfer_tracker.h @@ -11,7 +11,7 @@ #define MODULES_CONGESTION_CONTROLLER_BBR_DATA_TRANSFER_TRACKER_H_ #include -#include "modules/congestion_controller/network_control/include/network_units.h" +#include "modules/congestion_controller/network_control/units/network_units.h" namespace webrtc { namespace bbr { diff --git a/modules/congestion_controller/bbr/data_transfer_tracker_unittest.cc b/modules/congestion_controller/bbr/data_transfer_tracker_unittest.cc index e48f0f5c86..51afae4499 100644 --- a/modules/congestion_controller/bbr/data_transfer_tracker_unittest.cc +++ b/modules/congestion_controller/bbr/data_transfer_tracker_unittest.cc @@ -9,7 +9,7 @@ */ #include "modules/congestion_controller/bbr/data_transfer_tracker.h" -#include "modules/congestion_controller/network_control/include/network_units.h" +#include "modules/congestion_controller/network_control/units/network_units.h" #include "test/gtest.h" namespace webrtc { diff --git a/modules/congestion_controller/bbr/rtt_stats.cc b/modules/congestion_controller/bbr/rtt_stats.cc index 3d197e304e..9c65702477 100644 --- a/modules/congestion_controller/bbr/rtt_stats.cc +++ b/modules/congestion_controller/bbr/rtt_stats.cc @@ -12,8 +12,7 @@ #include -#include "modules/congestion_controller/network_control/include/network_units.h" -#include "modules/congestion_controller/network_control/include/network_units_to_string.h" +#include "modules/congestion_controller/network_control/units/network_units.h" #include "rtc_base/logging.h" namespace webrtc { diff --git a/modules/congestion_controller/bbr/rtt_stats.h b/modules/congestion_controller/bbr/rtt_stats.h index 26b843db61..13c52cee76 100644 --- a/modules/congestion_controller/bbr/rtt_stats.h +++ b/modules/congestion_controller/bbr/rtt_stats.h @@ -16,7 +16,7 @@ #include #include -#include "modules/congestion_controller/network_control/include/network_units.h" +#include "modules/congestion_controller/network_control/units/network_units.h" #include "rtc_base/constructormagic.h" #include "rtc_base/logging.h" diff --git a/modules/congestion_controller/bbr/windowed_filter_unittest.cc b/modules/congestion_controller/bbr/windowed_filter_unittest.cc index 10888f5e99..a7092a2297 100644 --- a/modules/congestion_controller/bbr/windowed_filter_unittest.cc +++ b/modules/congestion_controller/bbr/windowed_filter_unittest.cc @@ -11,7 +11,6 @@ #include "modules/congestion_controller/bbr/windowed_filter.h" #include "modules/congestion_controller/bbr/rtt_stats.h" -#include "modules/congestion_controller/network_control/include/network_units_to_string.h" #include "test/gtest.h" namespace webrtc { diff --git a/modules/congestion_controller/network_control/BUILD.gn b/modules/congestion_controller/network_control/BUILD.gn index a60b331129..047e06eb2d 100644 --- a/modules/congestion_controller/network_control/BUILD.gn +++ b/modules/congestion_controller/network_control/BUILD.gn @@ -12,11 +12,7 @@ rtc_static_library("network_control") { sources = [ "include/network_control.h", "include/network_types.h", - "include/network_units.h", - "include/network_units_to_string.h", "network_types.cc", - "network_units.cc", - "network_units_to_string.cc", ] deps = [ @@ -24,6 +20,7 @@ rtc_static_library("network_control") { "../../../api:optional", "../../../rtc_base:checks", "../../../rtc_base:rtc_base_approved", + "units", ] } @@ -41,16 +38,16 @@ if (rtc_include_tests) { "../../../rtc_base:checks", "../../../rtc_base:rtc_base_approved", "../../../test:test_support", + "units", ] } rtc_source_set("network_control_unittests") { testonly = true - sources = [ - "network_units_unittest.cc", - ] + sources = [] deps = [ ":network_control", "../../../test:test_support", + "units:units_unittests", ] } } diff --git a/modules/congestion_controller/network_control/include/network_control.h b/modules/congestion_controller/network_control/include/network_control.h index 49b18ea38d..afcc6d2105 100644 --- a/modules/congestion_controller/network_control/include/network_control.h +++ b/modules/congestion_controller/network_control/include/network_control.h @@ -14,7 +14,7 @@ #include #include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/congestion_controller/network_control/include/network_units.h" +#include "modules/congestion_controller/network_control/units/network_units.h" namespace webrtc { diff --git a/modules/congestion_controller/network_control/include/network_types.h b/modules/congestion_controller/network_control/include/network_types.h index 7a858eb2d6..321632469e 100644 --- a/modules/congestion_controller/network_control/include/network_types.h +++ b/modules/congestion_controller/network_control/include/network_types.h @@ -12,7 +12,7 @@ #define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_TYPES_H_ #include #include -#include "modules/congestion_controller/network_control/include/network_units.h" +#include "modules/congestion_controller/network_control/units/network_units.h" #include "modules/include/module_common_types.h" #include "rtc_base/constructormagic.h" diff --git a/modules/congestion_controller/network_control/include/network_units.h b/modules/congestion_controller/network_control/include/network_units.h deleted file mode 100644 index 4a61c747bb..0000000000 --- a/modules/congestion_controller/network_control/include/network_units.h +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_H_ -#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_H_ -#include -#include -#include "rtc_base/checks.h" - -namespace webrtc { -namespace units_internal { -constexpr int64_t kPlusInfinityVal = std::numeric_limits::max(); -constexpr int64_t kMinusInfinityVal = std::numeric_limits::min(); -constexpr int64_t kSignedNotInitializedVal = kMinusInfinityVal + 1; -constexpr int64_t kNotInitializedVal = -1; - -inline int64_t DivideAndRound(int64_t numerator, int64_t denominators) { - if (numerator >= 0) { - return (numerator + (denominators / 2)) / denominators; - } else { - return (numerator + (denominators / 2)) / denominators - 1; - } -} -} // namespace units_internal - -// TimeDelta represents the difference between two timestamps. Commonly this can -// be a duration. However since two Timestamps are not guaranteed to have the -// same epoch (they might come from different computers, making exact -// synchronisation infeasible), the duration covered by a TimeDelta can be -// undefined. To simplify usage, it can be constructed and converted to -// different units, specifically seconds (s), milliseconds (ms) and -// microseconds (us). -class TimeDelta { - public: - TimeDelta() : TimeDelta(units_internal::kSignedNotInitializedVal) {} - static TimeDelta Zero() { return TimeDelta(0); } - static TimeDelta PlusInfinity() { - return TimeDelta(units_internal::kPlusInfinityVal); - } - static TimeDelta MinusInfinity() { - return TimeDelta(units_internal::kMinusInfinityVal); - } - static TimeDelta seconds(int64_t seconds) { return TimeDelta::s(seconds); } - static TimeDelta s(int64_t seconds) { - return TimeDelta::us(seconds * 1000000); - } - static TimeDelta ms(int64_t milliseconds) { - return TimeDelta::us(milliseconds * 1000); - } - static TimeDelta us(int64_t microseconds) { - // Infinities only allowed via use of explicit constants. - RTC_DCHECK(microseconds > std::numeric_limits::min()); - RTC_DCHECK(microseconds < std::numeric_limits::max()); - return TimeDelta(microseconds); - } - int64_t s() const { return units_internal::DivideAndRound(us(), 1000000); } - int64_t ms() const { return units_internal::DivideAndRound(us(), 1000); } - int64_t us() const { - RTC_DCHECK(IsFinite()); - return microseconds_; - } - TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); } - - double SecondsAsDouble() const; - - bool IsZero() const { return microseconds_ == 0; } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - bool IsInitialized() const { - return microseconds_ != units_internal::kSignedNotInitializedVal; - } - bool IsInfinite() const { - return microseconds_ == units_internal::kPlusInfinityVal || - microseconds_ == units_internal::kMinusInfinityVal; - } - bool IsPlusInfinity() const { - return microseconds_ == units_internal::kPlusInfinityVal; - } - bool IsMinusInfinity() const { - return microseconds_ == units_internal::kMinusInfinityVal; - } - TimeDelta operator+(const TimeDelta& other) const { - return TimeDelta::us(us() + other.us()); - } - TimeDelta operator-(const TimeDelta& other) const { - return TimeDelta::us(us() - other.us()); - } - TimeDelta& operator-=(const TimeDelta& other) { - microseconds_ -= other.us(); - return *this; - } - TimeDelta& operator+=(const TimeDelta& other) { - microseconds_ += other.us(); - return *this; - } - TimeDelta operator*(double scalar) const; - TimeDelta operator*(int64_t scalar) const { - return TimeDelta::us(us() * scalar); - } - TimeDelta operator*(int32_t scalar) const { - return TimeDelta::us(us() * scalar); - } - TimeDelta operator/(int64_t scalar) const { - return TimeDelta::us(us() / scalar); - } - bool operator==(const TimeDelta& other) const { - return microseconds_ == other.microseconds_; - } - bool operator!=(const TimeDelta& other) const { - return microseconds_ != other.microseconds_; - } - bool operator<=(const TimeDelta& other) const { - return microseconds_ <= other.microseconds_; - } - bool operator>=(const TimeDelta& other) const { - return microseconds_ >= other.microseconds_; - } - bool operator>(const TimeDelta& other) const { - return microseconds_ > other.microseconds_; - } - bool operator<(const TimeDelta& other) const { - return microseconds_ < other.microseconds_; - } - - private: - explicit TimeDelta(int64_t us) : microseconds_(us) {} - int64_t microseconds_; -}; -inline TimeDelta operator*(const double& scalar, const TimeDelta& delta) { - return delta * scalar; -} -inline TimeDelta operator*(const int64_t& scalar, const TimeDelta& delta) { - return delta * scalar; -} -inline TimeDelta operator*(const int32_t& scalar, const TimeDelta& delta) { - return delta * scalar; -} - -// Timestamp represents the time that has passed since some unspecified epoch. -// The epoch is assumed to be before any represented timestamps, this means that -// negative values are not valid. The most notable feature is that the -// difference of two Timestamps results in a TimeDelta. -class Timestamp { - public: - Timestamp() : Timestamp(units_internal::kNotInitializedVal) {} - static Timestamp Infinity() { - return Timestamp(units_internal::kPlusInfinityVal); - } - static Timestamp seconds(int64_t seconds) { return Timestamp::s(seconds); } - static Timestamp s(int64_t seconds) { - return Timestamp::us(seconds * 1000000); - } - static Timestamp ms(int64_t millis) { return Timestamp::us(millis * 1000); } - static Timestamp us(int64_t micros) { - RTC_DCHECK_GE(micros, 0); - return Timestamp(micros); - } - int64_t s() const { return units_internal::DivideAndRound(us(), 1000000); } - int64_t ms() const { return units_internal::DivideAndRound(us(), 1000); } - int64_t us() const { - RTC_DCHECK(IsFinite()); - return microseconds_; - } - bool IsInfinite() const { - return microseconds_ == units_internal::kPlusInfinityVal; - } - bool IsInitialized() const { - return microseconds_ != units_internal::kNotInitializedVal; - } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - TimeDelta operator-(const Timestamp& other) const { - return TimeDelta::us(us() - other.us()); - } - Timestamp operator-(const TimeDelta& delta) const { - return Timestamp::us(us() - delta.us()); - } - Timestamp operator+(const TimeDelta& delta) const { - return Timestamp::us(us() + delta.us()); - } - Timestamp& operator-=(const TimeDelta& other) { - microseconds_ -= other.us(); - return *this; - } - Timestamp& operator+=(const TimeDelta& other) { - microseconds_ += other.us(); - return *this; - } - - double SecondsAsDouble() const; - bool operator==(const Timestamp& other) const { - return microseconds_ == other.microseconds_; - } - bool operator!=(const Timestamp& other) const { - return microseconds_ != other.microseconds_; - } - bool operator<=(const Timestamp& other) const { return us() <= other.us(); } - bool operator>=(const Timestamp& other) const { return us() >= other.us(); } - bool operator>(const Timestamp& other) const { return us() > other.us(); } - bool operator<(const Timestamp& other) const { return us() < other.us(); } - - private: - explicit Timestamp(int64_t us) : microseconds_(us) {} - int64_t microseconds_; -}; - -// DataSize is a class represeting a count of bytes. Note that while it can be -// initialized by a number of bits, it does not guarantee that the resolution is -// kept and the internal storage is in bytes. The number of bits will be -// truncated to fit. -class DataSize { - public: - DataSize() : DataSize(units_internal::kNotInitializedVal) {} - static DataSize Zero() { return DataSize(0); } - static DataSize Infinity() { - return DataSize(units_internal::kPlusInfinityVal); - } - static DataSize bytes(int64_t bytes) { - RTC_DCHECK_GE(bytes, 0); - return DataSize(bytes); - } - static DataSize bits(int64_t bits) { - RTC_DCHECK_GE(bits, 0); - return DataSize(bits / 8); - } - int64_t bytes() const { - RTC_DCHECK(IsFinite()); - return bytes_; - } - int64_t kilobytes() const { - return units_internal::DivideAndRound(bytes(), 1000); - } - int64_t bits() const { return bytes() * 8; } - int64_t kilobits() const { - return units_internal::DivideAndRound(bits(), 1000); - } - bool IsZero() const { return bytes_ == 0; } - bool IsInfinite() const { return bytes_ == units_internal::kPlusInfinityVal; } - bool IsInitialized() const { - return bytes_ != units_internal::kNotInitializedVal; - } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - DataSize operator-(const DataSize& other) const { - return DataSize::bytes(bytes() - other.bytes()); - } - DataSize operator+(const DataSize& other) const { - return DataSize::bytes(bytes() + other.bytes()); - } - DataSize operator*(double scalar) const; - DataSize operator*(int64_t scalar) const { - return DataSize::bytes(bytes() * scalar); - } - DataSize operator*(int32_t scalar) const { - return DataSize::bytes(bytes() * scalar); - } - DataSize operator/(int64_t scalar) const { - return DataSize::bytes(bytes() / scalar); - } - DataSize& operator-=(const DataSize& other) { - bytes_ -= other.bytes(); - return *this; - } - DataSize& operator+=(const DataSize& other) { - bytes_ += other.bytes(); - return *this; - } - bool operator==(const DataSize& other) const { - return bytes_ == other.bytes_; - } - bool operator!=(const DataSize& other) const { - return bytes_ != other.bytes_; - } - bool operator<=(const DataSize& other) const { - return bytes_ <= other.bytes_; - } - bool operator>=(const DataSize& other) const { - return bytes_ >= other.bytes_; - } - bool operator>(const DataSize& other) const { return bytes_ > other.bytes_; } - bool operator<(const DataSize& other) const { return bytes_ < other.bytes_; } - - private: - explicit DataSize(int64_t bytes) : bytes_(bytes) {} - int64_t bytes_; -}; -inline DataSize operator*(const double& scalar, const DataSize& size) { - return size * scalar; -} -inline DataSize operator*(const int64_t& scalar, const DataSize& size) { - return size * scalar; -} -inline DataSize operator*(const int32_t& scalar, const DataSize& size) { - return size * scalar; -} - -// DataRate is a class that represents a given data rate. This can be used to -// represent bandwidth, encoding bitrate, etc. The internal storage is currently -// bits per second (bps) since this makes it easier to intepret the raw value -// when debugging. The promised precision, however is only that it will -// represent bytes per second accurately. Any implementation depending on bps -// resolution should document this by changing this comment. -class DataRate { - public: - DataRate() : DataRate(units_internal::kNotInitializedVal) {} - static DataRate Zero() { return DataRate(0); } - static DataRate Infinity() { - return DataRate(units_internal::kPlusInfinityVal); - } - static DataRate bytes_per_second(int64_t bytes_per_sec) { - RTC_DCHECK_GE(bytes_per_sec, 0); - return DataRate(bytes_per_sec * 8); - } - static DataRate bits_per_second(int64_t bits_per_sec) { - RTC_DCHECK_GE(bits_per_sec, 0); - return DataRate(bits_per_sec); - } - static DataRate bps(int64_t bits_per_sec) { - return DataRate::bits_per_second(bits_per_sec); - } - static DataRate kbps(int64_t kilobits_per_sec) { - return DataRate::bits_per_second(kilobits_per_sec * 1000); - } - int64_t bits_per_second() const { - RTC_DCHECK(IsFinite()); - return bits_per_sec_; - } - int64_t bytes_per_second() const { return bits_per_second() / 8; } - int64_t bps() const { return bits_per_second(); } - int64_t bps_or(int64_t fallback) const { - return IsFinite() ? bits_per_second() : fallback; - } - int64_t kbps() const { return units_internal::DivideAndRound(bps(), 1000); } - bool IsZero() const { return bits_per_sec_ == 0; } - bool IsInfinite() const { - return bits_per_sec_ == units_internal::kPlusInfinityVal; - } - bool IsInitialized() const { - return bits_per_sec_ != units_internal::kNotInitializedVal; - } - bool IsFinite() const { return IsInitialized() && !IsInfinite(); } - DataRate operator*(double scalar) const; - DataRate operator*(int64_t scalar) const { - return DataRate::bytes_per_second(bytes_per_second() * scalar); - } - DataRate operator*(int32_t scalar) const { - return DataRate::bytes_per_second(bytes_per_second() * scalar); - } - bool operator==(const DataRate& other) const { - return bits_per_sec_ == other.bits_per_sec_; - } - bool operator!=(const DataRate& other) const { - return bits_per_sec_ != other.bits_per_sec_; - } - bool operator<=(const DataRate& other) const { - return bits_per_sec_ <= other.bits_per_sec_; - } - bool operator>=(const DataRate& other) const { - return bits_per_sec_ >= other.bits_per_sec_; - } - bool operator>(const DataRate& other) const { - return bits_per_sec_ > other.bits_per_sec_; - } - bool operator<(const DataRate& other) const { - return bits_per_sec_ < other.bits_per_sec_; - } - - private: - // Bits per second used internally to simplify debugging by making the value - // more recognizable. - explicit DataRate(int64_t bits_per_second) : bits_per_sec_(bits_per_second) {} - int64_t bits_per_sec_; -}; -inline DataRate operator*(const double& scalar, const DataRate& rate) { - return rate * scalar; -} -inline DataRate operator*(const int64_t& scalar, const DataRate& rate) { - return rate * scalar; -} -inline DataRate operator*(const int32_t& scalar, const DataRate& rate) { - return rate * scalar; -} - -DataRate operator/(const DataSize& size, const TimeDelta& duration); -TimeDelta operator/(const DataSize& size, const DataRate& rate); -DataSize operator*(const DataRate& rate, const TimeDelta& duration); -DataSize operator*(const TimeDelta& duration, const DataRate& rate); - -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_H_ diff --git a/modules/congestion_controller/network_control/include/network_units_to_string.h b/modules/congestion_controller/network_control/include/network_units_to_string.h deleted file mode 100644 index 2d62b64707..0000000000 --- a/modules/congestion_controller/network_control/include/network_units_to_string.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_TO_STRING_H_ -#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_TO_STRING_H_ - -#include -#include "modules/congestion_controller/network_control/include/network_units.h" - -namespace webrtc { -std::string ToString(const DataRate& datarate); -std::string ToString(const DataSize& datarate); -std::string ToString(const Timestamp& datarate); -std::string ToString(const TimeDelta& datarate); -} // namespace webrtc -#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_INCLUDE_NETWORK_UNITS_TO_STRING_H_ diff --git a/modules/congestion_controller/network_control/network_units.cc b/modules/congestion_controller/network_control/network_units.cc deleted file mode 100644 index a04eef7e90..0000000000 --- a/modules/congestion_controller/network_control/network_units.cc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include "modules/congestion_controller/network_control/include/network_units.h" -#include - -namespace webrtc { -TimeDelta TimeDelta::operator*(double scalar) const { - return TimeDelta::us(std::round(us() * scalar)); -} - -DataSize DataSize::operator*(double scalar) const { - return DataSize::bytes(std::round(bytes() * scalar)); -} -double TimeDelta::SecondsAsDouble() const { - if (IsPlusInfinity()) { - return std::numeric_limits::infinity(); - } else if (IsMinusInfinity()) { - return -std::numeric_limits::infinity(); - } else if (!IsInitialized()) { - return std::numeric_limits::signaling_NaN(); - } else { - return us() * 1e-6; - } -} - -double Timestamp::SecondsAsDouble() const { - if (IsInfinite()) { - return std::numeric_limits::infinity(); - } else if (!IsInitialized()) { - return std::numeric_limits::signaling_NaN(); - } else { - return us() * 1e-6; - } -} - -DataRate DataRate::operator*(double scalar) const { - return DataRate::bytes_per_second(std::round(bytes_per_second() * scalar)); -} - -DataRate operator/(const DataSize& size, const TimeDelta& duration) { - RTC_DCHECK(size.bytes() < std::numeric_limits::max() / 1000000) - << "size is too large, size: " << size.bytes() << " is not less than " - << std::numeric_limits::max() / 1000000; - auto bytes_per_sec = size.bytes() * 1000000 / duration.us(); - return DataRate::bytes_per_second(bytes_per_sec); -} - -TimeDelta operator/(const DataSize& size, const DataRate& rate) { - RTC_DCHECK(size.bytes() < std::numeric_limits::max() / 1000000) - << "size is too large, size: " << size.bytes() << " is not less than " - << std::numeric_limits::max() / 1000000; - auto microseconds = size.bytes() * 1000000 / rate.bytes_per_second(); - return TimeDelta::us(microseconds); -} - -DataSize operator*(const DataRate& rate, const TimeDelta& duration) { - auto micro_bytes = rate.bytes_per_second() * duration.us(); - auto bytes = units_internal::DivideAndRound(micro_bytes, 1000000); - return DataSize::bytes(bytes); -} - -DataSize operator*(const TimeDelta& duration, const DataRate& rate) { - return rate * duration; -} - -} // namespace webrtc diff --git a/modules/congestion_controller/network_control/network_units_to_string.cc b/modules/congestion_controller/network_control/network_units_to_string.cc deleted file mode 100644 index bbc6a250b1..0000000000 --- a/modules/congestion_controller/network_control/network_units_to_string.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2018 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. - */ -#include "modules/congestion_controller/network_control/include/network_units_to_string.h" -#include "rtc_base/strings/string_builder.h" - -namespace webrtc { -std::string ToString(const DataRate& value) { - char buf[64]; - rtc::SimpleStringBuilder sb(buf); - if (value.IsInfinite()) { - sb << "inf bps"; - } else if (!value.IsInitialized()) { - sb << "? bps"; - } else { - sb << value.bps() << " bps"; - } - return sb.str(); -} -std::string ToString(const DataSize& value) { - char buf[64]; - rtc::SimpleStringBuilder sb(buf); - if (value.IsInfinite()) { - sb << "inf bytes"; - } else if (!value.IsInitialized()) { - sb << "? bytes"; - } else { - sb << value.bytes() << " bytes"; - } - return sb.str(); -} -std::string ToString(const Timestamp& value) { - char buf[64]; - rtc::SimpleStringBuilder sb(buf); - if (value.IsInfinite()) { - sb << "inf ms"; - } else if (!value.IsInitialized()) { - sb << "? ms"; - } else { - sb << value.ms() << " ms"; - } - return sb.str(); -} -std::string ToString(const TimeDelta& value) { - char buf[64]; - rtc::SimpleStringBuilder sb(buf); - if (value.IsPlusInfinity()) { - sb << "+inf ms"; - } else if (value.IsMinusInfinity()) { - sb << "-inf ms"; - } else if (!value.IsInitialized()) { - sb << "? ms"; - } else { - sb << value.ms() << " ms"; - } - return sb.str(); -} -} // namespace webrtc diff --git a/modules/congestion_controller/network_control/network_units_unittest.cc b/modules/congestion_controller/network_control/network_units_unittest.cc deleted file mode 100644 index a50e0fb94f..0000000000 --- a/modules/congestion_controller/network_control/network_units_unittest.cc +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#include "modules/congestion_controller/network_control/include/network_units.h" -#include "test/gtest.h" - -namespace webrtc { -namespace test { - -TEST(TimeDeltaTest, GetBackSameValues) { - const int64_t kValue = 499; - for (int sign = -1; sign <= 1; ++sign) { - int64_t value = kValue * sign; - EXPECT_EQ(TimeDelta::ms(value).ms(), value); - EXPECT_EQ(TimeDelta::us(value).us(), value); - EXPECT_EQ(TimeDelta::s(value).s(), value); - EXPECT_EQ(TimeDelta::seconds(value).s(), value); - } - EXPECT_EQ(TimeDelta::Zero().us(), 0); -} - -TEST(TimeDeltaTest, GetDifferentPrefix) { - const int64_t kValue = 3000000; - EXPECT_EQ(TimeDelta::us(kValue).s(), kValue / 1000000); - EXPECT_EQ(TimeDelta::ms(kValue).s(), kValue / 1000); - EXPECT_EQ(TimeDelta::us(kValue).ms(), kValue / 1000); - - EXPECT_EQ(TimeDelta::ms(kValue).us(), kValue * 1000); - EXPECT_EQ(TimeDelta::s(kValue).ms(), kValue * 1000); - EXPECT_EQ(TimeDelta::s(kValue).us(), kValue * 1000000); -} - -TEST(TimeDeltaTest, IdentityChecks) { - const int64_t kValue = 3000; - EXPECT_TRUE(TimeDelta::Zero().IsZero()); - EXPECT_FALSE(TimeDelta::ms(kValue).IsZero()); - - EXPECT_TRUE(TimeDelta::PlusInfinity().IsInfinite()); - EXPECT_TRUE(TimeDelta::MinusInfinity().IsInfinite()); - EXPECT_FALSE(TimeDelta::Zero().IsInfinite()); - EXPECT_FALSE(TimeDelta::ms(-kValue).IsInfinite()); - EXPECT_FALSE(TimeDelta::ms(kValue).IsInfinite()); - - EXPECT_FALSE(TimeDelta::PlusInfinity().IsFinite()); - EXPECT_FALSE(TimeDelta::MinusInfinity().IsFinite()); - EXPECT_TRUE(TimeDelta::ms(-kValue).IsFinite()); - EXPECT_TRUE(TimeDelta::ms(kValue).IsFinite()); - EXPECT_TRUE(TimeDelta::Zero().IsFinite()); -} - -TEST(TimeDeltaTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - const TimeDelta small = TimeDelta::ms(kSmall); - const TimeDelta large = TimeDelta::ms(kLarge); - - EXPECT_EQ(TimeDelta::Zero(), TimeDelta::ms(0)); - EXPECT_EQ(TimeDelta::PlusInfinity(), TimeDelta::PlusInfinity()); - EXPECT_EQ(small, TimeDelta::ms(kSmall)); - EXPECT_LE(small, TimeDelta::ms(kSmall)); - EXPECT_GE(small, TimeDelta::ms(kSmall)); - EXPECT_NE(small, TimeDelta::ms(kLarge)); - EXPECT_LE(small, TimeDelta::ms(kLarge)); - EXPECT_LT(small, TimeDelta::ms(kLarge)); - EXPECT_GE(large, TimeDelta::ms(kSmall)); - EXPECT_GT(large, TimeDelta::ms(kSmall)); - EXPECT_LT(TimeDelta::Zero(), small); - EXPECT_GT(TimeDelta::Zero(), TimeDelta::ms(-kSmall)); - EXPECT_GT(TimeDelta::Zero(), TimeDelta::ms(-kSmall)); - - EXPECT_GT(TimeDelta::PlusInfinity(), large); - EXPECT_LT(TimeDelta::MinusInfinity(), TimeDelta::Zero()); -} - -TEST(TimeDeltaTest, MathOperations) { - const int64_t kValueA = 267; - const int64_t kValueB = 450; - const TimeDelta delta_a = TimeDelta::ms(kValueA); - const TimeDelta delta_b = TimeDelta::ms(kValueB); - EXPECT_EQ((delta_a + delta_b).ms(), kValueA + kValueB); - EXPECT_EQ((delta_a - delta_b).ms(), kValueA - kValueB); - - const int32_t kInt32Value = 123; - const double kFloatValue = 123.0; - EXPECT_EQ((TimeDelta::us(kValueA) * kValueB).us(), kValueA * kValueB); - EXPECT_EQ((TimeDelta::us(kValueA) * kInt32Value).us(), kValueA * kInt32Value); - EXPECT_EQ((TimeDelta::us(kValueA) * kFloatValue).us(), kValueA * kFloatValue); - - EXPECT_EQ(TimeDelta::us(-kValueA).Abs().us(), kValueA); - EXPECT_EQ(TimeDelta::us(kValueA).Abs().us(), kValueA); -} - -TEST(TimestampTest, GetBackSameValues) { - const int64_t kValue = 499; - EXPECT_EQ(Timestamp::ms(kValue).ms(), kValue); - EXPECT_EQ(Timestamp::us(kValue).us(), kValue); - EXPECT_EQ(Timestamp::s(kValue).s(), kValue); -} - -TEST(TimestampTest, GetDifferentPrefix) { - const int64_t kValue = 3000000; - EXPECT_EQ(Timestamp::us(kValue).s(), kValue / 1000000); - EXPECT_EQ(Timestamp::ms(kValue).s(), kValue / 1000); - EXPECT_EQ(Timestamp::us(kValue).ms(), kValue / 1000); - - EXPECT_EQ(Timestamp::ms(kValue).us(), kValue * 1000); - EXPECT_EQ(Timestamp::s(kValue).ms(), kValue * 1000); - EXPECT_EQ(Timestamp::s(kValue).us(), kValue * 1000000); -} - -TEST(TimestampTest, IdentityChecks) { - const int64_t kValue = 3000; - - EXPECT_TRUE(Timestamp::Infinity().IsInfinite()); - EXPECT_FALSE(Timestamp::ms(kValue).IsInfinite()); - - EXPECT_FALSE(Timestamp().IsFinite()); - EXPECT_FALSE(Timestamp::Infinity().IsFinite()); - EXPECT_TRUE(Timestamp::ms(kValue).IsFinite()); -} - -TEST(TimestampTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - - EXPECT_EQ(Timestamp::Infinity(), Timestamp::Infinity()); - EXPECT_EQ(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); - EXPECT_LE(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); - EXPECT_GE(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); - EXPECT_NE(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); - EXPECT_LE(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); - EXPECT_LT(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); - EXPECT_GE(Timestamp::ms(kLarge), Timestamp::ms(kSmall)); - EXPECT_GT(Timestamp::ms(kLarge), Timestamp::ms(kSmall)); -} - -TEST(UnitConversionTest, TimestampAndTimeDeltaMath) { - const int64_t kValueA = 267; - const int64_t kValueB = 450; - const Timestamp time_a = Timestamp::ms(kValueA); - const Timestamp time_b = Timestamp::ms(kValueB); - const TimeDelta delta_a = TimeDelta::ms(kValueA); - - EXPECT_EQ((time_a - time_b), TimeDelta::ms(kValueA - kValueB)); - EXPECT_EQ((time_b - delta_a), Timestamp::ms(kValueB - kValueA)); - EXPECT_EQ((time_b + delta_a), Timestamp::ms(kValueB + kValueA)); -} - -TEST(DataSizeTest, GetBackSameValues) { - const int64_t kValue = 123 * 8; - EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue); - EXPECT_EQ(DataSize::bits(kValue).bits(), kValue); -} - -TEST(DataSizeTest, GetDifferentPrefix) { - const int64_t kValue = 123 * 8000; - EXPECT_EQ(DataSize::bytes(kValue).bits(), kValue * 8); - EXPECT_EQ(DataSize::bits(kValue).bytes(), kValue / 8); - EXPECT_EQ(DataSize::bits(kValue).kilobits(), kValue / 1000); - EXPECT_EQ(DataSize::bytes(kValue).kilobytes(), kValue / 1000); -} - -TEST(DataSizeTest, IdentityChecks) { - const int64_t kValue = 3000; - EXPECT_TRUE(DataSize::Zero().IsZero()); - EXPECT_FALSE(DataSize::bytes(kValue).IsZero()); - - EXPECT_TRUE(DataSize::Infinity().IsInfinite()); - EXPECT_FALSE(DataSize::Zero().IsInfinite()); - EXPECT_FALSE(DataSize::bytes(kValue).IsInfinite()); - - EXPECT_FALSE(DataSize::Infinity().IsFinite()); - EXPECT_TRUE(DataSize::bytes(kValue).IsFinite()); - EXPECT_TRUE(DataSize::Zero().IsFinite()); -} - -TEST(DataSizeTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - const DataSize small = DataSize::bytes(kSmall); - const DataSize large = DataSize::bytes(kLarge); - - EXPECT_EQ(DataSize::Zero(), DataSize::bytes(0)); - EXPECT_EQ(DataSize::Infinity(), DataSize::Infinity()); - EXPECT_EQ(small, small); - EXPECT_LE(small, small); - EXPECT_GE(small, small); - EXPECT_NE(small, large); - EXPECT_LE(small, large); - EXPECT_LT(small, large); - EXPECT_GE(large, small); - EXPECT_GT(large, small); - EXPECT_LT(DataSize::Zero(), small); - EXPECT_GT(DataSize::Infinity(), large); -} - -TEST(DataSizeTest, MathOperations) { - const int64_t kValueA = 450; - const int64_t kValueB = 267; - const DataSize size_a = DataSize::bytes(kValueA); - const DataSize size_b = DataSize::bytes(kValueB); - EXPECT_EQ((size_a + size_b).bytes(), kValueA + kValueB); - EXPECT_EQ((size_a - size_b).bytes(), kValueA - kValueB); - - const int32_t kInt32Value = 123; - const double kFloatValue = 123.0; - EXPECT_EQ((size_a * kValueB).bytes(), kValueA * kValueB); - EXPECT_EQ((size_a * kInt32Value).bytes(), kValueA * kInt32Value); - EXPECT_EQ((size_a * kFloatValue).bytes(), kValueA * kFloatValue); - - EXPECT_EQ((size_a / 10).bytes(), kValueA / 10); - - DataSize mutable_size = DataSize::bytes(kValueA); - mutable_size += size_b; - EXPECT_EQ(mutable_size.bytes(), kValueA + kValueB); - mutable_size -= size_a; - EXPECT_EQ(mutable_size.bytes(), kValueB); -} - -TEST(DataRateTest, GetBackSameValues) { - const int64_t kValue = 123 * 8; - EXPECT_EQ(DataRate::bytes_per_second(kValue).bytes_per_second(), kValue); - EXPECT_EQ(DataRate::bits_per_second(kValue).bits_per_second(), kValue); - EXPECT_EQ(DataRate::bps(kValue).bps(), kValue); - EXPECT_EQ(DataRate::kbps(kValue).kbps(), kValue); -} - -TEST(DataRateTest, GetDifferentPrefix) { - const int64_t kValue = 123 * 8000; - EXPECT_EQ(DataRate::bytes_per_second(kValue).bps(), kValue * 8); - EXPECT_EQ(DataRate::bits_per_second(kValue).bytes_per_second(), kValue / 8); - EXPECT_EQ(DataRate::bps(kValue).kbps(), kValue / 1000); -} - -TEST(DataRateTest, IdentityChecks) { - const int64_t kValue = 3000; - EXPECT_TRUE(DataRate::Zero().IsZero()); - EXPECT_FALSE(DataRate::bytes_per_second(kValue).IsZero()); - - EXPECT_TRUE(DataRate::Infinity().IsInfinite()); - EXPECT_FALSE(DataRate::Zero().IsInfinite()); - EXPECT_FALSE(DataRate::bytes_per_second(kValue).IsInfinite()); - - EXPECT_FALSE(DataRate::Infinity().IsFinite()); - EXPECT_TRUE(DataRate::bytes_per_second(kValue).IsFinite()); - EXPECT_TRUE(DataRate::Zero().IsFinite()); -} - -TEST(DataRateTest, ComparisonOperators) { - const int64_t kSmall = 450; - const int64_t kLarge = 451; - const DataRate small = DataRate::bytes_per_second(kSmall); - const DataRate large = DataRate::bytes_per_second(kLarge); - - EXPECT_EQ(DataRate::Zero(), DataRate::bps(0)); - EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity()); - EXPECT_EQ(small, small); - EXPECT_LE(small, small); - EXPECT_GE(small, small); - EXPECT_NE(small, large); - EXPECT_LE(small, large); - EXPECT_LT(small, large); - EXPECT_GE(large, small); - EXPECT_GT(large, small); - EXPECT_LT(DataRate::Zero(), small); - EXPECT_GT(DataRate::Infinity(), large); -} - -TEST(DataRateTest, MathOperations) { - const int64_t kValueA = 450; - const int64_t kValueB = 267; - const DataRate size_a = DataRate::bytes_per_second(kValueA); - const int32_t kInt32Value = 123; - const double kFloatValue = 123.0; - EXPECT_EQ((size_a * kValueB).bytes_per_second(), kValueA * kValueB); - EXPECT_EQ((size_a * kInt32Value).bytes_per_second(), kValueA * kInt32Value); - EXPECT_EQ((size_a * kFloatValue).bytes_per_second(), kValueA * kFloatValue); -} - -TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) { - const int64_t kValueA = 5; - const int64_t kValueB = 450; - const int64_t kValueC = 45000; - const TimeDelta delta_a = TimeDelta::seconds(kValueA); - const DataRate rate_b = DataRate::bytes_per_second(kValueB); - const DataSize size_c = DataSize::bytes(kValueC); - EXPECT_EQ((delta_a * rate_b).bytes(), kValueA * kValueB); - EXPECT_EQ((size_c / delta_a).bytes_per_second(), kValueC / kValueA); - EXPECT_EQ((size_c / rate_b).s(), kValueC / kValueB); -} - -} // namespace test -} // namespace webrtc diff --git a/modules/congestion_controller/network_control/test/network_control_tester.cc b/modules/congestion_controller/network_control/test/network_control_tester.cc index 0bfef77927..d6cce8876f 100644 --- a/modules/congestion_controller/network_control/test/network_control_tester.cc +++ b/modules/congestion_controller/network_control/test/network_control_tester.cc @@ -9,12 +9,12 @@ */ #include "modules/congestion_controller/network_control/test/network_control_tester.h" -#include "modules/congestion_controller/network_control/include/network_units_to_string.h" #include #include "modules/congestion_controller/network_control/include/network_control.h" #include "rtc_base/logging.h" + namespace webrtc { namespace test { namespace { diff --git a/modules/congestion_controller/network_control/units/BUILD.gn b/modules/congestion_controller/network_control/units/BUILD.gn new file mode 100644 index 0000000000..ecb8554280 --- /dev/null +++ b/modules/congestion_controller/network_control/units/BUILD.gn @@ -0,0 +1,101 @@ +# Copyright (c) 2018 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. + +import("../../../../webrtc.gni") + +rtc_static_library("units") { + sources = [ + "network_units.h", + "unit_operators.cc", + "unit_operators.h", + ] + + deps = [ + ":data_rate", + ":data_size", + ":time_delta", + ":timestamp", + "../../../../api:optional", + "../../../../rtc_base:checks", + "../../../../rtc_base:rtc_base_approved", + ] +} + +rtc_source_set("data_rate") { + sources = [ + "data_rate.cc", + "data_rate.h", + ] + + deps = [ + "../../../../api:optional", + "../../../../rtc_base:checks", + "../../../../rtc_base:rtc_base_approved", + ] +} + +rtc_source_set("data_size") { + sources = [ + "data_size.cc", + "data_size.h", + ] + + deps = [ + ":data_rate", + "../../../../api:optional", + "../../../../rtc_base:checks", + "../../../../rtc_base:rtc_base_approved", + ] +} +rtc_source_set("time_delta") { + sources = [ + "time_delta.cc", + "time_delta.h", + ] + + deps = [ + "../../../../api:optional", + "../../../../rtc_base:checks", + "../../../../rtc_base:rtc_base_approved", + ] +} + +rtc_source_set("timestamp") { + sources = [ + "timestamp.cc", + "timestamp.h", + ] + + deps = [ + ":time_delta", + "../../../../api:optional", + "../../../../rtc_base:checks", + "../../../../rtc_base:rtc_base_approved", + ] +} + +if (rtc_include_tests) { + rtc_source_set("units_unittests") { + testonly = true + sources = [ + "data_rate_unittest.cc", + "data_size_unittest.cc", + "time_delta_unittest.cc", + "timestamp_unittest.cc", + "unit_operators_unittest.cc", + ] + deps = [ + ":data_rate", + ":data_size", + ":time_delta", + ":timestamp", + ":units", + "../../../../test:test_support", + ] + } +} diff --git a/modules/congestion_controller/network_control/units/data_rate.cc b/modules/congestion_controller/network_control/units/data_rate.cc new file mode 100644 index 0000000000..182c07b846 --- /dev/null +++ b/modules/congestion_controller/network_control/units/data_rate.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/data_rate.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +std::string ToString(const DataRate& value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsInfinite()) { + sb << "inf bps"; + } else if (!value.IsInitialized()) { + sb << "? bps"; + } else { + sb << value.bps() << " bps"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/data_rate.h b/modules/congestion_controller/network_control/units/data_rate.h new file mode 100644 index 0000000000..1cc43f5f30 --- /dev/null +++ b/modules/congestion_controller/network_control/units/data_rate.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_DATA_RATE_H_ +#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_DATA_RATE_H_ + +#include +#include +#include +#include + +#include "rtc_base/checks.h" + +namespace webrtc { +namespace data_rate_impl { +constexpr int64_t kPlusInfinityVal = std::numeric_limits::max(); +constexpr int64_t kNotInitializedVal = -1; +} // namespace data_rate_impl + +// DataRate is a class that represents a given data rate. This can be used to +// represent bandwidth, encoding bitrate, etc. The internal storage is currently +// bits per second (bps) since this makes it easier to intepret the raw value +// when debugging. The promised precision, however is only that it will +// represent bytes per second accurately. Any implementation depending on bps +// resolution should document this by changing this comment. +class DataRate { + public: + DataRate() : DataRate(data_rate_impl::kNotInitializedVal) {} + static DataRate Zero() { return DataRate(0); } + static DataRate Infinity() { + return DataRate(data_rate_impl::kPlusInfinityVal); + } + static DataRate bytes_per_second(int64_t bytes_per_sec) { + RTC_DCHECK_GE(bytes_per_sec, 0); + return DataRate(bytes_per_sec * 8); + } + static DataRate bits_per_second(int64_t bits_per_sec) { + RTC_DCHECK_GE(bits_per_sec, 0); + return DataRate(bits_per_sec); + } + static DataRate bps(int64_t bits_per_sec) { + return DataRate::bits_per_second(bits_per_sec); + } + static DataRate kbps(int64_t kilobits_per_sec) { + return DataRate::bits_per_second(kilobits_per_sec * 1000); + } + int64_t bits_per_second() const { + RTC_DCHECK(IsFinite()); + return bits_per_sec_; + } + int64_t bytes_per_second() const { return bits_per_second() / 8; } + int64_t bps() const { return bits_per_second(); } + int64_t bps_or(int64_t fallback) const { + return IsFinite() ? bits_per_second() : fallback; + } + int64_t kbps() const { return (bps() + 500) / 1000; } + bool IsZero() const { return bits_per_sec_ == 0; } + bool IsInfinite() const { + return bits_per_sec_ == data_rate_impl::kPlusInfinityVal; + } + bool IsInitialized() const { + return bits_per_sec_ != data_rate_impl::kNotInitializedVal; + } + bool IsFinite() const { return IsInitialized() && !IsInfinite(); } + DataRate operator*(double scalar) const { + return DataRate::bytes_per_second(std::round(bytes_per_second() * scalar)); + } + DataRate operator*(int64_t scalar) const { + return DataRate::bytes_per_second(bytes_per_second() * scalar); + } + DataRate operator*(int32_t scalar) const { + return DataRate::bytes_per_second(bytes_per_second() * scalar); + } + bool operator==(const DataRate& other) const { + return bits_per_sec_ == other.bits_per_sec_; + } + bool operator!=(const DataRate& other) const { + return bits_per_sec_ != other.bits_per_sec_; + } + bool operator<=(const DataRate& other) const { + return bits_per_sec_ <= other.bits_per_sec_; + } + bool operator>=(const DataRate& other) const { + return bits_per_sec_ >= other.bits_per_sec_; + } + bool operator>(const DataRate& other) const { + return bits_per_sec_ > other.bits_per_sec_; + } + bool operator<(const DataRate& other) const { + return bits_per_sec_ < other.bits_per_sec_; + } + + private: + // Bits per second used internally to simplify debugging by making the value + // more recognizable. + explicit DataRate(int64_t bits_per_second) : bits_per_sec_(bits_per_second) {} + int64_t bits_per_sec_; +}; +inline DataRate operator*(const double& scalar, const DataRate& rate) { + return rate * scalar; +} +inline DataRate operator*(const int64_t& scalar, const DataRate& rate) { + return rate * scalar; +} +inline DataRate operator*(const int32_t& scalar, const DataRate& rate) { + return rate * scalar; +} + +std::string ToString(const DataRate& value); +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_DATA_RATE_H_ diff --git a/modules/congestion_controller/network_control/units/data_rate_unittest.cc b/modules/congestion_controller/network_control/units/data_rate_unittest.cc new file mode 100644 index 0000000000..48d0e78837 --- /dev/null +++ b/modules/congestion_controller/network_control/units/data_rate_unittest.cc @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/data_rate.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +TEST(DataRateTest, GetBackSameValues) { + const int64_t kValue = 123 * 8; + EXPECT_EQ(DataRate::bytes_per_second(kValue).bytes_per_second(), kValue); + EXPECT_EQ(DataRate::bits_per_second(kValue).bits_per_second(), kValue); + EXPECT_EQ(DataRate::bps(kValue).bps(), kValue); + EXPECT_EQ(DataRate::kbps(kValue).kbps(), kValue); +} + +TEST(DataRateTest, GetDifferentPrefix) { + const int64_t kValue = 123 * 8000; + EXPECT_EQ(DataRate::bytes_per_second(kValue).bps(), kValue * 8); + EXPECT_EQ(DataRate::bits_per_second(kValue).bytes_per_second(), kValue / 8); + EXPECT_EQ(DataRate::bps(kValue).kbps(), kValue / 1000); +} + +TEST(DataRateTest, IdentityChecks) { + const int64_t kValue = 3000; + EXPECT_TRUE(DataRate::Zero().IsZero()); + EXPECT_FALSE(DataRate::bytes_per_second(kValue).IsZero()); + + EXPECT_TRUE(DataRate::Infinity().IsInfinite()); + EXPECT_FALSE(DataRate::Zero().IsInfinite()); + EXPECT_FALSE(DataRate::bytes_per_second(kValue).IsInfinite()); + + EXPECT_FALSE(DataRate::Infinity().IsFinite()); + EXPECT_TRUE(DataRate::bytes_per_second(kValue).IsFinite()); + EXPECT_TRUE(DataRate::Zero().IsFinite()); +} + +TEST(DataRateTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + const DataRate small = DataRate::bytes_per_second(kSmall); + const DataRate large = DataRate::bytes_per_second(kLarge); + + EXPECT_EQ(DataRate::Zero(), DataRate::bps(0)); + EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity()); + EXPECT_EQ(small, small); + EXPECT_LE(small, small); + EXPECT_GE(small, small); + EXPECT_NE(small, large); + EXPECT_LE(small, large); + EXPECT_LT(small, large); + EXPECT_GE(large, small); + EXPECT_GT(large, small); + EXPECT_LT(DataRate::Zero(), small); + EXPECT_GT(DataRate::Infinity(), large); +} + +TEST(DataRateTest, MathOperations) { + const int64_t kValueA = 450; + const int64_t kValueB = 267; + const DataRate size_a = DataRate::bytes_per_second(kValueA); + const int32_t kInt32Value = 123; + const double kFloatValue = 123.0; + EXPECT_EQ((size_a * kValueB).bytes_per_second(), kValueA * kValueB); + EXPECT_EQ((size_a * kInt32Value).bytes_per_second(), kValueA * kInt32Value); + EXPECT_EQ((size_a * kFloatValue).bytes_per_second(), kValueA * kFloatValue); +} +} // namespace test +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/data_size.cc b/modules/congestion_controller/network_control/units/data_size.cc new file mode 100644 index 0000000000..3068c5289f --- /dev/null +++ b/modules/congestion_controller/network_control/units/data_size.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/data_size.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +std::string ToString(const DataSize& value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsInfinite()) { + sb << "inf bytes"; + } else if (!value.IsInitialized()) { + sb << "? bytes"; + } else { + sb << value.bytes() << " bytes"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/data_size.h b/modules/congestion_controller/network_control/units/data_size.h new file mode 100644 index 0000000000..da396d8899 --- /dev/null +++ b/modules/congestion_controller/network_control/units/data_size.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_DATA_SIZE_H_ +#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_DATA_SIZE_H_ + +#include +#include +#include +#include + +#include "rtc_base/checks.h" + +namespace webrtc { +namespace data_size_impl { +constexpr int64_t kPlusInfinityVal = std::numeric_limits::max(); +constexpr int64_t kNotInitializedVal = -1; +} // namespace data_size_impl + +// DataSize is a class represeting a count of bytes. Note that while it can be +// initialized by a number of bits, it does not guarantee that the resolution is +// kept and the internal storage is in bytes. The number of bits will be +// truncated to fit. +class DataSize { + public: + DataSize() : DataSize(data_size_impl::kNotInitializedVal) {} + static DataSize Zero() { return DataSize(0); } + static DataSize Infinity() { + return DataSize(data_size_impl::kPlusInfinityVal); + } + static DataSize bytes(int64_t bytes) { + RTC_DCHECK_GE(bytes, 0); + return DataSize(bytes); + } + static DataSize bits(int64_t bits) { + RTC_DCHECK_GE(bits, 0); + return DataSize(bits / 8); + } + int64_t bytes() const { + RTC_DCHECK(IsFinite()); + return bytes_; + } + int64_t kilobytes() const { return (bytes() + 500) / 1000; } + int64_t bits() const { return bytes() * 8; } + int64_t kilobits() const { return (bits() + 500) / 1000; } + bool IsZero() const { return bytes_ == 0; } + bool IsInfinite() const { return bytes_ == data_size_impl::kPlusInfinityVal; } + bool IsInitialized() const { + return bytes_ != data_size_impl::kNotInitializedVal; + } + bool IsFinite() const { return IsInitialized() && !IsInfinite(); } + DataSize operator-(const DataSize& other) const { + return DataSize::bytes(bytes() - other.bytes()); + } + DataSize operator+(const DataSize& other) const { + return DataSize::bytes(bytes() + other.bytes()); + } + DataSize operator*(double scalar) const { + return DataSize::bytes(std::round(bytes() * scalar)); + } + DataSize operator*(int64_t scalar) const { + return DataSize::bytes(bytes() * scalar); + } + DataSize operator*(int32_t scalar) const { + return DataSize::bytes(bytes() * scalar); + } + DataSize operator/(int64_t scalar) const { + return DataSize::bytes(bytes() / scalar); + } + DataSize& operator-=(const DataSize& other) { + bytes_ -= other.bytes(); + return *this; + } + DataSize& operator+=(const DataSize& other) { + bytes_ += other.bytes(); + return *this; + } + bool operator==(const DataSize& other) const { + return bytes_ == other.bytes_; + } + bool operator!=(const DataSize& other) const { + return bytes_ != other.bytes_; + } + bool operator<=(const DataSize& other) const { + return bytes_ <= other.bytes_; + } + bool operator>=(const DataSize& other) const { + return bytes_ >= other.bytes_; + } + bool operator>(const DataSize& other) const { return bytes_ > other.bytes_; } + bool operator<(const DataSize& other) const { return bytes_ < other.bytes_; } + + private: + explicit DataSize(int64_t bytes) : bytes_(bytes) {} + int64_t bytes_; +}; +inline DataSize operator*(const double& scalar, const DataSize& size) { + return size * scalar; +} +inline DataSize operator*(const int64_t& scalar, const DataSize& size) { + return size * scalar; +} +inline DataSize operator*(const int32_t& scalar, const DataSize& size) { + return size * scalar; +} + +std::string ToString(const DataSize& value); + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_DATA_SIZE_H_ diff --git a/modules/congestion_controller/network_control/units/data_size_unittest.cc b/modules/congestion_controller/network_control/units/data_size_unittest.cc new file mode 100644 index 0000000000..6314787650 --- /dev/null +++ b/modules/congestion_controller/network_control/units/data_size_unittest.cc @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/data_size.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +TEST(DataSizeTest, GetBackSameValues) { + const int64_t kValue = 123 * 8; + EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue); + EXPECT_EQ(DataSize::bits(kValue).bits(), kValue); +} + +TEST(DataSizeTest, GetDifferentPrefix) { + const int64_t kValue = 123 * 8000; + EXPECT_EQ(DataSize::bytes(kValue).bits(), kValue * 8); + EXPECT_EQ(DataSize::bits(kValue).bytes(), kValue / 8); + EXPECT_EQ(DataSize::bits(kValue).kilobits(), kValue / 1000); + EXPECT_EQ(DataSize::bytes(kValue).kilobytes(), kValue / 1000); +} + +TEST(DataSizeTest, IdentityChecks) { + const int64_t kValue = 3000; + EXPECT_TRUE(DataSize::Zero().IsZero()); + EXPECT_FALSE(DataSize::bytes(kValue).IsZero()); + + EXPECT_TRUE(DataSize::Infinity().IsInfinite()); + EXPECT_FALSE(DataSize::Zero().IsInfinite()); + EXPECT_FALSE(DataSize::bytes(kValue).IsInfinite()); + + EXPECT_FALSE(DataSize::Infinity().IsFinite()); + EXPECT_TRUE(DataSize::bytes(kValue).IsFinite()); + EXPECT_TRUE(DataSize::Zero().IsFinite()); +} + +TEST(DataSizeTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + const DataSize small = DataSize::bytes(kSmall); + const DataSize large = DataSize::bytes(kLarge); + + EXPECT_EQ(DataSize::Zero(), DataSize::bytes(0)); + EXPECT_EQ(DataSize::Infinity(), DataSize::Infinity()); + EXPECT_EQ(small, small); + EXPECT_LE(small, small); + EXPECT_GE(small, small); + EXPECT_NE(small, large); + EXPECT_LE(small, large); + EXPECT_LT(small, large); + EXPECT_GE(large, small); + EXPECT_GT(large, small); + EXPECT_LT(DataSize::Zero(), small); + EXPECT_GT(DataSize::Infinity(), large); +} + +TEST(DataSizeTest, MathOperations) { + const int64_t kValueA = 450; + const int64_t kValueB = 267; + const DataSize size_a = DataSize::bytes(kValueA); + const DataSize size_b = DataSize::bytes(kValueB); + EXPECT_EQ((size_a + size_b).bytes(), kValueA + kValueB); + EXPECT_EQ((size_a - size_b).bytes(), kValueA - kValueB); + + const int32_t kInt32Value = 123; + const double kFloatValue = 123.0; + EXPECT_EQ((size_a * kValueB).bytes(), kValueA * kValueB); + EXPECT_EQ((size_a * kInt32Value).bytes(), kValueA * kInt32Value); + EXPECT_EQ((size_a * kFloatValue).bytes(), kValueA * kFloatValue); + + EXPECT_EQ((size_a / 10).bytes(), kValueA / 10); + + DataSize mutable_size = DataSize::bytes(kValueA); + mutable_size += size_b; + EXPECT_EQ(mutable_size.bytes(), kValueA + kValueB); + mutable_size -= size_a; + EXPECT_EQ(mutable_size.bytes(), kValueB); +} +} // namespace test +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/network_units.h b/modules/congestion_controller/network_control/units/network_units.h new file mode 100644 index 0000000000..5b8eeecfd7 --- /dev/null +++ b/modules/congestion_controller/network_control/units/network_units.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_NETWORK_UNITS_H_ +#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_NETWORK_UNITS_H_ + +#include "modules/congestion_controller/network_control/units/data_rate.h" +#include "modules/congestion_controller/network_control/units/data_size.h" +#include "modules/congestion_controller/network_control/units/time_delta.h" +#include "modules/congestion_controller/network_control/units/timestamp.h" +#include "modules/congestion_controller/network_control/units/unit_operators.h" + +#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_NETWORK_UNITS_H_ diff --git a/modules/congestion_controller/network_control/units/time_delta.cc b/modules/congestion_controller/network_control/units/time_delta.cc new file mode 100644 index 0000000000..85dc15afea --- /dev/null +++ b/modules/congestion_controller/network_control/units/time_delta.cc @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/time_delta.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { + +std::string ToString(const TimeDelta& value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsPlusInfinity()) { + sb << "+inf ms"; + } else if (value.IsMinusInfinity()) { + sb << "-inf ms"; + } else if (!value.IsInitialized()) { + sb << "? ms"; + } else { + sb << value.ms() << " ms"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/time_delta.h b/modules/congestion_controller/network_control/units/time_delta.h new file mode 100644 index 0000000000..3a54e002b9 --- /dev/null +++ b/modules/congestion_controller/network_control/units/time_delta.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_TIME_DELTA_H_ +#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_TIME_DELTA_H_ + +#include +#include +#include +#include + +#include "rtc_base/checks.h" + +namespace webrtc { +namespace timedelta_impl { +constexpr int64_t kPlusInfinityVal = std::numeric_limits::max(); +constexpr int64_t kMinusInfinityVal = std::numeric_limits::min(); +constexpr int64_t kSignedNotInitializedVal = kMinusInfinityVal + 1; + +} // namespace timedelta_impl + +// TimeDelta represents the difference between two timestamps. Commonly this can +// be a duration. However since two Timestamps are not guaranteed to have the +// same epoch (they might come from different computers, making exact +// synchronisation infeasible), the duration covered by a TimeDelta can be +// undefined. To simplify usage, it can be constructed and converted to +// different units, specifically seconds (s), milliseconds (ms) and +// microseconds (us). +class TimeDelta { + public: + TimeDelta() : TimeDelta(timedelta_impl::kSignedNotInitializedVal) {} + static TimeDelta Zero() { return TimeDelta(0); } + static TimeDelta PlusInfinity() { + return TimeDelta(timedelta_impl::kPlusInfinityVal); + } + static TimeDelta MinusInfinity() { + return TimeDelta(timedelta_impl::kMinusInfinityVal); + } + static TimeDelta seconds(int64_t seconds) { return TimeDelta::s(seconds); } + static TimeDelta s(int64_t seconds) { + return TimeDelta::us(seconds * 1000000); + } + static TimeDelta ms(int64_t milliseconds) { + return TimeDelta::us(milliseconds * 1000); + } + static TimeDelta us(int64_t microseconds) { + // Infinities only allowed via use of explicit constants. + RTC_DCHECK(microseconds > std::numeric_limits::min()); + RTC_DCHECK(microseconds < std::numeric_limits::max()); + RTC_DCHECK(microseconds != timedelta_impl::kSignedNotInitializedVal); + return TimeDelta(microseconds); + } + int64_t s() const { + return (us() + (us() >= 0 ? 500000 : -500000)) / 1000000; + } + int64_t ms() const { return (us() + (us() >= 0 ? 500 : -500)) / 1000; } + int64_t us() const { + RTC_DCHECK(IsFinite()); + return microseconds_; + } + + double SecondsAsDouble() const; + + TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); } + bool IsZero() const { return microseconds_ == 0; } + bool IsFinite() const { return IsInitialized() && !IsInfinite(); } + bool IsInitialized() const { + return microseconds_ != timedelta_impl::kSignedNotInitializedVal; + } + bool IsInfinite() const { + return microseconds_ == timedelta_impl::kPlusInfinityVal || + microseconds_ == timedelta_impl::kMinusInfinityVal; + } + bool IsPlusInfinity() const { + return microseconds_ == timedelta_impl::kPlusInfinityVal; + } + bool IsMinusInfinity() const { + return microseconds_ == timedelta_impl::kMinusInfinityVal; + } + TimeDelta operator+(const TimeDelta& other) const { + return TimeDelta::us(us() + other.us()); + } + TimeDelta operator-(const TimeDelta& other) const { + return TimeDelta::us(us() - other.us()); + } + TimeDelta& operator-=(const TimeDelta& other) { + microseconds_ -= other.us(); + return *this; + } + TimeDelta& operator+=(const TimeDelta& other) { + microseconds_ += other.us(); + return *this; + } + TimeDelta operator*(double scalar) const { + return TimeDelta::us(std::round(us() * scalar)); + } + TimeDelta operator*(int64_t scalar) const { + return TimeDelta::us(us() * scalar); + } + TimeDelta operator*(int32_t scalar) const { + return TimeDelta::us(us() * scalar); + } + TimeDelta operator/(int64_t scalar) const { + return TimeDelta::us(us() / scalar); + } + bool operator==(const TimeDelta& other) const { + return microseconds_ == other.microseconds_; + } + bool operator!=(const TimeDelta& other) const { + return microseconds_ != other.microseconds_; + } + bool operator<=(const TimeDelta& other) const { + return microseconds_ <= other.microseconds_; + } + bool operator>=(const TimeDelta& other) const { + return microseconds_ >= other.microseconds_; + } + bool operator>(const TimeDelta& other) const { + return microseconds_ > other.microseconds_; + } + bool operator<(const TimeDelta& other) const { + return microseconds_ < other.microseconds_; + } + + private: + explicit TimeDelta(int64_t us) : microseconds_(us) {} + int64_t microseconds_; +}; +inline TimeDelta operator*(const double& scalar, const TimeDelta& delta) { + return delta * scalar; +} +inline TimeDelta operator*(const int64_t& scalar, const TimeDelta& delta) { + return delta * scalar; +} +inline TimeDelta operator*(const int32_t& scalar, const TimeDelta& delta) { + return delta * scalar; +} + +std::string ToString(const TimeDelta& value); +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_TIME_DELTA_H_ diff --git a/modules/congestion_controller/network_control/units/time_delta_unittest.cc b/modules/congestion_controller/network_control/units/time_delta_unittest.cc new file mode 100644 index 0000000000..d771cd26a8 --- /dev/null +++ b/modules/congestion_controller/network_control/units/time_delta_unittest.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/time_delta.h" + +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +TEST(TimeDeltaTest, GetBackSameValues) { + const int64_t kValue = 499; + for (int sign = -1; sign <= 1; ++sign) { + int64_t value = kValue * sign; + EXPECT_EQ(TimeDelta::ms(value).ms(), value); + EXPECT_EQ(TimeDelta::us(value).us(), value); + EXPECT_EQ(TimeDelta::s(value).s(), value); + EXPECT_EQ(TimeDelta::seconds(value).s(), value); + } + EXPECT_EQ(TimeDelta::Zero().us(), 0); +} + +TEST(TimeDeltaTest, GetDifferentPrefix) { + const int64_t kValue = 3000000; + EXPECT_EQ(TimeDelta::us(kValue).s(), kValue / 1000000); + EXPECT_EQ(TimeDelta::ms(kValue).s(), kValue / 1000); + EXPECT_EQ(TimeDelta::us(kValue).ms(), kValue / 1000); + + EXPECT_EQ(TimeDelta::ms(kValue).us(), kValue * 1000); + EXPECT_EQ(TimeDelta::s(kValue).ms(), kValue * 1000); + EXPECT_EQ(TimeDelta::s(kValue).us(), kValue * 1000000); +} + +TEST(TimeDeltaTest, IdentityChecks) { + const int64_t kValue = 3000; + EXPECT_TRUE(TimeDelta::Zero().IsZero()); + EXPECT_FALSE(TimeDelta::ms(kValue).IsZero()); + + EXPECT_TRUE(TimeDelta::PlusInfinity().IsInfinite()); + EXPECT_TRUE(TimeDelta::MinusInfinity().IsInfinite()); + EXPECT_FALSE(TimeDelta::Zero().IsInfinite()); + EXPECT_FALSE(TimeDelta::ms(-kValue).IsInfinite()); + EXPECT_FALSE(TimeDelta::ms(kValue).IsInfinite()); + + EXPECT_FALSE(TimeDelta::PlusInfinity().IsFinite()); + EXPECT_FALSE(TimeDelta::MinusInfinity().IsFinite()); + EXPECT_TRUE(TimeDelta::ms(-kValue).IsFinite()); + EXPECT_TRUE(TimeDelta::ms(kValue).IsFinite()); + EXPECT_TRUE(TimeDelta::Zero().IsFinite()); +} + +TEST(TimeDeltaTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + const TimeDelta small = TimeDelta::ms(kSmall); + const TimeDelta large = TimeDelta::ms(kLarge); + + EXPECT_EQ(TimeDelta::Zero(), TimeDelta::ms(0)); + EXPECT_EQ(TimeDelta::PlusInfinity(), TimeDelta::PlusInfinity()); + EXPECT_EQ(small, TimeDelta::ms(kSmall)); + EXPECT_LE(small, TimeDelta::ms(kSmall)); + EXPECT_GE(small, TimeDelta::ms(kSmall)); + EXPECT_NE(small, TimeDelta::ms(kLarge)); + EXPECT_LE(small, TimeDelta::ms(kLarge)); + EXPECT_LT(small, TimeDelta::ms(kLarge)); + EXPECT_GE(large, TimeDelta::ms(kSmall)); + EXPECT_GT(large, TimeDelta::ms(kSmall)); + EXPECT_LT(TimeDelta::Zero(), small); + EXPECT_GT(TimeDelta::Zero(), TimeDelta::ms(-kSmall)); + EXPECT_GT(TimeDelta::Zero(), TimeDelta::ms(-kSmall)); + + EXPECT_GT(TimeDelta::PlusInfinity(), large); + EXPECT_LT(TimeDelta::MinusInfinity(), TimeDelta::Zero()); +} + +TEST(TimeDeltaTest, MathOperations) { + const int64_t kValueA = 267; + const int64_t kValueB = 450; + const TimeDelta delta_a = TimeDelta::ms(kValueA); + const TimeDelta delta_b = TimeDelta::ms(kValueB); + EXPECT_EQ((delta_a + delta_b).ms(), kValueA + kValueB); + EXPECT_EQ((delta_a - delta_b).ms(), kValueA - kValueB); + + const int32_t kInt32Value = 123; + const double kFloatValue = 123.0; + EXPECT_EQ((TimeDelta::us(kValueA) * kValueB).us(), kValueA * kValueB); + EXPECT_EQ((TimeDelta::us(kValueA) * kInt32Value).us(), kValueA * kInt32Value); + EXPECT_EQ((TimeDelta::us(kValueA) * kFloatValue).us(), kValueA * kFloatValue); + + EXPECT_EQ(TimeDelta::us(-kValueA).Abs().us(), kValueA); + EXPECT_EQ(TimeDelta::us(kValueA).Abs().us(), kValueA); +} +} // namespace test +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/timestamp.cc b/modules/congestion_controller/network_control/units/timestamp.cc new file mode 100644 index 0000000000..9b79fd5b65 --- /dev/null +++ b/modules/congestion_controller/network_control/units/timestamp.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/timestamp.h" + +#include "rtc_base/strings/string_builder.h" + +namespace webrtc { +double Timestamp::SecondsAsDouble() const { + if (IsInfinite()) { + return std::numeric_limits::infinity(); + } else if (!IsInitialized()) { + return std::numeric_limits::signaling_NaN(); + } else { + return us() * 1e-6; + } +} + +std::string ToString(const Timestamp& value) { + char buf[64]; + rtc::SimpleStringBuilder sb(buf); + if (value.IsInfinite()) { + sb << "inf ms"; + } else if (!value.IsInitialized()) { + sb << "? ms"; + } else { + sb << value.ms() << " ms"; + } + return sb.str(); +} +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/timestamp.h b/modules/congestion_controller/network_control/units/timestamp.h new file mode 100644 index 0000000000..ae22a68848 --- /dev/null +++ b/modules/congestion_controller/network_control/units/timestamp.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_TIMESTAMP_H_ +#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_TIMESTAMP_H_ + +#include +#include +#include + +#include "modules/congestion_controller/network_control/units/time_delta.h" +#include "rtc_base/checks.h" + +namespace webrtc { +namespace timestamp_impl { +constexpr int64_t kPlusInfinityVal = std::numeric_limits::max(); +constexpr int64_t kMinusInfinityVal = std::numeric_limits::min(); +constexpr int64_t kSignedNotInitializedVal = kMinusInfinityVal + 1; +constexpr int64_t kNotInitializedVal = -1; +} // namespace timestamp_impl + +// Timestamp represents the time that has passed since some unspecified epoch. +// The epoch is assumed to be before any represented timestamps, this means that +// negative values are not valid. The most notable feature is that the +// difference of two Timestamps results in a TimeDelta. +class Timestamp { + public: + Timestamp() : Timestamp(timestamp_impl::kNotInitializedVal) {} + static Timestamp Infinity() { + return Timestamp(timestamp_impl::kPlusInfinityVal); + } + static Timestamp seconds(int64_t seconds) { return Timestamp::s(seconds); } + static Timestamp s(int64_t seconds) { + return Timestamp::us(seconds * 1000000); + } + static Timestamp ms(int64_t millis) { return Timestamp::us(millis * 1000); } + static Timestamp us(int64_t micros) { + RTC_DCHECK_GE(micros, 0); + return Timestamp(micros); + } + int64_t s() const { return (us() + 500000) / 1000000; } + int64_t ms() const { return (us() + 500) / 1000; } + int64_t us() const { + RTC_DCHECK(IsFinite()); + return microseconds_; + } + + double SecondsAsDouble() const; + + bool IsInfinite() const { + return microseconds_ == timestamp_impl::kPlusInfinityVal; + } + bool IsInitialized() const { + return microseconds_ != timestamp_impl::kNotInitializedVal; + } + bool IsFinite() const { return IsInitialized() && !IsInfinite(); } + TimeDelta operator-(const Timestamp& other) const { + return TimeDelta::us(us() - other.us()); + } + Timestamp operator-(const TimeDelta& delta) const { + return Timestamp::us(us() - delta.us()); + } + Timestamp operator+(const TimeDelta& delta) const { + return Timestamp::us(us() + delta.us()); + } + Timestamp& operator-=(const TimeDelta& other) { + microseconds_ -= other.us(); + return *this; + } + Timestamp& operator+=(const TimeDelta& other) { + microseconds_ += other.us(); + return *this; + } + bool operator==(const Timestamp& other) const { + return microseconds_ == other.microseconds_; + } + bool operator!=(const Timestamp& other) const { + return microseconds_ != other.microseconds_; + } + bool operator<=(const Timestamp& other) const { return us() <= other.us(); } + bool operator>=(const Timestamp& other) const { return us() >= other.us(); } + bool operator>(const Timestamp& other) const { return us() > other.us(); } + bool operator<(const Timestamp& other) const { return us() < other.us(); } + + private: + explicit Timestamp(int64_t us) : microseconds_(us) {} + int64_t microseconds_; +}; + +std::string ToString(const Timestamp& value); + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_TIMESTAMP_H_ diff --git a/modules/congestion_controller/network_control/units/timestamp_unittest.cc b/modules/congestion_controller/network_control/units/timestamp_unittest.cc new file mode 100644 index 0000000000..eeddc7da2b --- /dev/null +++ b/modules/congestion_controller/network_control/units/timestamp_unittest.cc @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/timestamp.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +TEST(TimestampTest, GetBackSameValues) { + const int64_t kValue = 499; + EXPECT_EQ(Timestamp::ms(kValue).ms(), kValue); + EXPECT_EQ(Timestamp::us(kValue).us(), kValue); + EXPECT_EQ(Timestamp::s(kValue).s(), kValue); +} + +TEST(TimestampTest, GetDifferentPrefix) { + const int64_t kValue = 3000000; + EXPECT_EQ(Timestamp::us(kValue).s(), kValue / 1000000); + EXPECT_EQ(Timestamp::ms(kValue).s(), kValue / 1000); + EXPECT_EQ(Timestamp::us(kValue).ms(), kValue / 1000); + + EXPECT_EQ(Timestamp::ms(kValue).us(), kValue * 1000); + EXPECT_EQ(Timestamp::s(kValue).ms(), kValue * 1000); + EXPECT_EQ(Timestamp::s(kValue).us(), kValue * 1000000); +} + +TEST(TimestampTest, IdentityChecks) { + const int64_t kValue = 3000; + + EXPECT_TRUE(Timestamp::Infinity().IsInfinite()); + EXPECT_FALSE(Timestamp::ms(kValue).IsInfinite()); + + EXPECT_FALSE(Timestamp().IsFinite()); + EXPECT_FALSE(Timestamp::Infinity().IsFinite()); + EXPECT_TRUE(Timestamp::ms(kValue).IsFinite()); +} + +TEST(TimestampTest, ComparisonOperators) { + const int64_t kSmall = 450; + const int64_t kLarge = 451; + + EXPECT_EQ(Timestamp::Infinity(), Timestamp::Infinity()); + EXPECT_EQ(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); + EXPECT_LE(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); + EXPECT_GE(Timestamp::ms(kSmall), Timestamp::ms(kSmall)); + EXPECT_NE(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); + EXPECT_LE(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); + EXPECT_LT(Timestamp::ms(kSmall), Timestamp::ms(kLarge)); + EXPECT_GE(Timestamp::ms(kLarge), Timestamp::ms(kSmall)); + EXPECT_GT(Timestamp::ms(kLarge), Timestamp::ms(kSmall)); +} + +TEST(UnitConversionTest, TimestampAndTimeDeltaMath) { + const int64_t kValueA = 267; + const int64_t kValueB = 450; + const Timestamp time_a = Timestamp::ms(kValueA); + const Timestamp time_b = Timestamp::ms(kValueB); + const TimeDelta delta_a = TimeDelta::ms(kValueA); + + EXPECT_EQ((time_a - time_b), TimeDelta::ms(kValueA - kValueB)); + EXPECT_EQ((time_b - delta_a), Timestamp::ms(kValueB - kValueA)); + EXPECT_EQ((time_b + delta_a), Timestamp::ms(kValueB + kValueA)); +} +} // namespace test +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/unit_operators.cc b/modules/congestion_controller/network_control/units/unit_operators.cc new file mode 100644 index 0000000000..9ebc109e0b --- /dev/null +++ b/modules/congestion_controller/network_control/units/unit_operators.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/unit_operators.h" + +#include + +namespace webrtc { +DataRate operator/(const DataSize& size, const TimeDelta& duration) { + RTC_DCHECK(size.bytes() < std::numeric_limits::max() / 1000000) + << "size is too large, size: " << size.bytes() << " is not less than " + << std::numeric_limits::max() / 1000000; + int64_t bytes_per_sec = size.bytes() * 1000000 / duration.us(); + return DataRate::bytes_per_second(bytes_per_sec); +} + +TimeDelta operator/(const DataSize& size, const DataRate& rate) { + RTC_DCHECK(size.bytes() < std::numeric_limits::max() / 1000000) + << "size is too large, size: " << size.bytes() << " is not less than " + << std::numeric_limits::max() / 1000000; + int64_t microseconds = size.bytes() * 1000000 / rate.bytes_per_second(); + return TimeDelta::us(microseconds); +} + +DataSize operator*(const DataRate& rate, const TimeDelta& duration) { + int64_t micro_bytes = rate.bytes_per_second() * duration.us(); + return DataSize::bytes((micro_bytes + 500000) / 1000000); +} + +DataSize operator*(const TimeDelta& duration, const DataRate& rate) { + return rate * duration; +} +} // namespace webrtc diff --git a/modules/congestion_controller/network_control/units/unit_operators.h b/modules/congestion_controller/network_control/units/unit_operators.h new file mode 100644 index 0000000000..33de2a1908 --- /dev/null +++ b/modules/congestion_controller/network_control/units/unit_operators.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018 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 MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_UNIT_OPERATORS_H_ +#define MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_UNIT_OPERATORS_H_ + +#include "modules/congestion_controller/network_control/units/data_rate.h" +#include "modules/congestion_controller/network_control/units/data_size.h" +#include "modules/congestion_controller/network_control/units/time_delta.h" + +namespace webrtc { +DataRate operator/(const DataSize& size, const TimeDelta& duration); +TimeDelta operator/(const DataSize& size, const DataRate& rate); +DataSize operator*(const DataRate& rate, const TimeDelta& duration); +DataSize operator*(const TimeDelta& duration, const DataRate& rate); +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_NETWORK_CONTROL_UNITS_UNIT_OPERATORS_H_ diff --git a/modules/congestion_controller/network_control/units/unit_operators_unittest.cc b/modules/congestion_controller/network_control/units/unit_operators_unittest.cc new file mode 100644 index 0000000000..8c7b3e2a34 --- /dev/null +++ b/modules/congestion_controller/network_control/units/unit_operators_unittest.cc @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 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. + */ + +#include "modules/congestion_controller/network_control/units/unit_operators.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +TEST(UnitConversionTest, DataRateAndDataSizeAndTimeDelta) { + const int64_t kValueA = 5; + const int64_t kValueB = 450; + const int64_t kValueC = 45000; + const TimeDelta delta_a = TimeDelta::seconds(kValueA); + const DataRate rate_b = DataRate::bytes_per_second(kValueB); + const DataSize size_c = DataSize::bytes(kValueC); + EXPECT_EQ((delta_a * rate_b).bytes(), kValueA * kValueB); + EXPECT_EQ((rate_b * delta_a).bytes(), kValueA * kValueB); + EXPECT_EQ((size_c / delta_a).bytes_per_second(), kValueC / kValueA); + EXPECT_EQ((size_c / rate_b).s(), kValueC / kValueB); +} + +} // namespace test +} // namespace webrtc diff --git a/modules/congestion_controller/rtp/pacer_controller.cc b/modules/congestion_controller/rtp/pacer_controller.cc index a577f85e84..446ed9769b 100644 --- a/modules/congestion_controller/rtp/pacer_controller.cc +++ b/modules/congestion_controller/rtp/pacer_controller.cc @@ -10,7 +10,6 @@ #include "modules/congestion_controller/rtp/pacer_controller.h" -#include "modules/congestion_controller/network_control/include/network_units.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" diff --git a/modules/congestion_controller/rtp/send_side_congestion_controller.cc b/modules/congestion_controller/rtp/send_side_congestion_controller.cc index 4505ad39ee..66867ea805 100644 --- a/modules/congestion_controller/rtp/send_side_congestion_controller.cc +++ b/modules/congestion_controller/rtp/send_side_congestion_controller.cc @@ -17,7 +17,6 @@ #include "modules/congestion_controller/bbr/bbr_factory.h" #include "modules/congestion_controller/goog_cc/include/goog_cc_factory.h" #include "modules/congestion_controller/network_control/include/network_types.h" -#include "modules/congestion_controller/network_control/include/network_units.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/bind.h" #include "rtc_base/checks.h"