Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: webrtc/modules/video_coding/utility/quality_scaler_unittest.cc

Issue 1880103002: Revert of Make QualityScaler more responsive to downgrades. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/video_coding/utility/quality_scaler.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/video_coding/utility/quality_scaler.h" 11 #include "webrtc/modules/video_coding/utility/quality_scaler.h"
12 12
13 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
14 14
15 namespace webrtc { 15 namespace webrtc {
16 namespace { 16 namespace {
17 static const int kNumSeconds = 10; 17 static const int kNumSeconds = 10;
18 static const int kWidth = 1920; 18 static const int kWidth = 1920;
19 static const int kWidthVga = 640; 19 static const int kWidthVga = 640;
20 static const int kHalfWidth = kWidth / 2; 20 static const int kHalfWidth = kWidth / 2;
21 static const int kHeight = 1080; 21 static const int kHeight = 1080;
22 static const int kHeightVga = 480; 22 static const int kHeightVga = 480;
23 static const int kFramerate = 30; 23 static const int kFramerate = 30;
24 static const int kLowQp = 15; 24 static const int kLowQp = 15;
25 static const int kNormalQp = 30; 25 static const int kNormalQp = 30;
26 static const int kHighQp = 40; 26 static const int kHighQp = 40;
27 static const int kMaxQp = 56; 27 static const int kMaxQp = 56;
28 static const int kDisabledBadQpThreshold = kMaxQp + 1; 28 static const int kDisabledBadQpThreshold = kMaxQp + 1;
29 static const int kLowInitialBitrateKbps = 300; 29 static const int kLowInitialBitrateKbps = 300;
30 // These values need to be in sync with corresponding constants
31 // in quality_scaler.cc
32 static const int kMeasureSecondsDownscale = 3;
33 static const int kMeasureSecondsFastUpscale = 2;
34 static const int kMeasureSecondsUpscale = 5;
35 } // namespace 30 } // namespace
36 31
37 class QualityScalerTest : public ::testing::Test { 32 class QualityScalerTest : public ::testing::Test {
38 public: 33 public:
39 // Temporal and spatial resolution. 34 // Temporal and spatial resolution.
40 struct Resolution { 35 struct Resolution {
41 int framerate; 36 int framerate;
42 int width; 37 int width;
43 int height; 38 int height;
44 }; 39 };
45 40
46 protected: 41 protected:
47 enum ScaleDirection { 42 enum ScaleDirection {
48 kKeepScaleAtHighQp, 43 kKeepScaleAtHighQp,
49 kScaleDown, 44 kScaleDown,
50 kScaleDownAboveHighQp, 45 kScaleDownAboveHighQp,
51 kScaleUp 46 kScaleUp
52 }; 47 };
53 enum BadQualityMetric { kDropFrame, kReportLowQP }; 48 enum BadQualityMetric { kDropFrame, kReportLowQP };
54 49
55 QualityScalerTest() { 50 QualityScalerTest() {
56 input_frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, kHalfWidth, 51 input_frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, kHalfWidth,
57 kHalfWidth); 52 kHalfWidth);
58 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, kHighQp, false, 53 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, kHighQp, false,
59 0, 0, 0, kFramerate); 54 0, 0, 0);
55 qs_.ReportFramerate(kFramerate);
60 qs_.OnEncodeFrame(input_frame_); 56 qs_.OnEncodeFrame(input_frame_);
61 } 57 }
62 58
63 bool TriggerScale(ScaleDirection scale_direction) { 59 bool TriggerScale(ScaleDirection scale_direction) {
64 qs_.OnEncodeFrame(input_frame_); 60 qs_.OnEncodeFrame(input_frame_);
65 int initial_width = qs_.GetScaledResolution().width; 61 int initial_width = qs_.GetScaledResolution().width;
66 for (int i = 0; i < kFramerate * kNumSeconds; ++i) { 62 for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
67 switch (scale_direction) { 63 switch (scale_direction) {
68 case kScaleUp: 64 case kScaleUp:
69 qs_.ReportQP(kLowQp); 65 qs_.ReportQP(kLowQp);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 97
102 void ContinuouslyDownscalesByHalfDimensionsAndBackUp(); 98 void ContinuouslyDownscalesByHalfDimensionsAndBackUp();
103 99
104 void DoesNotDownscaleFrameDimensions(int width, int height); 100 void DoesNotDownscaleFrameDimensions(int width, int height);
105 101
106 Resolution TriggerResolutionChange(BadQualityMetric dropframe_lowqp, 102 Resolution TriggerResolutionChange(BadQualityMetric dropframe_lowqp,
107 int num_second, 103 int num_second,
108 int initial_framerate); 104 int initial_framerate);
109 105
110 void VerifyQualityAdaptation(int initial_framerate, 106 void VerifyQualityAdaptation(int initial_framerate,
111 int seconds_downscale, 107 int seconds,
112 int seconds_upscale,
113 bool expect_spatial_resize, 108 bool expect_spatial_resize,
114 bool expect_framerate_reduction); 109 bool expect_framerate_reduction);
115 110
116 void DownscaleEndsAt(int input_width, 111 void DownscaleEndsAt(int input_width,
117 int input_height, 112 int input_height,
118 int end_width, 113 int end_width,
119 int end_height); 114 int end_height);
120 115
121 QualityScaler qs_; 116 QualityScaler qs_;
122 VideoFrame input_frame_; 117 VideoFrame input_frame_;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 if (res.framerate != -1) 291 if (res.framerate != -1)
297 qs_.ReportFramerate(res.framerate); 292 qs_.ReportFramerate(res.framerate);
298 res.width = qs_.GetScaledResolution().width; 293 res.width = qs_.GetScaledResolution().width;
299 res.height = qs_.GetScaledResolution().height; 294 res.height = qs_.GetScaledResolution().height;
300 } 295 }
301 return res; 296 return res;
302 } 297 }
303 298
304 void QualityScalerTest::VerifyQualityAdaptation( 299 void QualityScalerTest::VerifyQualityAdaptation(
305 int initial_framerate, 300 int initial_framerate,
306 int seconds_downscale, 301 int seconds,
307 int seconds_upscale,
308 bool expect_spatial_resize, 302 bool expect_spatial_resize,
309 bool expect_framerate_reduction) { 303 bool expect_framerate_reduction) {
310 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, 304 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator,
311 kDisabledBadQpThreshold, true, 0, 0, 0, initial_framerate); 305 kDisabledBadQpThreshold, true, 0, 0, 0);
312 qs_.OnEncodeFrame(input_frame_); 306 qs_.OnEncodeFrame(input_frame_);
313 int init_width = qs_.GetScaledResolution().width; 307 int init_width = qs_.GetScaledResolution().width;
314 int init_height = qs_.GetScaledResolution().height; 308 int init_height = qs_.GetScaledResolution().height;
315 309
316 // Test reducing framerate by dropping frame continuously. 310 // Test reducing framerate by dropping frame continuously.
317 QualityScalerTest::Resolution res = 311 QualityScalerTest::Resolution res =
318 TriggerResolutionChange(kDropFrame, seconds_downscale, initial_framerate); 312 TriggerResolutionChange(kDropFrame, seconds, initial_framerate);
319 313
320 if (expect_framerate_reduction) { 314 if (expect_framerate_reduction) {
321 EXPECT_LT(res.framerate, initial_framerate); 315 EXPECT_LT(res.framerate, initial_framerate);
322 } else { 316 } else {
323 // No framerate reduction, video decimator should be disabled. 317 // No framerate reduction, video decimator should be disabled.
324 EXPECT_EQ(-1, res.framerate); 318 EXPECT_EQ(-1, res.framerate);
325 } 319 }
326 320
327 if (expect_spatial_resize) { 321 if (expect_spatial_resize) {
328 EXPECT_LT(res.width, init_width); 322 EXPECT_LT(res.width, init_width);
329 EXPECT_LT(res.height, init_height); 323 EXPECT_LT(res.height, init_height);
330 } else { 324 } else {
331 EXPECT_EQ(init_width, res.width); 325 EXPECT_EQ(init_width, res.width);
332 EXPECT_EQ(init_height, res.height); 326 EXPECT_EQ(init_height, res.height);
333 } 327 }
334 328
335 // The "seconds * 1.5" is to ensure spatial resolution to recover. 329 // The "seconds * 1.5" is to ensure spatial resolution to recover.
336 // For example, in 6 seconds test, framerate reduction happens in the first 330 // For example, in 10 seconds test, framerate reduction happens in the first
337 // 3 seconds from 30fps to 15fps and causes the buffer size to be half of the 331 // 5 seconds from 30fps to 15fps and causes the buffer size to be half of the
338 // original one. Then it will take only 45 samples to downscale (twice in 90 332 // original one. Then it will take only 75 samples to downscale (twice in 150
339 // samples). So to recover the resolution changes, we need more than 10 333 // samples). So to recover the resolution changes, we need more than 10
340 // seconds (i.e, seconds_upscale * 1.5). This is because the framerate 334 // seconds (i.e, seconds * 1.5). This is because the framerate increases
341 // increases before spatial size recovers, so it will take 150 samples to 335 // before spatial size recovers, so it will take 150 samples to recover
342 // recover spatial size (300 for twice). 336 // spatial size (300 for twice).
343 res = TriggerResolutionChange(kReportLowQP, seconds_upscale * 1.5, 337 res = TriggerResolutionChange(kReportLowQP, seconds * 1.5, initial_framerate);
344 initial_framerate);
345 EXPECT_EQ(-1, res.framerate); 338 EXPECT_EQ(-1, res.framerate);
346 EXPECT_EQ(init_width, res.width); 339 EXPECT_EQ(init_width, res.width);
347 EXPECT_EQ(init_height, res.height); 340 EXPECT_EQ(init_height, res.height);
348 } 341 }
349 342
350 // In 3 seconds test, only framerate adjusting should happen and 5 second 343 // In 5 seconds test, only framerate adjusting should happen.
351 // upscaling duration, only a framerate adjusting should happen.
352 TEST_F(QualityScalerTest, ChangeFramerateOnly) { 344 TEST_F(QualityScalerTest, ChangeFramerateOnly) {
353 VerifyQualityAdaptation(kFramerate, kMeasureSecondsDownscale, 345 VerifyQualityAdaptation(kFramerate, 5, false, true);
354 kMeasureSecondsUpscale, false, true);
355 } 346 }
356 347
357 // In 6 seconds test, framerate adjusting and scaling are both 348 // In 10 seconds test, framerate adjusting and scaling are both
358 // triggered, it shows that scaling would happen after framerate 349 // triggered, it shows that scaling would happen after framerate
359 // adjusting. 350 // adjusting.
360 TEST_F(QualityScalerTest, ChangeFramerateAndSpatialSize) { 351 TEST_F(QualityScalerTest, ChangeFramerateAndSpatialSize) {
361 VerifyQualityAdaptation(kFramerate, kMeasureSecondsDownscale * 2, 352 VerifyQualityAdaptation(kFramerate, 10, true, true);
362 kMeasureSecondsUpscale * 2, true, true);
363 } 353 }
364 354
365 // When starting from a low framerate, only spatial size will be changed. 355 // When starting from a low framerate, only spatial size will be changed.
366 TEST_F(QualityScalerTest, ChangeSpatialSizeOnly) { 356 TEST_F(QualityScalerTest, ChangeSpatialSizeOnly) {
367 qs_.ReportFramerate(kFramerate >> 1); 357 qs_.ReportFramerate(kFramerate >> 1);
368 VerifyQualityAdaptation(kFramerate >> 1, kMeasureSecondsDownscale * 2, 358 VerifyQualityAdaptation(kFramerate >> 1, 10, true, false);
369 kMeasureSecondsUpscale * 2, true, false);
370 } 359 }
371 360
372 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) { 361 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) {
373 DoesNotDownscaleFrameDimensions( 362 DoesNotDownscaleFrameDimensions(
374 2 * QualityScaler::kDefaultMinDownscaleDimension - 1, 1000); 363 2 * QualityScaler::kDefaultMinDownscaleDimension - 1, 1000);
375 } 364 }
376 365
377 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) { 366 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) {
378 DoesNotDownscaleFrameDimensions( 367 DoesNotDownscaleFrameDimensions(
379 1000, 2 * QualityScaler::kDefaultMinDownscaleDimension - 1); 368 1000, 2 * QualityScaler::kDefaultMinDownscaleDimension - 1);
380 } 369 }
381 370
382 TEST_F(QualityScalerTest, DownscaleToVgaOnLowInitialBitrate) { 371 TEST_F(QualityScalerTest, DownscaleToVgaOnLowInitialBitrate) {
383 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, 372 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator,
384 kDisabledBadQpThreshold, true, 373 kDisabledBadQpThreshold, true,
385 kLowInitialBitrateKbps, kWidth, kHeight, kFramerate); 374 kLowInitialBitrateKbps, kWidth, kHeight);
386 qs_.OnEncodeFrame(input_frame_); 375 qs_.OnEncodeFrame(input_frame_);
387 int init_width = qs_.GetScaledResolution().width; 376 int init_width = qs_.GetScaledResolution().width;
388 int init_height = qs_.GetScaledResolution().height; 377 int init_height = qs_.GetScaledResolution().height;
389 EXPECT_LE(init_width, kWidthVga); 378 EXPECT_LE(init_width, kWidthVga);
390 EXPECT_LE(init_height, kHeightVga); 379 EXPECT_LE(init_height, kHeightVga);
391 } 380 }
392 381
393 TEST_F(QualityScalerTest, DownscaleAfterMeasuredSecondsThenSlowerBackUp) {
394 QualityScalerTest::Resolution initial_res;
395 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, kHighQp, false, 0,
396 kWidth, kHeight, kFramerate);
397 qs_.OnEncodeFrame(input_frame_);
398 initial_res.width = qs_.GetScaledResolution().width;
399 initial_res.height = qs_.GetScaledResolution().height;
400
401 // Should not downscale if less than kMeasureSecondsDownscale seconds passed.
402 for (int i = 0; i < kFramerate * kMeasureSecondsDownscale - 1; ++i) {
403 qs_.ReportQP(kHighQp + 1);
404 qs_.OnEncodeFrame(input_frame_);
405 }
406 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
407 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
408
409 // Should downscale if more than kMeasureSecondsDownscale seconds passed (add
410 // last frame).
411 qs_.ReportQP(kHighQp + 1);
412 qs_.OnEncodeFrame(input_frame_);
413 EXPECT_GT(initial_res.width, qs_.GetScaledResolution().width);
414 EXPECT_GT(initial_res.height, qs_.GetScaledResolution().height);
415
416 // Should not upscale if less than kMeasureSecondsUpscale seconds passed since
417 // we saw issues initially (have already gone down).
418 for (int i = 0; i < kFramerate * kMeasureSecondsUpscale - 1; ++i) {
419 qs_.ReportQP(kLowQp);
420 qs_.OnEncodeFrame(input_frame_);
421 }
422 EXPECT_GT(initial_res.width, qs_.GetScaledResolution().width);
423 EXPECT_GT(initial_res.height, qs_.GetScaledResolution().height);
424
425 // Should upscale (back to initial) if kMeasureSecondsUpscale seconds passed
426 // (add last frame).
427 qs_.ReportQP(kLowQp);
428 qs_.OnEncodeFrame(input_frame_);
429 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
430 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
431 }
432
433 TEST_F(QualityScalerTest, UpscaleQuicklyInitiallyAfterMeasuredSeconds) {
434 QualityScalerTest::Resolution initial_res;
435 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, kHighQp, false,
436 kLowInitialBitrateKbps, kWidth, kHeight, kFramerate);
437 qs_.OnEncodeFrame(input_frame_);
438 initial_res.width = qs_.GetScaledResolution().width;
439 initial_res.height = qs_.GetScaledResolution().height;
440
441 // Should not upscale if less than kMeasureSecondsFastUpscale seconds passed.
442 for (int i = 0; i < kFramerate * kMeasureSecondsFastUpscale - 1; ++i) {
443 qs_.ReportQP(kLowQp);
444 qs_.OnEncodeFrame(input_frame_);
445 }
446 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
447 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
448
449 // Should upscale if kMeasureSecondsFastUpscale seconds passed (add last
450 // frame).
451 qs_.ReportQP(kLowQp);
452 qs_.OnEncodeFrame(input_frame_);
453 EXPECT_LT(initial_res.width, qs_.GetScaledResolution().width);
454 EXPECT_LT(initial_res.height, qs_.GetScaledResolution().height);
455 }
456
457 void QualityScalerTest::DownscaleEndsAt(int input_width, 382 void QualityScalerTest::DownscaleEndsAt(int input_width,
458 int input_height, 383 int input_height,
459 int end_width, 384 int end_width,
460 int end_height) { 385 int end_height) {
461 // Create a frame with 2x expected end width/height to verify that we can 386 // Create a frame with 2x expected end width/height to verify that we can
462 // scale down to expected end width/height. 387 // scale down to expected end width/height.
463 input_frame_.CreateEmptyFrame(input_width, input_height, input_width, 388 input_frame_.CreateEmptyFrame(input_width, input_height, input_width,
464 (input_width + 1) / 2, (input_width + 1) / 2); 389 (input_width + 1) / 2, (input_width + 1) / 2);
465 390
466 int last_width = input_width; 391 int last_width = input_width;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 DownscaleEndsAt(1600, 800, 200, 100); 431 DownscaleEndsAt(1600, 800, 200, 100);
507 } 432 }
508 433
509 TEST_F(QualityScalerTest, RespectsMinResolutionHeight) { 434 TEST_F(QualityScalerTest, RespectsMinResolutionHeight) {
510 // Should end at 100x200, as height can't go lower. 435 // Should end at 100x200, as height can't go lower.
511 qs_.SetMinResolution(10, 200); 436 qs_.SetMinResolution(10, 200);
512 DownscaleEndsAt(800, 1600, 100, 200); 437 DownscaleEndsAt(800, 1600, 100, 200);
513 } 438 }
514 439
515 } // namespace webrtc 440 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/utility/quality_scaler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698