blob: f8542ec67637f7d9b493be657b38fd5957af97fe [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
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
pbos@webrtc.orga4407322013-07-16 12:32:05 +000016#include "testing/gtest/include/gtest/gtest.h"
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000017
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010018#include "webrtc/modules/include/module_common_types.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010019#include "webrtc/modules/video_coding/qm_select.h"
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000020
21namespace webrtc {
22
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000023// Representative values of content metrics for: low/high/medium(default) state,
24// based on parameters settings in qm_select_data.h.
25const float kSpatialLow = 0.01f;
26const float kSpatialMedium = 0.03f;
27const float kSpatialHigh = 0.1f;
28const float kTemporalLow = 0.01f;
29const float kTemporalMedium = 0.06f;
30const float kTemporalHigh = 0.1f;
31
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000032class QmSelectTest : public ::testing::Test {
33 protected:
34 QmSelectTest()
philipel9d3ab612015-12-21 04:12:39 -080035 : qm_resolution_(new VCMQmResolution()),
36 content_metrics_(new VideoContentMetrics()),
37 qm_scale_(NULL) {}
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000038 VCMQmResolution* qm_resolution_;
39 VideoContentMetrics* content_metrics_;
40 VCMResolutionScale* qm_scale_;
41
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000042 void InitQmNativeData(float initial_bit_rate,
43 int user_frame_rate,
44 int native_width,
45 int native_height,
46 int num_layers);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000047
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000048 void UpdateQmEncodedFrame(size_t* encoded_size, size_t num_updates);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000049
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,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000062 float fac_width,
63 float fac_height,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +000064 float fac_temp,
65 uint16_t new_width,
66 uint16_t new_height,
67 float new_frame_rate);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000068
69 void TearDown() {
70 delete qm_resolution_;
71 delete content_metrics_;
72 }
73};
74
75TEST_F(QmSelectTest, HandleInputs) {
76 // Expect parameter error. Initialize with invalid inputs.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000077 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));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000080
81 // Expect uninitialized error.: No valid initialization before selection.
82 EXPECT_EQ(-7, qm_resolution_->SelectResolution(&qm_scale_));
83
84 VideoContentMetrics* content_metrics = NULL;
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000085 EXPECT_EQ(0, qm_resolution_->Initialize(1000, 30, 640, 480, 1));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000086 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_));
philipel9d3ab612015-12-21 04:12:39 -080089 EXPECT_TRUE(
90 IsSelectedActionCorrect(qm_scale_, 1.0, 1.0, 1.0, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000091}
92
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +000093// TODO(marpan): Add a test for number of temporal layers > 1.
94
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000095// No down-sampling action at high rates.
96TEST_F(QmSelectTest, NoActionHighRate) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +000097 // Initialize with bitrate, frame rate, native system width/height, and
98 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000099 InitQmNativeData(800, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000100
101 // Update with encoder frame size.
102 uint16_t codec_width = 640;
103 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000104 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000105 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000106
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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000116 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000117 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
118 EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
119 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800120 EXPECT_TRUE(
121 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000122}
123
124// Rate is well below transition, down-sampling action is taken,
125// depending on the content state.
126TEST_F(QmSelectTest, DownActionLowRate) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000127 // Initialize with bitrate, frame rate, native system width/height, and
128 // number of temporal layers.
129 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000130
131 // Update with encoder frame size.
132 uint16_t codec_width = 640;
133 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000134 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000135 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000136
137 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000138 int target_rate[] = {50, 50, 50};
139 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000140 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000147 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000148 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
149 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
150 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800151 EXPECT_TRUE(
152 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000153
154 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000155 // Low motion, low spatial: 2/3 temporal is expected.
156 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000157 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
158 EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800159 EXPECT_TRUE(
160 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000161
162 qm_resolution_->ResetDownSamplingState();
163 // Medium motion, low spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000164 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000165 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
166 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800167 EXPECT_TRUE(
168 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000169
170 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000171 // High motion, high spatial: 2/3 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000172 UpdateQmContentData(kTemporalHigh, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000173 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
174 EXPECT_EQ(4, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800175 EXPECT_TRUE(
176 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000177
178 qm_resolution_->ResetDownSamplingState();
179 // Low motion, high spatial: 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000180 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000181 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
182 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800183 EXPECT_TRUE(
184 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000185
186 qm_resolution_->ResetDownSamplingState();
187 // Medium motion, high spatial: 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000188 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
189 kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000190 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
191 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800192 EXPECT_TRUE(
193 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000194
195 qm_resolution_->ResetDownSamplingState();
196 // High motion, medium spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000197 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
198 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000199 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
200 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000201 // Target frame rate for frame dropper should be the same as previous == 15.
philipel9d3ab612015-12-21 04:12:39 -0800202 EXPECT_TRUE(
203 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000204
205 qm_resolution_->ResetDownSamplingState();
206 // Low motion, medium spatial: high frame rate, so 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000207 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
208 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000209 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
210 EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800211 EXPECT_TRUE(
212 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000213
214 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000215 // Medium motion, medium spatial: high frame rate, so 2/3 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000216 UpdateQmContentData(kTemporalMedium, kSpatialMedium, kSpatialMedium,
217 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000218 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
219 EXPECT_EQ(8, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800220 EXPECT_TRUE(
221 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000222}
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.
226TEST_F(QmSelectTest, DownActionHighRateMMOvershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000227 // Initialize with bitrate, frame rate, native system width/height, and
228 // number of temporal layers.
229 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000230
231 // Update with encoder frame size.
232 uint16_t codec_width = 640;
233 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000234 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000235 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000236
237 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000238 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000239 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000247 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000248 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
249 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
250 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800251 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
252 480, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000253
254 qm_resolution_->ResetDownSamplingState();
255 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000256 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000257 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
258 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800259 EXPECT_TRUE(
260 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000261}
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.
265TEST_F(QmSelectTest, NoActionHighRateMMUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000266 // Initialize with bitrate, frame rate, native system width/height, and
267 // number of temporal layers.
268 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000269
270 // Update with encoder frame size.
271 uint16_t codec_width = 640;
272 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000273 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000274 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000275
276 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000277 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000278 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000286 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000287 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
288 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
289 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800290 EXPECT_TRUE(
291 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000292
293 qm_resolution_->ResetDownSamplingState();
294 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000295 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000296 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
297 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800298 EXPECT_TRUE(
299 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000300}
301
302// Buffer is underflowing, and target rate is below max for down-sampling,
303// so action is taken.
304TEST_F(QmSelectTest, DownActionBufferUnderflow) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000305 // Initialize with bitrate, frame rate, native system width/height, and
306 // number of temporal layers.
307 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000308
309 // Update with encoder frame size.
310 uint16_t codec_width = 640;
311 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000312 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000313 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000314
315 // Update with encoded size over a number of frames.
316 // per-frame bandwidth = 15 = 450/30: simulate (decoder) buffer underflow:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000317 size_t encoded_size[] = {200, 100, 50, 30, 60, 40, 20, 30, 20, 40};
318 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000319
320 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000321 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000322 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000330 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000331 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
332 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
333 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800334 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
335 480, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000336
337 qm_resolution_->ResetDownSamplingState();
338 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000339 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000340 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
341 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800342 EXPECT_TRUE(
343 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000344}
345
346// Target rate is below max for down-sampling, but buffer level is stable,
347// so no action is taken.
348TEST_F(QmSelectTest, NoActionBufferStable) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000349 // Initialize with bitrate, frame rate, native system width/height, and
350 // number of temporal layers.
351 InitQmNativeData(350, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000352
353 // Update with encoder frame size.
354 uint16_t codec_width = 640;
355 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000356 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000357 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000358
359 // Update with encoded size over a number of frames.
360 // per-frame bandwidth = 15 = 450/30: simulate stable (decoder) buffer levels.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000361 size_t encoded_size[] = {40, 10, 10, 16, 18, 20, 17, 20, 16, 15};
362 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000363
364 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000365 int target_rate[] = {350, 350, 350};
366 int encoder_sent_rate[] = {350, 450, 450};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000367 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000374 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000375 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
376 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
377 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800378 EXPECT_TRUE(
379 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000380
381 qm_resolution_->ResetDownSamplingState();
382 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000383 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000384 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
385 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
philipel9d3ab612015-12-21 04:12:39 -0800386 EXPECT_TRUE(
387 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000388}
389
390// Very low rate, but no spatial down-sampling below some size (QCIF).
391TEST_F(QmSelectTest, LimitDownSpatialAction) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000392 // Initialize with bitrate, frame rate, native system width/height, and
393 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000394 InitQmNativeData(10, 30, 176, 144, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000395
396 // Update with encoder frame size.
397 uint16_t codec_width = 176;
398 uint16_t codec_height = 144;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000399 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000400 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000412 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000413 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
414 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
415 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800416 EXPECT_TRUE(
417 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 176, 144, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000418}
419
420// Very low rate, but no frame reduction below some frame_rate (8fps).
421TEST_F(QmSelectTest, LimitDownTemporalAction) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000422 // Initialize with bitrate, frame rate, native system width/height, and
423 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000424 InitQmNativeData(10, 8, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000425
426 // Update with encoder frame size.
427 uint16_t codec_width = 640;
428 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000429 qm_resolution_->UpdateCodecParameters(8.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000430 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000431
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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000442 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
443 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000444 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
445 EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
446 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800447 EXPECT_TRUE(
448 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 8.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000449}
450
451// Two stages: spatial down-sample and then back up spatially,
452// as rate as increased.
453TEST_F(QmSelectTest, 2StageDownSpatialUpSpatial) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000454 // Initialize with bitrate, frame rate, native system width/height, and
455 // number of temporal layers.
456 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000457
458 // Update with encoder frame size.
459 uint16_t codec_width = 640;
460 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000461 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000462 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000463
464 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000465 int target_rate[] = {50, 50, 50};
466 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000467 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,
philipel9d3ab612015-12-21 04:12:39 -0800470 fraction_lost, 3);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000471
472 // Update content: motion level, and 3 spatial prediction errors.
473 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000474 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000475 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
476 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
477 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800478 EXPECT_TRUE(
479 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000480
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000481 // 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 +0000482 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000483 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000484 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000485 // 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());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000494 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -0800495 EXPECT_TRUE(
496 IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000497
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));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000503}
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.
507TEST_F(QmSelectTest, 2StageDownSpatialUpSpatialUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000508 // Initialize with bitrate, frame rate, native system width/height, and
509 // number of temporal layers.
510 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000511
512 // Update with encoder frame size.
513 uint16_t codec_width = 640;
514 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000515 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000516 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000517
518 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000519 int target_rate[] = {50, 50, 50};
520 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000521 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,
philipel9d3ab612015-12-21 04:12:39 -0800524 fraction_lost, 3);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000525
526 // Update content: motion level, and 3 spatial prediction errors.
527 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000528 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000529 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
530 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
531 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800532 EXPECT_TRUE(
533 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000534
535 // Reset rates and simulate under-shooting scenario.: expect to go back up.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000536 // Goes up spatially in two stages for 1/2x1/2 down-sampling.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000537 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000538 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000539 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000540 // 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());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000549 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -0800550 EXPECT_TRUE(
551 IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000552
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));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000558}
559
560// Two stages: spatial down-sample and then no action to go up,
561// as encoding rate mis-match is too high.
562TEST_F(QmSelectTest, 2StageDownSpatialNoActionUp) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000563 // Initialize with bitrate, frame rate, native system width/height, and
564 // number of temporal layers.
565 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000566
567 // Update with encoder frame size.
568 uint16_t codec_width = 640;
569 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000570 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000571 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000572
573 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000574 int target_rate[] = {50, 50, 50};
575 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000576 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,
philipel9d3ab612015-12-21 04:12:39 -0800579 fraction_lost, 3);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000580
581 // Update content: motion level, and 3 spatial prediction errors.
582 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000583 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000584 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
585 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
586 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800587 EXPECT_TRUE(
588 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000589
590 // Reset and simulate large rate mis-match: expect no action to go back up.
591 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000592 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000593 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000594 // 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());
philipel9d3ab612015-12-21 04:12:39 -0800603 EXPECT_TRUE(
604 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000605}
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000606
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000607// Two stages: temporally down-sample and then back up temporally,
608// as rate as increased.
609TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporal) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000610 // Initialize with bitrate, frame rate, native system width/height, and
611 // number of temporal layers.
612 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000613
614 // Update with encoder frame size.
615 uint16_t codec_width = 640;
616 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000617 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000618 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000619
620 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000621 int target_rate[] = {50, 50, 50};
622 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000623 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000630 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000631 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
632 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
633 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800634 EXPECT_TRUE(
635 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000636
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());
philipel9d3ab612015-12-21 04:12:39 -0800648 EXPECT_TRUE(
649 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000650}
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.
654TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporalUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000655 // Initialize with bitrate, frame rate, native system width/height, and
656 // number of temporal layers.
657 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000658
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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000666 int target_rate[] = {50, 50, 50};
667 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000668 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,
philipel9d3ab612015-12-21 04:12:39 -0800671 fraction_lost, 3);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000672
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());
philipel9d3ab612015-12-21 04:12:39 -0800679 EXPECT_TRUE(
680 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480, 15.5f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000681
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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000685 int target_rate2[] = {150, 150, 150, 150, 150};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000686 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());
philipel9d3ab612015-12-21 04:12:39 -0800693 EXPECT_TRUE(
694 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000695}
696
697// Two stages: temporal down-sample and then no action to go up,
698// as encoding rate mis-match is too high.
699TEST_F(QmSelectTest, 2StageDownTemporalNoActionUp) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000700 // Initialize with bitrate, frame rate, native system width/height, and
701 // number of temporal layers.
702 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000703
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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000711 int target_rate[] = {50, 50, 50};
712 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000713 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));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000725
726 // Reset and simulate large rate mis-match: expect no action to go back up.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000727 qm_resolution_->UpdateCodecParameters(15.0f, codec_width, codec_height);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000728 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());
philipel9d3ab612015-12-21 04:12:39 -0800738 EXPECT_TRUE(
739 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480, 15.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000740}
741// 3 stages: spatial down-sample, followed by temporal down-sample,
742// and then go up to full state, as encoding rate has increased.
743TEST_F(QmSelectTest, 3StageDownSpatialTemporlaUpSpatialTemporal) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000744 // Initialize with bitrate, frame rate, native system width/height, and
745 // number of temporal layers.
746 InitQmNativeData(80, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000747
748 // Update with encoder frame size.
749 uint16_t codec_width = 640;
750 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000751 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000752 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000753
754 // Update rates for a sequence of intervals.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000755 int target_rate[] = {80, 80, 80};
756 int encoder_sent_rate[] = {80, 80, 80};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000757 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000764 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000765 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
766 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
767 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800768 EXPECT_TRUE(
769 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000770
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000771 // Change content data: expect temporal down-sample.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000772 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000773 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000774
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000775 // 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,
philipel9d3ab612015-12-21 04:12:39 -0800782 fraction_lost2, 5);
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000783
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000784 // Update content: motion level, and 3 spatial prediction errors.
785 // Low motion, high spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000786 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000787 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
788 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
789 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800790 EXPECT_TRUE(
791 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000792
793 // Reset rates and go high up in rate: expect to go back up both spatial
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000794 // and temporally. The 1/2x1/2 spatial is undone in two stages.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000795 qm_resolution_->ResetRates();
796 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000797 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);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000803
804 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
805 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
806 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000807 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -0800808 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
809 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000810
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));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000816}
817
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000818// No down-sampling below some total amount.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000819TEST_F(QmSelectTest, NoActionTooMuchDownSampling) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000820 // Initialize with bitrate, frame rate, native system width/height, and
821 // number of temporal layers.
822 InitQmNativeData(150, 30, 1280, 720, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000823
824 // Update with encoder frame size.
825 uint16_t codec_width = 1280;
826 uint16_t codec_height = 720;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000827 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000828 EXPECT_EQ(7, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000829
830 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000831 int target_rate[] = {150, 150, 150};
832 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000833 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000839 // High motion, low spatial.
840 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000841 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
842 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
843 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800844 EXPECT_TRUE(
845 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 640, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000846
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000847 // Reset and lower rates to get another spatial action (3/4x3/4).
848 // Lower the frame rate for spatial to be selected again.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000849 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000850 qm_resolution_->UpdateCodecParameters(10.0f, 640, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000851 EXPECT_EQ(4, qm_resolution_->GetImageType(640, 360));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000852 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000853 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};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000856 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
857 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
858 fraction_lost2, 5);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000859
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000860 // 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());
philipel9d3ab612015-12-21 04:12:39 -0800867 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
868 480, 270, 10.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000869
870 // Reset and go to very low rate: no action should be taken,
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000871 // we went down too much already.
872 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000873 qm_resolution_->UpdateCodecParameters(10.0f, 480, 270);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000874 EXPECT_EQ(3, qm_resolution_->GetImageType(480, 270));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000875 // 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};
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000878 int incoming_frame_rate3[] = {10, 10, 10, 10, 10};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000879 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_));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000883 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
884 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -0800885 EXPECT_TRUE(
886 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 480, 270, 10.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000887}
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,
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000891// followed by spatial 3/4x3/4. Then go up to full state,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000892// as encoding rate has increased.
893TEST_F(QmSelectTest, MultipleStagesCheckActionHistory1) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000894 // Initialize with bitrate, frame rate, native system width/height, and
895 // number of temporal layers.
896 InitQmNativeData(150, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000897
898 // Update with encoder frame size.
899 uint16_t codec_width = 640;
900 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000901 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000902 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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000906 int target_rate[] = {150, 150, 150};
907 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000908 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());
philipel9d3ab612015-12-21 04:12:39 -0800919 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
920 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000921 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000922 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000923 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());
philipel9d3ab612015-12-21 04:12:39 -0800938 EXPECT_TRUE(
939 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000940
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000941 // Go down 3/4x3/4 spatial:
942 qm_resolution_->UpdateCodecParameters(20.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000943 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000944 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};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000947 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
948 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
philipel9d3ab612015-12-21 04:12:39 -0800949 fraction_lost3, 5);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000950
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_));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000955 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
956 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000957 // The two spatial actions of 3/4x3/4 are converted to 1/2x1/2,
958 // so scale factor is 2.0.
philipel9d3ab612015-12-21 04:12:39 -0800959 EXPECT_TRUE(
960 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 20.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000961
962 // Reset rates and go high up in rate: expect to go up:
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000963 // 1/2x1x2 spatial and 1/2 temporally.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000964
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000965 // 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));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000968 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());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000980 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));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000983
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000984 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000985 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000986 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000987 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
988 640, 480, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000989}
990
991// Multiple down-sampling and up-sample stages, with partial undoing.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000992// 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.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000994TEST_F(QmSelectTest, MultipleStagesCheckActionHistory2) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000995 // Initialize with bitrate, frame rate, native system width/height, and
996 // number of temporal layers.
997 InitQmNativeData(80, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000998
999 // Update with encoder frame size.
1000 uint16_t codec_width = 640;
1001 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001002 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001003 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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001007 int target_rate[] = {80, 80, 80};
1008 int encoder_sent_rate[] = {80, 80, 80};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001009 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());
philipel9d3ab612015-12-21 04:12:39 -08001020 EXPECT_TRUE(
1021 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001022
1023 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001024 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001025 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
1026 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001027 int target_rate2[] = {40, 40, 40, 40, 40};
1028 int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001029 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());
philipel9d3ab612015-12-21 04:12:39 -08001041 EXPECT_TRUE(
1042 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001043
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001044 // Go up 2/3 temporally.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001045 qm_resolution_->UpdateCodecParameters(20.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001046 qm_resolution_->ResetRates();
1047 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001048 int target_rate3[] = {150, 150, 150, 150, 150};
1049 int encoder_sent_rate3[] = {150, 150, 150, 150, 150};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001050 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());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001058 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 320,
1059 240, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001060
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001061 // Go down 2/3 temporal.
1062 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
1063 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001064 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001065 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};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001068 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());
philipel9d3ab612015-12-21 04:12:39 -08001078 EXPECT_TRUE(
1079 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001080
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001081 // Go up spatial and temporal. Spatial undoing is done in 2 stages.
1082 qm_resolution_->UpdateCodecParameters(20.5f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001083 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};
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001087 int incoming_frame_rate5[] = {20, 20, 20, 20, 20};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001088 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_));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001093 float scale = (4.0f / 3.0f) / 2.0f;
philipel9d3ab612015-12-21 04:12:39 -08001094 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
1095 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001096
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));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001102}
1103
1104// Multiple down-sampling and up-sample stages, with partial undoing.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001105// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
1106// undo the temporal 2/3, and then undo the spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001107TEST_F(QmSelectTest, MultipleStagesCheckActionHistory3) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001108 // Initialize with bitrate, frame rate, native system width/height, and
1109 // number of temporal layers.
1110 InitQmNativeData(100, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001111
1112 // Update with encoder frame size.
1113 uint16_t codec_width = 640;
1114 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001115 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001116 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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001120 int target_rate[] = {100, 100, 100};
1121 int encoder_sent_rate[] = {100, 100, 100};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001122 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());
philipel9d3ab612015-12-21 04:12:39 -08001133 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
1134 480, 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001135
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001136 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001137 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001138 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());
philipel9d3ab612015-12-21 04:12:39 -08001153 EXPECT_TRUE(
1154 IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360, 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001155
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001156 // Go up 2/3 temporal.
1157 qm_resolution_->UpdateCodecParameters(20.5f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001158 qm_resolution_->ResetRates();
1159 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001160 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};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001163 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());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001170 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 480,
1171 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001172
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001173 // Go up spatial.
1174 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1175 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001176 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001177 int target_rate4[] = {500, 500, 500, 500, 500};
1178 int encoder_sent_rate4[] = {500, 500, 500, 500, 500};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001179 int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001180 uint8_t fraction_lost4[] = {30, 30, 30, 30, 30};
1181 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1182 fraction_lost4, 5);
1183
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001184 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001185 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
philipel9d3ab612015-12-21 04:12:39 -08001186 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
1187 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001188}
1189
1190// Two stages of 3/4x3/4 converted to one stage of 1/2x1/2.
1191TEST_F(QmSelectTest, ConvertThreeQuartersToOneHalf) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001192 // Initialize with bitrate, frame rate, native system width/height, and
1193 // number of temporal layers.
1194 InitQmNativeData(150, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001195
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.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001204 int target_rate[] = {150, 150, 150};
1205 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001206 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());
philipel9d3ab612015-12-21 04:12:39 -08001217 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f, 1.0f,
1218 480, 360, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001219
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();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001224 int target_rate2[] = {100, 100, 100, 100, 100};
1225 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001226 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());
philipel9d3ab612015-12-21 04:12:39 -08001237 EXPECT_TRUE(
1238 IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001239}
1240
1241void QmSelectTest::InitQmNativeData(float initial_bit_rate,
1242 int user_frame_rate,
1243 int native_width,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001244 int native_height,
1245 int num_layers) {
philipel9d3ab612015-12-21 04:12:39 -08001246 EXPECT_EQ(
1247 0, qm_resolution_->Initialize(initial_bit_rate, user_frame_rate,
1248 native_width, native_height, num_layers));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001249}
1250
1251void 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
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001262void QmSelectTest::UpdateQmEncodedFrame(size_t* encoded_size,
1263 size_t num_updates) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001264 for (size_t i = 0; i < num_updates; ++i) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001265 // Convert to bytes.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001266 size_t encoded_size_update = 1000 * encoded_size[i] / 8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001267 qm_resolution_->UpdateEncodedSize(encoded_size_update);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001268 }
1269}
1270
1271void QmSelectTest::UpdateQmRateData(int* target_rate,
1272 int* encoder_sent_rate,
1273 int* incoming_frame_rate,
1274 uint8_t* fraction_lost,
1275 int num_updates) {
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001276 for (int i = 0; i < num_updates; ++i) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001277 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];
philipel9d3ab612015-12-21 04:12:39 -08001281 qm_resolution_->UpdateRates(target_rate_update, encoder_sent_rate_update,
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001282 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|.
1289bool QmSelectTest::IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001290 float fac_width,
1291 float fac_height,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001292 float fac_temp,
1293 uint16_t new_width,
1294 uint16_t new_height,
1295 float new_frame_rate) {
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001296 if (qm_scale->spatial_width_fact == fac_width &&
1297 qm_scale->spatial_height_fact == fac_height &&
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001298 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) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001302 return true;
1303 } else {
1304 return false;
1305 }
1306}
1307} // namespace webrtc