Extended the bitrate allocator to allow allocation to tracks based upon priorities which are planned to be defined as a relative bitrate in the RTCRtpEncodingParameters.
Bug: None Change-Id: I80bc6c1e36b03537eb08f53df8c21d540e7408be Reviewed-on: https://webrtc-review.googlesource.com/16262 Commit-Queue: Seth Hampson <shampson@webrtc.org> Reviewed-by: Stefan Holmer <stefan@webrtc.org> Reviewed-by: Elad Alon <eladalon@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20680}
This commit is contained in:
@ -17,7 +17,8 @@
|
||||
#include "test/gmock.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
using testing::NiceMock;
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::_;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -518,4 +519,259 @@ TEST_F(BitrateAllocatorTest, PassProbingInterval) {
|
||||
allocator_->RemoveObserver(&observer);
|
||||
}
|
||||
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateOneObserverBasic) {
|
||||
TestBitrateObserver observer;
|
||||
const uint32_t kMinSendBitrateBps = 10;
|
||||
const uint32_t kMaxSendBitrateBps = 60;
|
||||
const uint32_t kNetworkBandwidthBps = 30;
|
||||
|
||||
allocator_->AddObserver(&observer, kMinSendBitrateBps, kMaxSendBitrateBps, 0,
|
||||
true, "", 2.0);
|
||||
allocator_->OnNetworkChanged(kNetworkBandwidthBps, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
EXPECT_EQ(kNetworkBandwidthBps, observer.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer);
|
||||
}
|
||||
|
||||
// Tests that two observers with the same bitrate priority are allocated
|
||||
// their bitrate evenly.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateTwoObserversBasic) {
|
||||
TestBitrateObserver observer_low_1;
|
||||
TestBitrateObserver observer_low_2;
|
||||
const uint32_t kMinSendBitrateBps = 10;
|
||||
const uint32_t kMaxSendBitrateBps = 60;
|
||||
const uint32_t kNetworkBandwidthBps = 60;
|
||||
allocator_->AddObserver(&observer_low_1, kMinSendBitrateBps,
|
||||
kMaxSendBitrateBps, 0, false, "low1", 2.0);
|
||||
allocator_->AddObserver(&observer_low_2, kMinSendBitrateBps,
|
||||
kMaxSendBitrateBps, 0, false, "low2", 2.0);
|
||||
allocator_->OnNetworkChanged(kNetworkBandwidthBps, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
EXPECT_EQ(kNetworkBandwidthBps / 2, observer_low_1.last_bitrate_bps_);
|
||||
EXPECT_EQ(kNetworkBandwidthBps / 2, observer_low_2.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low_1);
|
||||
allocator_->RemoveObserver(&observer_low_2);
|
||||
}
|
||||
|
||||
// Tests that there is no difference in functionality when the min bitrate is
|
||||
// enforced.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateTwoObserversBasicMinEnforced) {
|
||||
TestBitrateObserver observer_low_1;
|
||||
TestBitrateObserver observer_low_2;
|
||||
const uint32_t kMinSendBitrateBps = 0;
|
||||
const uint32_t kMaxSendBitrateBps = 60;
|
||||
const uint32_t kNetworkBandwidthBps = 60;
|
||||
allocator_->AddObserver(&observer_low_1, kMinSendBitrateBps,
|
||||
kMaxSendBitrateBps, 0, true, "low1", 2.0);
|
||||
allocator_->AddObserver(&observer_low_2, kMinSendBitrateBps,
|
||||
kMaxSendBitrateBps, 0, true, "low2", 2.0);
|
||||
allocator_->OnNetworkChanged(kNetworkBandwidthBps, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
EXPECT_EQ(kNetworkBandwidthBps / 2, observer_low_1.last_bitrate_bps_);
|
||||
EXPECT_EQ(kNetworkBandwidthBps / 2, observer_low_2.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low_1);
|
||||
allocator_->RemoveObserver(&observer_low_2);
|
||||
}
|
||||
|
||||
// Tests that if the available bandwidth is the sum of the max bitrate
|
||||
// of all observers, they will be allocated their max.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateTwoObserversBothAllocatedMax) {
|
||||
TestBitrateObserver observer_low;
|
||||
TestBitrateObserver observer_mid;
|
||||
const uint32_t kMinSendBitrateBps = 0;
|
||||
const uint32_t kMaxSendBitrateBps = 60;
|
||||
const uint32_t kNetworkBandwidthBps = kMaxSendBitrateBps * 2;
|
||||
allocator_->AddObserver(&observer_low, kMinSendBitrateBps, kMaxSendBitrateBps,
|
||||
0, true, "low", 2.0);
|
||||
allocator_->AddObserver(&observer_mid, kMinSendBitrateBps, kMaxSendBitrateBps,
|
||||
0, true, "mid", 4.0);
|
||||
allocator_->OnNetworkChanged(kNetworkBandwidthBps, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
EXPECT_EQ(kMaxSendBitrateBps, observer_low.last_bitrate_bps_);
|
||||
EXPECT_EQ(kMaxSendBitrateBps, observer_mid.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low);
|
||||
allocator_->RemoveObserver(&observer_mid);
|
||||
}
|
||||
|
||||
// Tests that after a higher bitrate priority observer has been allocated its
|
||||
// max bitrate the lower priority observer will then be allocated the remaining
|
||||
// bitrate.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateTwoObserversOneAllocatedToMax) {
|
||||
TestBitrateObserver observer_low;
|
||||
TestBitrateObserver observer_mid;
|
||||
allocator_->AddObserver(&observer_low, 10, 50, 0, false, "low", 2.0);
|
||||
allocator_->AddObserver(&observer_mid, 10, 50, 0, false, "mid", 4.0);
|
||||
allocator_->OnNetworkChanged(90, 0, 0, kDefaultProbingIntervalMs);
|
||||
|
||||
EXPECT_EQ(40u, observer_low.last_bitrate_bps_);
|
||||
EXPECT_EQ(50u, observer_mid.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low);
|
||||
allocator_->RemoveObserver(&observer_mid);
|
||||
}
|
||||
|
||||
// Tests that three observers with three different bitrate priorities will all
|
||||
// be allocated bitrate according to their relative bitrate priority.
|
||||
TEST_F(BitrateAllocatorTest,
|
||||
PriorityRateThreeObserversAllocatedRelativeAmounts) {
|
||||
TestBitrateObserver observer_low;
|
||||
TestBitrateObserver observer_mid;
|
||||
TestBitrateObserver observer_high;
|
||||
const uint32_t kMaxBitrate = 100;
|
||||
// Not enough bandwidth to fill any observer's max bitrate.
|
||||
const uint32_t kNetworkBandwidthBps = 70;
|
||||
const double kLowBitratePriority = 2.0;
|
||||
const double kMidBitratePriority = 4.0;
|
||||
const double kHighBitratePriority = 8.0;
|
||||
const double kTotalBitratePriority =
|
||||
kLowBitratePriority + kMidBitratePriority + kHighBitratePriority;
|
||||
allocator_->AddObserver(&observer_low, 0, kMaxBitrate, 0, false, "low",
|
||||
kLowBitratePriority);
|
||||
allocator_->AddObserver(&observer_mid, 0, kMaxBitrate, 0, false, "mid",
|
||||
kMidBitratePriority);
|
||||
allocator_->AddObserver(&observer_high, 0, kMaxBitrate, 0, false, "high",
|
||||
kHighBitratePriority);
|
||||
allocator_->OnNetworkChanged(kNetworkBandwidthBps, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
const double kLowFractionAllocated =
|
||||
kLowBitratePriority / kTotalBitratePriority;
|
||||
const double kMidFractionAllocated =
|
||||
kMidBitratePriority / kTotalBitratePriority;
|
||||
const double kHighFractionAllocated =
|
||||
kHighBitratePriority / kTotalBitratePriority;
|
||||
EXPECT_EQ(kLowFractionAllocated * kNetworkBandwidthBps,
|
||||
observer_low.last_bitrate_bps_);
|
||||
EXPECT_EQ(kMidFractionAllocated * kNetworkBandwidthBps,
|
||||
observer_mid.last_bitrate_bps_);
|
||||
EXPECT_EQ(kHighFractionAllocated * kNetworkBandwidthBps,
|
||||
observer_high.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low);
|
||||
allocator_->RemoveObserver(&observer_mid);
|
||||
allocator_->RemoveObserver(&observer_high);
|
||||
}
|
||||
|
||||
// Tests that after the high priority observer has been allocated its maximum
|
||||
// bitrate, the other two observers are still allocated bitrate according to
|
||||
// their relative bitrate priority.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateThreeObserversHighAllocatedToMax) {
|
||||
TestBitrateObserver observer_low;
|
||||
const double kLowBitratePriority = 2.0;
|
||||
TestBitrateObserver observer_mid;
|
||||
const double kMidBitratePriority = 4.0;
|
||||
TestBitrateObserver observer_high;
|
||||
const double kHighBitratePriority = 8.0;
|
||||
|
||||
const uint32_t kAvailableBitrate = 90;
|
||||
const uint32_t kMaxBitrate = 40;
|
||||
const uint32_t kMinBitrate = 10;
|
||||
// Remaining bitrate after allocating to all mins and knowing that the high
|
||||
// priority observer will have its max bitrate allocated.
|
||||
const uint32_t kRemainingBitrate =
|
||||
kAvailableBitrate - kMaxBitrate - (2 * kMinBitrate);
|
||||
|
||||
allocator_->AddObserver(&observer_low, kMinBitrate, kMaxBitrate, 0, false,
|
||||
"low", kLowBitratePriority);
|
||||
allocator_->AddObserver(&observer_mid, kMinBitrate, kMaxBitrate, 0, false,
|
||||
"mid", kMidBitratePriority);
|
||||
allocator_->AddObserver(&observer_high, kMinBitrate, kMaxBitrate, 0, false,
|
||||
"high", kHighBitratePriority);
|
||||
allocator_->OnNetworkChanged(kAvailableBitrate, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
const double kLowFractionAllocated =
|
||||
kLowBitratePriority / (kLowBitratePriority + kMidBitratePriority);
|
||||
const double kMidFractionAllocated =
|
||||
kMidBitratePriority / (kLowBitratePriority + kMidBitratePriority);
|
||||
EXPECT_EQ(kMinBitrate + (kRemainingBitrate * kLowFractionAllocated),
|
||||
observer_low.last_bitrate_bps_);
|
||||
EXPECT_EQ(kMinBitrate + (kRemainingBitrate * kMidFractionAllocated),
|
||||
observer_mid.last_bitrate_bps_);
|
||||
EXPECT_EQ(40u, observer_high.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low);
|
||||
allocator_->RemoveObserver(&observer_mid);
|
||||
allocator_->RemoveObserver(&observer_high);
|
||||
}
|
||||
|
||||
// Tests that after the low priority observer has been allocated its maximum
|
||||
// bitrate, the other two observers are still allocated bitrate according to
|
||||
// their relative bitrate priority.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateThreeObserversLowAllocatedToMax) {
|
||||
TestBitrateObserver observer_low;
|
||||
const double kLowBitratePriority = 2.0;
|
||||
const uint32_t kLowMaxBitrate = 10;
|
||||
TestBitrateObserver observer_mid;
|
||||
const double kMidBitratePriority = 4.0;
|
||||
TestBitrateObserver observer_high;
|
||||
const double kHighBitratePriority = 8.0;
|
||||
|
||||
const uint32_t kMinBitrate = 0;
|
||||
const uint32_t kMaxBitrate = 60;
|
||||
const uint32_t kAvailableBitrate = 100;
|
||||
// Remaining bitrate knowing that the low priority observer is allocated its
|
||||
// max bitrate. We know this because it is allocated 2.0/14.0 (1/7) of the
|
||||
// available bitrate, so 70 bps would be sufficient network bandwidth.
|
||||
const uint32_t kRemainingBitrate = kAvailableBitrate - kLowMaxBitrate;
|
||||
|
||||
allocator_->AddObserver(&observer_low, kMinBitrate, kLowMaxBitrate, 0, false,
|
||||
"low", kLowBitratePriority);
|
||||
allocator_->AddObserver(&observer_mid, kMinBitrate, kMaxBitrate, 0, false,
|
||||
"mid", kMidBitratePriority);
|
||||
allocator_->AddObserver(&observer_high, kMinBitrate, kMaxBitrate, 0, false,
|
||||
"high", kHighBitratePriority);
|
||||
allocator_->OnNetworkChanged(kAvailableBitrate, 0, 0,
|
||||
kDefaultProbingIntervalMs);
|
||||
|
||||
const double kMidFractionAllocated =
|
||||
kMidBitratePriority / (kMidBitratePriority + kHighBitratePriority);
|
||||
const double kHighFractionAllocated =
|
||||
kHighBitratePriority / (kMidBitratePriority + kHighBitratePriority);
|
||||
EXPECT_EQ(kLowMaxBitrate, observer_low.last_bitrate_bps_);
|
||||
EXPECT_EQ(kMinBitrate + (kRemainingBitrate * kMidFractionAllocated),
|
||||
observer_mid.last_bitrate_bps_);
|
||||
EXPECT_EQ(kMinBitrate + (kRemainingBitrate * kHighFractionAllocated),
|
||||
observer_high.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low);
|
||||
allocator_->RemoveObserver(&observer_mid);
|
||||
allocator_->RemoveObserver(&observer_high);
|
||||
}
|
||||
|
||||
// Tests that after two observers are allocated bitrate to their max, the
|
||||
// the remaining observer is allocated what's left appropriately. This test
|
||||
// handles an edge case where the medium and high observer reach their
|
||||
// "relative" max allocation at the same time. The high has 40 to allocate
|
||||
// above its min, and the mid has 20 to allocate above its min, which scaled
|
||||
// by their bitrate priority is the same for each.
|
||||
TEST_F(BitrateAllocatorTest, PriorityRateThreeObserversTwoAllocatedToMax) {
|
||||
TestBitrateObserver observer_low;
|
||||
TestBitrateObserver observer_mid;
|
||||
TestBitrateObserver observer_high;
|
||||
allocator_->AddObserver(&observer_low, 10, 40, 0, false, "low", 2.0);
|
||||
// Scaled allocation above the min allocation is the same for these two,
|
||||
// meaning they will get allocated their max at the same time.
|
||||
// Scaled (target allocation) = (max - min) / bitrate priority
|
||||
allocator_->AddObserver(&observer_mid, 10, 30, 0, false, "mid", 4.0);
|
||||
allocator_->AddObserver(&observer_high, 10, 50, 0, false, "high", 8.0);
|
||||
allocator_->OnNetworkChanged(110, 0, 0, kDefaultProbingIntervalMs);
|
||||
|
||||
EXPECT_EQ(30u, observer_low.last_bitrate_bps_);
|
||||
EXPECT_EQ(30u, observer_mid.last_bitrate_bps_);
|
||||
EXPECT_EQ(50u, observer_high.last_bitrate_bps_);
|
||||
|
||||
allocator_->RemoveObserver(&observer_low);
|
||||
allocator_->RemoveObserver(&observer_mid);
|
||||
allocator_->RemoveObserver(&observer_high);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user