Prepares for moving units to API.

Cleanup based on review of move CL. Using separate CL to keep the
move clean.

Bug: webrtc:9155
Change-Id: Ie0b15c6d3efcd86e2fa5761f014d0daf72ccfa06
Reviewed-on: https://webrtc-review.googlesource.com/73367
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23068}
This commit is contained in:
Sebastian Jansson 2018-04-30 16:54:57 +02:00 committed by Commit Bot
parent 71a720ba16
commit 66fa535e6e
6 changed files with 86 additions and 113 deletions

View File

@ -13,33 +13,6 @@
#include "rtc_base/strings/string_builder.h"
namespace webrtc {
namespace {
int64_t Microbytes(const DataSize& size) {
constexpr int64_t kMaxBeforeConversion =
std::numeric_limits<int64_t>::max() / 1000000;
RTC_DCHECK(size.bytes() < kMaxBeforeConversion)
<< "size is too large to be expressed in microbytes, size: "
<< size.bytes() << " is not less than " << kMaxBeforeConversion;
return size.bytes() * 1000000;
}
} // namespace
DataRate operator/(const DataSize& size, const TimeDelta& duration) {
return DataRate::bytes_per_second(Microbytes(size) / duration.us());
}
TimeDelta operator/(const DataSize& size, const DataRate& rate) {
return TimeDelta::us(Microbytes(size) / rate.bytes_per_second());
}
DataSize operator*(const DataRate& rate, const TimeDelta& duration) {
int64_t microbytes = rate.bytes_per_second() * duration.us();
return DataSize::bytes((microbytes + 500000) / 1000000);
}
DataSize operator*(const TimeDelta& duration, const DataRate& rate) {
return rate * duration;
}
std::string ToString(const DataRate& value) {
char buf[64];

View File

@ -25,14 +25,19 @@ namespace webrtc {
namespace data_rate_impl {
constexpr int64_t kPlusInfinityVal = std::numeric_limits<int64_t>::max();
constexpr int64_t kNotInitializedVal = -1;
inline int64_t Microbits(const DataSize& size) {
constexpr int64_t kMaxBeforeConversion =
std::numeric_limits<int64_t>::max() / 8000000;
RTC_DCHECK_LE(size.bytes(), kMaxBeforeConversion)
<< "size is too large to be expressed in microbytes";
return size.bytes() * 8000000;
}
} // 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.
// represent bandwidth, encoding bitrate, etc. The internal storage is bits per
// second (bps).
class DataRate {
public:
DataRate() : DataRate(data_rate_impl::kNotInitializedVal) {}
@ -40,10 +45,6 @@ class DataRate {
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);
@ -58,7 +59,6 @@ class DataRate {
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;
@ -72,15 +72,7 @@ class DataRate {
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_;
}
@ -106,20 +98,41 @@ class DataRate {
explicit DataRate(int64_t bits_per_second) : bits_per_sec_(bits_per_second) {}
int64_t bits_per_sec_;
};
inline DataRate operator*(const DataRate& rate, const double& scalar) {
return DataRate::bits_per_second(std::round(rate.bits_per_second() * scalar));
}
inline DataRate operator*(const double& scalar, const DataRate& rate) {
return rate * scalar;
}
inline DataRate operator*(const DataRate& rate, const int64_t& scalar) {
return DataRate::bits_per_second(rate.bits_per_second() * scalar);
}
inline DataRate operator*(const int64_t& scalar, const DataRate& rate) {
return rate * scalar;
}
inline DataRate operator*(const DataRate& rate, const int32_t& scalar) {
return DataRate::bits_per_second(rate.bits_per_second() * 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);
inline DataRate operator/(const DataSize& size, const TimeDelta& duration) {
return DataRate::bits_per_second(data_rate_impl::Microbits(size) /
duration.us());
}
inline TimeDelta operator/(const DataSize& size, const DataRate& rate) {
return TimeDelta::us(data_rate_impl::Microbits(size) /
rate.bits_per_second());
}
inline DataSize operator*(const DataRate& rate, const TimeDelta& duration) {
int64_t microbits = rate.bits_per_second() * duration.us();
return DataSize::bytes((microbits + 4000000) / 8000000);
}
inline DataSize operator*(const TimeDelta& duration, const DataRate& rate) {
return rate * duration;
}
std::string ToString(const DataRate& value);

View File

@ -15,7 +15,6 @@ 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);
@ -23,30 +22,28 @@ TEST(DataRateTest, GetBackSameValues) {
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_FALSE(DataRate::bits_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::bits_per_second(kValue).IsInfinite());
EXPECT_FALSE(DataRate::Infinity().IsFinite());
EXPECT_TRUE(DataRate::bytes_per_second(kValue).IsFinite());
EXPECT_TRUE(DataRate::bits_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);
const DataRate small = DataRate::bits_per_second(kSmall);
const DataRate large = DataRate::bits_per_second(kLarge);
EXPECT_EQ(DataRate::Zero(), DataRate::bps(0));
EXPECT_EQ(DataRate::Infinity(), DataRate::Infinity());
@ -65,25 +62,25 @@ TEST(DataRateTest, ComparisonOperators) {
TEST(DataRateTest, MathOperations) {
const int64_t kValueA = 450;
const int64_t kValueB = 267;
const DataRate size_a = DataRate::bytes_per_second(kValueA);
const DataRate size_a = DataRate::bits_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);
EXPECT_EQ((size_a * kValueB).bits_per_second(), kValueA * kValueB);
EXPECT_EQ((size_a * kInt32Value).bits_per_second(), kValueA * kInt32Value);
EXPECT_EQ((size_a * kFloatValue).bits_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((rate_b * delta_a).bytes(), kValueA * kValueB);
EXPECT_EQ((size_c / delta_a).bytes_per_second(), kValueC / kValueA);
EXPECT_EQ((size_c / rate_b).seconds(), kValueC / kValueB);
const int64_t kSeconds = 5;
const int64_t kBitsPerSecond = 440;
const int64_t kBytes = 44000;
const TimeDelta delta_a = TimeDelta::seconds(kSeconds);
const DataRate rate_b = DataRate::bits_per_second(kBitsPerSecond);
const DataSize size_c = DataSize::bytes(kBytes);
EXPECT_EQ((delta_a * rate_b).bytes(), kSeconds * kBitsPerSecond / 8);
EXPECT_EQ((rate_b * delta_a).bytes(), kSeconds * kBitsPerSecond / 8);
EXPECT_EQ((size_c / delta_a).bits_per_second(), kBytes * 8 / kSeconds);
EXPECT_EQ((size_c / rate_b).seconds(), kBytes * 8 / kBitsPerSecond);
}
#if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
@ -103,9 +100,9 @@ TEST(UnitConversionTest, DivisionFailsOnLargeSize) {
// Note that the failure is expected since the current implementation is
// implementated in a way that does not support division of large sizes. If
// the implementation is changed, this test can safely be removed.
const int64_t kToolargeForDivision =
std::numeric_limits<int64_t>::max() / 1000000;
const int64_t kJustSmallEnoughForDivision = kToolargeForDivision - 1;
const int64_t kJustSmallEnoughForDivision =
std::numeric_limits<int64_t>::max() / 8000000;
const int64_t kToolargeForDivision = kJustSmallEnoughForDivision + 1;
const DataSize large_size = DataSize::bytes(kJustSmallEnoughForDivision);
const DataSize too_large_size = DataSize::bytes(kToolargeForDivision);
const DataRate data_rate = DataRate::kbps(100);

View File

@ -24,10 +24,7 @@ constexpr int64_t kPlusInfinityVal = std::numeric_limits<int64_t>::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.
// DataSize is a class represeting a count of bytes.
class DataSize {
public:
DataSize() : DataSize(data_size_impl::kNotInitializedVal) {}
@ -39,17 +36,11 @@ class DataSize {
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 {
@ -62,18 +53,6 @@ class DataSize {
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;
@ -101,15 +80,27 @@ class DataSize {
explicit DataSize(int64_t bytes) : bytes_(bytes) {}
int64_t bytes_;
};
inline DataSize operator*(const DataSize& size, const double& scalar) {
return DataSize::bytes(std::round(size.bytes() * scalar));
}
inline DataSize operator*(const double& scalar, const DataSize& size) {
return size * scalar;
}
inline DataSize operator*(const DataSize& size, const int64_t& scalar) {
return DataSize::bytes(size.bytes() * scalar);
}
inline DataSize operator*(const int64_t& scalar, const DataSize& size) {
return size * scalar;
}
inline DataSize operator*(const DataSize& size, const int32_t& scalar) {
return DataSize::bytes(size.bytes() * scalar);
}
inline DataSize operator*(const int32_t& scalar, const DataSize& size) {
return size * scalar;
}
inline DataSize operator/(const DataSize& size, const int64_t& scalar) {
return DataSize::bytes(size.bytes() / scalar);
}
std::string ToString(const DataSize& value);

View File

@ -17,14 +17,10 @@ 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);
}

View File

@ -97,18 +97,7 @@ class TimeDelta {
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_;
}
@ -132,16 +121,30 @@ class TimeDelta {
explicit TimeDelta(int64_t us) : microseconds_(us) {}
int64_t microseconds_;
};
inline TimeDelta operator*(const TimeDelta& delta, const double& scalar) {
return TimeDelta::us(std::round(delta.us() * scalar));
}
inline TimeDelta operator*(const double& scalar, const TimeDelta& delta) {
return delta * scalar;
}
inline TimeDelta operator*(const TimeDelta& delta, const int64_t& scalar) {
return TimeDelta::us(delta.us() * scalar);
}
inline TimeDelta operator*(const int64_t& scalar, const TimeDelta& delta) {
return delta * scalar;
}
inline TimeDelta operator*(const TimeDelta& delta, const int32_t& scalar) {
return TimeDelta::us(delta.us() * scalar);
}
inline TimeDelta operator*(const int32_t& scalar, const TimeDelta& delta) {
return delta * scalar;
}
inline TimeDelta operator/(const TimeDelta& delta, const int64_t& scalar) {
return TimeDelta::us(delta.us() / scalar);
}
std::string ToString(const TimeDelta& value);
} // namespace webrtc