OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 #include "webrtc/modules/video_coding/utility/simulcast_state.h" |
| 12 |
| 13 #include <algorithm> |
| 14 #include <memory> |
| 15 #include <vector> |
| 16 |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace webrtc { |
| 20 namespace { |
| 21 const int kMaxStreams = kMaxSimulcastStreams; |
| 22 } // namespace |
| 23 |
| 24 class SimulcastStateTest : public ::testing::Test { |
| 25 public: |
| 26 SimulcastStateTest() {} |
| 27 virtual ~SimulcastStateTest() {} |
| 28 |
| 29 void SetUp() override { |
| 30 memset(&codec_, 0, sizeof(VideoCodec)); |
| 31 codec_.codecType = kVideoCodecVP8; |
| 32 codec_.numberOfSimulcastStreams = 0; |
| 33 codec_.minBitrate = 60; |
| 34 codec_.targetBitrate = 600; |
| 35 codec_.maxBitrate = 2400; |
| 36 codec_.startBitrate = 300; |
| 37 } |
| 38 |
| 39 void ExpectState( |
| 40 const std::vector<SimulcastState::Stream>& expected_streams) { |
| 41 const std::vector<SimulcastState::Stream>& actual_streams = |
| 42 simulcast_state_->Streams(); |
| 43 ASSERT_EQ(expected_streams.size(), actual_streams.size()); |
| 44 const int num_streams = expected_streams.size(); |
| 45 ASSERT_LE(num_streams, kMaxStreams); |
| 46 for (int i = 0; i < num_streams; ++i) { |
| 47 const SimulcastState::Stream& expected = expected_streams[i]; |
| 48 const SimulcastState::Stream& actual = actual_streams[i]; |
| 49 EXPECT_EQ(i, expected.idx); |
| 50 EXPECT_EQ(i, actual.idx); |
| 51 EXPECT_EQ(expected.allocated_rate_bps, actual.allocated_rate_bps); |
| 52 EXPECT_EQ(expected.sending, actual.sending); |
| 53 EXPECT_EQ(expected.keyframe_request, actual.keyframe_request); |
| 54 } |
| 55 } |
| 56 |
| 57 void TestRateAllocation() { |
| 58 int spillover_bps = 0; |
| 59 int margin_bps = 0; |
| 60 std::vector<SimulcastState::Stream> expected_streams; |
| 61 for (int i = 0; i < codec_.numberOfSimulcastStreams; ++i) { |
| 62 SimulcastState::Stream stream(i, &codec_, 0); |
| 63 stream.sending = i == 0; |
| 64 stream.keyframe_request = stream.sending; |
| 65 stream.allocated_rate_bps = |
| 66 stream.sending ? stream.config.minBitrate * 1000 : 0; |
| 67 expected_streams.push_back(stream); |
| 68 } |
| 69 |
| 70 simulcast_state_.reset(new SimulcastState(codec_)); |
| 71 simulcast_state_->AllocateBitrate(0); |
| 72 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 73 expected_streams[0].keyframe_request = false; |
| 74 |
| 75 int top_layer = 0; |
| 76 for (uint32_t i = 1; i < codec_.maxBitrate; ++i) { |
| 77 simulcast_state_->AllocateBitrate(i * 1000); |
| 78 ExpectState(expected_streams); |
| 79 |
| 80 // Always allocate enough bitrate for the lowest stream. |
| 81 if (top_layer == 0 && i < codec_.simulcastStream[0].minBitrate) { |
| 82 expected_streams[0].allocated_rate_bps = |
| 83 codec_.simulcastStream[0].minBitrate * 1000; |
| 84 continue; |
| 85 } |
| 86 |
| 87 const int min_bitrate = |
| 88 expected_streams[top_layer].config.minBitrate * 1000; |
| 89 const int target_bitrate = |
| 90 expected_streams[top_layer].config.targetBitrate * 1000; |
| 91 const int max_bitrate = |
| 92 expected_streams[top_layer].config.maxBitrate * 1000; |
| 93 |
| 94 if (top_layer > 0 && |
| 95 expected_streams[top_layer].allocated_rate_bps == min_bitrate) { |
| 96 // Update and reset key frame status on first updater after enabling |
| 97 // layer. |
| 98 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(top_layer)); |
| 99 expected_streams[top_layer].keyframe_request = false; |
| 100 } |
| 101 |
| 102 // First fill up the top layer until target_bitrate. |
| 103 if (expected_streams[top_layer].allocated_rate_bps < target_bitrate) { |
| 104 expected_streams[top_layer].allocated_rate_bps += 1000; |
| 105 continue; |
| 106 } |
| 107 |
| 108 // We have allocated up to the target bitrate. Anything above this may |
| 109 // be reallocated to a higher layer once it has enough bitrate to reach |
| 110 // its min_bitrate. |
| 111 margin_bps += 1000; |
| 112 if (expected_streams[top_layer].allocated_rate_bps < max_bitrate) { |
| 113 expected_streams[top_layer].allocated_rate_bps += 1000; |
| 114 } else { |
| 115 // TODO(sprang): When we enable allocating extra bits to layers other |
| 116 // than the top one, traverse down and do that here. |
| 117 spillover_bps += 1000; |
| 118 } |
| 119 |
| 120 // Check if there is enough bitrate to enable the next layer. |
| 121 if (top_layer + 1 < codec_.numberOfSimulcastStreams && |
| 122 margin_bps >= static_cast<int>( |
| 123 expected_streams[top_layer + 1].config.minBitrate) * |
| 124 1000) { |
| 125 ++top_layer; |
| 126 expected_streams[top_layer].sending = true; |
| 127 expected_streams[top_layer].keyframe_request = true; |
| 128 |
| 129 // Steal margin bits from the lower layers. |
| 130 // TODO(sprang): Loop over j when we enable allocating extra bits to |
| 131 // layers other than the top one. |
| 132 int j = top_layer - 1; |
| 133 int available_margin = |
| 134 expected_streams[j].allocated_rate_bps - |
| 135 (expected_streams[j].config.targetBitrate * 1000); |
| 136 int consumed_margin = std::min(available_margin, margin_bps); |
| 137 expected_streams[j].allocated_rate_bps -= consumed_margin; |
| 138 margin_bps -= consumed_margin; |
| 139 |
| 140 if (margin_bps > 0 && spillover_bps > 0) { |
| 141 // The rest of the needed margin is in allocated spillover. |
| 142 EXPECT_EQ(margin_bps, spillover_bps); |
| 143 spillover_bps = 0; |
| 144 margin_bps = 0; |
| 145 } else { |
| 146 EXPECT_EQ(0, margin_bps); |
| 147 } |
| 148 |
| 149 expected_streams[top_layer].allocated_rate_bps = |
| 150 expected_streams[top_layer].config.minBitrate * 1000; |
| 151 } |
| 152 } |
| 153 } |
| 154 |
| 155 VideoCodec codec_; |
| 156 std::unique_ptr<SimulcastState> simulcast_state_; |
| 157 }; |
| 158 |
| 159 TEST_F(SimulcastStateTest, NoSimulcast) { |
| 160 simulcast_state_.reset(new SimulcastState(codec_)); |
| 161 |
| 162 SimulcastState::Stream expected_stream(0, &codec_, |
| 163 codec_.startBitrate * 1000); |
| 164 std::vector<SimulcastState::Stream> expected_streams; |
| 165 expected_streams.push_back(expected_stream); |
| 166 |
| 167 ExpectState(expected_streams); |
| 168 |
| 169 for (uint32_t i = 0; i < codec_.maxBitrate + 1; ++i) { |
| 170 simulcast_state_->AllocateBitrate(i * 1000); |
| 171 if (i < codec_.minBitrate) { |
| 172 expected_streams[0].allocated_rate_bps = codec_.minBitrate * 1000; |
| 173 } else if (i > codec_.maxBitrate) { |
| 174 expected_streams[0].allocated_rate_bps = codec_.maxBitrate * 1000; |
| 175 } else { |
| 176 expected_streams[0].allocated_rate_bps = i * 1000; |
| 177 } |
| 178 ExpectState(expected_streams); |
| 179 } |
| 180 } |
| 181 |
| 182 TEST_F(SimulcastStateTest, MultipleStreamsRates) { |
| 183 for (int num_streams = 1; num_streams < kMaxStreams; ++num_streams) { |
| 184 codec_.numberOfSimulcastStreams = num_streams; |
| 185 codec_.startBitrate = 0; |
| 186 |
| 187 for (int i = 0; i < num_streams; ++i) { |
| 188 codec_.simulcastStream[i].minBitrate = |
| 189 ((i + 1) * codec_.minBitrate) / kMaxStreams; |
| 190 codec_.simulcastStream[i].targetBitrate = |
| 191 ((i + 1) * codec_.targetBitrate) / kMaxStreams; |
| 192 codec_.simulcastStream[i].maxBitrate = |
| 193 ((i + 1) * codec_.maxBitrate) / kMaxStreams; |
| 194 } |
| 195 |
| 196 TestRateAllocation(); |
| 197 } |
| 198 } |
| 199 |
| 200 TEST_F(SimulcastStateTest, NextMinLargerThanMax) { |
| 201 codec_.startBitrate = 0; |
| 202 codec_.numberOfSimulcastStreams = 2; |
| 203 codec_.simulcastStream[0].minBitrate = 10; |
| 204 codec_.simulcastStream[0].targetBitrate = 100; |
| 205 codec_.simulcastStream[0].maxBitrate = 200; |
| 206 codec_.simulcastStream[1].minBitrate = 300; |
| 207 codec_.simulcastStream[1].targetBitrate = 400; |
| 208 codec_.simulcastStream[1].maxBitrate = 500; |
| 209 |
| 210 TestRateAllocation(); |
| 211 } |
| 212 |
| 213 TEST_F(SimulcastStateTest, LargerMinButLowerMax) { |
| 214 codec_.startBitrate = 0; |
| 215 codec_.numberOfSimulcastStreams = 3; |
| 216 codec_.simulcastStream[0].minBitrate = 100; |
| 217 codec_.simulcastStream[0].targetBitrate = 200; |
| 218 codec_.simulcastStream[0].maxBitrate = 600; |
| 219 codec_.simulcastStream[1].minBitrate = 200; |
| 220 codec_.simulcastStream[1].targetBitrate = 300; |
| 221 codec_.simulcastStream[1].maxBitrate = 400; |
| 222 codec_.simulcastStream[2].minBitrate = 300; |
| 223 codec_.simulcastStream[2].targetBitrate = 600; |
| 224 codec_.simulcastStream[2].maxBitrate = 800; |
| 225 |
| 226 TestRateAllocation(); |
| 227 } |
| 228 |
| 229 TEST_F(SimulcastStateTest, SetsSendingAndKeyframeStates) { |
| 230 codec_.startBitrate = 0; |
| 231 codec_.numberOfSimulcastStreams = 3; |
| 232 |
| 233 codec_.simulcastStream[0].minBitrate = 100; |
| 234 codec_.simulcastStream[0].targetBitrate = 200; |
| 235 codec_.simulcastStream[0].maxBitrate = 600; |
| 236 const int kFirstCutoff = codec_.simulcastStream[0].minBitrate * 1000; |
| 237 |
| 238 codec_.simulcastStream[1].minBitrate = 300; |
| 239 codec_.simulcastStream[1].targetBitrate = 600; |
| 240 codec_.simulcastStream[1].maxBitrate = 1200; |
| 241 const int kSecondCutoff = (codec_.simulcastStream[0].targetBitrate + |
| 242 codec_.simulcastStream[1].minBitrate) * |
| 243 1000; |
| 244 |
| 245 codec_.simulcastStream[2].minBitrate = 500; |
| 246 codec_.simulcastStream[2].targetBitrate = 800; |
| 247 codec_.simulcastStream[2].maxBitrate = 1500; |
| 248 const int kThirdCutoff = (codec_.simulcastStream[0].targetBitrate + |
| 249 codec_.simulcastStream[1].targetBitrate + |
| 250 codec_.simulcastStream[2].minBitrate) * |
| 251 1000; |
| 252 |
| 253 simulcast_state_.reset(new SimulcastState(codec_)); |
| 254 |
| 255 simulcast_state_->AllocateBitrate(kFirstCutoff); |
| 256 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 257 EXPECT_TRUE(simulcast_state_->IsSending(0)); |
| 258 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(1)); |
| 259 EXPECT_FALSE(simulcast_state_->IsSending(1)); |
| 260 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(2)); |
| 261 EXPECT_FALSE(simulcast_state_->IsSending(2)); |
| 262 |
| 263 simulcast_state_->AllocateBitrate(kSecondCutoff); |
| 264 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 265 EXPECT_TRUE(simulcast_state_->IsSending(0)); |
| 266 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(1)); |
| 267 EXPECT_TRUE(simulcast_state_->IsSending(1)); |
| 268 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(2)); |
| 269 EXPECT_FALSE(simulcast_state_->IsSending(2)); |
| 270 |
| 271 simulcast_state_->AllocateBitrate(kThirdCutoff); |
| 272 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 273 EXPECT_TRUE(simulcast_state_->IsSending(0)); |
| 274 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(1)); |
| 275 EXPECT_TRUE(simulcast_state_->IsSending(1)); |
| 276 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(2)); |
| 277 EXPECT_TRUE(simulcast_state_->IsSending(2)); |
| 278 |
| 279 simulcast_state_->AllocateBitrate(kSecondCutoff); |
| 280 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 281 EXPECT_TRUE(simulcast_state_->IsSending(0)); |
| 282 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(1)); |
| 283 EXPECT_TRUE(simulcast_state_->IsSending(1)); |
| 284 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(2)); |
| 285 EXPECT_FALSE(simulcast_state_->IsSending(2)); |
| 286 |
| 287 simulcast_state_->AllocateBitrate(kFirstCutoff); |
| 288 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 289 EXPECT_TRUE(simulcast_state_->IsSending(0)); |
| 290 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(1)); |
| 291 EXPECT_FALSE(simulcast_state_->IsSending(1)); |
| 292 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(2)); |
| 293 EXPECT_FALSE(simulcast_state_->IsSending(2)); |
| 294 |
| 295 simulcast_state_->AllocateBitrate(kThirdCutoff); |
| 296 EXPECT_FALSE(simulcast_state_->GetAndResetKeyFrameRequest(0)); |
| 297 EXPECT_TRUE(simulcast_state_->IsSending(0)); |
| 298 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(1)); |
| 299 EXPECT_TRUE(simulcast_state_->IsSending(1)); |
| 300 EXPECT_TRUE(simulcast_state_->GetAndResetKeyFrameRequest(2)); |
| 301 EXPECT_TRUE(simulcast_state_->IsSending(2)); |
| 302 } |
| 303 |
| 304 } // namespace webrtc |
OLD | NEW |