| OLD | NEW |
| 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 kHalfWidth = kWidth / 2; | 20 static const int kHalfWidth = kWidth / 2; |
| 20 static const int kHeight = 1080; | 21 static const int kHeight = 1080; |
| 22 static const int kHeightVga = 480; |
| 21 static const int kFramerate = 30; | 23 static const int kFramerate = 30; |
| 22 static const int kLowQp = 15; | 24 static const int kLowQp = 15; |
| 23 static const int kNormalQp = 30; | 25 static const int kNormalQp = 30; |
| 24 static const int kHighQp = 40; | 26 static const int kHighQp = 40; |
| 25 static const int kMaxQp = 56; | 27 static const int kMaxQp = 56; |
| 28 static const int kDisabledBadQpThreshold = kMaxQp + 1; |
| 29 static const int kLowInitialBitrateKbps = 300; |
| 26 } // namespace | 30 } // namespace |
| 27 | 31 |
| 28 class QualityScalerTest : public ::testing::Test { | 32 class QualityScalerTest : public ::testing::Test { |
| 29 public: | 33 public: |
| 30 // Temporal and spatial resolution. | 34 // Temporal and spatial resolution. |
| 31 struct Resolution { | 35 struct Resolution { |
| 32 int framerate; | 36 int framerate; |
| 33 int width; | 37 int width; |
| 34 int height; | 38 int height; |
| 35 }; | 39 }; |
| 36 | 40 |
| 37 protected: | 41 protected: |
| 38 enum ScaleDirection { | 42 enum ScaleDirection { |
| 39 kKeepScaleAtHighQp, | 43 kKeepScaleAtHighQp, |
| 40 kScaleDown, | 44 kScaleDown, |
| 41 kScaleDownAboveHighQp, | 45 kScaleDownAboveHighQp, |
| 42 kScaleUp | 46 kScaleUp |
| 43 }; | 47 }; |
| 44 enum BadQualityMetric { kDropFrame, kReportLowQP }; | 48 enum BadQualityMetric { kDropFrame, kReportLowQP }; |
| 45 | 49 |
| 46 QualityScalerTest() { | 50 QualityScalerTest() { |
| 47 input_frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, kHalfWidth, | 51 input_frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, kHalfWidth, |
| 48 kHalfWidth); | 52 kHalfWidth); |
| 49 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, kHighQp, false); | 53 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, kHighQp, false, |
| 54 0, 0, 0); |
| 50 qs_.ReportFramerate(kFramerate); | 55 qs_.ReportFramerate(kFramerate); |
| 51 qs_.OnEncodeFrame(input_frame_); | 56 qs_.OnEncodeFrame(input_frame_); |
| 52 } | 57 } |
| 53 | 58 |
| 54 bool TriggerScale(ScaleDirection scale_direction) { | 59 bool TriggerScale(ScaleDirection scale_direction) { |
| 55 qs_.OnEncodeFrame(input_frame_); | 60 qs_.OnEncodeFrame(input_frame_); |
| 56 int initial_width = qs_.GetScaledResolution().width; | 61 int initial_width = qs_.GetScaledResolution().width; |
| 57 for (int i = 0; i < kFramerate * kNumSeconds; ++i) { | 62 for (int i = 0; i < kFramerate * kNumSeconds; ++i) { |
| 58 switch (scale_direction) { | 63 switch (scale_direction) { |
| 59 case kScaleUp: | 64 case kScaleUp: |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 res.height = qs_.GetScaledResolution().height; | 294 res.height = qs_.GetScaledResolution().height; |
| 290 } | 295 } |
| 291 return res; | 296 return res; |
| 292 } | 297 } |
| 293 | 298 |
| 294 void QualityScalerTest::VerifyQualityAdaptation( | 299 void QualityScalerTest::VerifyQualityAdaptation( |
| 295 int initial_framerate, | 300 int initial_framerate, |
| 296 int seconds, | 301 int seconds, |
| 297 bool expect_spatial_resize, | 302 bool expect_spatial_resize, |
| 298 bool expect_framerate_reduction) { | 303 bool expect_framerate_reduction) { |
| 299 const int kDisabledBadQpThreshold = kMaxQp + 1; | |
| 300 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, | 304 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, |
| 301 kDisabledBadQpThreshold, true); | 305 kDisabledBadQpThreshold, true, 0, 0, 0); |
| 302 qs_.OnEncodeFrame(input_frame_); | 306 qs_.OnEncodeFrame(input_frame_); |
| 303 int init_width = qs_.GetScaledResolution().width; | 307 int init_width = qs_.GetScaledResolution().width; |
| 304 int init_height = qs_.GetScaledResolution().height; | 308 int init_height = qs_.GetScaledResolution().height; |
| 305 | 309 |
| 306 // Test reducing framerate by dropping frame continuously. | 310 // Test reducing framerate by dropping frame continuously. |
| 307 QualityScalerTest::Resolution res = | 311 QualityScalerTest::Resolution res = |
| 308 TriggerResolutionChange(kDropFrame, seconds, initial_framerate); | 312 TriggerResolutionChange(kDropFrame, seconds, initial_framerate); |
| 309 | 313 |
| 310 if (expect_framerate_reduction) { | 314 if (expect_framerate_reduction) { |
| 311 EXPECT_LT(res.framerate, initial_framerate); | 315 EXPECT_LT(res.framerate, initial_framerate); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) { | 361 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) { |
| 358 DoesNotDownscaleFrameDimensions( | 362 DoesNotDownscaleFrameDimensions( |
| 359 2 * QualityScaler::kDefaultMinDownscaleDimension - 1, 1000); | 363 2 * QualityScaler::kDefaultMinDownscaleDimension - 1, 1000); |
| 360 } | 364 } |
| 361 | 365 |
| 362 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) { | 366 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) { |
| 363 DoesNotDownscaleFrameDimensions( | 367 DoesNotDownscaleFrameDimensions( |
| 364 1000, 2 * QualityScaler::kDefaultMinDownscaleDimension - 1); | 368 1000, 2 * QualityScaler::kDefaultMinDownscaleDimension - 1); |
| 365 } | 369 } |
| 366 | 370 |
| 371 TEST_F(QualityScalerTest, DownscaleToVgaOnLowInitialBitrate) { |
| 372 qs_.Init(kMaxQp / QualityScaler::kDefaultLowQpDenominator, |
| 373 kDisabledBadQpThreshold, true, |
| 374 kLowInitialBitrateKbps, kWidth, kHeight); |
| 375 qs_.OnEncodeFrame(input_frame_); |
| 376 int init_width = qs_.GetScaledResolution().width; |
| 377 int init_height = qs_.GetScaledResolution().height; |
| 378 EXPECT_LE(init_width, kWidthVga); |
| 379 EXPECT_LE(init_height, kHeightVga); |
| 380 } |
| 381 |
| 367 void QualityScalerTest::DownscaleEndsAt(int input_width, | 382 void QualityScalerTest::DownscaleEndsAt(int input_width, |
| 368 int input_height, | 383 int input_height, |
| 369 int end_width, | 384 int end_width, |
| 370 int end_height) { | 385 int end_height) { |
| 371 // 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 |
| 372 // scale down to expected end width/height. | 387 // scale down to expected end width/height. |
| 373 input_frame_.CreateEmptyFrame(input_width, input_height, input_width, | 388 input_frame_.CreateEmptyFrame(input_width, input_height, input_width, |
| 374 (input_width + 1) / 2, (input_width + 1) / 2); | 389 (input_width + 1) / 2, (input_width + 1) / 2); |
| 375 | 390 |
| 376 int last_width = input_width; | 391 int last_width = input_width; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 DownscaleEndsAt(1600, 800, 200, 100); | 431 DownscaleEndsAt(1600, 800, 200, 100); |
| 417 } | 432 } |
| 418 | 433 |
| 419 TEST_F(QualityScalerTest, RespectsMinResolutionHeight) { | 434 TEST_F(QualityScalerTest, RespectsMinResolutionHeight) { |
| 420 // Should end at 100x200, as height can't go lower. | 435 // Should end at 100x200, as height can't go lower. |
| 421 qs_.SetMinResolution(10, 200); | 436 qs_.SetMinResolution(10, 200); |
| 422 DownscaleEndsAt(800, 1600, 100, 200); | 437 DownscaleEndsAt(800, 1600, 100, 200); |
| 423 } | 438 } |
| 424 | 439 |
| 425 } // namespace webrtc | 440 } // namespace webrtc |
| OLD | NEW |