Split WebRTC-UseShortVP8TL3Pattern field trial in two.

- WebRTC-UseShortVP8TL3Pattern: Use a temporal pattern of length 4.
- WebRTC-UseBaseHeavyVP8TL3RateAllocation: Allocate 60/20/20 to the TLs.

Bug: webrtc:9477
Change-Id: Ib22d74c9390273e6498d417354d2cd311d9439b9
Reviewed-on: https://webrtc-review.googlesource.com/102920
Commit-Queue: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24924}
This commit is contained in:
Rasmus Brandt
2018-10-02 11:12:52 +02:00
committed by Commit Bot
parent 9551375c02
commit 73d117f64e
4 changed files with 108 additions and 40 deletions

View File

@ -25,6 +25,9 @@ namespace cricket {
namespace { namespace {
constexpr char kUseBaseHeavyVP8TL3RateAllocationFieldTrial[] =
"WebRTC-UseBaseHeavyVP8TL3RateAllocation";
// Limits for legacy conference screensharing mode. Currently used for the // Limits for legacy conference screensharing mode. Currently used for the
// lower of the two simulcast streams. // lower of the two simulcast streams.
constexpr int kScreenshareDefaultTl0BitrateKbps = 200; constexpr int kScreenshareDefaultTl0BitrateKbps = 200;
@ -257,15 +260,16 @@ std::vector<webrtc::VideoStream> GetNormalSimulcastLayers(
layers[s].target_bitrate_bps = FindSimulcastTargetBitrateBps(width, height); layers[s].target_bitrate_bps = FindSimulcastTargetBitrateBps(width, height);
int num_temporal_layers = DefaultNumberOfTemporalLayers(s, false); int num_temporal_layers = DefaultNumberOfTemporalLayers(s, false);
if (s == 0) { if (s == 0) {
// If alternative number temporal layers is selected, adjust the // If alternative temporal rate allocation is selected, adjust the
// bitrate of the lowest simulcast stream so that absolute bitrate for // bitrate of the lowest simulcast stream so that absolute bitrate for
// the base temporal layer matches the bitrate for the base temporal // the base temporal layer matches the bitrate for the base temporal
// layer with the default 3 simulcast streams. Otherwise we risk a // layer with the default 3 simulcast streams. Otherwise we risk a
// higher threshold for receiving a feed at all. // higher threshold for receiving a feed at all.
float rate_factor = 1.0; float rate_factor = 1.0;
if (num_temporal_layers == 3) { if (num_temporal_layers == 3) {
if (webrtc::field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) { if (webrtc::field_trial::IsEnabled(
// Shortened pattern increases TL0 bitrate from 40% to 60%. kUseBaseHeavyVP8TL3RateAllocationFieldTrial)) {
// Base heavy allocation increases TL0 bitrate from 40% to 60%.
rate_factor = 0.4 / 0.6; rate_factor = 0.4 / 0.6;
} }
} else { } else {
@ -341,7 +345,8 @@ std::vector<webrtc::VideoStream> GetScreenshareLayers(
webrtc::SimulcastRateAllocator::GetTemporalRateAllocation( webrtc::SimulcastRateAllocator::GetTemporalRateAllocation(
num_temporal_layers, 0)); num_temporal_layers, 0));
} else if (DefaultNumberOfTemporalLayers(1, true) != 3 || } else if (DefaultNumberOfTemporalLayers(1, true) != 3 ||
webrtc::field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) { webrtc::field_trial::IsEnabled(
kUseBaseHeavyVP8TL3RateAllocationFieldTrial)) {
// Experimental temporal layer mode used, use increased max bitrate. // Experimental temporal layer mode used, use increased max bitrate.
max_bitrate_bps = kScreenshareHighStreamMaxBitrateBps; max_bitrate_bps = kScreenshareHighStreamMaxBitrateBps;
using_boosted_bitrate = true; using_boosted_bitrate = true;

View File

@ -108,6 +108,29 @@ TEST(SimulcastTest, GetConfig) {
EXPECT_FALSE(streams[2].bitrate_priority); EXPECT_FALSE(streams[2].bitrate_priority);
} }
TEST(SimulcastTest, GetConfigWithBaseHeavyVP8TL3RateAllocation) {
test::ScopedFieldTrials field_trials(
"WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/");
const std::vector<VideoStream> kExpected = GetSimulcastBitrates720p();
const size_t kMaxLayers = 3;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
kMaxLayers, 1280, 720, kMaxBitrateBps, kBitratePriority, kQpMax, kMaxFps,
!kScreenshare);
EXPECT_EQ(kExpected[0].min_bitrate_bps, streams[0].min_bitrate_bps);
EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].target_bitrate_bps / 0.6),
streams[0].target_bitrate_bps);
EXPECT_EQ(static_cast<int>(0.4 * kExpected[0].max_bitrate_bps / 0.6),
streams[0].max_bitrate_bps);
for (size_t i = 1; i < streams.size(); ++i) {
EXPECT_EQ(kExpected[i].min_bitrate_bps, streams[i].min_bitrate_bps);
EXPECT_EQ(kExpected[i].target_bitrate_bps, streams[i].target_bitrate_bps);
EXPECT_EQ(kExpected[i].max_bitrate_bps, streams[i].max_bitrate_bps);
}
}
TEST(SimulcastTest, GetConfigWithLimitedMaxLayers) { TEST(SimulcastTest, GetConfigWithLimitedMaxLayers) {
const size_t kMaxLayers = 2; const size_t kMaxLayers = 2;
std::vector<VideoStream> streams = cricket::GetSimulcastConfig( std::vector<VideoStream> streams = cricket::GetSimulcastConfig(
@ -221,7 +244,7 @@ TEST(SimulcastTest, SimulcastScreenshareMaxBitrateAdjustedForResolution) {
constexpr int kScreenshareHighStreamMinBitrateBps = 600000; constexpr int kScreenshareHighStreamMinBitrateBps = 600000;
constexpr int kScreenshareHighStreamMaxBitrateBps = 1250000; constexpr int kScreenshareHighStreamMaxBitrateBps = 1250000;
constexpr int kMaxBirate960_540 = 900000; constexpr int kMaxBitrate960_540 = 900000;
// Normal case, max bitrate not limited by resolution. // Normal case, max bitrate not limited by resolution.
const size_t kMaxLayers = 2; const size_t kMaxLayers = 2;
@ -238,7 +261,7 @@ TEST(SimulcastTest, SimulcastScreenshareMaxBitrateAdjustedForResolution) {
kBitratePriority, kQpMax, kMaxFps, kBitratePriority, kQpMax, kMaxFps,
kScreenshare); kScreenshare);
EXPECT_EQ(kMaxLayers, streams.size()); EXPECT_EQ(kMaxLayers, streams.size());
EXPECT_EQ(streams[1].max_bitrate_bps, kMaxBirate960_540); EXPECT_EQ(streams[1].max_bitrate_bps, kMaxBitrate960_540);
EXPECT_EQ(streams[1].min_bitrate_bps, kScreenshareHighStreamMinBitrateBps); EXPECT_EQ(streams[1].min_bitrate_bps, kScreenshareHighStreamMinBitrateBps);
EXPECT_GE(streams[1].max_bitrate_bps, streams[1].min_bitrate_bps); EXPECT_GE(streams[1].max_bitrate_bps, streams[1].min_bitrate_bps);

View File

@ -32,7 +32,7 @@ static const float
{0.25f, 0.4f, 0.6f, 1.0f} // 4 layers {25%, 15%, 20%, 40%} {0.25f, 0.4f, 0.6f, 1.0f} // 4 layers {25%, 15%, 20%, 40%}
}; };
static const float kShort3TlRateAllocation[kMaxTemporalStreams] = { static const float kBaseHeavy3TlRateAllocation[kMaxTemporalStreams] = {
0.6f, 0.8f, 1.0f, 1.0f // 3 layers {60%, 20%, 20%} 0.6f, 0.8f, 1.0f, 1.0f // 3 layers {60%, 20%, 20%}
}; };
@ -74,8 +74,8 @@ float SimulcastRateAllocator::GetTemporalRateAllocation(int num_layers,
RTC_CHECK_GE(temporal_id, 0); RTC_CHECK_GE(temporal_id, 0);
RTC_CHECK_LT(temporal_id, num_layers); RTC_CHECK_LT(temporal_id, num_layers);
if (num_layers == 3 && if (num_layers == 3 &&
field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) { field_trial::IsEnabled("WebRTC-UseBaseHeavyVP8TL3RateAllocation")) {
return kShort3TlRateAllocation[temporal_id]; return kBaseHeavy3TlRateAllocation[temporal_id];
} }
return kLayerRateAllocation[num_layers - 1][temporal_id]; return kLayerRateAllocation[num_layers - 1][temporal_id];
} }

View File

@ -17,6 +17,7 @@
#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h" #include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
#include "test/field_trial.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
@ -91,32 +92,45 @@ class SimulcastRateAllocatorTest : public ::testing::TestWithParam<bool> {
allocator_.reset(new SimulcastRateAllocator(codec_)); allocator_.reset(new SimulcastRateAllocator(codec_));
} }
void SetupCodecThreeSimulcastStreams( void SetupCodec3SL3TL(const std::vector<bool>& active_streams) {
const std::vector<bool>& active_streams) { const size_t num_simulcast_layers = 3;
size_t num_streams = 3; RTC_DCHECK_GE(active_streams.size(), num_simulcast_layers);
RTC_DCHECK_GE(active_streams.size(), num_streams); SetupCodec2SL3TL(active_streams);
SetupCodecTwoSimulcastStreams(active_streams); codec_.numberOfSimulcastStreams = num_simulcast_layers;
codec_.numberOfSimulcastStreams = num_streams; codec_.simulcastStream[2].numberOfTemporalLayers = 3;
codec_.simulcastStream[2].minBitrate = 2000;
codec_.simulcastStream[2].targetBitrate = 3000;
codec_.simulcastStream[2].maxBitrate = 4000; codec_.simulcastStream[2].maxBitrate = 4000;
codec_.simulcastStream[2].targetBitrate = 3000;
codec_.simulcastStream[2].minBitrate = 2000;
codec_.simulcastStream[2].active = active_streams[2]; codec_.simulcastStream[2].active = active_streams[2];
} }
void SetupCodecTwoSimulcastStreams(const std::vector<bool>& active_streams) { void SetupCodec2SL3TL(const std::vector<bool>& active_streams) {
size_t num_streams = 2; const size_t num_simulcast_layers = 2;
RTC_DCHECK_GE(active_streams.size(), num_streams); RTC_DCHECK_GE(active_streams.size(), num_simulcast_layers);
codec_.numberOfSimulcastStreams = num_streams; SetupCodec1SL3TL(active_streams);
codec_.maxBitrate = 0; codec_.numberOfSimulcastStreams = num_simulcast_layers;
codec_.simulcastStream[0].minBitrate = 10; codec_.simulcastStream[1].numberOfTemporalLayers = 3;
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[1].maxBitrate = 1000;
for (size_t i = 0; i < num_streams; ++i) { codec_.simulcastStream[1].targetBitrate = 500;
codec_.simulcastStream[i].active = active_streams[i]; codec_.simulcastStream[1].minBitrate = 50;
} codec_.simulcastStream[1].active = active_streams[1];
}
void SetupCodec1SL3TL(const std::vector<bool>& active_streams) {
const size_t num_simulcast_layers = 2;
RTC_DCHECK_GE(active_streams.size(), num_simulcast_layers);
SetupCodec3TL();
codec_.numberOfSimulcastStreams = num_simulcast_layers;
codec_.simulcastStream[0].numberOfTemporalLayers = 3;
codec_.simulcastStream[0].maxBitrate = 500;
codec_.simulcastStream[0].targetBitrate = 100;
codec_.simulcastStream[0].minBitrate = 10;
codec_.simulcastStream[0].active = active_streams[0];
}
void SetupCodec3TL() {
codec_.maxBitrate = 0;
codec_.VP8()->numberOfTemporalLayers = 3;
} }
VideoBitrateAllocation GetAllocation(uint32_t target_bitrate) { VideoBitrateAllocation GetAllocation(uint32_t target_bitrate) {
@ -219,6 +233,37 @@ TEST_F(SimulcastRateAllocatorTest, SingleSimulcastWithinLimits) {
} }
} }
TEST_F(SimulcastRateAllocatorTest, Regular3TLTemporalRateAllocation) {
SetupCodec3SL3TL({true, true, true});
CreateAllocator();
const VideoBitrateAllocation alloc = GetAllocation(kMinBitrateKbps);
// 40/20/40.
EXPECT_EQ(static_cast<uint32_t>(0.4 * kMinBitrateKbps),
alloc.GetBitrate(0, 0) / 1000);
EXPECT_EQ(static_cast<uint32_t>(0.2 * kMinBitrateKbps),
alloc.GetBitrate(0, 1) / 1000);
EXPECT_EQ(static_cast<uint32_t>(0.4 * kMinBitrateKbps),
alloc.GetBitrate(0, 2) / 1000);
}
TEST_F(SimulcastRateAllocatorTest, BaseHeavy3TLTemporalRateAllocation) {
test::ScopedFieldTrials field_trials(
"WebRTC-UseBaseHeavyVP8TL3RateAllocation/Enabled/");
SetupCodec3SL3TL({true, true, true});
CreateAllocator();
const VideoBitrateAllocation alloc = GetAllocation(kMinBitrateKbps);
// 60/20/20.
EXPECT_EQ(static_cast<uint32_t>(0.6 * kMinBitrateKbps),
alloc.GetBitrate(0, 0) / 1000);
EXPECT_EQ(static_cast<uint32_t>(0.2 * kMinBitrateKbps),
alloc.GetBitrate(0, 1) / 1000);
EXPECT_EQ(static_cast<uint32_t>(0.2 * kMinBitrateKbps),
alloc.GetBitrate(0, 2) / 1000);
}
TEST_F(SimulcastRateAllocatorTest, SingleSimulcastInactive) { TEST_F(SimulcastRateAllocatorTest, SingleSimulcastInactive) {
codec_.numberOfSimulcastStreams = 1; codec_.numberOfSimulcastStreams = 1;
codec_.simulcastStream[0].minBitrate = kMinBitrateKbps; codec_.simulcastStream[0].minBitrate = kMinBitrateKbps;
@ -234,8 +279,7 @@ TEST_F(SimulcastRateAllocatorTest, SingleSimulcastInactive) {
} }
TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) { TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) {
const std::vector<bool> active_streams(3, true); SetupCodec3SL3TL({true, true, true});
SetupCodecThreeSimulcastStreams(active_streams);
CreateAllocator(); CreateAllocator();
{ {
@ -326,8 +370,7 @@ TEST_F(SimulcastRateAllocatorTest, OneToThreeStreams) {
// If three simulcast streams that are all inactive, none of them should be // If three simulcast streams that are all inactive, none of them should be
// allocated bitrate. // allocated bitrate.
TEST_F(SimulcastRateAllocatorTest, ThreeStreamsInactive) { TEST_F(SimulcastRateAllocatorTest, ThreeStreamsInactive) {
const std::vector<bool> active_streams(3, false); SetupCodec3SL3TL({false, false, false});
SetupCodecThreeSimulcastStreams(active_streams);
CreateAllocator(); CreateAllocator();
// Just enough to allocate the min. // Just enough to allocate the min.
@ -352,8 +395,7 @@ TEST_F(SimulcastRateAllocatorTest, ThreeStreamsInactive) {
// If there are two simulcast streams, we expect the high active stream to be // If there are two simulcast streams, we expect the high active stream to be
// allocated as if it is a single active stream. // allocated as if it is a single active stream.
TEST_F(SimulcastRateAllocatorTest, TwoStreamsLowInactive) { TEST_F(SimulcastRateAllocatorTest, TwoStreamsLowInactive) {
const std::vector<bool> active_streams({false, true}); SetupCodec2SL3TL({false, true});
SetupCodecTwoSimulcastStreams(active_streams);
CreateAllocator(); CreateAllocator();
const uint32_t kActiveStreamMinBitrate = codec_.simulcastStream[1].minBitrate; const uint32_t kActiveStreamMinBitrate = codec_.simulcastStream[1].minBitrate;
@ -385,8 +427,7 @@ TEST_F(SimulcastRateAllocatorTest, TwoStreamsLowInactive) {
// If there are two simulcast streams, we expect the low active stream to be // If there are two simulcast streams, we expect the low active stream to be
// allocated as if it is a single active stream. // allocated as if it is a single active stream.
TEST_F(SimulcastRateAllocatorTest, TwoStreamsHighInactive) { TEST_F(SimulcastRateAllocatorTest, TwoStreamsHighInactive) {
const std::vector<bool> active_streams({true, false}); SetupCodec2SL3TL({true, false});
SetupCodecTwoSimulcastStreams(active_streams);
CreateAllocator(); CreateAllocator();
const uint32_t kActiveStreamMinBitrate = codec_.simulcastStream[0].minBitrate; const uint32_t kActiveStreamMinBitrate = codec_.simulcastStream[0].minBitrate;
@ -419,8 +460,7 @@ TEST_F(SimulcastRateAllocatorTest, TwoStreamsHighInactive) {
// other two streams should be allocated bitrate the same as if they are two // other two streams should be allocated bitrate the same as if they are two
// active simulcast streams. // active simulcast streams.
TEST_F(SimulcastRateAllocatorTest, ThreeStreamsMiddleInactive) { TEST_F(SimulcastRateAllocatorTest, ThreeStreamsMiddleInactive) {
const std::vector<bool> active_streams({true, false, true}); SetupCodec3SL3TL({true, false, true});
SetupCodecThreeSimulcastStreams(active_streams);
CreateAllocator(); CreateAllocator();
{ {