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

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

Issue 1885893002: Remove QualityScaler framerate reduction. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: rebase Created 4 years, 7 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
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
(...skipping 16 matching lines...) Expand all
27 static const int kLowInitialBitrateKbps = 300; 27 static const int kLowInitialBitrateKbps = 300;
28 // These values need to be in sync with corresponding constants 28 // These values need to be in sync with corresponding constants
29 // in quality_scaler.cc 29 // in quality_scaler.cc
30 static const int kMeasureSecondsFastUpscale = 2; 30 static const int kMeasureSecondsFastUpscale = 2;
31 static const int kMeasureSecondsUpscale = 5; 31 static const int kMeasureSecondsUpscale = 5;
32 static const int kMeasureSecondsDownscale = 5; 32 static const int kMeasureSecondsDownscale = 5;
33 static const int kMinDownscaleDimension = 140; 33 static const int kMinDownscaleDimension = 140;
34 } // namespace 34 } // namespace
35 35
36 class QualityScalerTest : public ::testing::Test { 36 class QualityScalerTest : public ::testing::Test {
37 public:
38 // Temporal and spatial resolution.
39 struct Resolution {
40 int framerate;
41 int width;
42 int height;
43 };
44
45 protected: 37 protected:
46 enum ScaleDirection { 38 enum ScaleDirection {
47 kKeepScaleAtHighQp, 39 kKeepScaleAtHighQp,
48 kScaleDown, 40 kScaleDown,
49 kScaleDownAboveHighQp, 41 kScaleDownAboveHighQp,
50 kScaleUp 42 kScaleUp
51 }; 43 };
52 enum BadQualityMetric { kDropFrame, kReportLowQP };
53 44
54 QualityScalerTest() { 45 QualityScalerTest() {
55 input_frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, kHalfWidth, 46 input_frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, kHalfWidth,
56 kHalfWidth); 47 kHalfWidth);
57 qs_.Init(kLowQpThreshold, kHighQp, false, 0, 0, 0, kFramerate); 48 qs_.Init(kLowQpThreshold, kHighQp, 0, 0, 0, kFramerate);
58 qs_.OnEncodeFrame(input_frame_); 49 qs_.OnEncodeFrame(input_frame_);
59 } 50 }
60 51
61 bool TriggerScale(ScaleDirection scale_direction) { 52 bool TriggerScale(ScaleDirection scale_direction) {
62 qs_.OnEncodeFrame(input_frame_); 53 qs_.OnEncodeFrame(input_frame_);
63 int initial_width = qs_.GetScaledResolution().width; 54 int initial_width = qs_.GetScaledResolution().width;
64 for (int i = 0; i < kFramerate * kNumSeconds; ++i) { 55 for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
65 switch (scale_direction) { 56 switch (scale_direction) {
66 case kScaleUp: 57 case kScaleUp:
67 qs_.ReportQP(kLowQp); 58 qs_.ReportQP(kLowQp);
(...skipping 26 matching lines...) Expand all
94 QualityScaler::Resolution res = qs_.GetScaledResolution(); 85 QualityScaler::Resolution res = qs_.GetScaledResolution();
95 const VideoFrame& scaled_frame = qs_.GetScaledFrame(input_frame_); 86 const VideoFrame& scaled_frame = qs_.GetScaledFrame(input_frame_);
96 EXPECT_EQ(res.width, scaled_frame.width()); 87 EXPECT_EQ(res.width, scaled_frame.width());
97 EXPECT_EQ(res.height, scaled_frame.height()); 88 EXPECT_EQ(res.height, scaled_frame.height());
98 } 89 }
99 90
100 void ContinuouslyDownscalesByHalfDimensionsAndBackUp(); 91 void ContinuouslyDownscalesByHalfDimensionsAndBackUp();
101 92
102 void DoesNotDownscaleFrameDimensions(int width, int height); 93 void DoesNotDownscaleFrameDimensions(int width, int height);
103 94
104 Resolution TriggerResolutionChange(BadQualityMetric dropframe_lowqp,
105 int num_second,
106 int initial_framerate);
107
108 void VerifyQualityAdaptation(int initial_framerate,
109 int seconds_downscale,
110 int seconds_upscale,
111 bool expect_spatial_resize,
112 bool expect_framerate_reduction);
113
114 void DownscaleEndsAt(int input_width, 95 void DownscaleEndsAt(int input_width,
115 int input_height, 96 int input_height,
116 int end_width, 97 int end_width,
117 int end_height); 98 int end_height);
118 99
119 QualityScaler qs_; 100 QualityScaler qs_;
120 VideoFrame input_frame_; 101 VideoFrame input_frame_;
121 }; 102 };
122 103
123 TEST_F(QualityScalerTest, UsesOriginalFrameInitially) { 104 TEST_F(QualityScalerTest, UsesOriginalFrameInitially) {
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 } 242 }
262 243
263 TEST_F(QualityScalerTest, DoesNotDownscaleFrom1PxHeight) { 244 TEST_F(QualityScalerTest, DoesNotDownscaleFrom1PxHeight) {
264 DoesNotDownscaleFrameDimensions(kWidth, 1); 245 DoesNotDownscaleFrameDimensions(kWidth, 1);
265 } 246 }
266 247
267 TEST_F(QualityScalerTest, DoesNotDownscaleFrom1Px) { 248 TEST_F(QualityScalerTest, DoesNotDownscaleFrom1Px) {
268 DoesNotDownscaleFrameDimensions(1, 1); 249 DoesNotDownscaleFrameDimensions(1, 1);
269 } 250 }
270 251
271 QualityScalerTest::Resolution QualityScalerTest::TriggerResolutionChange(
272 BadQualityMetric dropframe_lowqp,
273 int num_second,
274 int initial_framerate) {
275 QualityScalerTest::Resolution res;
276 res.framerate = initial_framerate;
277 qs_.OnEncodeFrame(input_frame_);
278 res.width = qs_.GetScaledResolution().width;
279 res.height = qs_.GetScaledResolution().height;
280 for (int i = 0; i < kFramerate * num_second; ++i) {
281 switch (dropframe_lowqp) {
282 case kReportLowQP:
283 qs_.ReportQP(kLowQp);
284 break;
285 case kDropFrame:
286 qs_.ReportDroppedFrame();
287 break;
288 }
289 qs_.OnEncodeFrame(input_frame_);
290 // Simulate the case when SetRates is called right after reducing
291 // framerate.
292 qs_.ReportFramerate(initial_framerate);
293 res.framerate = qs_.GetTargetFramerate();
294 if (res.framerate != -1)
295 qs_.ReportFramerate(res.framerate);
296 res.width = qs_.GetScaledResolution().width;
297 res.height = qs_.GetScaledResolution().height;
298 }
299 return res;
300 }
301
302 void QualityScalerTest::VerifyQualityAdaptation(
303 int initial_framerate,
304 int seconds_downscale,
305 int seconds_upscale,
306 bool expect_spatial_resize,
307 bool expect_framerate_reduction) {
308 qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, true, 0, 0, 0,
309 initial_framerate);
310 qs_.OnEncodeFrame(input_frame_);
311 int init_width = qs_.GetScaledResolution().width;
312 int init_height = qs_.GetScaledResolution().height;
313
314 // Test reducing framerate by dropping frame continuously.
315 QualityScalerTest::Resolution res =
316 TriggerResolutionChange(kDropFrame, seconds_downscale, initial_framerate);
317
318 if (expect_framerate_reduction) {
319 EXPECT_LT(res.framerate, initial_framerate);
320 } else {
321 // No framerate reduction, video decimator should be disabled.
322 EXPECT_EQ(-1, res.framerate);
323 }
324
325 if (expect_spatial_resize) {
326 EXPECT_LT(res.width, init_width);
327 EXPECT_LT(res.height, init_height);
328 } else {
329 EXPECT_EQ(init_width, res.width);
330 EXPECT_EQ(init_height, res.height);
331 }
332
333 // The "seconds * 1.5" is to ensure spatial resolution to recover.
334 // For example, in 6 seconds test, framerate reduction happens in the first
335 // 3 seconds from 30fps to 15fps and causes the buffer size to be half of the
336 // original one. Then it will take only 45 samples to downscale (twice in 90
337 // samples). So to recover the resolution changes, we need more than 10
338 // seconds (i.e, seconds_upscale * 1.5). This is because the framerate
339 // increases before spatial size recovers, so it will take 150 samples to
340 // recover spatial size (300 for twice).
341 res = TriggerResolutionChange(kReportLowQP, seconds_upscale * 1.5,
342 initial_framerate);
343 EXPECT_EQ(-1, res.framerate);
344 EXPECT_EQ(init_width, res.width);
345 EXPECT_EQ(init_height, res.height);
346 }
347
348 // In 3 seconds test, only framerate adjusting should happen and 5 second
349 // upscaling duration, only a framerate adjusting should happen.
350 TEST_F(QualityScalerTest, ChangeFramerateOnly) {
351 VerifyQualityAdaptation(kFramerate, kMeasureSecondsDownscale,
352 kMeasureSecondsUpscale, false, true);
353 }
354
355 // In 6 seconds test, framerate adjusting and scaling are both
356 // triggered, it shows that scaling would happen after framerate
357 // adjusting.
358 TEST_F(QualityScalerTest, ChangeFramerateAndSpatialSize) {
359 VerifyQualityAdaptation(kFramerate, kMeasureSecondsDownscale * 2,
360 kMeasureSecondsUpscale * 2, true, true);
361 }
362
363 // When starting from a low framerate, only spatial size will be changed.
364 TEST_F(QualityScalerTest, ChangeSpatialSizeOnly) {
365 qs_.ReportFramerate(kFramerate >> 1);
366 VerifyQualityAdaptation(kFramerate >> 1, kMeasureSecondsDownscale * 2,
367 kMeasureSecondsUpscale * 2, true, false);
368 }
369
370 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) { 252 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) {
371 DoesNotDownscaleFrameDimensions( 253 DoesNotDownscaleFrameDimensions(
372 2 * kMinDownscaleDimension - 1, 1000); 254 2 * kMinDownscaleDimension - 1, 1000);
373 } 255 }
374 256
375 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) { 257 TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) {
376 DoesNotDownscaleFrameDimensions( 258 DoesNotDownscaleFrameDimensions(
377 1000, 2 * kMinDownscaleDimension - 1); 259 1000, 2 * kMinDownscaleDimension - 1);
378 } 260 }
379 261
380 TEST_F(QualityScalerTest, DownscaleToVgaOnLowInitialBitrate) { 262 TEST_F(QualityScalerTest, DownscaleToVgaOnLowInitialBitrate) {
381 static const int kWidth720p = 1280; 263 static const int kWidth720p = 1280;
382 static const int kHeight720p = 720; 264 static const int kHeight720p = 720;
383 static const int kInitialBitrateKbps = 300; 265 static const int kInitialBitrateKbps = 300;
384 input_frame_.CreateEmptyFrame(kWidth720p, kHeight720p, kWidth720p, 266 input_frame_.CreateEmptyFrame(kWidth720p, kHeight720p, kWidth720p,
385 kWidth720p / 2, kWidth720p / 2); 267 kWidth720p / 2, kWidth720p / 2);
386 qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, true, kInitialBitrateKbps, 268 qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, kInitialBitrateKbps,
387 kWidth720p, kHeight720p, kFramerate); 269 kWidth720p, kHeight720p, kFramerate);
388 qs_.OnEncodeFrame(input_frame_); 270 qs_.OnEncodeFrame(input_frame_);
389 int init_width = qs_.GetScaledResolution().width; 271 int init_width = qs_.GetScaledResolution().width;
390 int init_height = qs_.GetScaledResolution().height; 272 int init_height = qs_.GetScaledResolution().height;
391 EXPECT_EQ(640, init_width); 273 EXPECT_EQ(640, init_width);
392 EXPECT_EQ(360, init_height); 274 EXPECT_EQ(360, init_height);
393 } 275 }
394 276
395 TEST_F(QualityScalerTest, DownscaleToQvgaOnLowerInitialBitrate) { 277 TEST_F(QualityScalerTest, DownscaleToQvgaOnLowerInitialBitrate) {
396 static const int kWidth720p = 1280; 278 static const int kWidth720p = 1280;
397 static const int kHeight720p = 720; 279 static const int kHeight720p = 720;
398 static const int kInitialBitrateKbps = 200; 280 static const int kInitialBitrateKbps = 200;
399 input_frame_.CreateEmptyFrame(kWidth720p, kHeight720p, kWidth720p, 281 input_frame_.CreateEmptyFrame(kWidth720p, kHeight720p, kWidth720p,
400 kWidth720p / 2, kWidth720p / 2); 282 kWidth720p / 2, kWidth720p / 2);
401 qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, true, kInitialBitrateKbps, 283 qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, kInitialBitrateKbps,
402 kWidth720p, kHeight720p, kFramerate); 284 kWidth720p, kHeight720p, kFramerate);
403 qs_.OnEncodeFrame(input_frame_); 285 qs_.OnEncodeFrame(input_frame_);
404 int init_width = qs_.GetScaledResolution().width; 286 int init_width = qs_.GetScaledResolution().width;
405 int init_height = qs_.GetScaledResolution().height; 287 int init_height = qs_.GetScaledResolution().height;
406 EXPECT_EQ(320, init_width); 288 EXPECT_EQ(320, init_width);
407 EXPECT_EQ(180, init_height); 289 EXPECT_EQ(180, init_height);
408 } 290 }
409 291
410 TEST_F(QualityScalerTest, DownscaleAfterMeasuredSecondsThenSlowerBackUp) { 292 TEST_F(QualityScalerTest, DownscaleAfterMeasuredSecondsThenSlowerBackUp) {
411 QualityScalerTest::Resolution initial_res; 293 qs_.Init(kLowQpThreshold, kHighQp, 0, kWidth, kHeight, kFramerate);
412 qs_.Init(kLowQpThreshold, kHighQp, false, 0, kWidth, kHeight, kFramerate);
413 qs_.OnEncodeFrame(input_frame_); 294 qs_.OnEncodeFrame(input_frame_);
414 initial_res.width = qs_.GetScaledResolution().width; 295 QualityScaler::Resolution initial_res = qs_.GetScaledResolution();
415 initial_res.height = qs_.GetScaledResolution().height;
416 296
417 // Should not downscale if less than kMeasureSecondsDownscale seconds passed. 297 // Should not downscale if less than kMeasureSecondsDownscale seconds passed.
418 for (int i = 0; i < kFramerate * kMeasureSecondsDownscale - 1; ++i) { 298 for (int i = 0; i < kFramerate * kMeasureSecondsDownscale - 1; ++i) {
419 qs_.ReportQP(kHighQp + 1); 299 qs_.ReportQP(kHighQp + 1);
420 qs_.OnEncodeFrame(input_frame_); 300 qs_.OnEncodeFrame(input_frame_);
421 } 301 }
422 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width); 302 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
423 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height); 303 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
424 304
425 // Should downscale if more than kMeasureSecondsDownscale seconds passed (add 305 // Should downscale if more than kMeasureSecondsDownscale seconds passed (add
(...skipping 14 matching lines...) Expand all
440 320
441 // Should upscale (back to initial) if kMeasureSecondsUpscale seconds passed 321 // Should upscale (back to initial) if kMeasureSecondsUpscale seconds passed
442 // (add last frame). 322 // (add last frame).
443 qs_.ReportQP(kLowQp); 323 qs_.ReportQP(kLowQp);
444 qs_.OnEncodeFrame(input_frame_); 324 qs_.OnEncodeFrame(input_frame_);
445 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width); 325 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
446 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height); 326 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
447 } 327 }
448 328
449 TEST_F(QualityScalerTest, UpscaleQuicklyInitiallyAfterMeasuredSeconds) { 329 TEST_F(QualityScalerTest, UpscaleQuicklyInitiallyAfterMeasuredSeconds) {
450 QualityScalerTest::Resolution initial_res; 330 qs_.Init(kLowQpThreshold, kHighQp, kLowInitialBitrateKbps, kWidth, kHeight,
451 qs_.Init(kLowQpThreshold, kHighQp, false, kLowInitialBitrateKbps, kWidth, 331 kFramerate);
452 kHeight, kFramerate);
453 qs_.OnEncodeFrame(input_frame_); 332 qs_.OnEncodeFrame(input_frame_);
454 initial_res.width = qs_.GetScaledResolution().width; 333 QualityScaler::Resolution initial_res = qs_.GetScaledResolution();
455 initial_res.height = qs_.GetScaledResolution().height;
456 334
457 // Should not upscale if less than kMeasureSecondsFastUpscale seconds passed. 335 // Should not upscale if less than kMeasureSecondsFastUpscale seconds passed.
458 for (int i = 0; i < kFramerate * kMeasureSecondsFastUpscale - 1; ++i) { 336 for (int i = 0; i < kFramerate * kMeasureSecondsFastUpscale - 1; ++i) {
459 qs_.ReportQP(kLowQp); 337 qs_.ReportQP(kLowQp);
460 qs_.OnEncodeFrame(input_frame_); 338 qs_.OnEncodeFrame(input_frame_);
461 } 339 }
462 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width); 340 EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
463 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height); 341 EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
464 342
465 // Should upscale if kMeasureSecondsFastUpscale seconds passed (add last 343 // Should upscale if kMeasureSecondsFastUpscale seconds passed (add last
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 384
507 TEST_F(QualityScalerTest, DownscalesFrom1280x720To320x180) { 385 TEST_F(QualityScalerTest, DownscalesFrom1280x720To320x180) {
508 DownscaleEndsAt(1280, 720, 320, 180); 386 DownscaleEndsAt(1280, 720, 320, 180);
509 } 387 }
510 388
511 TEST_F(QualityScalerTest, DoesntDownscaleInitialQvga) { 389 TEST_F(QualityScalerTest, DoesntDownscaleInitialQvga) {
512 DownscaleEndsAt(320, 180, 320, 180); 390 DownscaleEndsAt(320, 180, 320, 180);
513 } 391 }
514 392
515 } // namespace webrtc 393 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/utility/quality_scaler.cc ('k') | webrtc/modules/video_coding/video_sender.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698