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:
QmSelectTest()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
TearDown()69 void TearDown() {
70 delete qm_resolution_;
71 delete content_metrics_;
72 }
73 };
74
TEST_F(QmSelectTest,HandleInputs)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.
TEST_F(QmSelectTest,NoActionHighRate)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.
TEST_F(QmSelectTest,DownActionLowRate)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.
TEST_F(QmSelectTest,DownActionHighRateMMOvershoot)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.
TEST_F(QmSelectTest,NoActionHighRateMMUndershoot)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.
TEST_F(QmSelectTest,DownActionBufferUnderflow)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.
TEST_F(QmSelectTest,NoActionBufferStable)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).
TEST_F(QmSelectTest,LimitDownSpatialAction)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).
TEST_F(QmSelectTest,LimitDownTemporalAction)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.
TEST_F(QmSelectTest,NoActionTooMuchDownSampling)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.
TEST_F(QmSelectTest,MultipleStagesCheckActionHistory1)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.
TEST_F(QmSelectTest,MultipleStagesCheckActionHistory2)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.
TEST_F(QmSelectTest,MultipleStagesCheckActionHistory3)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.
TEST_F(QmSelectTest,ConvertThreeQuartersToOneHalf)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
InitQmNativeData(float initial_bit_rate,int user_frame_rate,int native_width,int native_height,int num_layers)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
UpdateQmContentData(float motion_metric,float spatial_metric,float spatial_metric_horiz,float spatial_metric_vert)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
UpdateQmEncodedFrame(size_t * encoded_size,size_t num_updates)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
UpdateQmRateData(int * target_rate,int * encoder_sent_rate,int * incoming_frame_rate,uint8_t * fraction_lost,int num_updates)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|.
IsSelectedActionCorrect(VCMResolutionScale * qm_scale,float fac_width,float fac_height,float fac_temp,uint16_t new_width,uint16_t new_height,float new_frame_rate)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