data_rate.h (5356B)
1 /* 2 * Copyright (c) 2018 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 #ifndef API_UNITS_DATA_RATE_H_ 12 #define API_UNITS_DATA_RATE_H_ 13 14 #include <cstdint> 15 #include <limits> 16 #include <string> 17 #include <type_traits> 18 19 #include "api/units/data_size.h" 20 #include "api/units/frequency.h" 21 #include "api/units/time_delta.h" 22 #include "rtc_base/checks.h" 23 #include "rtc_base/system/rtc_export.h" 24 #include "rtc_base/units/unit_base.h" // IWYU pragma: export 25 26 namespace webrtc { 27 // DataRate is a class that represents a given data rate. This can be used to 28 // represent bandwidth, encoding bitrate, etc. The internal storage is bits per 29 // second (bps). 30 class DataRate final : public rtc_units_impl::RelativeUnit<DataRate> { 31 public: 32 template <typename T> 33 static constexpr DataRate BitsPerSec(T value) { 34 static_assert(std::is_arithmetic<T>::value, ""); 35 return FromValue(value); 36 } 37 template <typename T> 38 static constexpr DataRate BytesPerSec(T value) { 39 static_assert(std::is_arithmetic<T>::value, ""); 40 return FromFraction(8, value); 41 } 42 template <typename T> 43 static constexpr DataRate KilobitsPerSec(T value) { 44 static_assert(std::is_arithmetic<T>::value, ""); 45 return FromFraction(1000, value); 46 } 47 static constexpr DataRate Infinity() { return PlusInfinity(); } 48 49 constexpr DataRate() = default; 50 51 template <typename Sink> 52 friend void AbslStringify(Sink& sink, DataRate value); 53 54 template <typename T = int64_t> 55 constexpr T bps() const { 56 return ToValue<T>(); 57 } 58 template <typename T = int64_t> 59 constexpr T bytes_per_sec() const { 60 return ToFraction<8, T>(); 61 } 62 template <typename T = int64_t> 63 constexpr T kbps() const { 64 return ToFraction<1000, T>(); 65 } 66 constexpr int64_t bps_or(int64_t fallback_value) const { 67 return ToValueOr(fallback_value); 68 } 69 constexpr int64_t kbps_or(int64_t fallback_value) const { 70 return ToFractionOr<1000>(fallback_value); 71 } 72 73 private: 74 // Bits per second used internally to simplify debugging by making the value 75 // more recognizable. 76 friend class rtc_units_impl::UnitBase<DataRate>; 77 using RelativeUnit::RelativeUnit; 78 static constexpr bool one_sided = true; 79 }; 80 81 namespace data_rate_impl { 82 inline constexpr int64_t Microbits(const DataSize& size) { 83 constexpr int64_t kMaxBeforeConversion = 84 std::numeric_limits<int64_t>::max() / 8000000; 85 RTC_DCHECK_LE(size.bytes(), kMaxBeforeConversion) 86 << "size is too large to be expressed in microbits"; 87 return size.bytes() * 8000000; 88 } 89 90 inline constexpr int64_t MillibytePerSec(const DataRate& size) { 91 constexpr int64_t kMaxBeforeConversion = 92 std::numeric_limits<int64_t>::max() / (1000 / 8); 93 RTC_DCHECK_LE(size.bps(), kMaxBeforeConversion) 94 << "rate is too large to be expressed in microbytes per second"; 95 return size.bps() * (1000 / 8); 96 } 97 } // namespace data_rate_impl 98 99 inline constexpr DataRate operator/(const DataSize size, 100 const TimeDelta duration) { 101 return DataRate::BitsPerSec(data_rate_impl::Microbits(size) / duration.us()); 102 } 103 inline constexpr TimeDelta operator/(const DataSize size, const DataRate rate) { 104 return TimeDelta::Micros(data_rate_impl::Microbits(size) / rate.bps()); 105 } 106 inline constexpr DataSize operator*(const DataRate rate, 107 const TimeDelta duration) { 108 int64_t microbits = rate.bps() * duration.us(); 109 return DataSize::Bytes((microbits + 4000000) / 8000000); 110 } 111 inline constexpr DataSize operator*(const TimeDelta duration, 112 const DataRate rate) { 113 return rate * duration; 114 } 115 116 inline constexpr DataSize operator/(const DataRate rate, 117 const Frequency frequency) { 118 int64_t millihertz = frequency.millihertz<int64_t>(); 119 // Note that the value is truncated here reather than rounded, potentially 120 // introducing an error of .5 bytes if rounding were expected. 121 return DataSize::Bytes(data_rate_impl::MillibytePerSec(rate) / millihertz); 122 } 123 inline constexpr Frequency operator/(const DataRate rate, const DataSize size) { 124 return Frequency::MilliHertz(data_rate_impl::MillibytePerSec(rate) / 125 size.bytes()); 126 } 127 inline constexpr DataRate operator*(const DataSize size, 128 const Frequency frequency) { 129 RTC_DCHECK(frequency.IsZero() || 130 size.bytes() <= std::numeric_limits<int64_t>::max() / 8 / 131 frequency.millihertz<int64_t>()); 132 int64_t millibits_per_second = 133 size.bytes() * 8 * frequency.millihertz<int64_t>(); 134 return DataRate::BitsPerSec((millibits_per_second + 500) / 1000); 135 } 136 inline constexpr DataRate operator*(const Frequency frequency, 137 const DataSize size) { 138 return size * frequency; 139 } 140 141 RTC_EXPORT std::string ToString(DataRate value); 142 143 template <typename Sink> 144 void AbslStringify(Sink& sink, DataRate value) { 145 sink.Append(ToString(value)); 146 } 147 148 } // namespace webrtc 149 150 #endif // API_UNITS_DATA_RATE_H_