| 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
|
|
|