From 571e6c9105881dd7f93916e940d915d87c2bca03 Mon Sep 17 00:00:00 2001 From: Sergey Silkin Date: Tue, 3 Apr 2018 10:03:31 +0200 Subject: [PATCH] Fix rate allocation between temporal layers in SVC. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bitrate of three temporal layers as fraction of total bitrate after fix: 0.54, 0.16, 0.30 before fix: 0.54, 0.30, 0.16 Bug: none Change-Id: I8134abc19d5d6723b7a959196ca9c1635026eadc Reviewed-on: https://webrtc-review.googlesource.com/66060 Reviewed-by: Rasmus Brandt Reviewed-by: Åsa Persson Reviewed-by: Michael Horowitz Commit-Queue: Sergey Silkin Cr-Commit-Position: refs/heads/master@{#22726} --- .../codecs/vp9/svc_rate_allocator.cc | 21 ++++++++++++++++--- video/video_send_stream_tests.cc | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/modules/video_coding/codecs/vp9/svc_rate_allocator.cc b/modules/video_coding/codecs/vp9/svc_rate_allocator.cc index 2b5253f3c2..4e72790f7f 100644 --- a/modules/video_coding/codecs/vp9/svc_rate_allocator.cc +++ b/modules/video_coding/codecs/vp9/svc_rate_allocator.cc @@ -95,9 +95,24 @@ BitrateAllocation SvcRateAllocator::GetAllocation(uint32_t total_bitrate_bps, SplitBitrate(num_temporal_layers, spatial_layer_bitrate_bps[sl_idx], kTemporalLayeringRateScalingFactor); - for (size_t tl_idx = 0; tl_idx < num_temporal_layers; ++tl_idx) { - bitrate_allocation.SetBitrate(sl_idx, num_temporal_layers - tl_idx - 1, - temporal_layer_bitrate_bps[tl_idx]); + // Distribute rate across temporal layers. Allocate more bits to lower + // layers since they are used for prediction of higher layers and their + // references are far apart. + if (num_temporal_layers == 1) { + bitrate_allocation.SetBitrate(sl_idx, 0, temporal_layer_bitrate_bps[0]); + } else if (num_temporal_layers == 2) { + bitrate_allocation.SetBitrate(sl_idx, 0, temporal_layer_bitrate_bps[1]); + bitrate_allocation.SetBitrate(sl_idx, 1, temporal_layer_bitrate_bps[0]); + } else { + RTC_CHECK_EQ(num_temporal_layers, 3); + // In case of three temporal layers the high layer has two frames and the + // middle layer has one frame within GOP (in between two consecutive low + // layer frames). Thus high layer requires more bits (comparing pure + // bitrate of layer, excluding bitrate of base layers) to keep quality on + // par with lower layers. + bitrate_allocation.SetBitrate(sl_idx, 0, temporal_layer_bitrate_bps[2]); + bitrate_allocation.SetBitrate(sl_idx, 1, temporal_layer_bitrate_bps[0]); + bitrate_allocation.SetBitrate(sl_idx, 2, temporal_layer_bitrate_bps[1]); } } diff --git a/video/video_send_stream_tests.cc b/video/video_send_stream_tests.cc index 0fac281106..1fe4bec777 100644 --- a/video/video_send_stream_tests.cc +++ b/video/video_send_stream_tests.cc @@ -2448,7 +2448,7 @@ TEST_F(VideoSendStreamTest, EncoderSetupPropagatesCommonEncoderConfigValues) { RunBaseTest(&test); } -static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 4; +static const size_t kVideoCodecConfigObserverNumberOfTemporalLayers = 3; template class VideoCodecConfigObserver : public test::SendTest, public test::FakeEncoder {