1 /* 2 * Copyright (c) 2012 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 /* 12 * This file includes unit tests the QmResolution class 13 * In particular, for the selection of spatial and/or temporal down-sampling. 14 */ 15 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 #include "webrtc/modules/include/module_common_types.h" 19 #include "webrtc/modules/video_coding/qm_select.h" 20 21 namespace webrtc { 22 23 // Representative values of content metrics for: low/high/medium(default) state, 24 // based on parameters settings in qm_select_data.h. 25 const float kSpatialLow = 0.01f; 26 const float kSpatialMedium = 0.03f; 27 const float kSpatialHigh = 0.1f; 28 const float kTemporalLow = 0.01f; 29 const float kTemporalMedium = 0.06f; 30 const float kTemporalHigh = 0.1f; 31 32 class QmSelectTest : public ::testing::Test { 33 protected: 34 QmSelectTest() 35 : qm_resolution_(new VCMQmResolution()), 36 content_metrics_(new VideoContentMetrics()), 37 qm_scale_(NULL) {} 38 VCMQmResolution* qm_resolution_; 39 VideoContentMetrics* content_metrics_; 40 VCMResolutionScale* qm_scale_; 41 42 void InitQmNativeData(float initial_bit_rate, 43 int user_frame_rate, 44 int native_width, 45 int native_height, 46 int num_layers); 47 48 void UpdateQmEncodedFrame(size_t* encoded_size, size_t num_updates); 49 50 void UpdateQmRateData(int* target_rate, 51 int* encoder_sent_rate, 52 int* incoming_frame_rate, 53 uint8_t* fraction_lost, 54 int num_updates); 55 56 void UpdateQmContentData(float motion_metric, 57 float spatial_metric, 58 float spatial_metric_horiz, 59 float spatial_metric_vert); 60 61 bool IsSelectedActionCorrect(VCMResolutionScale* qm_scale, 62 float fac_width, 63 float fac_height, 64 float fac_temp, 65 uint16_t new_width, 66 uint16_t new_height, 67 float new_frame_rate); 68 69 void TearDown() { 70 delete qm_resolution_; 71 delete content_metrics_; 72 } 73 }; 74 75 TEST_F(QmSelectTest, HandleInputs) { 76 // Expect parameter error. Initialize with invalid inputs. 77 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 0, 640, 480, 1)); 78 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 640, 0, 1)); 79 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 0, 480, 1)); 80 81 // Expect uninitialized error.: No valid initialization before selection. 82 EXPECT_EQ(-7, qm_resolution_->SelectResolution(&qm_scale_)); 83 84 VideoContentMetrics* content_metrics = NULL; 85 EXPECT_EQ(0, qm_resolution_->Initialize(1000, 30, 640, 480, 1)); 86 qm_resolution_->UpdateContent(content_metrics); 87 // Content metrics are NULL: Expect success and no down-sampling action. 88 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 89 EXPECT_TRUE( 90 IsSelectedActionCorrect(qm_scale_, 1.0, 1.0, 1.0, 640, 480, 30.0f)); 91 } 92 93 // TODO(marpan): Add a test for number of temporal layers > 1. 94 95 // No down-sampling action at high rates. 96 TEST_F(QmSelectTest, NoActionHighRate) { 97 // Initialize with bitrate, frame rate, native system width/height, and 98 // number of temporal layers. 99 InitQmNativeData(800, 30, 640, 480, 1); 100 101 // Update with encoder frame size. 102 uint16_t codec_width = 640; 103 uint16_t codec_height = 480; 104 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 105 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 106 107 // Update rates for a sequence of intervals. 108 int target_rate[] = {800, 800, 800}; 109 int encoder_sent_rate[] = {800, 800, 800}; 110 int incoming_frame_rate[] = {30, 30, 30}; 111 uint8_t fraction_lost[] = {10, 10, 10}; 112 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 113 fraction_lost, 3); 114 115 // Update content: motion level, and 3 spatial prediction errors. 116 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow); 117 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 118 EXPECT_EQ(0, qm_resolution_->ComputeContentClass()); 119 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 120 EXPECT_TRUE( 121 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f)); 122 } 123 124 // Rate is well below transition, down-sampling action is taken, 125 // depending on the content state. 126 TEST_F(QmSelectTest, DownActionLowRate) { 127 // Initialize with bitrate, frame rate, native system width/height, and 128 // number of temporal layers. 129 InitQmNativeData(50, 30, 640, 480, 1); 130 131 // Update with encoder frame size. 132 uint16_t codec_width = 640; 133 uint16_t codec_height = 480; 134 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 135 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 136 137 // Update rates for a sequence of intervals. 138 int target_rate[] = {50, 50, 50}; 139 int encoder_sent_rate[] = {50, 50, 50}; 140 int incoming_frame_rate[] = {30, 30, 30}; 141 uint8_t fraction_lost[] = {10, 10, 10}; 142 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 143 fraction_lost, 3); 144 145 // Update content: motion level, and 3 spatial prediction errors. 146 // High motion, low spatial: 2x2 spatial expected. 147 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 148 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 149 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 150 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 151 EXPECT_TRUE( 152 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 153 154 qm_resolution_->ResetDownSamplingState(); 155 // Low motion, low spatial: 2/3 temporal is expected. 156 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow); 157 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 158 EXPECT_EQ(0, qm_resolution_->ComputeContentClass()); 159 EXPECT_TRUE( 160 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f)); 161 162 qm_resolution_->ResetDownSamplingState(); 163 // Medium motion, low spatial: 2x2 spatial expected. 164 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow); 165 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 166 EXPECT_EQ(6, qm_resolution_->ComputeContentClass()); 167 EXPECT_TRUE( 168 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 169 170 qm_resolution_->ResetDownSamplingState(); 171 // High motion, high spatial: 2/3 temporal expected. 172 UpdateQmContentData(kTemporalHigh, kSpatialHigh, kSpatialHigh, kSpatialHigh); 173 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 174 EXPECT_EQ(4, qm_resolution_->ComputeContentClass()); 175 EXPECT_TRUE( 176 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f)); 177 178 qm_resolution_->ResetDownSamplingState(); 179 // Low motion, high spatial: 1/2 temporal expected. 180 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 181 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 182 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 183 EXPECT_TRUE( 184 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f)); 185 186 qm_resolution_->ResetDownSamplingState(); 187 // Medium motion, high spatial: 1/2 temporal expected. 188 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh, 189 kSpatialHigh); 190 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 191 EXPECT_EQ(7, qm_resolution_->ComputeContentClass()); 192 EXPECT_TRUE( 193 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f)); 194 195 qm_resolution_->ResetDownSamplingState(); 196 // High motion, medium spatial: 2x2 spatial expected. 197 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium, 198 kSpatialMedium); 199 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 200 EXPECT_EQ(5, qm_resolution_->ComputeContentClass()); 201 // Target frame rate for frame dropper should be the same as previous == 15. 202 EXPECT_TRUE( 203 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 204 205 qm_resolution_->ResetDownSamplingState(); 206 // Low motion, medium spatial: high frame rate, so 1/2 temporal expected. 207 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium, 208 kSpatialMedium); 209 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 210 EXPECT_EQ(2, qm_resolution_->ComputeContentClass()); 211 EXPECT_TRUE( 212 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f)); 213 214 qm_resolution_->ResetDownSamplingState(); 215 // Medium motion, medium spatial: high frame rate, so 2/3 temporal expected. 216 UpdateQmContentData(kTemporalMedium, kSpatialMedium, kSpatialMedium, 217 kSpatialMedium); 218 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 219 EXPECT_EQ(8, qm_resolution_->ComputeContentClass()); 220 EXPECT_TRUE( 221 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f)); 222 } 223 224 // Rate mis-match is high, and we have over-shooting. 225 // since target rate is below max for down-sampling, down-sampling is selected. 226 TEST_F(QmSelectTest, DownActionHighRateMMOvershoot) { 227 // Initialize with bitrate, frame rate, native system width/height, and 228 // number of temporal layers. 229 InitQmNativeData(300, 30, 640, 480, 1); 230 231 // Update with encoder frame size. 232 uint16_t codec_width = 640; 233 uint16_t codec_height = 480; 234 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 235 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 236 237 // Update rates for a sequence of intervals. 238 int target_rate[] = {300, 300, 300}; 239 int encoder_sent_rate[] = {900, 900, 900}; 240 int incoming_frame_rate[] = {30, 30, 30}; 241 uint8_t fraction_lost[] = {10, 10, 10}; 242 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 243 fraction_lost, 3); 244 245 // Update content: motion level, and 3 spatial prediction errors. 246 // High motion, low spatial. 247 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 248 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 249 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 250 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState()); 251 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f, 252 480, 360, 30.0f)); 253 254 qm_resolution_->ResetDownSamplingState(); 255 // Low motion, high spatial 256 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 257 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 258 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 259 EXPECT_TRUE( 260 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f)); 261 } 262 263 // Rate mis-match is high, target rate is below max for down-sampling, 264 // but since we have consistent under-shooting, no down-sampling action. 265 TEST_F(QmSelectTest, NoActionHighRateMMUndershoot) { 266 // Initialize with bitrate, frame rate, native system width/height, and 267 // number of temporal layers. 268 InitQmNativeData(300, 30, 640, 480, 1); 269 270 // Update with encoder frame size. 271 uint16_t codec_width = 640; 272 uint16_t codec_height = 480; 273 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 274 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 275 276 // Update rates for a sequence of intervals. 277 int target_rate[] = {300, 300, 300}; 278 int encoder_sent_rate[] = {100, 100, 100}; 279 int incoming_frame_rate[] = {30, 30, 30}; 280 uint8_t fraction_lost[] = {10, 10, 10}; 281 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 282 fraction_lost, 3); 283 284 // Update content: motion level, and 3 spatial prediction errors. 285 // High motion, low spatial. 286 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 287 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 288 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 289 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState()); 290 EXPECT_TRUE( 291 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f)); 292 293 qm_resolution_->ResetDownSamplingState(); 294 // Low motion, high spatial 295 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 296 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 297 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 298 EXPECT_TRUE( 299 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f)); 300 } 301 302 // Buffer is underflowing, and target rate is below max for down-sampling, 303 // so action is taken. 304 TEST_F(QmSelectTest, DownActionBufferUnderflow) { 305 // Initialize with bitrate, frame rate, native system width/height, and 306 // number of temporal layers. 307 InitQmNativeData(300, 30, 640, 480, 1); 308 309 // Update with encoder frame size. 310 uint16_t codec_width = 640; 311 uint16_t codec_height = 480; 312 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 313 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 314 315 // Update with encoded size over a number of frames. 316 // per-frame bandwidth = 15 = 450/30: simulate (decoder) buffer underflow: 317 size_t encoded_size[] = {200, 100, 50, 30, 60, 40, 20, 30, 20, 40}; 318 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size)); 319 320 // Update rates for a sequence of intervals. 321 int target_rate[] = {300, 300, 300}; 322 int encoder_sent_rate[] = {450, 450, 450}; 323 int incoming_frame_rate[] = {30, 30, 30}; 324 uint8_t fraction_lost[] = {10, 10, 10}; 325 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 326 fraction_lost, 3); 327 328 // Update content: motion level, and 3 spatial prediction errors. 329 // High motion, low spatial. 330 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 331 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 332 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 333 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState()); 334 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f, 335 480, 360, 30.0f)); 336 337 qm_resolution_->ResetDownSamplingState(); 338 // Low motion, high spatial 339 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 340 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 341 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 342 EXPECT_TRUE( 343 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f)); 344 } 345 346 // Target rate is below max for down-sampling, but buffer level is stable, 347 // so no action is taken. 348 TEST_F(QmSelectTest, NoActionBufferStable) { 349 // Initialize with bitrate, frame rate, native system width/height, and 350 // number of temporal layers. 351 InitQmNativeData(350, 30, 640, 480, 1); 352 353 // Update with encoder frame size. 354 uint16_t codec_width = 640; 355 uint16_t codec_height = 480; 356 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 357 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 358 359 // Update with encoded size over a number of frames. 360 // per-frame bandwidth = 15 = 450/30: simulate stable (decoder) buffer levels. 361 size_t encoded_size[] = {40, 10, 10, 16, 18, 20, 17, 20, 16, 15}; 362 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size)); 363 364 // Update rates for a sequence of intervals. 365 int target_rate[] = {350, 350, 350}; 366 int encoder_sent_rate[] = {350, 450, 450}; 367 int incoming_frame_rate[] = {30, 30, 30}; 368 uint8_t fraction_lost[] = {10, 10, 10}; 369 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 370 fraction_lost, 3); 371 372 // Update content: motion level, and 3 spatial prediction errors. 373 // High motion, low spatial. 374 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 375 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 376 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 377 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 378 EXPECT_TRUE( 379 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f)); 380 381 qm_resolution_->ResetDownSamplingState(); 382 // Low motion, high spatial 383 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 384 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 385 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 386 EXPECT_TRUE( 387 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f)); 388 } 389 390 // Very low rate, but no spatial down-sampling below some size (QCIF). 391 TEST_F(QmSelectTest, LimitDownSpatialAction) { 392 // Initialize with bitrate, frame rate, native system width/height, and 393 // number of temporal layers. 394 InitQmNativeData(10, 30, 176, 144, 1); 395 396 // Update with encoder frame size. 397 uint16_t codec_width = 176; 398 uint16_t codec_height = 144; 399 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 400 EXPECT_EQ(0, qm_resolution_->GetImageType(codec_width, codec_height)); 401 402 // Update rates for a sequence of intervals. 403 int target_rate[] = {10, 10, 10}; 404 int encoder_sent_rate[] = {10, 10, 10}; 405 int incoming_frame_rate[] = {30, 30, 30}; 406 uint8_t fraction_lost[] = {10, 10, 10}; 407 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 408 fraction_lost, 3); 409 410 // Update content: motion level, and 3 spatial prediction errors. 411 // High motion, low spatial. 412 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 413 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 414 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 415 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 416 EXPECT_TRUE( 417 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 176, 144, 30.0f)); 418 } 419 420 // Very low rate, but no frame reduction below some frame_rate (8fps). 421 TEST_F(QmSelectTest, LimitDownTemporalAction) { 422 // Initialize with bitrate, frame rate, native system width/height, and 423 // number of temporal layers. 424 InitQmNativeData(10, 8, 640, 480, 1); 425 426 // Update with encoder frame size. 427 uint16_t codec_width = 640; 428 uint16_t codec_height = 480; 429 qm_resolution_->UpdateCodecParameters(8.0f, codec_width, codec_height); 430 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 431 432 // Update rates for a sequence of intervals. 433 int target_rate[] = {10, 10, 10}; 434 int encoder_sent_rate[] = {10, 10, 10}; 435 int incoming_frame_rate[] = {8, 8, 8}; 436 uint8_t fraction_lost[] = {10, 10, 10}; 437 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 438 fraction_lost, 3); 439 440 // Update content: motion level, and 3 spatial prediction errors. 441 // Low motion, medium spatial. 442 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium, 443 kSpatialMedium); 444 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 445 EXPECT_EQ(2, qm_resolution_->ComputeContentClass()); 446 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 447 EXPECT_TRUE( 448 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 8.0f)); 449 } 450 451 // Two stages: spatial down-sample and then back up spatially, 452 // as rate as increased. 453 TEST_F(QmSelectTest, 2StageDownSpatialUpSpatial) { 454 // Initialize with bitrate, frame rate, native system width/height, and 455 // number of temporal layers. 456 InitQmNativeData(50, 30, 640, 480, 1); 457 458 // Update with encoder frame size. 459 uint16_t codec_width = 640; 460 uint16_t codec_height = 480; 461 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 462 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 463 464 // Update rates for a sequence of intervals. 465 int target_rate[] = {50, 50, 50}; 466 int encoder_sent_rate[] = {50, 50, 50}; 467 int incoming_frame_rate[] = {30, 30, 30}; 468 uint8_t fraction_lost[] = {10, 10, 10}; 469 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 470 fraction_lost, 3); 471 472 // Update content: motion level, and 3 spatial prediction errors. 473 // High motion, low spatial. 474 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 475 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 476 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 477 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 478 EXPECT_TRUE( 479 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 480 481 // Reset and go up in rate: expected to go back up, in 2 stages of 3/4. 482 qm_resolution_->ResetRates(); 483 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240); 484 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 485 // Update rates for a sequence of intervals. 486 int target_rate2[] = {400, 400, 400, 400, 400}; 487 int encoder_sent_rate2[] = {400, 400, 400, 400, 400}; 488 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 489 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 490 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 491 fraction_lost2, 5); 492 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 493 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 494 float scale = (4.0f / 3.0f) / 2.0f; 495 EXPECT_TRUE( 496 IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360, 30.0f)); 497 498 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 499 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 500 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 501 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f, 502 640, 480, 30.0f)); 503 } 504 505 // Two stages: spatial down-sample and then back up spatially, since encoder 506 // is under-shooting target even though rate has not increased much. 507 TEST_F(QmSelectTest, 2StageDownSpatialUpSpatialUndershoot) { 508 // Initialize with bitrate, frame rate, native system width/height, and 509 // number of temporal layers. 510 InitQmNativeData(50, 30, 640, 480, 1); 511 512 // Update with encoder frame size. 513 uint16_t codec_width = 640; 514 uint16_t codec_height = 480; 515 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 516 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 517 518 // Update rates for a sequence of intervals. 519 int target_rate[] = {50, 50, 50}; 520 int encoder_sent_rate[] = {50, 50, 50}; 521 int incoming_frame_rate[] = {30, 30, 30}; 522 uint8_t fraction_lost[] = {10, 10, 10}; 523 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 524 fraction_lost, 3); 525 526 // Update content: motion level, and 3 spatial prediction errors. 527 // High motion, low spatial. 528 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 529 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 530 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 531 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 532 EXPECT_TRUE( 533 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 534 535 // Reset rates and simulate under-shooting scenario.: expect to go back up. 536 // Goes up spatially in two stages for 1/2x1/2 down-sampling. 537 qm_resolution_->ResetRates(); 538 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240); 539 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 540 // Update rates for a sequence of intervals. 541 int target_rate2[] = {200, 200, 200, 200, 200}; 542 int encoder_sent_rate2[] = {50, 50, 50, 50, 50}; 543 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 544 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 545 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 546 fraction_lost2, 5); 547 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 548 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState()); 549 float scale = (4.0f / 3.0f) / 2.0f; 550 EXPECT_TRUE( 551 IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360, 30.0f)); 552 553 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 554 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 555 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 556 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f, 557 640, 480, 30.0f)); 558 } 559 560 // Two stages: spatial down-sample and then no action to go up, 561 // as encoding rate mis-match is too high. 562 TEST_F(QmSelectTest, 2StageDownSpatialNoActionUp) { 563 // Initialize with bitrate, frame rate, native system width/height, and 564 // number of temporal layers. 565 InitQmNativeData(50, 30, 640, 480, 1); 566 567 // Update with encoder frame size. 568 uint16_t codec_width = 640; 569 uint16_t codec_height = 480; 570 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 571 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 572 573 // Update rates for a sequence of intervals. 574 int target_rate[] = {50, 50, 50}; 575 int encoder_sent_rate[] = {50, 50, 50}; 576 int incoming_frame_rate[] = {30, 30, 30}; 577 uint8_t fraction_lost[] = {10, 10, 10}; 578 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 579 fraction_lost, 3); 580 581 // Update content: motion level, and 3 spatial prediction errors. 582 // High motion, low spatial. 583 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 584 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 585 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 586 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 587 EXPECT_TRUE( 588 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 589 590 // Reset and simulate large rate mis-match: expect no action to go back up. 591 qm_resolution_->ResetRates(); 592 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240); 593 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 594 // Update rates for a sequence of intervals. 595 int target_rate2[] = {400, 400, 400, 400, 400}; 596 int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000}; 597 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 598 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 599 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 600 fraction_lost2, 5); 601 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 602 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState()); 603 EXPECT_TRUE( 604 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 320, 240, 30.0f)); 605 } 606 607 // Two stages: temporally down-sample and then back up temporally, 608 // as rate as increased. 609 TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporal) { 610 // Initialize with bitrate, frame rate, native system width/height, and 611 // number of temporal layers. 612 InitQmNativeData(50, 30, 640, 480, 1); 613 614 // Update with encoder frame size. 615 uint16_t codec_width = 640; 616 uint16_t codec_height = 480; 617 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 618 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 619 620 // Update rates for a sequence of intervals. 621 int target_rate[] = {50, 50, 50}; 622 int encoder_sent_rate[] = {50, 50, 50}; 623 int incoming_frame_rate[] = {30, 30, 30}; 624 uint8_t fraction_lost[] = {10, 10, 10}; 625 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 626 fraction_lost, 3); 627 628 // Update content: motion level, and 3 spatial prediction errors. 629 // Low motion, high spatial. 630 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 631 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 632 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 633 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 634 EXPECT_TRUE( 635 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f)); 636 637 // Reset rates and go up in rate: expect to go back up. 638 qm_resolution_->ResetRates(); 639 // Update rates for a sequence of intervals. 640 int target_rate2[] = {400, 400, 400, 400, 400}; 641 int encoder_sent_rate2[] = {400, 400, 400, 400, 400}; 642 int incoming_frame_rate2[] = {15, 15, 15, 15, 15}; 643 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 644 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 645 fraction_lost2, 5); 646 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 647 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 648 EXPECT_TRUE( 649 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480, 30.0f)); 650 } 651 652 // Two stages: temporal down-sample and then back up temporally, since encoder 653 // is under-shooting target even though rate has not increased much. 654 TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporalUndershoot) { 655 // Initialize with bitrate, frame rate, native system width/height, and 656 // number of temporal layers. 657 InitQmNativeData(50, 30, 640, 480, 1); 658 659 // Update with encoder frame size. 660 uint16_t codec_width = 640; 661 uint16_t codec_height = 480; 662 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 663 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 664 665 // Update rates for a sequence of intervals. 666 int target_rate[] = {50, 50, 50}; 667 int encoder_sent_rate[] = {50, 50, 50}; 668 int incoming_frame_rate[] = {30, 30, 30}; 669 uint8_t fraction_lost[] = {10, 10, 10}; 670 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 671 fraction_lost, 3); 672 673 // Update content: motion level, and 3 spatial prediction errors. 674 // Low motion, high spatial. 675 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 676 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 677 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 678 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 679 EXPECT_TRUE( 680 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f)); 681 682 // Reset rates and simulate under-shooting scenario.: expect to go back up. 683 qm_resolution_->ResetRates(); 684 // Update rates for a sequence of intervals. 685 int target_rate2[] = {150, 150, 150, 150, 150}; 686 int encoder_sent_rate2[] = {50, 50, 50, 50, 50}; 687 int incoming_frame_rate2[] = {15, 15, 15, 15, 15}; 688 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 689 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 690 fraction_lost2, 5); 691 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 692 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState()); 693 EXPECT_TRUE( 694 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480, 30.0f)); 695 } 696 697 // Two stages: temporal down-sample and then no action to go up, 698 // as encoding rate mis-match is too high. 699 TEST_F(QmSelectTest, 2StageDownTemporalNoActionUp) { 700 // Initialize with bitrate, frame rate, native system width/height, and 701 // number of temporal layers. 702 InitQmNativeData(50, 30, 640, 480, 1); 703 704 // Update with encoder frame size. 705 uint16_t codec_width = 640; 706 uint16_t codec_height = 480; 707 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 708 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 709 710 // Update rates for a sequence of intervals. 711 int target_rate[] = {50, 50, 50}; 712 int encoder_sent_rate[] = {50, 50, 50}; 713 int incoming_frame_rate[] = {30, 30, 30}; 714 uint8_t fraction_lost[] = {10, 10, 10}; 715 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 716 fraction_lost, 3); 717 718 // Update content: motion level, and 3 spatial prediction errors. 719 // Low motion, high spatial. 720 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 721 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 722 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 723 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 724 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1, 1, 2, 640, 480, 15.5f)); 725 726 // Reset and simulate large rate mis-match: expect no action to go back up. 727 qm_resolution_->UpdateCodecParameters(15.0f, codec_width, codec_height); 728 qm_resolution_->ResetRates(); 729 // Update rates for a sequence of intervals. 730 int target_rate2[] = {600, 600, 600, 600, 600}; 731 int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000}; 732 int incoming_frame_rate2[] = {15, 15, 15, 15, 15}; 733 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 734 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 735 fraction_lost2, 5); 736 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 737 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState()); 738 EXPECT_TRUE( 739 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 15.0f)); 740 } 741 // 3 stages: spatial down-sample, followed by temporal down-sample, 742 // and then go up to full state, as encoding rate has increased. 743 TEST_F(QmSelectTest, 3StageDownSpatialTemporlaUpSpatialTemporal) { 744 // Initialize with bitrate, frame rate, native system width/height, and 745 // number of temporal layers. 746 InitQmNativeData(80, 30, 640, 480, 1); 747 748 // Update with encoder frame size. 749 uint16_t codec_width = 640; 750 uint16_t codec_height = 480; 751 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 752 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 753 754 // Update rates for a sequence of intervals. 755 int target_rate[] = {80, 80, 80}; 756 int encoder_sent_rate[] = {80, 80, 80}; 757 int incoming_frame_rate[] = {30, 30, 30}; 758 uint8_t fraction_lost[] = {10, 10, 10}; 759 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 760 fraction_lost, 3); 761 762 // Update content: motion level, and 3 spatial prediction errors. 763 // High motion, low spatial. 764 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 765 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 766 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 767 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 768 EXPECT_TRUE( 769 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 770 771 // Change content data: expect temporal down-sample. 772 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240); 773 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 774 775 // Reset rates and go lower in rate. 776 qm_resolution_->ResetRates(); 777 int target_rate2[] = {40, 40, 40, 40, 40}; 778 int encoder_sent_rate2[] = {40, 40, 40, 40, 40}; 779 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 780 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 781 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 782 fraction_lost2, 5); 783 784 // Update content: motion level, and 3 spatial prediction errors. 785 // Low motion, high spatial. 786 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 787 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 788 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 789 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 790 EXPECT_TRUE( 791 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f)); 792 793 // Reset rates and go high up in rate: expect to go back up both spatial 794 // and temporally. The 1/2x1/2 spatial is undone in two stages. 795 qm_resolution_->ResetRates(); 796 // Update rates for a sequence of intervals. 797 int target_rate3[] = {1000, 1000, 1000, 1000, 1000}; 798 int encoder_sent_rate3[] = {1000, 1000, 1000, 1000, 1000}; 799 int incoming_frame_rate3[] = {20, 20, 20, 20, 20}; 800 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10}; 801 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3, 802 fraction_lost3, 5); 803 804 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 805 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 806 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 807 float scale = (4.0f / 3.0f) / 2.0f; 808 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480, 809 360, 30.0f)); 810 811 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 812 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 813 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 814 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f, 815 640, 480, 30.0f)); 816 } 817 818 // No down-sampling below some total amount. 819 TEST_F(QmSelectTest, NoActionTooMuchDownSampling) { 820 // Initialize with bitrate, frame rate, native system width/height, and 821 // number of temporal layers. 822 InitQmNativeData(150, 30, 1280, 720, 1); 823 824 // Update with encoder frame size. 825 uint16_t codec_width = 1280; 826 uint16_t codec_height = 720; 827 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 828 EXPECT_EQ(7, qm_resolution_->GetImageType(codec_width, codec_height)); 829 830 // Update rates for a sequence of intervals. 831 int target_rate[] = {150, 150, 150}; 832 int encoder_sent_rate[] = {150, 150, 150}; 833 int incoming_frame_rate[] = {30, 30, 30}; 834 uint8_t fraction_lost[] = {10, 10, 10}; 835 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 836 fraction_lost, 3); 837 838 // Update content: motion level, and 3 spatial prediction errors. 839 // High motion, low spatial. 840 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 841 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 842 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 843 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 844 EXPECT_TRUE( 845 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 640, 360, 30.0f)); 846 847 // Reset and lower rates to get another spatial action (3/4x3/4). 848 // Lower the frame rate for spatial to be selected again. 849 qm_resolution_->ResetRates(); 850 qm_resolution_->UpdateCodecParameters(10.0f, 640, 360); 851 EXPECT_EQ(4, qm_resolution_->GetImageType(640, 360)); 852 // Update rates for a sequence of intervals. 853 int target_rate2[] = {70, 70, 70, 70, 70}; 854 int encoder_sent_rate2[] = {70, 70, 70, 70, 70}; 855 int incoming_frame_rate2[] = {10, 10, 10, 10, 10}; 856 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 857 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 858 fraction_lost2, 5); 859 860 // Update content: motion level, and 3 spatial prediction errors. 861 // High motion, medium spatial. 862 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium, 863 kSpatialMedium); 864 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 865 EXPECT_EQ(5, qm_resolution_->ComputeContentClass()); 866 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 867 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f, 868 480, 270, 10.0f)); 869 870 // Reset and go to very low rate: no action should be taken, 871 // we went down too much already. 872 qm_resolution_->ResetRates(); 873 qm_resolution_->UpdateCodecParameters(10.0f, 480, 270); 874 EXPECT_EQ(3, qm_resolution_->GetImageType(480, 270)); 875 // Update rates for a sequence of intervals. 876 int target_rate3[] = {10, 10, 10, 10, 10}; 877 int encoder_sent_rate3[] = {10, 10, 10, 10, 10}; 878 int incoming_frame_rate3[] = {10, 10, 10, 10, 10}; 879 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10}; 880 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3, 881 fraction_lost3, 5); 882 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 883 EXPECT_EQ(5, qm_resolution_->ComputeContentClass()); 884 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 885 EXPECT_TRUE( 886 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 480, 270, 10.0f)); 887 } 888 889 // Multiple down-sampling stages and then undo all of them. 890 // Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3, 891 // followed by spatial 3/4x3/4. Then go up to full state, 892 // as encoding rate has increased. 893 TEST_F(QmSelectTest, MultipleStagesCheckActionHistory1) { 894 // Initialize with bitrate, frame rate, native system width/height, and 895 // number of temporal layers. 896 InitQmNativeData(150, 30, 640, 480, 1); 897 898 // Update with encoder frame size. 899 uint16_t codec_width = 640; 900 uint16_t codec_height = 480; 901 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 902 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 903 904 // Go down spatial 3/4x3/4. 905 // Update rates for a sequence of intervals. 906 int target_rate[] = {150, 150, 150}; 907 int encoder_sent_rate[] = {150, 150, 150}; 908 int incoming_frame_rate[] = {30, 30, 30}; 909 uint8_t fraction_lost[] = {10, 10, 10}; 910 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 911 fraction_lost, 3); 912 913 // Update content: motion level, and 3 spatial prediction errors. 914 // Medium motion, low spatial. 915 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow); 916 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 917 EXPECT_EQ(6, qm_resolution_->ComputeContentClass()); 918 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 919 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f, 920 480, 360, 30.0f)); 921 // Go down 2/3 temporal. 922 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 923 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 924 qm_resolution_->ResetRates(); 925 int target_rate2[] = {100, 100, 100, 100, 100}; 926 int encoder_sent_rate2[] = {100, 100, 100, 100, 100}; 927 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 928 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 929 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 930 fraction_lost2, 5); 931 932 // Update content: motion level, and 3 spatial prediction errors. 933 // Low motion, high spatial. 934 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 935 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 936 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 937 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 938 EXPECT_TRUE( 939 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360, 20.5f)); 940 941 // Go down 3/4x3/4 spatial: 942 qm_resolution_->UpdateCodecParameters(20.0f, 480, 360); 943 qm_resolution_->ResetRates(); 944 int target_rate3[] = {80, 80, 80, 80, 80}; 945 int encoder_sent_rate3[] = {80, 80, 80, 80, 80}; 946 int incoming_frame_rate3[] = {20, 20, 20, 20, 20}; 947 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10}; 948 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3, 949 fraction_lost3, 5); 950 951 // Update content: motion level, and 3 spatial prediction errors. 952 // High motion, low spatial. 953 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow); 954 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 955 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 956 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 957 // The two spatial actions of 3/4x3/4 are converted to 1/2x1/2, 958 // so scale factor is 2.0. 959 EXPECT_TRUE( 960 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 20.0f)); 961 962 // Reset rates and go high up in rate: expect to go up: 963 // 1/2x1x2 spatial and 1/2 temporally. 964 965 // Go up 1/2x1/2 spatially and 1/2 temporally. Spatial is done in 2 stages. 966 qm_resolution_->UpdateCodecParameters(15.0f, 320, 240); 967 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 968 qm_resolution_->ResetRates(); 969 // Update rates for a sequence of intervals. 970 int target_rate4[] = {1000, 1000, 1000, 1000, 1000}; 971 int encoder_sent_rate4[] = {1000, 1000, 1000, 1000, 1000}; 972 int incoming_frame_rate4[] = {15, 15, 15, 15, 15}; 973 uint8_t fraction_lost4[] = {10, 10, 10, 10, 10}; 974 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4, 975 fraction_lost4, 5); 976 977 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 978 EXPECT_EQ(3, qm_resolution_->ComputeContentClass()); 979 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 980 float scale = (4.0f / 3.0f) / 2.0f; 981 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480, 982 360, 30.0f)); 983 984 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 985 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 986 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 987 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f, 988 640, 480, 30.0f)); 989 } 990 991 // Multiple down-sampling and up-sample stages, with partial undoing. 992 // Spatial down-sample 1/2x1/2, followed by temporal down-sample 2/3, undo the 993 // temporal, then another temporal, and then undo both spatial and temporal. 994 TEST_F(QmSelectTest, MultipleStagesCheckActionHistory2) { 995 // Initialize with bitrate, frame rate, native system width/height, and 996 // number of temporal layers. 997 InitQmNativeData(80, 30, 640, 480, 1); 998 999 // Update with encoder frame size. 1000 uint16_t codec_width = 640; 1001 uint16_t codec_height = 480; 1002 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 1003 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 1004 1005 // Go down 1/2x1/2 spatial. 1006 // Update rates for a sequence of intervals. 1007 int target_rate[] = {80, 80, 80}; 1008 int encoder_sent_rate[] = {80, 80, 80}; 1009 int incoming_frame_rate[] = {30, 30, 30}; 1010 uint8_t fraction_lost[] = {10, 10, 10}; 1011 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 1012 fraction_lost, 3); 1013 1014 // Update content: motion level, and 3 spatial prediction errors. 1015 // Medium motion, low spatial. 1016 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow); 1017 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1018 EXPECT_EQ(6, qm_resolution_->ComputeContentClass()); 1019 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1020 EXPECT_TRUE( 1021 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 1022 1023 // Go down 2/3 temporal. 1024 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240); 1025 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 1026 qm_resolution_->ResetRates(); 1027 int target_rate2[] = {40, 40, 40, 40, 40}; 1028 int encoder_sent_rate2[] = {40, 40, 40, 40, 40}; 1029 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 1030 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 1031 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 1032 fraction_lost2, 5); 1033 1034 // Update content: motion level, and 3 spatial prediction errors. 1035 // Medium motion, high spatial. 1036 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh, 1037 kSpatialHigh); 1038 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1039 EXPECT_EQ(7, qm_resolution_->ComputeContentClass()); 1040 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1041 EXPECT_TRUE( 1042 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f)); 1043 1044 // Go up 2/3 temporally. 1045 qm_resolution_->UpdateCodecParameters(20.0f, 320, 240); 1046 qm_resolution_->ResetRates(); 1047 // Update rates for a sequence of intervals. 1048 int target_rate3[] = {150, 150, 150, 150, 150}; 1049 int encoder_sent_rate3[] = {150, 150, 150, 150, 150}; 1050 int incoming_frame_rate3[] = {20, 20, 20, 20, 20}; 1051 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10}; 1052 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3, 1053 fraction_lost3, 5); 1054 1055 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1056 EXPECT_EQ(7, qm_resolution_->ComputeContentClass()); 1057 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1058 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 320, 1059 240, 30.0f)); 1060 1061 // Go down 2/3 temporal. 1062 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240); 1063 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240)); 1064 qm_resolution_->ResetRates(); 1065 int target_rate4[] = {40, 40, 40, 40, 40}; 1066 int encoder_sent_rate4[] = {40, 40, 40, 40, 40}; 1067 int incoming_frame_rate4[] = {30, 30, 30, 30, 30}; 1068 uint8_t fraction_lost4[] = {10, 10, 10, 10, 10}; 1069 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4, 1070 fraction_lost4, 5); 1071 1072 // Update content: motion level, and 3 spatial prediction errors. 1073 // Low motion, high spatial. 1074 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 1075 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1076 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 1077 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1078 EXPECT_TRUE( 1079 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f)); 1080 1081 // Go up spatial and temporal. Spatial undoing is done in 2 stages. 1082 qm_resolution_->UpdateCodecParameters(20.5f, 320, 240); 1083 qm_resolution_->ResetRates(); 1084 // Update rates for a sequence of intervals. 1085 int target_rate5[] = {1000, 1000, 1000, 1000, 1000}; 1086 int encoder_sent_rate5[] = {1000, 1000, 1000, 1000, 1000}; 1087 int incoming_frame_rate5[] = {20, 20, 20, 20, 20}; 1088 uint8_t fraction_lost5[] = {10, 10, 10, 10, 10}; 1089 UpdateQmRateData(target_rate5, encoder_sent_rate5, incoming_frame_rate5, 1090 fraction_lost5, 5); 1091 1092 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1093 float scale = (4.0f / 3.0f) / 2.0f; 1094 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480, 1095 360, 30.0f)); 1096 1097 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 1098 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 1099 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1100 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f, 1101 640, 480, 30.0f)); 1102 } 1103 1104 // Multiple down-sampling and up-sample stages, with partial undoing. 1105 // Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3, 1106 // undo the temporal 2/3, and then undo the spatial. 1107 TEST_F(QmSelectTest, MultipleStagesCheckActionHistory3) { 1108 // Initialize with bitrate, frame rate, native system width/height, and 1109 // number of temporal layers. 1110 InitQmNativeData(100, 30, 640, 480, 1); 1111 1112 // Update with encoder frame size. 1113 uint16_t codec_width = 640; 1114 uint16_t codec_height = 480; 1115 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 1116 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 1117 1118 // Go down 3/4x3/4 spatial. 1119 // Update rates for a sequence of intervals. 1120 int target_rate[] = {100, 100, 100}; 1121 int encoder_sent_rate[] = {100, 100, 100}; 1122 int incoming_frame_rate[] = {30, 30, 30}; 1123 uint8_t fraction_lost[] = {10, 10, 10}; 1124 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 1125 fraction_lost, 3); 1126 1127 // Update content: motion level, and 3 spatial prediction errors. 1128 // Medium motion, low spatial. 1129 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow); 1130 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1131 EXPECT_EQ(6, qm_resolution_->ComputeContentClass()); 1132 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1133 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f, 1134 480, 360, 30.0f)); 1135 1136 // Go down 2/3 temporal. 1137 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 1138 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 1139 qm_resolution_->ResetRates(); 1140 int target_rate2[] = {100, 100, 100, 100, 100}; 1141 int encoder_sent_rate2[] = {100, 100, 100, 100, 100}; 1142 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 1143 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 1144 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 1145 fraction_lost2, 5); 1146 1147 // Update content: motion level, and 3 spatial prediction errors. 1148 // Low motion, high spatial. 1149 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh); 1150 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1151 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 1152 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1153 EXPECT_TRUE( 1154 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360, 20.5f)); 1155 1156 // Go up 2/3 temporal. 1157 qm_resolution_->UpdateCodecParameters(20.5f, 480, 360); 1158 qm_resolution_->ResetRates(); 1159 // Update rates for a sequence of intervals. 1160 int target_rate3[] = {250, 250, 250, 250, 250}; 1161 int encoder_sent_rate3[] = {250, 250, 250, 250, 250}; 1162 int incoming_frame_rate3[] = {20, 20, 20, 20, 120}; 1163 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10}; 1164 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3, 1165 fraction_lost3, 5); 1166 1167 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1168 EXPECT_EQ(1, qm_resolution_->ComputeContentClass()); 1169 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1170 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 480, 1171 360, 30.0f)); 1172 1173 // Go up spatial. 1174 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 1175 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 1176 qm_resolution_->ResetRates(); 1177 int target_rate4[] = {500, 500, 500, 500, 500}; 1178 int encoder_sent_rate4[] = {500, 500, 500, 500, 500}; 1179 int incoming_frame_rate4[] = {30, 30, 30, 30, 30}; 1180 uint8_t fraction_lost4[] = {30, 30, 30, 30, 30}; 1181 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4, 1182 fraction_lost4, 5); 1183 1184 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1185 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1186 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f, 1187 640, 480, 30.0f)); 1188 } 1189 1190 // Two stages of 3/4x3/4 converted to one stage of 1/2x1/2. 1191 TEST_F(QmSelectTest, ConvertThreeQuartersToOneHalf) { 1192 // Initialize with bitrate, frame rate, native system width/height, and 1193 // number of temporal layers. 1194 InitQmNativeData(150, 30, 640, 480, 1); 1195 1196 // Update with encoder frame size. 1197 uint16_t codec_width = 640; 1198 uint16_t codec_height = 480; 1199 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height); 1200 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height)); 1201 1202 // Go down 3/4x3/4 spatial. 1203 // Update rates for a sequence of intervals. 1204 int target_rate[] = {150, 150, 150}; 1205 int encoder_sent_rate[] = {150, 150, 150}; 1206 int incoming_frame_rate[] = {30, 30, 30}; 1207 uint8_t fraction_lost[] = {10, 10, 10}; 1208 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate, 1209 fraction_lost, 3); 1210 1211 // Update content: motion level, and 3 spatial prediction errors. 1212 // Medium motion, low spatial. 1213 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow); 1214 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1215 EXPECT_EQ(6, qm_resolution_->ComputeContentClass()); 1216 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1217 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f, 1218 480, 360, 30.0f)); 1219 1220 // Set rates to go down another 3/4 spatial. Should be converted ton 1/2. 1221 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360); 1222 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360)); 1223 qm_resolution_->ResetRates(); 1224 int target_rate2[] = {100, 100, 100, 100, 100}; 1225 int encoder_sent_rate2[] = {100, 100, 100, 100, 100}; 1226 int incoming_frame_rate2[] = {30, 30, 30, 30, 30}; 1227 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10}; 1228 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2, 1229 fraction_lost2, 5); 1230 1231 // Update content: motion level, and 3 spatial prediction errors. 1232 // Medium motion, low spatial. 1233 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow); 1234 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_)); 1235 EXPECT_EQ(6, qm_resolution_->ComputeContentClass()); 1236 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState()); 1237 EXPECT_TRUE( 1238 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f)); 1239 } 1240 1241 void QmSelectTest::InitQmNativeData(float initial_bit_rate, 1242 int user_frame_rate, 1243 int native_width, 1244 int native_height, 1245 int num_layers) { 1246 EXPECT_EQ( 1247 0, qm_resolution_->Initialize(initial_bit_rate, user_frame_rate, 1248 native_width, native_height, num_layers)); 1249 } 1250 1251 void QmSelectTest::UpdateQmContentData(float motion_metric, 1252 float spatial_metric, 1253 float spatial_metric_horiz, 1254 float spatial_metric_vert) { 1255 content_metrics_->motion_magnitude = motion_metric; 1256 content_metrics_->spatial_pred_err = spatial_metric; 1257 content_metrics_->spatial_pred_err_h = spatial_metric_horiz; 1258 content_metrics_->spatial_pred_err_v = spatial_metric_vert; 1259 qm_resolution_->UpdateContent(content_metrics_); 1260 } 1261 1262 void QmSelectTest::UpdateQmEncodedFrame(size_t* encoded_size, 1263 size_t num_updates) { 1264 for (size_t i = 0; i < num_updates; ++i) { 1265 // Convert to bytes. 1266 size_t encoded_size_update = 1000 * encoded_size[i] / 8; 1267 qm_resolution_->UpdateEncodedSize(encoded_size_update); 1268 } 1269 } 1270 1271 void QmSelectTest::UpdateQmRateData(int* target_rate, 1272 int* encoder_sent_rate, 1273 int* incoming_frame_rate, 1274 uint8_t* fraction_lost, 1275 int num_updates) { 1276 for (int i = 0; i < num_updates; ++i) { 1277 float target_rate_update = target_rate[i]; 1278 float encoder_sent_rate_update = encoder_sent_rate[i]; 1279 float incoming_frame_rate_update = incoming_frame_rate[i]; 1280 uint8_t fraction_lost_update = fraction_lost[i]; 1281 qm_resolution_->UpdateRates(target_rate_update, encoder_sent_rate_update, 1282 incoming_frame_rate_update, 1283 fraction_lost_update); 1284 } 1285 } 1286 1287 // Check is the selected action from the QmResolution class is the same 1288 // as the expected scales from |fac_width|, |fac_height|, |fac_temp|. 1289 bool QmSelectTest::IsSelectedActionCorrect(VCMResolutionScale* qm_scale, 1290 float fac_width, 1291 float fac_height, 1292 float fac_temp, 1293 uint16_t new_width, 1294 uint16_t new_height, 1295 float new_frame_rate) { 1296 if (qm_scale->spatial_width_fact == fac_width && 1297 qm_scale->spatial_height_fact == fac_height && 1298 qm_scale->temporal_fact == fac_temp && 1299 qm_scale->codec_width == new_width && 1300 qm_scale->codec_height == new_height && 1301 qm_scale->frame_rate == new_frame_rate) { 1302 return true; 1303 } else { 1304 return false; 1305 } 1306 } 1307 } // namespace webrtc 1308