blob: a0a822c827f56b9f44f33af3cde5f01cac55d646 [file] [log] [blame]
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001/*
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
pbos@webrtc.orga4407322013-07-16 12:32:05 +000011#include "testing/gtest/include/gtest/gtest.h"
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000012
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010013#include "webrtc/modules/include/module_common_types.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010014#include "webrtc/modules/video_coding/qm_select.h"
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000015
16namespace webrtc {
17
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000018// Representative values of content metrics for: low/high/medium(default) state,
19// based on parameters settings in qm_select_data.h.
20const float kSpatialLow = 0.01f;
21const float kSpatialMedium = 0.03f;
22const float kSpatialHigh = 0.1f;
23const float kTemporalLow = 0.01f;
24const float kTemporalMedium = 0.06f;
25const float kTemporalHigh = 0.1f;
26
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000027class QmSelectTest : public ::testing::Test {
28 protected:
29 QmSelectTest()
philipel9d3ab612015-12-21 04:12:39 -080030 : qm_resolution_(new VCMQmResolution()),
31 content_metrics_(new VideoContentMetrics()),
32 qm_scale_(NULL) {}
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000033 VCMQmResolution* qm_resolution_;
34 VideoContentMetrics* content_metrics_;
35 VCMResolutionScale* qm_scale_;
36
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000037 void InitQmNativeData(float initial_bit_rate,
38 int user_frame_rate,
39 int native_width,
40 int native_height,
41 int num_layers);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000042
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000043 void UpdateQmEncodedFrame(size_t* encoded_size, size_t num_updates);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000044
45 void UpdateQmRateData(int* target_rate,
46 int* encoder_sent_rate,
47 int* incoming_frame_rate,
48 uint8_t* fraction_lost,
49 int num_updates);
50
51 void UpdateQmContentData(float motion_metric,
52 float spatial_metric,
53 float spatial_metric_horiz,
54 float spatial_metric_vert);
55
56 bool IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000057 float fac_width,
58 float fac_height,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +000059 float fac_temp,
60 uint16_t new_width,
61 uint16_t new_height,
62 float new_frame_rate);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000063
64 void TearDown() {
65 delete qm_resolution_;
66 delete content_metrics_;
67 }
68};
69
70TEST_F(QmSelectTest, HandleInputs) {
71 // Expect parameter error. Initialize with invalid inputs.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000072 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 0, 640, 480, 1));
73 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 640, 0, 1));
74 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 0, 480, 1));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000075
76 // Expect uninitialized error.: No valid initialization before selection.
77 EXPECT_EQ(-7, qm_resolution_->SelectResolution(&qm_scale_));
78
79 VideoContentMetrics* content_metrics = NULL;
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000080 EXPECT_EQ(0, qm_resolution_->Initialize(1000, 30, 640, 480, 1));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000081 qm_resolution_->UpdateContent(content_metrics);
82 // Content metrics are NULL: Expect success and no down-sampling action.
83 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
philipel9d3ab612015-12-21 04:12:39 -080084 EXPECT_TRUE(
85 IsSelectedActionCorrect(qm_scale_, 1.0, 1.0, 1.0, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000086}
87
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +000088// TODO(marpan): Add a test for number of temporal layers > 1.
89
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000090// No down-sampling action at high rates.
91TEST_F(QmSelectTest, NoActionHighRate) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +000092 // Initialize with bitrate, frame rate, native system width/height, and
93 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000094 InitQmNativeData(800, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000095
96 // Update with encoder frame size.
97 uint16_t codec_width = 640;
98 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +000099 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000100 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000101
102 // Update rates for a sequence of intervals.
103 int target_rate[] = {800, 800, 800};
104 int encoder_sent_rate[] = {800, 800, 800};
105 int incoming_frame_rate[] = {30, 30, 30};
106 uint8_t fraction_lost[] = {10, 10, 10};
107 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
108 fraction_lost, 3);
109
110 // Update content: motion level, and 3 spatial prediction errors.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000111 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000112 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
113 EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
114 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800115 EXPECT_TRUE(
116 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000117}
118
119// Rate is well below transition, down-sampling action is taken,
120// depending on the content state.
121TEST_F(QmSelectTest, DownActionLowRate) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000122 // Initialize with bitrate, frame rate, native system width/height, and
123 // number of temporal layers.
124 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000125
126 // Update with encoder frame size.
127 uint16_t codec_width = 640;
128 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000129 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000130 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000131
132 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000133 int target_rate[] = {50, 50, 50};
134 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000135 int incoming_frame_rate[] = {30, 30, 30};
136 uint8_t fraction_lost[] = {10, 10, 10};
137 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
138 fraction_lost, 3);
139
140 // Update content: motion level, and 3 spatial prediction errors.
141 // High motion, low spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000142 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000143 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
144 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
145 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800146 EXPECT_TRUE(
147 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000148
149 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000150 // Low motion, low spatial: 2/3 temporal is expected.
151 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000152 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
153 EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800154 EXPECT_TRUE(
155 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000156
157 qm_resolution_->ResetDownSamplingState();
158 // Medium motion, low spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000159 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000160 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
161 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800162 EXPECT_TRUE(
163 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000164
165 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000166 // High motion, high spatial: 2/3 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000167 UpdateQmContentData(kTemporalHigh, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000168 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
169 EXPECT_EQ(4, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800170 EXPECT_TRUE(
171 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000172
173 qm_resolution_->ResetDownSamplingState();
174 // Low motion, high spatial: 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000175 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000176 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
177 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800178 EXPECT_TRUE(
179 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000180
181 qm_resolution_->ResetDownSamplingState();
182 // Medium motion, high spatial: 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000183 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
184 kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000185 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
186 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800187 EXPECT_TRUE(
188 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000189
190 qm_resolution_->ResetDownSamplingState();
191 // High motion, medium spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000192 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
193 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000194 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
195 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000196 // Target frame rate for frame dropper should be the same as previous == 15.
philipel9d3ab612015-12-21 04:12:39 -0800197 EXPECT_TRUE(
198 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000199
200 qm_resolution_->ResetDownSamplingState();
201 // Low motion, medium spatial: high frame rate, so 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000202 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
203 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000204 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
205 EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800206 EXPECT_TRUE(
207 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000208
209 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000210 // Medium motion, medium spatial: high frame rate, so 2/3 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000211 UpdateQmContentData(kTemporalMedium, kSpatialMedium, kSpatialMedium,
212 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000213 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
214 EXPECT_EQ(8, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800215 EXPECT_TRUE(
216 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000217}
218
219// Rate mis-match is high, and we have over-shooting.
220// since target rate is below max for down-sampling, down-sampling is selected.
221TEST_F(QmSelectTest, DownActionHighRateMMOvershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000222 // Initialize with bitrate, frame rate, native system width/height, and
223 // number of temporal layers.
224 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000225
226 // Update with encoder frame size.
227 uint16_t codec_width = 640;
228 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000229 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000230 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000231
232 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000233 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000234 int encoder_sent_rate[] = {900, 900, 900};
235 int incoming_frame_rate[] = {30, 30, 30};
236 uint8_t fraction_lost[] = {10, 10, 10};
237 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
238 fraction_lost, 3);
239
240 // Update content: motion level, and 3 spatial prediction errors.
241 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000242 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000243 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
244 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
245 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800246 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
247 480, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000248
249 qm_resolution_->ResetDownSamplingState();
250 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000251 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000252 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
253 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800254 EXPECT_TRUE(
255 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000256}
257
258// Rate mis-match is high, target rate is below max for down-sampling,
259// but since we have consistent under-shooting, no down-sampling action.
260TEST_F(QmSelectTest, NoActionHighRateMMUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000261 // Initialize with bitrate, frame rate, native system width/height, and
262 // number of temporal layers.
263 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000264
265 // Update with encoder frame size.
266 uint16_t codec_width = 640;
267 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000268 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000269 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000270
271 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000272 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000273 int encoder_sent_rate[] = {100, 100, 100};
274 int incoming_frame_rate[] = {30, 30, 30};
275 uint8_t fraction_lost[] = {10, 10, 10};
276 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
277 fraction_lost, 3);
278
279 // Update content: motion level, and 3 spatial prediction errors.
280 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000281 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000282 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
283 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
284 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800285 EXPECT_TRUE(
286 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000287
288 qm_resolution_->ResetDownSamplingState();
289 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000290 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000291 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
292 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800293 EXPECT_TRUE(
294 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000295}
296
297// Buffer is underflowing, and target rate is below max for down-sampling,
298// so action is taken.
299TEST_F(QmSelectTest, DownActionBufferUnderflow) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000300 // Initialize with bitrate, frame rate, native system width/height, and
301 // number of temporal layers.
302 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000303
304 // Update with encoder frame size.
305 uint16_t codec_width = 640;
306 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000307 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000308 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000309
310 // Update with encoded size over a number of frames.
311 // per-frame bandwidth = 15 = 450/30: simulate (decoder) buffer underflow:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000312 size_t encoded_size[] = {200, 100, 50, 30, 60, 40, 20, 30, 20, 40};
313 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000314
315 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000316 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000317 int encoder_sent_rate[] = {450, 450, 450};
318 int incoming_frame_rate[] = {30, 30, 30};
319 uint8_t fraction_lost[] = {10, 10, 10};
320 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
321 fraction_lost, 3);
322
323 // Update content: motion level, and 3 spatial prediction errors.
324 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000325 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000326 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
327 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
328 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800329 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
330 480, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000331
332 qm_resolution_->ResetDownSamplingState();
333 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000334 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000335 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
336 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800337 EXPECT_TRUE(
338 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000339}
340
341// Target rate is below max for down-sampling, but buffer level is stable,
342// so no action is taken.
343TEST_F(QmSelectTest, NoActionBufferStable) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000344 // Initialize with bitrate, frame rate, native system width/height, and
345 // number of temporal layers.
346 InitQmNativeData(350, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000347
348 // Update with encoder frame size.
349 uint16_t codec_width = 640;
350 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000351 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000352 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000353
354 // Update with encoded size over a number of frames.
355 // per-frame bandwidth = 15 = 450/30: simulate stable (decoder) buffer levels.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000356 size_t encoded_size[] = {40, 10, 10, 16, 18, 20, 17, 20, 16, 15};
357 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000358
359 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000360 int target_rate[] = {350, 350, 350};
361 int encoder_sent_rate[] = {350, 450, 450};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000362 int incoming_frame_rate[] = {30, 30, 30};
363 uint8_t fraction_lost[] = {10, 10, 10};
364 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
365 fraction_lost, 3);
366
367 // Update content: motion level, and 3 spatial prediction errors.
368 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000369 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000370 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
371 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
372 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800373 EXPECT_TRUE(
374 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000375
376 qm_resolution_->ResetDownSamplingState();
377 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000378 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000379 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
380 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800381 EXPECT_TRUE(
382 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000383}
384
385// Very low rate, but no spatial down-sampling below some size (QCIF).
386TEST_F(QmSelectTest, LimitDownSpatialAction) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000387 // Initialize with bitrate, frame rate, native system width/height, and
388 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000389 InitQmNativeData(10, 30, 176, 144, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000390
391 // Update with encoder frame size.
392 uint16_t codec_width = 176;
393 uint16_t codec_height = 144;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000394 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000395 EXPECT_EQ(0, qm_resolution_->GetImageType(codec_width, codec_height));
396
397 // Update rates for a sequence of intervals.
398 int target_rate[] = {10, 10, 10};
399 int encoder_sent_rate[] = {10, 10, 10};
400 int incoming_frame_rate[] = {30, 30, 30};
401 uint8_t fraction_lost[] = {10, 10, 10};
402 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
403 fraction_lost, 3);
404
405 // Update content: motion level, and 3 spatial prediction errors.
406 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000407 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000408 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
409 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
410 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800411 EXPECT_TRUE(
412 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 176, 144, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000413}
414
415// Very low rate, but no frame reduction below some frame_rate (8fps).
416TEST_F(QmSelectTest, LimitDownTemporalAction) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000417 // Initialize with bitrate, frame rate, native system width/height, and
418 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000419 InitQmNativeData(10, 8, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000420
421 // Update with encoder frame size.
422 uint16_t codec_width = 640;
423 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000424 qm_resolution_->UpdateCodecParameters(8.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000425 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000426
427 // Update rates for a sequence of intervals.
428 int target_rate[] = {10, 10, 10};
429 int encoder_sent_rate[] = {10, 10, 10};
430 int incoming_frame_rate[] = {8, 8, 8};
431 uint8_t fraction_lost[] = {10, 10, 10};
432 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
433 fraction_lost, 3);
434
435 // Update content: motion level, and 3 spatial prediction errors.
436 // Low motion, medium spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000437 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
438 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000439 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
440 EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
441 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800442 EXPECT_TRUE(
443 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 8.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000444}
445
446// Two stages: spatial down-sample and then back up spatially,
447// as rate as increased.
448TEST_F(QmSelectTest, 2StageDownSpatialUpSpatial) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000449 // Initialize with bitrate, frame rate, native system width/height, and
450 // number of temporal layers.
451 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000452
453 // Update with encoder frame size.
454 uint16_t codec_width = 640;
455 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000456 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000457 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000458
459 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000460 int target_rate[] = {50, 50, 50};
461 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000462 int incoming_frame_rate[] = {30, 30, 30};
463 uint8_t fraction_lost[] = {10, 10, 10};
464 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
philipel9d3ab612015-12-21 04:12:39 -0800465 fraction_lost, 3);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000466
467 // Update content: motion level, and 3 spatial prediction errors.
468 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000469 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000470 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
471 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
472 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800473 EXPECT_TRUE(
474 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000475
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000476 // Reset and go up in rate: expected to go back up, in 2 stages of 3/4.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000477 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000478 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000479 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000480 // Update rates for a sequence of intervals.
481 int target_rate2[] = {400, 400, 400, 400, 400};
482 int encoder_sent_rate2[] = {400, 400, 400, 400, 400};
483 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
484 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
485 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
486 fraction_lost2, 5);
487 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
488 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000489 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -0800490 EXPECT_TRUE(
491 IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000492
493 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
494 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
495 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
496 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
497 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000498}
499
500// Two stages: spatial down-sample and then back up spatially, since encoder
501// is under-shooting target even though rate has not increased much.
502TEST_F(QmSelectTest, 2StageDownSpatialUpSpatialUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000503 // Initialize with bitrate, frame rate, native system width/height, and
504 // number of temporal layers.
505 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000506
507 // Update with encoder frame size.
508 uint16_t codec_width = 640;
509 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000510 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000511 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000512
513 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000514 int target_rate[] = {50, 50, 50};
515 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000516 int incoming_frame_rate[] = {30, 30, 30};
517 uint8_t fraction_lost[] = {10, 10, 10};
518 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
philipel9d3ab612015-12-21 04:12:39 -0800519 fraction_lost, 3);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000520
521 // Update content: motion level, and 3 spatial prediction errors.
522 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000523 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000524 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
525 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
526 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800527 EXPECT_TRUE(
528 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000529
530 // Reset rates and simulate under-shooting scenario.: expect to go back up.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000531 // Goes up spatially in two stages for 1/2x1/2 down-sampling.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000532 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000533 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000534 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000535 // Update rates for a sequence of intervals.
536 int target_rate2[] = {200, 200, 200, 200, 200};
537 int encoder_sent_rate2[] = {50, 50, 50, 50, 50};
538 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
539 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
540 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
541 fraction_lost2, 5);
542 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
543 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000544 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -0800545 EXPECT_TRUE(
546 IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000547
548 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
549 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
550 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
551 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
552 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000553}
554
555// Two stages: spatial down-sample and then no action to go up,
556// as encoding rate mis-match is too high.
557TEST_F(QmSelectTest, 2StageDownSpatialNoActionUp) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000558 // Initialize with bitrate, frame rate, native system width/height, and
559 // number of temporal layers.
560 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000561
562 // Update with encoder frame size.
563 uint16_t codec_width = 640;
564 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000565 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000566 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000567
568 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000569 int target_rate[] = {50, 50, 50};
570 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000571 int incoming_frame_rate[] = {30, 30, 30};
572 uint8_t fraction_lost[] = {10, 10, 10};
573 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
philipel9d3ab612015-12-21 04:12:39 -0800574 fraction_lost, 3);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000575
576 // Update content: motion level, and 3 spatial prediction errors.
577 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000578 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000579 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
580 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
581 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800582 EXPECT_TRUE(
583 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000584
585 // Reset and simulate large rate mis-match: expect no action to go back up.
586 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000587 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000588 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000589 // Update rates for a sequence of intervals.
590 int target_rate2[] = {400, 400, 400, 400, 400};
591 int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000};
592 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
593 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
594 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
595 fraction_lost2, 5);
596 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
597 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800598 EXPECT_TRUE(
599 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000600}
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000601
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000602// Two stages: temporally down-sample and then back up temporally,
603// as rate as increased.
604TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporal) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000605 // Initialize with bitrate, frame rate, native system width/height, and
606 // number of temporal layers.
607 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000608
609 // Update with encoder frame size.
610 uint16_t codec_width = 640;
611 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000612 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000613 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000614
615 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000616 int target_rate[] = {50, 50, 50};
617 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000618 int incoming_frame_rate[] = {30, 30, 30};
619 uint8_t fraction_lost[] = {10, 10, 10};
620 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
621 fraction_lost, 3);
622
623 // Update content: motion level, and 3 spatial prediction errors.
624 // Low motion, high spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000625 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000626 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
627 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
628 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800629 EXPECT_TRUE(
630 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000631
632 // Reset rates and go up in rate: expect to go back up.
633 qm_resolution_->ResetRates();
634 // Update rates for a sequence of intervals.
635 int target_rate2[] = {400, 400, 400, 400, 400};
636 int encoder_sent_rate2[] = {400, 400, 400, 400, 400};
637 int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
638 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
639 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
640 fraction_lost2, 5);
641 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
642 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800643 EXPECT_TRUE(
644 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000645}
646
647// Two stages: temporal down-sample and then back up temporally, since encoder
648// is under-shooting target even though rate has not increased much.
649TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporalUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000650 // Initialize with bitrate, frame rate, native system width/height, and
651 // number of temporal layers.
652 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000653
654 // Update with encoder frame size.
655 uint16_t codec_width = 640;
656 uint16_t codec_height = 480;
657 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
658 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
659
660 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000661 int target_rate[] = {50, 50, 50};
662 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000663 int incoming_frame_rate[] = {30, 30, 30};
664 uint8_t fraction_lost[] = {10, 10, 10};
665 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
philipel9d3ab612015-12-21 04:12:39 -0800666 fraction_lost, 3);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000667
668 // Update content: motion level, and 3 spatial prediction errors.
669 // Low motion, high spatial.
670 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
671 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
672 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
673 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800674 EXPECT_TRUE(
675 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000676
677 // Reset rates and simulate under-shooting scenario.: expect to go back up.
678 qm_resolution_->ResetRates();
679 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000680 int target_rate2[] = {150, 150, 150, 150, 150};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000681 int encoder_sent_rate2[] = {50, 50, 50, 50, 50};
682 int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
683 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
684 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
685 fraction_lost2, 5);
686 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
687 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800688 EXPECT_TRUE(
689 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000690}
691
692// Two stages: temporal down-sample and then no action to go up,
693// as encoding rate mis-match is too high.
694TEST_F(QmSelectTest, 2StageDownTemporalNoActionUp) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000695 // Initialize with bitrate, frame rate, native system width/height, and
696 // number of temporal layers.
697 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000698
699 // Update with encoder frame size.
700 uint16_t codec_width = 640;
701 uint16_t codec_height = 480;
702 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
703 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
704
705 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000706 int target_rate[] = {50, 50, 50};
707 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000708 int incoming_frame_rate[] = {30, 30, 30};
709 uint8_t fraction_lost[] = {10, 10, 10};
710 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
711 fraction_lost, 3);
712
713 // Update content: motion level, and 3 spatial prediction errors.
714 // Low motion, high spatial.
715 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
716 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
717 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
718 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
719 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1, 1, 2, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000720
721 // Reset and simulate large rate mis-match: expect no action to go back up.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000722 qm_resolution_->UpdateCodecParameters(15.0f, codec_width, codec_height);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000723 qm_resolution_->ResetRates();
724 // Update rates for a sequence of intervals.
725 int target_rate2[] = {600, 600, 600, 600, 600};
726 int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000};
727 int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
728 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
729 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
730 fraction_lost2, 5);
731 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
732 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800733 EXPECT_TRUE(
734 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 15.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000735}
736// 3 stages: spatial down-sample, followed by temporal down-sample,
737// and then go up to full state, as encoding rate has increased.
738TEST_F(QmSelectTest, 3StageDownSpatialTemporlaUpSpatialTemporal) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000739 // Initialize with bitrate, frame rate, native system width/height, and
740 // number of temporal layers.
741 InitQmNativeData(80, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000742
743 // Update with encoder frame size.
744 uint16_t codec_width = 640;
745 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000746 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000747 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000748
749 // Update rates for a sequence of intervals.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000750 int target_rate[] = {80, 80, 80};
751 int encoder_sent_rate[] = {80, 80, 80};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000752 int incoming_frame_rate[] = {30, 30, 30};
753 uint8_t fraction_lost[] = {10, 10, 10};
754 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
755 fraction_lost, 3);
756
757 // Update content: motion level, and 3 spatial prediction errors.
758 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000759 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000760 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
761 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
762 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800763 EXPECT_TRUE(
764 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000765
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000766 // Change content data: expect temporal down-sample.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000767 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000768 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000769
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000770 // Reset rates and go lower in rate.
771 qm_resolution_->ResetRates();
772 int target_rate2[] = {40, 40, 40, 40, 40};
773 int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
774 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
775 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
776 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
philipel9d3ab612015-12-21 04:12:39 -0800777 fraction_lost2, 5);
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000778
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000779 // Update content: motion level, and 3 spatial prediction errors.
780 // Low motion, high spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000781 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000782 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
783 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
784 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800785 EXPECT_TRUE(
786 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000787
788 // Reset rates and go high up in rate: expect to go back up both spatial
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000789 // and temporally. The 1/2x1/2 spatial is undone in two stages.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000790 qm_resolution_->ResetRates();
791 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000792 int target_rate3[] = {1000, 1000, 1000, 1000, 1000};
793 int encoder_sent_rate3[] = {1000, 1000, 1000, 1000, 1000};
794 int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
795 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
796 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
797 fraction_lost3, 5);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000798
799 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
800 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
801 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000802 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -0800803 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
804 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000805
806 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
807 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
808 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
809 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
810 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000811}
812
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000813// No down-sampling below some total amount.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000814TEST_F(QmSelectTest, NoActionTooMuchDownSampling) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000815 // Initialize with bitrate, frame rate, native system width/height, and
816 // number of temporal layers.
817 InitQmNativeData(150, 30, 1280, 720, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000818
819 // Update with encoder frame size.
820 uint16_t codec_width = 1280;
821 uint16_t codec_height = 720;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000822 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000823 EXPECT_EQ(7, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000824
825 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000826 int target_rate[] = {150, 150, 150};
827 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000828 int incoming_frame_rate[] = {30, 30, 30};
829 uint8_t fraction_lost[] = {10, 10, 10};
830 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
831 fraction_lost, 3);
832
833 // Update content: motion level, and 3 spatial prediction errors.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000834 // High motion, low spatial.
835 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000836 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
837 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
838 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800839 EXPECT_TRUE(
840 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 640, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000841
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000842 // Reset and lower rates to get another spatial action (3/4x3/4).
843 // Lower the frame rate for spatial to be selected again.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000844 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000845 qm_resolution_->UpdateCodecParameters(10.0f, 640, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000846 EXPECT_EQ(4, qm_resolution_->GetImageType(640, 360));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000847 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000848 int target_rate2[] = {70, 70, 70, 70, 70};
849 int encoder_sent_rate2[] = {70, 70, 70, 70, 70};
850 int incoming_frame_rate2[] = {10, 10, 10, 10, 10};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000851 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
852 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
853 fraction_lost2, 5);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000854
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000855 // Update content: motion level, and 3 spatial prediction errors.
856 // High motion, medium spatial.
857 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
858 kSpatialMedium);
859 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
860 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
861 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800862 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
863 480, 270, 10.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000864
865 // Reset and go to very low rate: no action should be taken,
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000866 // we went down too much already.
867 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000868 qm_resolution_->UpdateCodecParameters(10.0f, 480, 270);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000869 EXPECT_EQ(3, qm_resolution_->GetImageType(480, 270));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000870 // Update rates for a sequence of intervals.
871 int target_rate3[] = {10, 10, 10, 10, 10};
872 int encoder_sent_rate3[] = {10, 10, 10, 10, 10};
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000873 int incoming_frame_rate3[] = {10, 10, 10, 10, 10};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000874 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
875 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
876 fraction_lost3, 5);
877 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000878 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
879 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800880 EXPECT_TRUE(
881 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 480, 270, 10.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000882}
883
884// Multiple down-sampling stages and then undo all of them.
885// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000886// followed by spatial 3/4x3/4. Then go up to full state,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000887// as encoding rate has increased.
888TEST_F(QmSelectTest, MultipleStagesCheckActionHistory1) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000889 // Initialize with bitrate, frame rate, native system width/height, and
890 // number of temporal layers.
891 InitQmNativeData(150, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000892
893 // Update with encoder frame size.
894 uint16_t codec_width = 640;
895 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000896 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000897 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
898
899 // Go down spatial 3/4x3/4.
900 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000901 int target_rate[] = {150, 150, 150};
902 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000903 int incoming_frame_rate[] = {30, 30, 30};
904 uint8_t fraction_lost[] = {10, 10, 10};
905 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
906 fraction_lost, 3);
907
908 // Update content: motion level, and 3 spatial prediction errors.
909 // Medium motion, low spatial.
910 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
911 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
912 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
913 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800914 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
915 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000916 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000917 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000918 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
919 qm_resolution_->ResetRates();
920 int target_rate2[] = {100, 100, 100, 100, 100};
921 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
922 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
923 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
924 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
925 fraction_lost2, 5);
926
927 // Update content: motion level, and 3 spatial prediction errors.
928 // Low motion, high spatial.
929 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
930 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
931 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
932 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800933 EXPECT_TRUE(
934 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000935
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000936 // Go down 3/4x3/4 spatial:
937 qm_resolution_->UpdateCodecParameters(20.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000938 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000939 int target_rate3[] = {80, 80, 80, 80, 80};
940 int encoder_sent_rate3[] = {80, 80, 80, 80, 80};
941 int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000942 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
943 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
philipel9d3ab612015-12-21 04:12:39 -0800944 fraction_lost3, 5);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000945
946 // Update content: motion level, and 3 spatial prediction errors.
947 // High motion, low spatial.
948 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
949 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000950 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
951 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000952 // The two spatial actions of 3/4x3/4 are converted to 1/2x1/2,
953 // so scale factor is 2.0.
philipel9d3ab612015-12-21 04:12:39 -0800954 EXPECT_TRUE(
955 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 20.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000956
957 // Reset rates and go high up in rate: expect to go up:
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000958 // 1/2x1x2 spatial and 1/2 temporally.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000959
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000960 // Go up 1/2x1/2 spatially and 1/2 temporally. Spatial is done in 2 stages.
961 qm_resolution_->UpdateCodecParameters(15.0f, 320, 240);
962 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000963 qm_resolution_->ResetRates();
964 // Update rates for a sequence of intervals.
965 int target_rate4[] = {1000, 1000, 1000, 1000, 1000};
966 int encoder_sent_rate4[] = {1000, 1000, 1000, 1000, 1000};
967 int incoming_frame_rate4[] = {15, 15, 15, 15, 15};
968 uint8_t fraction_lost4[] = {10, 10, 10, 10, 10};
969 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
970 fraction_lost4, 5);
971
972 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
973 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
974 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000975 float scale = (4.0f / 3.0f) / 2.0f;
976 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
977 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000978
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000979 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000980 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000981 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000982 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
983 640, 480, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000984}
985
986// Multiple down-sampling and up-sample stages, with partial undoing.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000987// Spatial down-sample 1/2x1/2, followed by temporal down-sample 2/3, undo the
988// temporal, then another temporal, and then undo both spatial and temporal.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000989TEST_F(QmSelectTest, MultipleStagesCheckActionHistory2) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000990 // Initialize with bitrate, frame rate, native system width/height, and
991 // number of temporal layers.
992 InitQmNativeData(80, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000993
994 // Update with encoder frame size.
995 uint16_t codec_width = 640;
996 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000997 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000998 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
999
1000 // Go down 1/2x1/2 spatial.
1001 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001002 int target_rate[] = {80, 80, 80};
1003 int encoder_sent_rate[] = {80, 80, 80};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001004 int incoming_frame_rate[] = {30, 30, 30};
1005 uint8_t fraction_lost[] = {10, 10, 10};
1006 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1007 fraction_lost, 3);
1008
1009 // Update content: motion level, and 3 spatial prediction errors.
1010 // Medium motion, low spatial.
1011 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1012 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1013 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1014 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001015 EXPECT_TRUE(
1016 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001017
1018 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001019 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001020 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
1021 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001022 int target_rate2[] = {40, 40, 40, 40, 40};
1023 int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001024 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1025 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1026 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1027 fraction_lost2, 5);
1028
1029 // Update content: motion level, and 3 spatial prediction errors.
1030 // Medium motion, high spatial.
1031 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
1032 kSpatialHigh);
1033 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1034 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
1035 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001036 EXPECT_TRUE(
1037 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001038
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001039 // Go up 2/3 temporally.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001040 qm_resolution_->UpdateCodecParameters(20.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001041 qm_resolution_->ResetRates();
1042 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001043 int target_rate3[] = {150, 150, 150, 150, 150};
1044 int encoder_sent_rate3[] = {150, 150, 150, 150, 150};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001045 int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
1046 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
1047 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
1048 fraction_lost3, 5);
1049
1050 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1051 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
1052 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001053 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 320,
1054 240, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001055
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001056 // Go down 2/3 temporal.
1057 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
1058 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001059 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001060 int target_rate4[] = {40, 40, 40, 40, 40};
1061 int encoder_sent_rate4[] = {40, 40, 40, 40, 40};
1062 int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001063 uint8_t fraction_lost4[] = {10, 10, 10, 10, 10};
1064 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1065 fraction_lost4, 5);
1066
1067 // Update content: motion level, and 3 spatial prediction errors.
1068 // Low motion, high spatial.
1069 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
1070 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1071 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1072 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001073 EXPECT_TRUE(
1074 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001075
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001076 // Go up spatial and temporal. Spatial undoing is done in 2 stages.
1077 qm_resolution_->UpdateCodecParameters(20.5f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001078 qm_resolution_->ResetRates();
1079 // Update rates for a sequence of intervals.
1080 int target_rate5[] = {1000, 1000, 1000, 1000, 1000};
1081 int encoder_sent_rate5[] = {1000, 1000, 1000, 1000, 1000};
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001082 int incoming_frame_rate5[] = {20, 20, 20, 20, 20};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001083 uint8_t fraction_lost5[] = {10, 10, 10, 10, 10};
1084 UpdateQmRateData(target_rate5, encoder_sent_rate5, incoming_frame_rate5,
1085 fraction_lost5, 5);
1086
1087 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001088 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -08001089 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
1090 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001091
1092 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1093 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1094 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1095 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
1096 640, 480, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001097}
1098
1099// Multiple down-sampling and up-sample stages, with partial undoing.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001100// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
1101// undo the temporal 2/3, and then undo the spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001102TEST_F(QmSelectTest, MultipleStagesCheckActionHistory3) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001103 // Initialize with bitrate, frame rate, native system width/height, and
1104 // number of temporal layers.
1105 InitQmNativeData(100, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001106
1107 // Update with encoder frame size.
1108 uint16_t codec_width = 640;
1109 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001110 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001111 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1112
1113 // Go down 3/4x3/4 spatial.
1114 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001115 int target_rate[] = {100, 100, 100};
1116 int encoder_sent_rate[] = {100, 100, 100};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001117 int incoming_frame_rate[] = {30, 30, 30};
1118 uint8_t fraction_lost[] = {10, 10, 10};
1119 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1120 fraction_lost, 3);
1121
1122 // Update content: motion level, and 3 spatial prediction errors.
1123 // Medium motion, low spatial.
1124 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1125 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1126 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1127 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001128 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
1129 480, 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001130
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001131 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001132 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001133 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1134 qm_resolution_->ResetRates();
1135 int target_rate2[] = {100, 100, 100, 100, 100};
1136 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
1137 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1138 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1139 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1140 fraction_lost2, 5);
1141
1142 // Update content: motion level, and 3 spatial prediction errors.
1143 // Low motion, high spatial.
1144 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
1145 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1146 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1147 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001148 EXPECT_TRUE(
1149 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001150
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001151 // Go up 2/3 temporal.
1152 qm_resolution_->UpdateCodecParameters(20.5f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001153 qm_resolution_->ResetRates();
1154 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001155 int target_rate3[] = {250, 250, 250, 250, 250};
1156 int encoder_sent_rate3[] = {250, 250, 250, 250, 250};
1157 int incoming_frame_rate3[] = {20, 20, 20, 20, 120};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001158 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
1159 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
1160 fraction_lost3, 5);
1161
1162 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1163 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1164 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001165 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 480,
1166 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001167
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001168 // Go up spatial.
1169 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1170 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001171 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001172 int target_rate4[] = {500, 500, 500, 500, 500};
1173 int encoder_sent_rate4[] = {500, 500, 500, 500, 500};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001174 int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001175 uint8_t fraction_lost4[] = {30, 30, 30, 30, 30};
1176 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1177 fraction_lost4, 5);
1178
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001179 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001180 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001181 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
1182 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001183}
1184
1185// Two stages of 3/4x3/4 converted to one stage of 1/2x1/2.
1186TEST_F(QmSelectTest, ConvertThreeQuartersToOneHalf) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001187 // Initialize with bitrate, frame rate, native system width/height, and
1188 // number of temporal layers.
1189 InitQmNativeData(150, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001190
1191 // Update with encoder frame size.
1192 uint16_t codec_width = 640;
1193 uint16_t codec_height = 480;
1194 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
1195 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1196
1197 // Go down 3/4x3/4 spatial.
1198 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001199 int target_rate[] = {150, 150, 150};
1200 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001201 int incoming_frame_rate[] = {30, 30, 30};
1202 uint8_t fraction_lost[] = {10, 10, 10};
1203 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1204 fraction_lost, 3);
1205
1206 // Update content: motion level, and 3 spatial prediction errors.
1207 // Medium motion, low spatial.
1208 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1209 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1210 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1211 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001212 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
1213 480, 360, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001214
1215 // Set rates to go down another 3/4 spatial. Should be converted ton 1/2.
1216 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1217 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1218 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001219 int target_rate2[] = {100, 100, 100, 100, 100};
1220 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001221 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1222 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1223 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1224 fraction_lost2, 5);
1225
1226 // Update content: motion level, and 3 spatial prediction errors.
1227 // Medium motion, low spatial.
1228 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1229 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1230 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1231 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001232 EXPECT_TRUE(
1233 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001234}
1235
1236void QmSelectTest::InitQmNativeData(float initial_bit_rate,
1237 int user_frame_rate,
1238 int native_width,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001239 int native_height,
1240 int num_layers) {
philipel9d3ab612015-12-21 04:12:39 -08001241 EXPECT_EQ(
1242 0, qm_resolution_->Initialize(initial_bit_rate, user_frame_rate,
1243 native_width, native_height, num_layers));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001244}
1245
1246void QmSelectTest::UpdateQmContentData(float motion_metric,
1247 float spatial_metric,
1248 float spatial_metric_horiz,
1249 float spatial_metric_vert) {
1250 content_metrics_->motion_magnitude = motion_metric;
1251 content_metrics_->spatial_pred_err = spatial_metric;
1252 content_metrics_->spatial_pred_err_h = spatial_metric_horiz;
1253 content_metrics_->spatial_pred_err_v = spatial_metric_vert;
1254 qm_resolution_->UpdateContent(content_metrics_);
1255}
1256
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001257void QmSelectTest::UpdateQmEncodedFrame(size_t* encoded_size,
1258 size_t num_updates) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001259 for (size_t i = 0; i < num_updates; ++i) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001260 // Convert to bytes.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001261 size_t encoded_size_update = 1000 * encoded_size[i] / 8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001262 qm_resolution_->UpdateEncodedSize(encoded_size_update);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001263 }
1264}
1265
1266void QmSelectTest::UpdateQmRateData(int* target_rate,
1267 int* encoder_sent_rate,
1268 int* incoming_frame_rate,
1269 uint8_t* fraction_lost,
1270 int num_updates) {
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001271 for (int i = 0; i < num_updates; ++i) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001272 float target_rate_update = target_rate[i];
1273 float encoder_sent_rate_update = encoder_sent_rate[i];
1274 float incoming_frame_rate_update = incoming_frame_rate[i];
1275 uint8_t fraction_lost_update = fraction_lost[i];
philipel9d3ab612015-12-21 04:12:39 -08001276 qm_resolution_->UpdateRates(target_rate_update, encoder_sent_rate_update,
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001277 incoming_frame_rate_update,
1278 fraction_lost_update);
1279 }
1280}
1281
1282// Check is the selected action from the QmResolution class is the same
1283// as the expected scales from |fac_width|, |fac_height|, |fac_temp|.
1284bool QmSelectTest::IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001285 float fac_width,
1286 float fac_height,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001287 float fac_temp,
1288 uint16_t new_width,
1289 uint16_t new_height,
1290 float new_frame_rate) {
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001291 if (qm_scale->spatial_width_fact == fac_width &&
1292 qm_scale->spatial_height_fact == fac_height &&
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001293 qm_scale->temporal_fact == fac_temp &&
1294 qm_scale->codec_width == new_width &&
1295 qm_scale->codec_height == new_height &&
1296 qm_scale->frame_rate == new_frame_rate) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001297 return true;
1298 } else {
1299 return false;
1300 }
1301}
1302} // namespace webrtc