Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/webrtc/modules/video_coding/main/source/qm_select_unittest.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

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