1 /* 2 * Copyright (c) 2013 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 "testing/gmock/include/gmock/gmock.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 #include "webrtc/system_wrappers/interface/clock.h" 15 #include "webrtc/system_wrappers/interface/scoped_ptr.h" 16 #include "webrtc/video_engine/include/vie_base.h" 17 #include "webrtc/video_engine/overuse_frame_detector.h" 18 19 namespace webrtc { 20 namespace { 21 const int kWidth = 640; 22 const int kHeight = 480; 23 const int kFrameInterval33ms = 33; 24 const int kProcessIntervalMs = 5000; 25 } // namespace 26 27 class MockCpuOveruseObserver : public CpuOveruseObserver { 28 public: 29 MockCpuOveruseObserver() {} 30 virtual ~MockCpuOveruseObserver() {} 31 32 MOCK_METHOD0(OveruseDetected, void()); 33 MOCK_METHOD0(NormalUsage, void()); 34 }; 35 36 class CpuOveruseObserverImpl : public CpuOveruseObserver { 37 public: 38 CpuOveruseObserverImpl() : 39 overuse_(0), 40 normaluse_(0) {} 41 virtual ~CpuOveruseObserverImpl() {} 42 43 void OveruseDetected() { ++overuse_; } 44 void NormalUsage() { ++normaluse_; } 45 46 int overuse_; 47 int normaluse_; 48 }; 49 50 class OveruseFrameDetectorTest : public ::testing::Test { 51 protected: 52 virtual void SetUp() { 53 clock_.reset(new SimulatedClock(1234)); 54 observer_.reset(new MockCpuOveruseObserver()); 55 overuse_detector_.reset(new OveruseFrameDetector(clock_.get())); 56 57 options_.low_capture_jitter_threshold_ms = 10.0f; 58 options_.high_capture_jitter_threshold_ms = 15.0f; 59 options_.min_process_count = 0; 60 overuse_detector_->SetOptions(options_); 61 overuse_detector_->SetObserver(observer_.get()); 62 } 63 64 int InitialJitter() { 65 return ((options_.low_capture_jitter_threshold_ms + 66 options_.high_capture_jitter_threshold_ms) / 2.0f) + 0.5; 67 } 68 69 int InitialEncodeUsage() { 70 return ((options_.low_encode_usage_threshold_percent + 71 options_.high_encode_usage_threshold_percent) / 2.0f) + 0.5; 72 } 73 74 int InitialEncodeRsd() { 75 return std::max( 76 ((options_.low_encode_time_rsd_threshold + 77 options_.high_encode_time_rsd_threshold) / 2.0f) + 0.5f, 0.0f); 78 } 79 80 void InsertFramesWithInterval( 81 size_t num_frames, int interval_ms, int width, int height) { 82 while (num_frames-- > 0) { 83 clock_->AdvanceTimeMilliseconds(interval_ms); 84 overuse_detector_->FrameCaptured(width, height); 85 } 86 } 87 88 void InsertAndEncodeFramesWithInterval( 89 int num_frames, int interval_ms, int width, int height, int encode_ms) { 90 while (num_frames-- > 0) { 91 overuse_detector_->FrameCaptured(width, height); 92 clock_->AdvanceTimeMilliseconds(encode_ms); 93 overuse_detector_->FrameEncoded(encode_ms); 94 clock_->AdvanceTimeMilliseconds(interval_ms - encode_ms); 95 } 96 } 97 98 void TriggerOveruse(int num_times) { 99 for (int i = 0; i < num_times; ++i) { 100 InsertFramesWithInterval(200, kFrameInterval33ms, kWidth, kHeight); 101 InsertFramesWithInterval(50, 110, kWidth, kHeight); 102 overuse_detector_->Process(); 103 } 104 } 105 106 void TriggerNormalUsage() { 107 InsertFramesWithInterval(900, kFrameInterval33ms, kWidth, kHeight); 108 overuse_detector_->Process(); 109 } 110 111 void TriggerOveruseWithEncodeUsage(int num_times) { 112 const int kEncodeTimeMs = 32; 113 for (int i = 0; i < num_times; ++i) { 114 InsertAndEncodeFramesWithInterval( 115 1000, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs); 116 overuse_detector_->Process(); 117 } 118 } 119 120 void TriggerOveruseWithEncodeRsd(int num_times) { 121 const int kEncodeTimeMs1 = 10; 122 const int kEncodeTimeMs2 = 25; 123 for (int i = 0; i < num_times; ++i) { 124 InsertAndEncodeFramesWithInterval( 125 200, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs1); 126 InsertAndEncodeFramesWithInterval( 127 10, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs2); 128 overuse_detector_->Process(); 129 } 130 } 131 132 void TriggerNormalUsageWithEncodeTime() { 133 const int kEncodeTimeMs1 = 5; 134 const int kEncodeTimeMs2 = 6; 135 InsertAndEncodeFramesWithInterval( 136 1300, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs1); 137 InsertAndEncodeFramesWithInterval( 138 1, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs2); 139 overuse_detector_->Process(); 140 } 141 142 int CaptureJitterMs() { 143 CpuOveruseMetrics metrics; 144 overuse_detector_->GetCpuOveruseMetrics(&metrics); 145 return metrics.capture_jitter_ms; 146 } 147 148 int AvgEncodeTimeMs() { 149 CpuOveruseMetrics metrics; 150 overuse_detector_->GetCpuOveruseMetrics(&metrics); 151 return metrics.avg_encode_time_ms; 152 } 153 154 int EncodeUsagePercent() { 155 CpuOveruseMetrics metrics; 156 overuse_detector_->GetCpuOveruseMetrics(&metrics); 157 return metrics.encode_usage_percent; 158 } 159 160 int EncodeRsd() { 161 CpuOveruseMetrics metrics; 162 overuse_detector_->GetCpuOveruseMetrics(&metrics); 163 return metrics.encode_rsd; 164 } 165 166 CpuOveruseOptions options_; 167 scoped_ptr<SimulatedClock> clock_; 168 scoped_ptr<MockCpuOveruseObserver> observer_; 169 scoped_ptr<OveruseFrameDetector> overuse_detector_; 170 }; 171 172 // enable_capture_jitter_method = true; 173 // CaptureJitterMs() > high_capture_jitter_threshold_ms => overuse. 174 // CaptureJitterMs() < low_capture_jitter_threshold_ms => underuse. 175 TEST_F(OveruseFrameDetectorTest, TriggerOveruse) { 176 // capture_jitter > high => overuse 177 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 178 TriggerOveruse(options_.high_threshold_consecutive_count); 179 } 180 181 TEST_F(OveruseFrameDetectorTest, OveruseAndRecover) { 182 // capture_jitter > high => overuse 183 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 184 TriggerOveruse(options_.high_threshold_consecutive_count); 185 // capture_jitter < low => underuse 186 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 187 TriggerNormalUsage(); 188 } 189 190 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithNoObserver) { 191 overuse_detector_->SetObserver(NULL); 192 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); 193 TriggerOveruse(options_.high_threshold_consecutive_count); 194 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 195 TriggerNormalUsage(); 196 } 197 198 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithMethodDisabled) { 199 options_.enable_capture_jitter_method = false; 200 options_.enable_encode_usage_method = false; 201 overuse_detector_->SetOptions(options_); 202 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); 203 TriggerOveruse(options_.high_threshold_consecutive_count); 204 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 205 TriggerNormalUsage(); 206 } 207 208 TEST_F(OveruseFrameDetectorTest, DoubleOveruseAndRecover) { 209 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(2); 210 TriggerOveruse(options_.high_threshold_consecutive_count); 211 TriggerOveruse(options_.high_threshold_consecutive_count); 212 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 213 TriggerNormalUsage(); 214 } 215 216 TEST_F(OveruseFrameDetectorTest, TriggerNormalUsageWithMinProcessCount) { 217 CpuOveruseObserverImpl overuse_observer_; 218 overuse_detector_->SetObserver(&overuse_observer_); 219 options_.min_process_count = 1; 220 overuse_detector_->SetOptions(options_); 221 InsertFramesWithInterval(1200, kFrameInterval33ms, kWidth, kHeight); 222 overuse_detector_->Process(); 223 EXPECT_EQ(0, overuse_observer_.normaluse_); 224 clock_->AdvanceTimeMilliseconds(kProcessIntervalMs); 225 overuse_detector_->Process(); 226 EXPECT_EQ(1, overuse_observer_.normaluse_); 227 } 228 229 TEST_F(OveruseFrameDetectorTest, ConstantOveruseGivesNoNormalUsage) { 230 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 231 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(64); 232 for(size_t i = 0; i < 64; ++i) { 233 TriggerOveruse(options_.high_threshold_consecutive_count); 234 } 235 } 236 237 TEST_F(OveruseFrameDetectorTest, ConsecutiveCountTriggersOveruse) { 238 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 239 options_.high_threshold_consecutive_count = 2; 240 overuse_detector_->SetOptions(options_); 241 TriggerOveruse(2); 242 } 243 244 TEST_F(OveruseFrameDetectorTest, IncorrectConsecutiveCountTriggersNoOveruse) { 245 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); 246 options_.high_threshold_consecutive_count = 2; 247 overuse_detector_->SetOptions(options_); 248 TriggerOveruse(1); 249 } 250 251 TEST_F(OveruseFrameDetectorTest, GetCpuOveruseMetrics) { 252 CpuOveruseMetrics metrics; 253 overuse_detector_->GetCpuOveruseMetrics(&metrics); 254 EXPECT_GT(metrics.capture_jitter_ms, 0); 255 EXPECT_GT(metrics.avg_encode_time_ms, 0); 256 EXPECT_GT(metrics.encode_usage_percent, 0); 257 EXPECT_GE(metrics.capture_queue_delay_ms_per_s, 0); 258 EXPECT_GE(metrics.encode_rsd, 0); 259 } 260 261 TEST_F(OveruseFrameDetectorTest, CaptureJitter) { 262 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 263 InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight); 264 EXPECT_NE(InitialJitter(), CaptureJitterMs()); 265 } 266 267 TEST_F(OveruseFrameDetectorTest, CaptureJitterResetAfterResolutionChange) { 268 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 269 InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight); 270 EXPECT_NE(InitialJitter(), CaptureJitterMs()); 271 // Verify reset. 272 InsertFramesWithInterval(1, kFrameInterval33ms, kWidth, kHeight + 1); 273 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 274 } 275 276 TEST_F(OveruseFrameDetectorTest, CaptureJitterResetAfterFrameTimeout) { 277 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 278 InsertFramesWithInterval(1000, kFrameInterval33ms, kWidth, kHeight); 279 EXPECT_NE(InitialJitter(), CaptureJitterMs()); 280 InsertFramesWithInterval( 281 1, options_.frame_timeout_interval_ms, kWidth, kHeight); 282 EXPECT_NE(InitialJitter(), CaptureJitterMs()); 283 // Verify reset. 284 InsertFramesWithInterval( 285 1, options_.frame_timeout_interval_ms + 1, kWidth, kHeight); 286 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 287 } 288 289 TEST_F(OveruseFrameDetectorTest, CaptureJitterResetAfterChangingThreshold) { 290 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 291 options_.high_capture_jitter_threshold_ms = 90.0f; 292 overuse_detector_->SetOptions(options_); 293 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 294 options_.low_capture_jitter_threshold_ms = 30.0f; 295 overuse_detector_->SetOptions(options_); 296 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 297 } 298 299 TEST_F(OveruseFrameDetectorTest, MinFrameSamplesBeforeUpdatingCaptureJitter) { 300 options_.min_frame_samples = 40; 301 overuse_detector_->SetOptions(options_); 302 InsertFramesWithInterval(40, kFrameInterval33ms, kWidth, kHeight); 303 EXPECT_EQ(InitialJitter(), CaptureJitterMs()); 304 } 305 306 TEST_F(OveruseFrameDetectorTest, NoCaptureQueueDelay) { 307 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 0); 308 overuse_detector_->FrameCaptured(kWidth, kHeight); 309 overuse_detector_->FrameProcessingStarted(); 310 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 0); 311 } 312 313 TEST_F(OveruseFrameDetectorTest, CaptureQueueDelay) { 314 overuse_detector_->FrameCaptured(kWidth, kHeight); 315 clock_->AdvanceTimeMilliseconds(100); 316 overuse_detector_->FrameProcessingStarted(); 317 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 100); 318 } 319 320 TEST_F(OveruseFrameDetectorTest, CaptureQueueDelayMultipleFrames) { 321 overuse_detector_->FrameCaptured(kWidth, kHeight); 322 clock_->AdvanceTimeMilliseconds(10); 323 overuse_detector_->FrameCaptured(kWidth, kHeight); 324 clock_->AdvanceTimeMilliseconds(20); 325 326 overuse_detector_->FrameProcessingStarted(); 327 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 30); 328 overuse_detector_->FrameProcessingStarted(); 329 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 20); 330 } 331 332 TEST_F(OveruseFrameDetectorTest, CaptureQueueDelayResetAtResolutionSwitch) { 333 overuse_detector_->FrameCaptured(kWidth, kHeight); 334 clock_->AdvanceTimeMilliseconds(10); 335 overuse_detector_->FrameCaptured(kWidth, kHeight + 1); 336 clock_->AdvanceTimeMilliseconds(20); 337 338 overuse_detector_->FrameProcessingStarted(); 339 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 20); 340 } 341 342 TEST_F(OveruseFrameDetectorTest, CaptureQueueDelayNoMatchingCapturedFrame) { 343 overuse_detector_->FrameCaptured(kWidth, kHeight); 344 clock_->AdvanceTimeMilliseconds(100); 345 overuse_detector_->FrameProcessingStarted(); 346 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 100); 347 // No new captured frame. The last delay should be reported. 348 overuse_detector_->FrameProcessingStarted(); 349 EXPECT_EQ(overuse_detector_->CaptureQueueDelayMsPerS(), 100); 350 } 351 352 TEST_F(OveruseFrameDetectorTest, EncodedFrame) { 353 const int kInitialAvgEncodeTimeInMs = 5; 354 EXPECT_EQ(kInitialAvgEncodeTimeInMs, AvgEncodeTimeMs()); 355 for (int i = 0; i < 30; i++) { 356 clock_->AdvanceTimeMilliseconds(33); 357 overuse_detector_->FrameEncoded(2); 358 } 359 EXPECT_EQ(2, AvgEncodeTimeMs()); 360 } 361 362 TEST_F(OveruseFrameDetectorTest, InitialEncodeUsage) { 363 EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent()); 364 } 365 366 TEST_F(OveruseFrameDetectorTest, EncodedUsage) { 367 const int kEncodeTimeMs = 5; 368 InsertAndEncodeFramesWithInterval( 369 1000, kFrameInterval33ms, kWidth, kHeight, kEncodeTimeMs); 370 EXPECT_EQ(kEncodeTimeMs * 100 / kFrameInterval33ms, EncodeUsagePercent()); 371 } 372 373 TEST_F(OveruseFrameDetectorTest, EncodeUsageResetAfterChangingThreshold) { 374 EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent()); 375 options_.high_encode_usage_threshold_percent = 100; 376 overuse_detector_->SetOptions(options_); 377 EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent()); 378 options_.low_encode_usage_threshold_percent = 20; 379 overuse_detector_->SetOptions(options_); 380 EXPECT_EQ(InitialEncodeUsage(), EncodeUsagePercent()); 381 } 382 383 // enable_encode_usage_method = true; 384 // EncodeUsagePercent() > high_encode_usage_threshold_percent => overuse. 385 // EncodeUsagePercent() < low_encode_usage_threshold_percent => underuse. 386 TEST_F(OveruseFrameDetectorTest, TriggerOveruseWithEncodeUsage) { 387 options_.enable_capture_jitter_method = false; 388 options_.enable_encode_usage_method = true; 389 overuse_detector_->SetOptions(options_); 390 // usage > high => overuse 391 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 392 TriggerOveruseWithEncodeUsage(options_.high_threshold_consecutive_count); 393 } 394 395 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithEncodeUsage) { 396 options_.enable_capture_jitter_method = false; 397 options_.enable_encode_usage_method = true; 398 overuse_detector_->SetOptions(options_); 399 // usage > high => overuse 400 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 401 TriggerOveruseWithEncodeUsage(options_.high_threshold_consecutive_count); 402 // usage < low => underuse 403 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 404 TriggerNormalUsageWithEncodeTime(); 405 } 406 407 TEST_F(OveruseFrameDetectorTest, 408 OveruseAndRecoverWithEncodeUsageMethodDisabled) { 409 options_.enable_capture_jitter_method = false; 410 options_.enable_encode_usage_method = false; 411 overuse_detector_->SetOptions(options_); 412 // usage > high => overuse 413 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(0); 414 TriggerOveruseWithEncodeUsage(options_.high_threshold_consecutive_count); 415 // usage < low => underuse 416 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 417 TriggerNormalUsageWithEncodeTime(); 418 } 419 420 TEST_F(OveruseFrameDetectorTest, EncodeRsdResetAfterChangingThreshold) { 421 EXPECT_EQ(InitialEncodeRsd(), EncodeRsd()); 422 options_.high_encode_time_rsd_threshold = 100; 423 overuse_detector_->SetOptions(options_); 424 EXPECT_EQ(InitialEncodeRsd(), EncodeRsd()); 425 options_.low_encode_time_rsd_threshold = 20; 426 overuse_detector_->SetOptions(options_); 427 EXPECT_EQ(InitialEncodeRsd(), EncodeRsd()); 428 } 429 430 // enable_encode_usage_method = true; 431 // low/high_encode_time_rsd_threshold >= 0 432 // EncodeUsagePercent() > high_encode_usage_threshold_percent || 433 // EncodeRsd() > high_encode_time_rsd_threshold => overuse. 434 // EncodeUsagePercent() < low_encode_usage_threshold_percent && 435 // EncodeRsd() < low_encode_time_rsd_threshold => underuse. 436 TEST_F(OveruseFrameDetectorTest, TriggerOveruseWithEncodeRsd) { 437 options_.enable_capture_jitter_method = false; 438 options_.enable_encode_usage_method = true; 439 options_.high_encode_time_rsd_threshold = 80; 440 overuse_detector_->SetOptions(options_); 441 // rsd > high, usage < high => overuse 442 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 443 TriggerOveruseWithEncodeRsd(options_.high_threshold_consecutive_count); 444 EXPECT_LT(EncodeUsagePercent(), options_.high_encode_usage_threshold_percent); 445 } 446 447 TEST_F(OveruseFrameDetectorTest, OveruseAndRecoverWithEncodeRsd) { 448 options_.enable_capture_jitter_method = false; 449 options_.enable_encode_usage_method = true; 450 options_.low_encode_time_rsd_threshold = 25; 451 options_.high_encode_time_rsd_threshold = 80; 452 overuse_detector_->SetOptions(options_); 453 // rsd > high, usage < high => overuse 454 EXPECT_CALL(*(observer_.get()), OveruseDetected()).Times(1); 455 TriggerOveruseWithEncodeRsd(options_.high_threshold_consecutive_count); 456 EXPECT_LT(EncodeUsagePercent(), options_.high_encode_usage_threshold_percent); 457 // rsd < low, usage < low => underuse 458 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(testing::AtLeast(1)); 459 TriggerNormalUsageWithEncodeTime(); 460 } 461 462 TEST_F(OveruseFrameDetectorTest, NoUnderuseWithEncodeRsd_UsageGtLowThreshold) { 463 options_.enable_capture_jitter_method = false; 464 options_.enable_encode_usage_method = true; 465 options_.low_encode_usage_threshold_percent = 1; 466 options_.low_encode_time_rsd_threshold = 25; 467 options_.high_encode_time_rsd_threshold = 90; 468 overuse_detector_->SetOptions(options_); 469 // rsd < low, usage > low => no underuse 470 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 471 TriggerNormalUsageWithEncodeTime(); 472 EXPECT_LT(EncodeRsd(), options_.low_encode_time_rsd_threshold); 473 EXPECT_GT(EncodeUsagePercent(), options_.low_encode_usage_threshold_percent); 474 } 475 476 TEST_F(OveruseFrameDetectorTest, NoUnderuseWithEncodeRsd_RsdGtLowThreshold) { 477 options_.enable_capture_jitter_method = false; 478 options_.enable_encode_usage_method = true; 479 options_.low_encode_usage_threshold_percent = 20; 480 options_.low_encode_time_rsd_threshold = 1; 481 options_.high_encode_time_rsd_threshold = 90; 482 overuse_detector_->SetOptions(options_); 483 // rsd > low, usage < low => no underuse 484 EXPECT_CALL(*(observer_.get()), NormalUsage()).Times(0); 485 TriggerNormalUsageWithEncodeTime(); 486 EXPECT_GT(EncodeRsd(), options_.low_encode_time_rsd_threshold); 487 EXPECT_LT(EncodeUsagePercent(), options_.low_encode_usage_threshold_percent); 488 } 489 } // namespace webrtc 490