Tune bitrates and minQP thresholds for high-fps screenshare.
Raise MinQP to allow easier steady-state convergence.
Update SVC rate allocator to not waste bandwidth if there's not enough
for the highest layer.
Bug: webrtc:10257
Change-Id: Iba937bf3c224ffed256308bdb6434be8b5223f84
Reviewed-on: https://webrtc-review.googlesource.com/c/122843
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26710}
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index e001872..09d37b3 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -227,16 +227,22 @@
// The selected thresholds for QVGA and VGA corresponded to a QP around 10.
// The change in QP declined above the selected bitrates.
-static int GetMaxDefaultVideoBitrateKbps(int width, int height) {
+static int GetMaxDefaultVideoBitrateKbps(int width,
+ int height,
+ bool is_screenshare) {
+ int max_bitrate;
if (width * height <= 320 * 240) {
- return 600;
+ max_bitrate = 600;
} else if (width * height <= 640 * 480) {
- return 1700;
+ max_bitrate = 1700;
} else if (width * height <= 960 * 540) {
- return 2000;
+ max_bitrate = 2000;
} else {
- return 2500;
+ max_bitrate = 2500;
}
+ if (is_screenshare)
+ max_bitrate = std::max(max_bitrate, 1200);
+ return max_bitrate;
}
bool GetVp9LayersFromFieldTrialGroup(size_t* num_spatial_layers,
@@ -2783,7 +2789,8 @@
int max_bitrate_bps =
(encoder_config.max_bitrate_bps > 0)
? encoder_config.max_bitrate_bps
- : GetMaxDefaultVideoBitrateKbps(width, height) * 1000;
+ : GetMaxDefaultVideoBitrateKbps(width, height, is_screenshare_) *
+ 1000;
int min_bitrate_bps = GetMinVideoBitrateBps();
if (encoder_config.simulcast_layers[0].min_bitrate_bps > 0) {
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index 7a23325..ea1b994 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -409,7 +409,8 @@
configurations_[0].g_pass = VPX_RC_ONE_PASS;
// Handle resizing outside of libvpx.
configurations_[0].rc_resize_allowed = 0;
- configurations_[0].rc_min_quantizer = 2;
+ configurations_[0].rc_min_quantizer =
+ codec_.mode == VideoCodecMode::kScreensharing ? 12 : 2;
if (inst->qpMax >= configurations_[0].rc_min_quantizer) {
qp_max_ = inst->qpMax;
}
@@ -645,7 +646,7 @@
// Allow more screen content to be detected as static.
libvpx_->codec_control(
&(encoders_[i]), VP8E_SET_STATIC_THRESHOLD,
- codec_.mode == VideoCodecMode::kScreensharing ? 300u : 1u);
+ codec_.mode == VideoCodecMode::kScreensharing ? 100u : 1u);
libvpx_->codec_control(&(encoders_[i]), VP8E_SET_CPUUSED, cpu_speed_[i]);
libvpx_->codec_control(
&(encoders_[i]), VP8E_SET_TOKEN_PARTITIONS,
diff --git a/modules/video_coding/codecs/vp9/svc_config.cc b/modules/video_coding/codecs/vp9/svc_config.cc
index 1754195..138822a 100644
--- a/modules/video_coding/codecs/vp9/svc_config.cc
+++ b/modules/video_coding/codecs/vp9/svc_config.cc
@@ -24,7 +24,10 @@
const size_t kMaxNumLayersForScreenSharing = 3;
const float kMaxScreenSharingLayerFramerateFps[] = {5.0, 5.0, 30.0};
-const size_t kMaxScreenSharingLayerBitrateKbps[] = {200, 500, 1250};
+const size_t kMinScreenSharingLayerBitrateKbps[] = {30, 150, 500};
+const size_t kTargetScreenSharingLayerBitrateKbps[] = {150, 350, 1000};
+const size_t kMaxScreenSharingLayerBitrateKbps[] = {200, 500, 1000};
+
} // namespace
std::vector<SpatialLayer> ConfigureSvcScreenSharing(size_t input_width,
@@ -42,10 +45,12 @@
spatial_layer.maxFramerate =
std::min(kMaxScreenSharingLayerFramerateFps[sl_idx], max_framerate_fps);
spatial_layer.numberOfTemporalLayers = 1;
- spatial_layer.minBitrate = static_cast<int>(kMinVp9SvcBitrateKbps);
+ spatial_layer.minBitrate =
+ static_cast<int>(kMinScreenSharingLayerBitrateKbps[sl_idx]);
spatial_layer.maxBitrate =
static_cast<int>(kMaxScreenSharingLayerBitrateKbps[sl_idx]);
- spatial_layer.targetBitrate = spatial_layer.maxBitrate;
+ spatial_layer.targetBitrate =
+ static_cast<int>(kTargetScreenSharingLayerBitrateKbps[sl_idx]);
spatial_layer.active = true;
spatial_layers.push_back(spatial_layer);
}
diff --git a/modules/video_coding/codecs/vp9/svc_rate_allocator.cc b/modules/video_coding/codecs/vp9/svc_rate_allocator.cc
index f6ddb1e..daa59b1 100644
--- a/modules/video_coding/codecs/vp9/svc_rate_allocator.cc
+++ b/modules/video_coding/codecs/vp9/svc_rate_allocator.cc
@@ -184,20 +184,27 @@
return bitrate_allocation;
}
+// Bit-rate is allocated in such a way, that the highest enabled layer will have
+// between min and max bitrate, and all others will have exactly target
+// bit-rate allocated.
VideoBitrateAllocation SvcRateAllocator::GetAllocationScreenSharing(
uint32_t total_bitrate_bps,
size_t num_spatial_layers) const {
+ if (num_spatial_layers == 0 ||
+ total_bitrate_bps < codec_.spatialLayers[0].minBitrate * 1000) {
+ return VideoBitrateAllocation();
+ }
VideoBitrateAllocation bitrate_allocation;
- // Add next layer after bitrate of previous layer has reached its maximum.
size_t left_bitrate_bps = total_bitrate_bps;
- for (size_t sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
+ size_t sl_idx;
+ for (sl_idx = 0; sl_idx < num_spatial_layers; ++sl_idx) {
const size_t min_bitrate_bps =
codec_.spatialLayers[sl_idx].minBitrate * 1000;
- const size_t max_bitrate_bps =
- codec_.spatialLayers[sl_idx].maxBitrate * 1000;
+ const size_t target_bitrate_bps =
+ codec_.spatialLayers[sl_idx].targetBitrate * 1000;
- const size_t bitrate_bps = std::min(left_bitrate_bps, max_bitrate_bps);
+ const size_t bitrate_bps = std::min(left_bitrate_bps, target_bitrate_bps);
if (bitrate_bps >= min_bitrate_bps) {
bitrate_allocation.SetBitrate(sl_idx, 0, bitrate_bps);
} else {
@@ -207,6 +214,17 @@
left_bitrate_bps -= bitrate_bps;
}
+ if (left_bitrate_bps > 0 && sl_idx > 0) {
+ // Add leftover to the last allocated layer.
+ const size_t max_bitrate_bps =
+ codec_.spatialLayers[sl_idx - 1].maxBitrate * 1000;
+
+ const size_t bitrate_bps = std::min(
+ bitrate_allocation.GetBitrate(sl_idx - 1, 0) + left_bitrate_bps,
+ max_bitrate_bps);
+ bitrate_allocation.SetBitrate(sl_idx - 1, 0, bitrate_bps);
+ }
+
return bitrate_allocation;
}
@@ -245,7 +263,7 @@
uint32_t min_bitrate_kbps = 0;
for (size_t sl_idx = 0; sl_idx < num_spatial_layers - 1; ++sl_idx) {
- min_bitrate_kbps += codec.spatialLayers[sl_idx].maxBitrate;
+ min_bitrate_kbps += codec.spatialLayers[sl_idx].targetBitrate;
}
min_bitrate_kbps += codec.spatialLayers[num_spatial_layers - 1].minBitrate;
diff --git a/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc b/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc
index e1e1df7..f1c6bdd 100644
--- a/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc
+++ b/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc
@@ -159,8 +159,8 @@
EXPECT_EQ(allocation.GetSpatialLayerSum(1), 0UL);
allocation = allocator.GetAllocation(
- (layers[0].maxBitrate + layers[1].minBitrate) * 1000, 30);
- EXPECT_EQ(allocation.GetSpatialLayerSum(0) / 1000, layers[0].maxBitrate);
+ (layers[0].targetBitrate + layers[1].minBitrate) * 1000, 30);
+ EXPECT_EQ(allocation.GetSpatialLayerSum(0) / 1000, layers[0].targetBitrate);
EXPECT_EQ(allocation.GetSpatialLayerSum(1) / 1000, layers[1].minBitrate);
}
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc
index 5feca0b..ac9f8f9 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -48,7 +48,7 @@
int kMaxNumTiles4kVideo = 8;
// Maximum allowed PID difference for variable frame-rate mode.
-const int kMaxAllowedPidDIff = 8;
+const int kMaxAllowedPidDIff = 30;
// Only positive speeds, range for real-time coding currently is: 5 - 8.
// Lower means slower/better quality, higher means fastest/lower quality.
@@ -441,7 +441,8 @@
config_->rc_dropframe_thresh = inst->VP9().frameDroppingOn ? 30 : 0;
config_->rc_end_usage = VPX_CBR;
config_->g_pass = VPX_RC_ONE_PASS;
- config_->rc_min_quantizer = 2;
+ config_->rc_min_quantizer =
+ codec_.mode == VideoCodecMode::kScreensharing ? 8 : 2;
config_->rc_max_quantizer = 52;
config_->rc_undershoot_pct = 50;
config_->rc_overshoot_pct = 50;