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 |
index 57fd5d22bdfb235b0524228cb6e1a9e03c42a815..f87c717681a64154816fa271698e357eef0d5bd9 100644 |
--- a/webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc |
+++ b/webrtc/modules/video_coding/utility/simulcast_rate_allocator_unittest.cc |
@@ -12,23 +12,26 @@ |
#include <limits> |
#include <memory> |
+#include <utility> |
+#include <vector> |
#include "webrtc/test/gtest.h" |
namespace webrtc { |
namespace { |
-constexpr uint32_t kMinBitrate = 50; |
-constexpr uint32_t kTargetBitrate = 100; |
-constexpr uint32_t kMaxBitrate = 1000; |
+constexpr uint32_t kMinBitrateKbps = 50; |
+constexpr uint32_t kTargetBitrateKbps = 100; |
+constexpr uint32_t kMaxBitrateKbps = 1000; |
+constexpr uint32_t kFramerateFps = 5; |
} // namespace |
-class SimulcastRateAllocatorTest : public ::testing::Test { |
+class SimulcastRateAllocatorTest : public ::testing::TestWithParam<bool> { |
public: |
SimulcastRateAllocatorTest() { |
memset(&codec_, 0, sizeof(VideoCodec)); |
- codec_.minBitrate = kMinBitrate; |
- codec_.targetBitrate = kTargetBitrate; |
- codec_.maxBitrate = kMaxBitrate; |
+ codec_.minBitrate = kMinBitrateKbps; |
+ codec_.targetBitrate = kTargetBitrateKbps; |
+ codec_.maxBitrate = kMaxBitrateKbps; |
CreateAllocator(); |
} |
virtual ~SimulcastRateAllocatorTest() {} |
@@ -41,43 +44,81 @@ class SimulcastRateAllocatorTest : public ::testing::Test { |
EXPECT_EQ(expected[i], actual[i]) << "Mismatch at index " << i; |
} |
+ template <size_t S> |
+ void ExpectEqual(uint32_t (&expected)[S], const BitrateAllocation& actual) { |
+ // EXPECT_EQ(S, actual.size()); |
+ uint32_t sum = 0; |
+ for (size_t i = 0; i < S; ++i) { |
+ uint32_t layer_bitrate = actual.GetSpatialLayerSum(i); |
+ EXPECT_EQ(expected[i] * 1000U, layer_bitrate) << "Mismatch at index " |
+ << i; |
+ sum += layer_bitrate; |
+ } |
+ EXPECT_EQ(sum, actual.get_sum_bps()); |
+ } |
+ |
void CreateAllocator() { |
- allocator_.reset(new SimulcastRateAllocator(codec_)); |
+ std::unique_ptr<TemporalLayersFactory> tl_factory(GetTlFactory()); |
+ codec_.VP8()->tl_factory = tl_factory.get(); |
+ allocator_.reset(new SimulcastRateAllocator(codec_, std::move(tl_factory))); |
+ |
+ // Simulate InitEncode(). |
+ tl_factories_.clear(); |
+ if (codec_.numberOfSimulcastStreams == 0) { |
+ tl_factories_.push_back( |
+ std::unique_ptr<TemporalLayers>(codec_.VP8()->tl_factory->Create( |
+ 0, codec_.VP8()->numberOfTemporalLayers, 0))); |
+ } else { |
+ for (uint32_t i = 0; i < codec_.numberOfSimulcastStreams; ++i) { |
+ tl_factories_.push_back( |
+ std::unique_ptr<TemporalLayers>(codec_.VP8()->tl_factory->Create( |
+ i, codec_.simulcastStream[i].numberOfTemporalLayers, 0))); |
+ } |
+ } |
+ } |
+ |
+ virtual std::unique_ptr<TemporalLayersFactory> GetTlFactory() { |
+ return std::unique_ptr<TemporalLayersFactory>(new TemporalLayersFactory()); |
+ } |
+ |
+ BitrateAllocation GetAllocation(uint32_t target_bitrate) { |
+ return allocator_->GetAllocation(target_bitrate * 1000U, kDefaultFrameRate); |
} |
protected: |
+ static const int kDefaultFrameRate = 30; |
VideoCodec codec_; |
std::unique_ptr<SimulcastRateAllocator> allocator_; |
+ std::vector<std::unique_ptr<TemporalLayers>> tl_factories_; |
}; |
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)); |
+ ExpectEqual(expected, GetAllocation(codec_.minBitrate - 1)); |
+ ExpectEqual(expected, GetAllocation(1)); |
+ ExpectEqual(expected, 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())); |
+ ExpectEqual(expected, GetAllocation(codec_.maxBitrate + 1)); |
+ ExpectEqual(expected, GetAllocation(std::numeric_limits<uint32_t>::max())); |
} |
TEST_F(SimulcastRateAllocatorTest, NoSimulcastNoMax) { |
- constexpr uint32_t kMax = std::numeric_limits<uint32_t>::max(); |
+ const uint32_t kMax = BitrateAllocation::kMaxBitrateBps / 1000; |
codec_.maxBitrate = 0; |
CreateAllocator(); |
uint32_t expected[] = {kMax}; |
- ExpectEqual(expected, allocator_->GetAllocation(kMax)); |
+ ExpectEqual(expected, 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)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
} |
@@ -86,38 +127,39 @@ TEST_F(SimulcastRateAllocatorTest, SingleSimulcastBelowMin) { |
codec_.numberOfSimulcastStreams = 1; |
const uint32_t kMin = codec_.minBitrate - 10; |
codec_.simulcastStream[0].minBitrate = kMin; |
- codec_.simulcastStream[0].targetBitrate = kTargetBitrate; |
+ codec_.simulcastStream[0].targetBitrate = kTargetBitrateKbps; |
CreateAllocator(); |
uint32_t expected[] = {kMin}; |
- ExpectEqual(expected, allocator_->GetAllocation(kMin - 1)); |
- ExpectEqual(expected, allocator_->GetAllocation(1)); |
- ExpectEqual(expected, allocator_->GetAllocation(0)); |
+ ExpectEqual(expected, GetAllocation(kMin - 1)); |
+ ExpectEqual(expected, GetAllocation(1)); |
+ ExpectEqual(expected, GetAllocation(0)); |
} |
TEST_F(SimulcastRateAllocatorTest, SingleSimulcastAboveMax) { |
codec_.numberOfSimulcastStreams = 1; |
- codec_.simulcastStream[0].minBitrate = kMinBitrate; |
+ codec_.simulcastStream[0].minBitrate = kMinBitrateKbps; |
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())); |
+ ExpectEqual(expected, GetAllocation(kMax)); |
+ ExpectEqual(expected, GetAllocation(kMax + 1)); |
+ ExpectEqual(expected, 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; |
+ codec_.simulcastStream[0].minBitrate = kMinBitrateKbps; |
+ codec_.simulcastStream[0].targetBitrate = kTargetBitrateKbps; |
+ codec_.simulcastStream[0].maxBitrate = kMaxBitrateKbps; |
CreateAllocator(); |
- for (uint32_t bitrate = kMinBitrate; bitrate <= kMaxBitrate; ++bitrate) { |
+ for (uint32_t bitrate = kMinBitrateKbps; bitrate <= kMaxBitrateKbps; |
+ ++bitrate) { |
uint32_t expected[] = {bitrate}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
} |
@@ -139,14 +181,14 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
// Single stream, min bitrate. |
const uint32_t bitrate = codec_.simulcastStream[0].minBitrate; |
uint32_t expected[] = {bitrate, 0, 0}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, 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)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
{ |
@@ -154,7 +196,7 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
const uint32_t bitrate = codec_.simulcastStream[0].targetBitrate + |
codec_.simulcastStream[1].minBitrate - 1; |
uint32_t expected[] = {bitrate, 0, 0}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
{ |
@@ -163,7 +205,7 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
codec_.simulcastStream[1].minBitrate; |
uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
codec_.simulcastStream[1].minBitrate, 0}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
{ |
@@ -172,7 +214,7 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
codec_.simulcastStream[1].maxBitrate; |
uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
codec_.simulcastStream[1].maxBitrate, 0}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
{ |
@@ -182,7 +224,7 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
codec_.simulcastStream[1].maxBitrate + 499; |
uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
codec_.simulcastStream[1].maxBitrate, 0}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
{ |
@@ -193,7 +235,7 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
codec_.simulcastStream[1].targetBitrate, |
codec_.simulcastStream[2].minBitrate}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
{ |
@@ -204,12 +246,13 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { |
uint32_t expected[] = {codec_.simulcastStream[0].targetBitrate, |
codec_.simulcastStream[1].targetBitrate, |
codec_.simulcastStream[2].maxBitrate}; |
- ExpectEqual(expected, allocator_->GetAllocation(bitrate)); |
+ ExpectEqual(expected, GetAllocation(bitrate)); |
} |
} |
-TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrate) { |
- EXPECT_EQ(codec_.maxBitrate, allocator_->GetPreferedBitrate()); |
+TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrateBps) { |
+ EXPECT_EQ(codec_.maxBitrate * 1000, |
+ allocator_->GetPreferredBitrateBps(codec_.maxFramerate)); |
} |
TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrateSimulcast) { |
@@ -228,12 +271,83 @@ TEST_F(SimulcastRateAllocatorTest, GetPreferredBitrateSimulcast) { |
codec_.simulcastStream[2].maxBitrate = 4000; |
CreateAllocator(); |
- uint32_t preferred_bitrate; |
- preferred_bitrate = codec_.simulcastStream[0].targetBitrate; |
- preferred_bitrate += codec_.simulcastStream[1].targetBitrate; |
- preferred_bitrate += codec_.simulcastStream[2].maxBitrate; |
+ uint32_t preferred_bitrate_kbps; |
+ preferred_bitrate_kbps = codec_.simulcastStream[0].targetBitrate; |
+ preferred_bitrate_kbps += codec_.simulcastStream[1].targetBitrate; |
+ preferred_bitrate_kbps += codec_.simulcastStream[2].maxBitrate; |
+ |
+ EXPECT_EQ(preferred_bitrate_kbps * 1000, |
+ allocator_->GetPreferredBitrateBps(codec_.maxFramerate)); |
+} |
+ |
+class ScreenshareRateAllocationTest : public SimulcastRateAllocatorTest { |
+ public: |
+ void SetupConferenceScreenshare(bool use_simulcast) { |
+ codec_.mode = VideoCodecMode::kScreensharing; |
+ codec_.minBitrate = kMinBitrateKbps; |
+ codec_.maxBitrate = kMaxBitrateKbps; |
+ if (use_simulcast) { |
+ codec_.numberOfSimulcastStreams = 1; |
+ codec_.simulcastStream[0].minBitrate = kMinBitrateKbps; |
+ codec_.simulcastStream[0].targetBitrate = kTargetBitrateKbps; |
+ codec_.simulcastStream[0].maxBitrate = kMaxBitrateKbps; |
+ codec_.simulcastStream[0].numberOfTemporalLayers = 2; |
+ } else { |
+ codec_.numberOfSimulcastStreams = 0; |
+ codec_.targetBitrate = kTargetBitrateKbps; |
+ codec_.VP8()->numberOfTemporalLayers = 2; |
+ } |
+ } |
+ |
+ std::unique_ptr<TemporalLayersFactory> GetTlFactory() override { |
+ return std::unique_ptr<TemporalLayersFactory>( |
+ new ScreenshareTemporalLayersFactory()); |
+ } |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(ScreenshareTest, |
+ ScreenshareRateAllocationTest, |
+ ::testing::Bool()); |
+ |
+TEST_P(ScreenshareRateAllocationTest, BitrateBelowTl0) { |
+ SetupConferenceScreenshare(GetParam()); |
+ CreateAllocator(); |
+ |
+ BitrateAllocation allocation = |
+ allocator_->GetAllocation(kTargetBitrateKbps * 1000, kFramerateFps); |
+ |
+ // All allocation should go in TL0. |
+ EXPECT_EQ(kTargetBitrateKbps, allocation.get_sum_kbps()); |
+ EXPECT_EQ(kTargetBitrateKbps, allocation.GetBitrate(0, 0) / 1000); |
+} |
+ |
+TEST_P(ScreenshareRateAllocationTest, BitrateAboveTl0) { |
+ SetupConferenceScreenshare(GetParam()); |
+ CreateAllocator(); |
+ |
+ uint32_t target_bitrate_kbps = (kTargetBitrateKbps + kMaxBitrateKbps) / 2; |
+ BitrateAllocation allocation = |
+ allocator_->GetAllocation(target_bitrate_kbps * 1000, kFramerateFps); |
+ |
+ // Fill TL0, then put the rest in TL1. |
+ EXPECT_EQ(target_bitrate_kbps, allocation.get_sum_kbps()); |
+ EXPECT_EQ(kTargetBitrateKbps, allocation.GetBitrate(0, 0) / 1000); |
+ EXPECT_EQ(target_bitrate_kbps - kTargetBitrateKbps, |
+ allocation.GetBitrate(0, 1) / 1000); |
+} |
+ |
+TEST_P(ScreenshareRateAllocationTest, BitrateAboveTl1) { |
+ SetupConferenceScreenshare(GetParam()); |
+ CreateAllocator(); |
+ |
+ BitrateAllocation allocation = |
+ allocator_->GetAllocation(kMaxBitrateKbps * 2000, kFramerateFps); |
- EXPECT_EQ(preferred_bitrate, allocator_->GetPreferedBitrate()); |
+ // Fill both TL0 and TL1, but no more. |
+ EXPECT_EQ(kMaxBitrateKbps, allocation.get_sum_kbps()); |
+ EXPECT_EQ(kTargetBitrateKbps, allocation.GetBitrate(0, 0) / 1000); |
+ EXPECT_EQ(kMaxBitrateKbps - kTargetBitrateKbps, |
+ allocation.GetBitrate(0, 1) / 1000); |
} |
} // namespace webrtc |