From 098f8d2c1c678cd65555a44ba1d06bb02b6ac860 Mon Sep 17 00:00:00 2001 From: Sergey Silkin Date: Sat, 14 Apr 2018 22:25:22 +0200 Subject: [PATCH] Round down when converting allocated bitrate from bits to kilobits. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With rounding to the nearest the result can exceed the allocated bitrate. Bug: none Change-Id: I0260a1640a1454951ca8e48fd447e047ef0271ee Reviewed-on: https://webrtc-review.googlesource.com/69982 Reviewed-by: Erik Språng Reviewed-by: Stefan Holmer Commit-Queue: Sergey Silkin Cr-Commit-Position: refs/heads/master@{#22879} --- common_types.h | 5 ++++- .../video_coding/codecs/vp9/svc_rate_allocator.cc | 13 +++++++++++-- .../codecs/vp9/svc_rate_allocator_unittest.cc | 9 +++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/common_types.h b/common_types.h index 5896fd62dc..292db5ee23 100644 --- a/common_types.h +++ b/common_types.h @@ -570,7 +570,10 @@ class BitrateAllocation { std::vector GetTemporalLayerAllocation(size_t spatial_index) const; uint32_t get_sum_bps() const { return sum_; } // Sum of all bitrates. - uint32_t get_sum_kbps() const { return (sum_ + 500) / 1000; } + uint32_t get_sum_kbps() const { + // Round down to not exceed the allocated bitrate. + return sum_ / 1000; + } inline bool operator==(const BitrateAllocation& other) const { return memcmp(bitrates_, other.bitrates_, sizeof(bitrates_)) == 0; diff --git a/modules/video_coding/codecs/vp9/svc_rate_allocator.cc b/modules/video_coding/codecs/vp9/svc_rate_allocator.cc index 48d22fdfb1..e335550cdc 100644 --- a/modules/video_coding/codecs/vp9/svc_rate_allocator.cc +++ b/modules/video_coding/codecs/vp9/svc_rate_allocator.cc @@ -12,6 +12,7 @@ #include #include +#include #include "rtc_base/checks.h" @@ -132,17 +133,25 @@ std::vector SvcRateAllocator::SplitBitrate(size_t num_layers, float rate_scaling_factor) { std::vector bitrates; - float denominator = 0.0f; + double denominator = 0.0; for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) { denominator += std::pow(rate_scaling_factor, layer_idx); } - float numerator = std::pow(rate_scaling_factor, num_layers - 1); + double numerator = std::pow(rate_scaling_factor, num_layers - 1); for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) { bitrates.push_back(numerator * total_bitrate / denominator); numerator /= rate_scaling_factor; } + const size_t sum = std::accumulate(bitrates.begin(), bitrates.end(), 0); + // Ensure the sum of split bitrates doesn't exceed the total bitrate. + RTC_DCHECK_LE(sum, total_bitrate); + + // Keep the sum of split bitrates equal to the total bitrate by adding bits, + // which were lost due to rounding, to the latest layer. + bitrates.back() += total_bitrate - sum; + return bitrates; } 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 f75dfe104b..e89416694c 100644 --- a/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc +++ b/modules/video_coding/codecs/vp9/svc_rate_allocator_unittest.cc @@ -134,12 +134,9 @@ TEST(SvcRateAllocatorTest, BitrateIsCapped) { EXPECT_EQ(allocation.get_sum_kbps(), layers[0].maxBitrate + layers[1].maxBitrate + layers[2].maxBitrate); - EXPECT_EQ((allocation.GetSpatialLayerSum(0) + 500) / 1000, - layers[0].maxBitrate); - EXPECT_EQ((allocation.GetSpatialLayerSum(1) + 500) / 1000, - layers[1].maxBitrate); - EXPECT_EQ((allocation.GetSpatialLayerSum(2) + 500) / 1000, - layers[2].maxBitrate); + EXPECT_EQ(allocation.GetSpatialLayerSum(0) / 1000, layers[0].maxBitrate); + EXPECT_EQ(allocation.GetSpatialLayerSum(1) / 1000, layers[1].maxBitrate); + EXPECT_EQ(allocation.GetSpatialLayerSum(2) / 1000, layers[2].maxBitrate); } } // namespace webrtc