Index: webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc |
diff --git a/webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc b/webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fbfc41dfd806f11284a67adad54e79341f59cbc2 |
--- /dev/null |
+++ b/webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc |
@@ -0,0 +1,246 @@ |
+/* |
+ * Copyright (c) 2016 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 "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h" |
+ |
+#include <limits> |
+#include <memory> |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace webrtc { |
+namespace { |
+constexpr uint32_t kMinBitrate = 50; |
+constexpr uint32_t kTargetBitrate = 100; |
+constexpr uint32_t kMaxBitrate = 1000; |
+} // namespace |
+ |
+class SimulcastRateAllocatorTest : public ::testing::Test { |
+ public: |
+ SimulcastRateAllocatorTest() { |
+ memset(&codec_, 0, sizeof(VideoCodec)); |
+ codec_.minBitrate = kMinBitrate; |
+ codec_.targetBitrate = kTargetBitrate; |
+ codec_.maxBitrate = kMaxBitrate; |
+ CreateAllocator(); |
+ } |
+ virtual ~SimulcastRateAllocatorTest() {} |
+ |
+ template <size_t S> |
+ void ExpectEqual(uint32_t (&expected)[S], |
+ const std::vector<uint32_t>& actual) { |
+ EXPECT_EQ(S, actual.size()); |
+ for (size_t i = 0; i < S; ++i) |
+ EXPECT_EQ(expected[i], actual[i]) << "Mismatch at index " << i; |
+ } |
+ |
+ void CreateAllocator() { |
+ allocator_.reset(new SimulcastRateAllocator(codec_)); |
+ } |
+ |
+ protected: |
+ VideoCodec codec_; |
+ std::unique_ptr<SimulcastRateAllocator> allocator_; |
+}; |
+ |
+TEST_F(SimulcastRateAllocatorTest, NoSimulcastBelowMin) { |
+ uint32_t expected[] = {codec_.minBitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(codec_.minBitrate - 1)); |
+ ExpectEqual(expected, allocator_->GetAllocation(1)); |
+ ExpectEqual(expected, allocator_->GetAllocation(0)); |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, NoSimulcastAboveMax) { |
+ uint32_t expected[] = {codec_.maxBitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(codec_.maxBitrate + 1)); |
+ ExpectEqual(expected, |
+ allocator_->GetAllocation(std::numeric_limits<uint32_t>::max())); |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, NoSimulcastNoMax) { |
+ constexpr uint32_t kMax = std::numeric_limits<uint32_t>::max(); |
+ codec_.maxBitrate = 0; |
+ CreateAllocator(); |
+ |
+ uint32_t expected[] = {kMax}; |
+ ExpectEqual(expected, allocator_->GetAllocation(kMax)); |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, NoSimulcastWithinLimits) { |
+ for (uint32_t bitrate = codec_.minBitrate; bitrate <= codec_.maxBitrate; |
+ ++bitrate) { |
+ uint32_t expected[] = {bitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, SingleSimulcastBelowMin) { |
+ // With simulcast, use the min bitrate from the ss spec instead of the global. |
+ codec_.numberOfSimulcastStreams = 1; |
+ const uint32_t kMin = codec_.minBitrate - 10; |
+ codec_.simulcastStream[0].minBitrate = kMin; |
+ codec_.simulcastStream[0].targetBitrate = kTargetBitrate; |
+ CreateAllocator(); |
+ |
+ uint32_t expected[] = {kMin}; |
+ ExpectEqual(expected, allocator_->GetAllocation(kMin - 1)); |
+ ExpectEqual(expected, allocator_->GetAllocation(1)); |
+ ExpectEqual(expected, allocator_->GetAllocation(0)); |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, SingleSimulcastAboveMax) { |
+ codec_.numberOfSimulcastStreams = 1; |
+ codec_.simulcastStream[0].minBitrate = kMinBitrate; |
+ const uint32_t kMax = codec_.simulcastStream[0].maxBitrate + 1000; |
+ codec_.simulcastStream[0].maxBitrate = kMax; |
+ CreateAllocator(); |
+ |
+ uint32_t expected[] = {kMax}; |
+ ExpectEqual(expected, allocator_->GetAllocation(kMax + 1)); |
+ ExpectEqual(expected, |
+ allocator_->GetAllocation(std::numeric_limits<uint32_t>::max())); |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, SingleSimulcastWithinLimits) { |
+ codec_.numberOfSimulcastStreams = 1; |
+ codec_.simulcastStream[0].minBitrate = kMinBitrate; |
+ codec_.simulcastStream[0].targetBitrate = kTargetBitrate; |
+ codec_.simulcastStream[0].maxBitrate = kMaxBitrate; |
+ CreateAllocator(); |
+ |
+ for (uint32_t bitrate = kMinBitrate; bitrate <= kMaxBitrate; ++bitrate) { |
+ uint32_t expected[] = {bitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+} |
+ |
+TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
+ codec_.numberOfSimulcastStreams = 3; |
+ codec_.maxBitrate = 0; |
+ codec_.simulcastStream[0].minBitrate = 10; |
+ codec_.simulcastStream[0].targetBitrate = 100; |
+ codec_.simulcastStream[0].maxBitrate = 500; |
+ codec_.simulcastStream[1].minBitrate = 50; |
+ codec_.simulcastStream[1].targetBitrate = 500; |
+ codec_.simulcastStream[1].maxBitrate = 1000; |
+ codec_.simulcastStream[2].minBitrate = 2000; |
+ codec_.simulcastStream[2].targetBitrate = 3000; |
+ codec_.simulcastStream[2].maxBitrate = 4000; |
+ CreateAllocator(); |
+ |
+ { |
+ // Single stream, min bitrate. |
+ const uint32_t bitrate = codec_.simulcastStream[0].minBitrate; |
+ uint32_t expected[] = {bitrate, 0, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Single stream at target bitrate. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate; |
+ uint32_t expected[] = {bitrate, 0, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Bitrate above target for first stream, but below min for the next one. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
+ codec_.simulcastStream[1].minBitrate - 1; |
+ uint32_t expected[] = {bitrate, 0, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Just enough for two streams. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
+ codec_.simulcastStream[1].minBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
+ codec_.simulcastStream[1].minBitrate, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Second stream maxed out, but not enough for third. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
+ codec_.simulcastStream[1].maxBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
+ codec_.simulcastStream[1].maxBitrate, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // First two streams maxed out, but not enough for third. |
+ const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate + |
+ codec_.simulcastStream[1].maxBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].maxBitrate, |
+ codec_.simulcastStream[1].maxBitrate, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // First two streams maxed out, but not enough for third. Nowhere to put |
+ // remaining bits. |
+ const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate + |
+ codec_.simulcastStream[1].maxBitrate + 499; |
+ uint32_t expected[] = {codec_.simulcastStream[0].maxBitrate, |
+ codec_.simulcastStream[1].maxBitrate, 0}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Just enough for all three streams. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
+ codec_.simulcastStream[1].targetBitrate + |
+ codec_.simulcastStream[2].minBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
+ codec_.simulcastStream[1].targetBitrate, |
+ codec_.simulcastStream[2].minBitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Third maxed out. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
+ codec_.simulcastStream[1].targetBitrate + |
+ codec_.simulcastStream[2].maxBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
+ codec_.simulcastStream[1].targetBitrate, |
+ codec_.simulcastStream[2].maxBitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // Layer 2, 3 maxed out. |
+ const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
+ codec_.simulcastStream[1].maxBitrate + |
+ codec_.simulcastStream[2].maxBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
+ codec_.simulcastStream[1].maxBitrate, |
+ codec_.simulcastStream[2].maxBitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ } |
+ |
+ { |
+ // All three maxed out. |
+ const uint32_t bitrate = codec_.simulcastStream[0].maxBitrate + |
+ codec_.simulcastStream[1].maxBitrate + |
+ codec_.simulcastStream[2].maxBitrate; |
+ uint32_t expected[] = {codec_.simulcastStream[0].maxBitrate, |
+ codec_.simulcastStream[1].maxBitrate, |
+ codec_.simulcastStream[2].maxBitrate}; |
+ ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ |
+ // Can't go any higher. |
+ ExpectEqual(expected, allocator_->GetAllocation( |
+ std::numeric_limits<uint32_t>::max())); |
+ } |
+} |
+ |
+} // namespace webrtc |