blob: 61a12ef3e185a002775099bd51850292a12c9482 [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()
35 : qm_resolution_(new VCMQmResolution()),
36 content_metrics_(new VideoContentMetrics()),
37 qm_scale_(NULL) {
38 }
39 VCMQmResolution* qm_resolution_;
40 VideoContentMetrics* content_metrics_;
41 VCMResolutionScale* qm_scale_;
42
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000043 void InitQmNativeData(float initial_bit_rate,
44 int user_frame_rate,
45 int native_width,
46 int native_height,
47 int num_layers);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000048
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000049 void UpdateQmEncodedFrame(size_t* encoded_size, size_t num_updates);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000050
51 void UpdateQmRateData(int* target_rate,
52 int* encoder_sent_rate,
53 int* incoming_frame_rate,
54 uint8_t* fraction_lost,
55 int num_updates);
56
57 void UpdateQmContentData(float motion_metric,
58 float spatial_metric,
59 float spatial_metric_horiz,
60 float spatial_metric_vert);
61
62 bool IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000063 float fac_width,
64 float fac_height,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +000065 float fac_temp,
66 uint16_t new_width,
67 uint16_t new_height,
68 float new_frame_rate);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000069
70 void TearDown() {
71 delete qm_resolution_;
72 delete content_metrics_;
73 }
74};
75
76TEST_F(QmSelectTest, HandleInputs) {
77 // Expect parameter error. Initialize with invalid inputs.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000078 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 0, 640, 480, 1));
79 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 640, 0, 1));
80 EXPECT_EQ(-4, qm_resolution_->Initialize(1000, 30, 0, 480, 1));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000081
82 // Expect uninitialized error.: No valid initialization before selection.
83 EXPECT_EQ(-7, qm_resolution_->SelectResolution(&qm_scale_));
84
85 VideoContentMetrics* content_metrics = NULL;
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +000086 EXPECT_EQ(0, qm_resolution_->Initialize(1000, 30, 640, 480, 1));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000087 qm_resolution_->UpdateContent(content_metrics);
88 // Content metrics are NULL: Expect success and no down-sampling action.
89 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +000090 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0, 1.0, 1.0, 640, 480,
91 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000092}
93
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +000094// TODO(marpan): Add a test for number of temporal layers > 1.
95
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +000096// No down-sampling action at high rates.
97TEST_F(QmSelectTest, NoActionHighRate) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +000098 // Initialize with bitrate, frame rate, native system width/height, and
99 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000100 InitQmNativeData(800, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000101
102 // Update with encoder frame size.
103 uint16_t codec_width = 640;
104 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000105 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000106 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000107
108 // Update rates for a sequence of intervals.
109 int target_rate[] = {800, 800, 800};
110 int encoder_sent_rate[] = {800, 800, 800};
111 int incoming_frame_rate[] = {30, 30, 30};
112 uint8_t fraction_lost[] = {10, 10, 10};
113 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
114 fraction_lost, 3);
115
116 // Update content: motion level, and 3 spatial prediction errors.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000117 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000118 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
119 EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
120 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000121 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
122 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000123}
124
125// Rate is well below transition, down-sampling action is taken,
126// depending on the content state.
127TEST_F(QmSelectTest, DownActionLowRate) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000128 // Initialize with bitrate, frame rate, native system width/height, and
129 // number of temporal layers.
130 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000131
132 // Update with encoder frame size.
133 uint16_t codec_width = 640;
134 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000135 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000136 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000137
138 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000139 int target_rate[] = {50, 50, 50};
140 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000141 int incoming_frame_rate[] = {30, 30, 30};
142 uint8_t fraction_lost[] = {10, 10, 10};
143 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
144 fraction_lost, 3);
145
146 // Update content: motion level, and 3 spatial prediction errors.
147 // High motion, low spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000148 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000149 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
150 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
151 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000152 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
153 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000154
155 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000156 // Low motion, low spatial: 2/3 temporal is expected.
157 UpdateQmContentData(kTemporalLow, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000158 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
159 EXPECT_EQ(0, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000160 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
161 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000162
163 qm_resolution_->ResetDownSamplingState();
164 // Medium motion, low spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000165 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000166 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
167 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000168 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
169 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000170
171 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000172 // High motion, high spatial: 2/3 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000173 UpdateQmContentData(kTemporalHigh, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000174 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
175 EXPECT_EQ(4, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000176 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
177 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000178
179 qm_resolution_->ResetDownSamplingState();
180 // Low motion, high spatial: 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000181 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000182 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
183 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000184 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
185 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000186
187 qm_resolution_->ResetDownSamplingState();
188 // Medium motion, high spatial: 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000189 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
190 kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000191 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
192 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000193 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
194 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000195
196 qm_resolution_->ResetDownSamplingState();
197 // High motion, medium spatial: 2x2 spatial expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000198 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
199 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000200 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
201 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000202 // Target frame rate for frame dropper should be the same as previous == 15.
203 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
204 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000205
206 qm_resolution_->ResetDownSamplingState();
207 // Low motion, medium spatial: high frame rate, so 1/2 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000208 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
209 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000210 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
211 EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000212 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
213 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000214
215 qm_resolution_->ResetDownSamplingState();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000216 // Medium motion, medium spatial: high frame rate, so 2/3 temporal expected.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000217 UpdateQmContentData(kTemporalMedium, kSpatialMedium, kSpatialMedium,
218 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000219 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
220 EXPECT_EQ(8, qm_resolution_->ComputeContentClass());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000221 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
222 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000223}
224
225// Rate mis-match is high, and we have over-shooting.
226// since target rate is below max for down-sampling, down-sampling is selected.
227TEST_F(QmSelectTest, DownActionHighRateMMOvershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000228 // Initialize with bitrate, frame rate, native system width/height, and
229 // number of temporal layers.
230 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000231
232 // Update with encoder frame size.
233 uint16_t codec_width = 640;
234 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000235 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000236 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000237
238 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000239 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000240 int encoder_sent_rate[] = {900, 900, 900};
241 int incoming_frame_rate[] = {30, 30, 30};
242 uint8_t fraction_lost[] = {10, 10, 10};
243 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
244 fraction_lost, 3);
245
246 // Update content: motion level, and 3 spatial prediction errors.
247 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000248 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000249 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
250 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
251 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000252 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000253 1.0f, 480, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000254
255 qm_resolution_->ResetDownSamplingState();
256 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000257 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000258 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
259 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000260 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
261 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000262}
263
264// Rate mis-match is high, target rate is below max for down-sampling,
265// but since we have consistent under-shooting, no down-sampling action.
266TEST_F(QmSelectTest, NoActionHighRateMMUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000267 // Initialize with bitrate, frame rate, native system width/height, and
268 // number of temporal layers.
269 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000270
271 // Update with encoder frame size.
272 uint16_t codec_width = 640;
273 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000274 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000275 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000276
277 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000278 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000279 int encoder_sent_rate[] = {100, 100, 100};
280 int incoming_frame_rate[] = {30, 30, 30};
281 uint8_t fraction_lost[] = {10, 10, 10};
282 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
283 fraction_lost, 3);
284
285 // Update content: motion level, and 3 spatial prediction errors.
286 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000287 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000288 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
289 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
290 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000291 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
292 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000293
294 qm_resolution_->ResetDownSamplingState();
295 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000296 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000297 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
298 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000299 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
300 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000301}
302
303// Buffer is underflowing, and target rate is below max for down-sampling,
304// so action is taken.
305TEST_F(QmSelectTest, DownActionBufferUnderflow) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000306 // Initialize with bitrate, frame rate, native system width/height, and
307 // number of temporal layers.
308 InitQmNativeData(300, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000309
310 // Update with encoder frame size.
311 uint16_t codec_width = 640;
312 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000313 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000314 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000315
316 // Update with encoded size over a number of frames.
317 // per-frame bandwidth = 15 = 450/30: simulate (decoder) buffer underflow:
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000318 size_t encoded_size[] = {200, 100, 50, 30, 60, 40, 20, 30, 20, 40};
319 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000320
321 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000322 int target_rate[] = {300, 300, 300};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000323 int encoder_sent_rate[] = {450, 450, 450};
324 int incoming_frame_rate[] = {30, 30, 30};
325 uint8_t fraction_lost[] = {10, 10, 10};
326 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
327 fraction_lost, 3);
328
329 // Update content: motion level, and 3 spatial prediction errors.
330 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000331 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000332 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
333 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
334 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000335 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000336 1.0f, 480, 360, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000337
338 qm_resolution_->ResetDownSamplingState();
339 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000340 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000341 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
342 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000343 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 640, 480,
344 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000345}
346
347// Target rate is below max for down-sampling, but buffer level is stable,
348// so no action is taken.
349TEST_F(QmSelectTest, NoActionBufferStable) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000350 // Initialize with bitrate, frame rate, native system width/height, and
351 // number of temporal layers.
352 InitQmNativeData(350, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000353
354 // Update with encoder frame size.
355 uint16_t codec_width = 640;
356 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000357 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000358 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000359
360 // Update with encoded size over a number of frames.
361 // per-frame bandwidth = 15 = 450/30: simulate stable (decoder) buffer levels.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000362 size_t encoded_size[] = {40, 10, 10, 16, 18, 20, 17, 20, 16, 15};
363 UpdateQmEncodedFrame(encoded_size, GTEST_ARRAY_SIZE_(encoded_size));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000364
365 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000366 int target_rate[] = {350, 350, 350};
367 int encoder_sent_rate[] = {350, 450, 450};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000368 int incoming_frame_rate[] = {30, 30, 30};
369 uint8_t fraction_lost[] = {10, 10, 10};
370 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
371 fraction_lost, 3);
372
373 // Update content: motion level, and 3 spatial prediction errors.
374 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000375 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000376 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
377 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
378 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000379 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
380 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000381
382 qm_resolution_->ResetDownSamplingState();
383 // Low motion, high spatial
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000384 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000385 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
386 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000387 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
388 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000389}
390
391// Very low rate, but no spatial down-sampling below some size (QCIF).
392TEST_F(QmSelectTest, LimitDownSpatialAction) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000393 // Initialize with bitrate, frame rate, native system width/height, and
394 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000395 InitQmNativeData(10, 30, 176, 144, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000396
397 // Update with encoder frame size.
398 uint16_t codec_width = 176;
399 uint16_t codec_height = 144;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000400 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000401 EXPECT_EQ(0, qm_resolution_->GetImageType(codec_width, codec_height));
402
403 // Update rates for a sequence of intervals.
404 int target_rate[] = {10, 10, 10};
405 int encoder_sent_rate[] = {10, 10, 10};
406 int incoming_frame_rate[] = {30, 30, 30};
407 uint8_t fraction_lost[] = {10, 10, 10};
408 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
409 fraction_lost, 3);
410
411 // Update content: motion level, and 3 spatial prediction errors.
412 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000413 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000414 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
415 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
416 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000417 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 176, 144,
418 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000419}
420
421// Very low rate, but no frame reduction below some frame_rate (8fps).
422TEST_F(QmSelectTest, LimitDownTemporalAction) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000423 // Initialize with bitrate, frame rate, native system width/height, and
424 // number of temporal layers.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000425 InitQmNativeData(10, 8, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000426
427 // Update with encoder frame size.
428 uint16_t codec_width = 640;
429 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000430 qm_resolution_->UpdateCodecParameters(8.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000431 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000432
433 // Update rates for a sequence of intervals.
434 int target_rate[] = {10, 10, 10};
435 int encoder_sent_rate[] = {10, 10, 10};
436 int incoming_frame_rate[] = {8, 8, 8};
437 uint8_t fraction_lost[] = {10, 10, 10};
438 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
439 fraction_lost, 3);
440
441 // Update content: motion level, and 3 spatial prediction errors.
442 // Low motion, medium spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000443 UpdateQmContentData(kTemporalLow, kSpatialMedium, kSpatialMedium,
444 kSpatialMedium);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000445 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
446 EXPECT_EQ(2, qm_resolution_->ComputeContentClass());
447 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000448 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
449 8.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000450}
451
452// Two stages: spatial down-sample and then back up spatially,
453// as rate as increased.
454TEST_F(QmSelectTest, 2StageDownSpatialUpSpatial) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000455 // Initialize with bitrate, frame rate, native system width/height, and
456 // number of temporal layers.
457 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000458
459 // Update with encoder frame size.
460 uint16_t codec_width = 640;
461 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000462 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000463 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000464
465 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000466 int target_rate[] = {50, 50, 50};
467 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000468 int incoming_frame_rate[] = {30, 30, 30};
469 uint8_t fraction_lost[] = {10, 10, 10};
470 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
471 fraction_lost, 3);
472
473 // Update content: motion level, and 3 spatial prediction errors.
474 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000475 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000476 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
477 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
478 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000479 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
480 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000481
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000482 // 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 +0000483 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000484 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000485 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000486 // Update rates for a sequence of intervals.
487 int target_rate2[] = {400, 400, 400, 400, 400};
488 int encoder_sent_rate2[] = {400, 400, 400, 400, 400};
489 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
490 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
491 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
492 fraction_lost2, 5);
493 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
494 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000495 float scale = (4.0f / 3.0f) / 2.0f;
496 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000497 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000498
499 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
500 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
501 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
502 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
503 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000504}
505
506// Two stages: spatial down-sample and then back up spatially, since encoder
507// is under-shooting target even though rate has not increased much.
508TEST_F(QmSelectTest, 2StageDownSpatialUpSpatialUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000509 // Initialize with bitrate, frame rate, native system width/height, and
510 // number of temporal layers.
511 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000512
513 // Update with encoder frame size.
514 uint16_t codec_width = 640;
515 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000516 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000517 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000518
519 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000520 int target_rate[] = {50, 50, 50};
521 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000522 int incoming_frame_rate[] = {30, 30, 30};
523 uint8_t fraction_lost[] = {10, 10, 10};
524 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
525 fraction_lost, 3);
526
527 // Update content: motion level, and 3 spatial prediction errors.
528 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000529 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000530 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
531 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
532 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000533 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
534 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000535
536 // Reset rates and simulate under-shooting scenario.: expect to go back up.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000537 // Goes up spatially in two stages for 1/2x1/2 down-sampling.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000538 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000539 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000540 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000541 // Update rates for a sequence of intervals.
542 int target_rate2[] = {200, 200, 200, 200, 200};
543 int encoder_sent_rate2[] = {50, 50, 50, 50, 50};
544 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
545 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
546 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
547 fraction_lost2, 5);
548 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
549 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000550 float scale = (4.0f / 3.0f) / 2.0f;
551 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 1.0f, 480, 360,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000552 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000553
554 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
555 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
556 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
557 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
558 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000559}
560
561// Two stages: spatial down-sample and then no action to go up,
562// as encoding rate mis-match is too high.
563TEST_F(QmSelectTest, 2StageDownSpatialNoActionUp) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000564 // Initialize with bitrate, frame rate, native system width/height, and
565 // number of temporal layers.
566 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000567
568 // Update with encoder frame size.
569 uint16_t codec_width = 640;
570 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000571 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000572 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000573
574 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000575 int target_rate[] = {50, 50, 50};
576 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000577 int incoming_frame_rate[] = {30, 30, 30};
578 uint8_t fraction_lost[] = {10, 10, 10};
579 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
580 fraction_lost, 3);
581
582 // Update content: motion level, and 3 spatial prediction errors.
583 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000584 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000585 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
586 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
587 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000588 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
589 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000590
591 // Reset and simulate large rate mis-match: expect no action to go back up.
592 qm_resolution_->ResetRates();
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000593 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000594 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000595 // Update rates for a sequence of intervals.
596 int target_rate2[] = {400, 400, 400, 400, 400};
597 int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000};
598 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
599 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
600 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
601 fraction_lost2, 5);
602 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
603 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000604 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 320, 240,
605 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000606}
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000607
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000608// Two stages: temporally down-sample and then back up temporally,
609// as rate as increased.
610TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporal) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000611 // Initialize with bitrate, frame rate, native system width/height, and
612 // number of temporal layers.
613 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000614
615 // Update with encoder frame size.
616 uint16_t codec_width = 640;
617 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000618 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000619 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000620
621 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000622 int target_rate[] = {50, 50, 50};
623 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000624 int incoming_frame_rate[] = {30, 30, 30};
625 uint8_t fraction_lost[] = {10, 10, 10};
626 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
627 fraction_lost, 3);
628
629 // Update content: motion level, and 3 spatial prediction errors.
630 // Low motion, high spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000631 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000632 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
633 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
634 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000635 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
636 15.5f));
637
638 // Reset rates and go up in rate: expect to go back up.
639 qm_resolution_->ResetRates();
640 // Update rates for a sequence of intervals.
641 int target_rate2[] = {400, 400, 400, 400, 400};
642 int encoder_sent_rate2[] = {400, 400, 400, 400, 400};
643 int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
644 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
645 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
646 fraction_lost2, 5);
647 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
648 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
649 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480,
650 30.0f));
651}
652
653// Two stages: temporal down-sample and then back up temporally, since encoder
654// is under-shooting target even though rate has not increased much.
655TEST_F(QmSelectTest, 2StatgeDownTemporalUpTemporalUndershoot) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000656 // Initialize with bitrate, frame rate, native system width/height, and
657 // number of temporal layers.
658 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000659
660 // Update with encoder frame size.
661 uint16_t codec_width = 640;
662 uint16_t codec_height = 480;
663 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
664 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
665
666 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000667 int target_rate[] = {50, 50, 50};
668 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000669 int incoming_frame_rate[] = {30, 30, 30};
670 uint8_t fraction_lost[] = {10, 10, 10};
671 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
672 fraction_lost, 3);
673
674 // Update content: motion level, and 3 spatial prediction errors.
675 // Low motion, high spatial.
676 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
677 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
678 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
679 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
680 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f, 640, 480,
681 15.5f));
682
683 // Reset rates and simulate under-shooting scenario.: expect to go back up.
684 qm_resolution_->ResetRates();
685 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000686 int target_rate2[] = {150, 150, 150, 150, 150};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000687 int encoder_sent_rate2[] = {50, 50, 50, 50, 50};
688 int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
689 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
690 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
691 fraction_lost2, 5);
692 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
693 EXPECT_EQ(kEasyEncoding, qm_resolution_->GetEncoderState());
694 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 0.5f, 640, 480,
695 30.0f));
696}
697
698// Two stages: temporal down-sample and then no action to go up,
699// as encoding rate mis-match is too high.
700TEST_F(QmSelectTest, 2StageDownTemporalNoActionUp) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000701 // Initialize with bitrate, frame rate, native system width/height, and
702 // number of temporal layers.
703 InitQmNativeData(50, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000704
705 // Update with encoder frame size.
706 uint16_t codec_width = 640;
707 uint16_t codec_height = 480;
708 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
709 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
710
711 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000712 int target_rate[] = {50, 50, 50};
713 int encoder_sent_rate[] = {50, 50, 50};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000714 int incoming_frame_rate[] = {30, 30, 30};
715 uint8_t fraction_lost[] = {10, 10, 10};
716 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
717 fraction_lost, 3);
718
719 // Update content: motion level, and 3 spatial prediction errors.
720 // Low motion, high spatial.
721 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
722 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
723 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
724 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
725 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1, 1, 2, 640, 480, 15.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000726
727 // Reset and simulate large rate mis-match: expect no action to go back up.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000728 qm_resolution_->UpdateCodecParameters(15.0f, codec_width, codec_height);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000729 qm_resolution_->ResetRates();
730 // Update rates for a sequence of intervals.
731 int target_rate2[] = {600, 600, 600, 600, 600};
732 int encoder_sent_rate2[] = {1000, 1000, 1000, 1000, 1000};
733 int incoming_frame_rate2[] = {15, 15, 15, 15, 15};
734 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
735 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
736 fraction_lost2, 5);
737 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
738 EXPECT_EQ(kStressedEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000739 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 640, 480,
740 15.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000741}
742// 3 stages: spatial down-sample, followed by temporal down-sample,
743// and then go up to full state, as encoding rate has increased.
744TEST_F(QmSelectTest, 3StageDownSpatialTemporlaUpSpatialTemporal) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000745 // Initialize with bitrate, frame rate, native system width/height, and
746 // number of temporal layers.
747 InitQmNativeData(80, 30, 640, 480, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000748
749 // Update with encoder frame size.
750 uint16_t codec_width = 640;
751 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000752 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000753 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000754
755 // Update rates for a sequence of intervals.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000756 int target_rate[] = {80, 80, 80};
757 int encoder_sent_rate[] = {80, 80, 80};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000758 int incoming_frame_rate[] = {30, 30, 30};
759 uint8_t fraction_lost[] = {10, 10, 10};
760 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
761 fraction_lost, 3);
762
763 // Update content: motion level, and 3 spatial prediction errors.
764 // High motion, low spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000765 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000766 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
767 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
768 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000769 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
770 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000771
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000772 // Change content data: expect temporal down-sample.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000773 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000774 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000775
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000776 // Reset rates and go lower in rate.
777 qm_resolution_->ResetRates();
778 int target_rate2[] = {40, 40, 40, 40, 40};
779 int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
780 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
781 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
782 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
783 fraction_lost2, 5);
784
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000785 // Update content: motion level, and 3 spatial prediction errors.
786 // Low motion, high spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000787 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000788 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
789 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
790 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000791 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240,
792 20.5f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000793
794 // Reset rates and go high up in rate: expect to go back up both spatial
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000795 // and temporally. The 1/2x1/2 spatial is undone in two stages.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000796 qm_resolution_->ResetRates();
797 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000798 int target_rate3[] = {1000, 1000, 1000, 1000, 1000};
799 int encoder_sent_rate3[] = {1000, 1000, 1000, 1000, 1000};
800 int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
801 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
802 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
803 fraction_lost3, 5);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000804
805 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
806 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
807 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000808 float scale = (4.0f / 3.0f) / 2.0f;
809 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f,
810 480, 360, 30.0f));
811
812 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
813 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
814 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
815 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
816 640, 480, 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000817}
818
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000819// No down-sampling below some total amount.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000820TEST_F(QmSelectTest, NoActionTooMuchDownSampling) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000821 // Initialize with bitrate, frame rate, native system width/height, and
822 // number of temporal layers.
823 InitQmNativeData(150, 30, 1280, 720, 1);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000824
825 // Update with encoder frame size.
826 uint16_t codec_width = 1280;
827 uint16_t codec_height = 720;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000828 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000829 EXPECT_EQ(7, qm_resolution_->GetImageType(codec_width, codec_height));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000830
831 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000832 int target_rate[] = {150, 150, 150};
833 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000834 int incoming_frame_rate[] = {30, 30, 30};
835 uint8_t fraction_lost[] = {10, 10, 10};
836 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
837 fraction_lost, 3);
838
839 // Update content: motion level, and 3 spatial prediction errors.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000840 // High motion, low spatial.
841 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000842 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
843 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
844 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000845 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 640, 360,
846 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000847
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000848 // Reset and lower rates to get another spatial action (3/4x3/4).
849 // Lower the frame rate for spatial to be selected again.
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000850 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000851 qm_resolution_->UpdateCodecParameters(10.0f, 640, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000852 EXPECT_EQ(4, qm_resolution_->GetImageType(640, 360));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000853 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000854 int target_rate2[] = {70, 70, 70, 70, 70};
855 int encoder_sent_rate2[] = {70, 70, 70, 70, 70};
856 int incoming_frame_rate2[] = {10, 10, 10, 10, 10};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000857 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
858 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
859 fraction_lost2, 5);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000860
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000861 // Update content: motion level, and 3 spatial prediction errors.
862 // High motion, medium spatial.
863 UpdateQmContentData(kTemporalHigh, kSpatialMedium, kSpatialMedium,
864 kSpatialMedium);
865 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
866 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
867 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
868 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000869 1.0f, 480, 270, 10.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000870
871 // Reset and go to very low rate: no action should be taken,
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000872 // we went down too much already.
873 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000874 qm_resolution_->UpdateCodecParameters(10.0f, 480, 270);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000875 EXPECT_EQ(3, qm_resolution_->GetImageType(480, 270));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000876 // Update rates for a sequence of intervals.
877 int target_rate3[] = {10, 10, 10, 10, 10};
878 int encoder_sent_rate3[] = {10, 10, 10, 10, 10};
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000879 int incoming_frame_rate3[] = {10, 10, 10, 10, 10};
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000880 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
881 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
882 fraction_lost3, 5);
883 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000884 EXPECT_EQ(5, qm_resolution_->ComputeContentClass());
885 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000886 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.0f, 480, 270,
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000887 10.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000888}
889
890// Multiple down-sampling stages and then undo all of them.
891// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000892// followed by spatial 3/4x3/4. Then go up to full state,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000893// as encoding rate has increased.
894TEST_F(QmSelectTest, MultipleStagesCheckActionHistory1) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000895 // Initialize with bitrate, frame rate, native system width/height, and
896 // number of temporal layers.
897 InitQmNativeData(150, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000898
899 // Update with encoder frame size.
900 uint16_t codec_width = 640;
901 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000902 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000903 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
904
905 // Go down spatial 3/4x3/4.
906 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000907 int target_rate[] = {150, 150, 150};
908 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000909 int incoming_frame_rate[] = {30, 30, 30};
910 uint8_t fraction_lost[] = {10, 10, 10};
911 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
912 fraction_lost, 3);
913
914 // Update content: motion level, and 3 spatial prediction errors.
915 // Medium motion, low spatial.
916 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
917 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
918 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
919 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
920 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000921 1.0f, 480, 360, 30.0f));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000922 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000923 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000924 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
925 qm_resolution_->ResetRates();
926 int target_rate2[] = {100, 100, 100, 100, 100};
927 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
928 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
929 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
930 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
931 fraction_lost2, 5);
932
933 // Update content: motion level, and 3 spatial prediction errors.
934 // Low motion, high spatial.
935 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
936 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
937 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
938 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000939 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360,
940 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000941
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000942 // Go down 3/4x3/4 spatial:
943 qm_resolution_->UpdateCodecParameters(20.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000944 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000945 int target_rate3[] = {80, 80, 80, 80, 80};
946 int encoder_sent_rate3[] = {80, 80, 80, 80, 80};
947 int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000948 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
949 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
950 fraction_lost3, 5);
951
952 // Update content: motion level, and 3 spatial prediction errors.
953 // High motion, low spatial.
954 UpdateQmContentData(kTemporalHigh, kSpatialLow, kSpatialLow, kSpatialLow);
955 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +0000956 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
957 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000958 // The two spatial actions of 3/4x3/4 are converted to 1/2x1/2,
959 // so scale factor is 2.0.
960 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
961 20.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000962
963 // Reset rates and go high up in rate: expect to go up:
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000964 // 1/2x1x2 spatial and 1/2 temporally.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000965
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000966 // Go up 1/2x1/2 spatially and 1/2 temporally. Spatial is done in 2 stages.
967 qm_resolution_->UpdateCodecParameters(15.0f, 320, 240);
968 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000969 qm_resolution_->ResetRates();
970 // Update rates for a sequence of intervals.
971 int target_rate4[] = {1000, 1000, 1000, 1000, 1000};
972 int encoder_sent_rate4[] = {1000, 1000, 1000, 1000, 1000};
973 int incoming_frame_rate4[] = {15, 15, 15, 15, 15};
974 uint8_t fraction_lost4[] = {10, 10, 10, 10, 10};
975 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
976 fraction_lost4, 5);
977
978 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
979 EXPECT_EQ(3, qm_resolution_->ComputeContentClass());
980 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000981 float scale = (4.0f / 3.0f) / 2.0f;
982 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f, 480,
983 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000984
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +0000985 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000986 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000987 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000988 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
989 640, 480, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000990}
991
992// Multiple down-sampling and up-sample stages, with partial undoing.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000993// Spatial down-sample 1/2x1/2, followed by temporal down-sample 2/3, undo the
994// temporal, then another temporal, and then undo both spatial and temporal.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000995TEST_F(QmSelectTest, MultipleStagesCheckActionHistory2) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +0000996 // Initialize with bitrate, frame rate, native system width/height, and
997 // number of temporal layers.
998 InitQmNativeData(80, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +0000999
1000 // Update with encoder frame size.
1001 uint16_t codec_width = 640;
1002 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001003 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001004 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1005
1006 // Go down 1/2x1/2 spatial.
1007 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001008 int target_rate[] = {80, 80, 80};
1009 int encoder_sent_rate[] = {80, 80, 80};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001010 int incoming_frame_rate[] = {30, 30, 30};
1011 uint8_t fraction_lost[] = {10, 10, 10};
1012 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1013 fraction_lost, 3);
1014
1015 // Update content: motion level, and 3 spatial prediction errors.
1016 // Medium motion, low spatial.
1017 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1018 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1019 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1020 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001021 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
1022 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001023
1024 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001025 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001026 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
1027 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001028 int target_rate2[] = {40, 40, 40, 40, 40};
1029 int encoder_sent_rate2[] = {40, 40, 40, 40, 40};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001030 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1031 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1032 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1033 fraction_lost2, 5);
1034
1035 // Update content: motion level, and 3 spatial prediction errors.
1036 // Medium motion, high spatial.
1037 UpdateQmContentData(kTemporalMedium, kSpatialHigh, kSpatialHigh,
1038 kSpatialHigh);
1039 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1040 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
1041 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001042 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240,
1043 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001044
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001045 // Go up 2/3 temporally.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001046 qm_resolution_->UpdateCodecParameters(20.0f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001047 qm_resolution_->ResetRates();
1048 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001049 int target_rate3[] = {150, 150, 150, 150, 150};
1050 int encoder_sent_rate3[] = {150, 150, 150, 150, 150};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001051 int incoming_frame_rate3[] = {20, 20, 20, 20, 20};
1052 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
1053 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
1054 fraction_lost3, 5);
1055
1056 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1057 EXPECT_EQ(7, qm_resolution_->ComputeContentClass());
1058 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001059 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 320,
1060 240, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001061
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001062 // Go down 2/3 temporal.
1063 qm_resolution_->UpdateCodecParameters(30.0f, 320, 240);
1064 EXPECT_EQ(2, qm_resolution_->GetImageType(320, 240));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001065 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001066 int target_rate4[] = {40, 40, 40, 40, 40};
1067 int encoder_sent_rate4[] = {40, 40, 40, 40, 40};
1068 int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001069 uint8_t fraction_lost4[] = {10, 10, 10, 10, 10};
1070 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1071 fraction_lost4, 5);
1072
1073 // Update content: motion level, and 3 spatial prediction errors.
1074 // Low motion, high spatial.
1075 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
1076 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1077 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1078 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001079 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 320, 240,
1080 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001081
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001082 // Go up spatial and temporal. Spatial undoing is done in 2 stages.
1083 qm_resolution_->UpdateCodecParameters(20.5f, 320, 240);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001084 qm_resolution_->ResetRates();
1085 // Update rates for a sequence of intervals.
1086 int target_rate5[] = {1000, 1000, 1000, 1000, 1000};
1087 int encoder_sent_rate5[] = {1000, 1000, 1000, 1000, 1000};
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001088 int incoming_frame_rate5[] = {20, 20, 20, 20, 20};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001089 uint8_t fraction_lost5[] = {10, 10, 10, 10, 10};
1090 UpdateQmRateData(target_rate5, encoder_sent_rate5, incoming_frame_rate5,
1091 fraction_lost5, 5);
1092
1093 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001094 float scale = (4.0f / 3.0f) / 2.0f;
1095 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, scale, scale, 2.0f / 3.0f,
1096 480, 360, 30.0f));
1097
1098 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1099 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1100 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1101 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f, 1.0f,
1102 640, 480, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001103}
1104
1105// Multiple down-sampling and up-sample stages, with partial undoing.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001106// Spatial down-sample 3/4x3/4, followed by temporal down-sample 2/3,
1107// undo the temporal 2/3, and then undo the spatial.
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001108TEST_F(QmSelectTest, MultipleStagesCheckActionHistory3) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001109 // Initialize with bitrate, frame rate, native system width/height, and
1110 // number of temporal layers.
1111 InitQmNativeData(100, 30, 640, 480, 1);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001112
1113 // Update with encoder frame size.
1114 uint16_t codec_width = 640;
1115 uint16_t codec_height = 480;
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001116 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001117 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1118
1119 // Go down 3/4x3/4 spatial.
1120 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001121 int target_rate[] = {100, 100, 100};
1122 int encoder_sent_rate[] = {100, 100, 100};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001123 int incoming_frame_rate[] = {30, 30, 30};
1124 uint8_t fraction_lost[] = {10, 10, 10};
1125 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1126 fraction_lost, 3);
1127
1128 // Update content: motion level, and 3 spatial prediction errors.
1129 // Medium motion, low spatial.
1130 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1131 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1132 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1133 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1134 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001135 1.0f, 480, 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001136
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001137 // Go down 2/3 temporal.
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001138 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001139 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1140 qm_resolution_->ResetRates();
1141 int target_rate2[] = {100, 100, 100, 100, 100};
1142 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
1143 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1144 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1145 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1146 fraction_lost2, 5);
1147
1148 // Update content: motion level, and 3 spatial prediction errors.
1149 // Low motion, high spatial.
1150 UpdateQmContentData(kTemporalLow, kSpatialHigh, kSpatialHigh, kSpatialHigh);
1151 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1152 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1153 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001154 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 1.5f, 480, 360,
1155 20.5f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001156
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001157 // Go up 2/3 temporal.
1158 qm_resolution_->UpdateCodecParameters(20.5f, 480, 360);
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001159 qm_resolution_->ResetRates();
1160 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001161 int target_rate3[] = {250, 250, 250, 250, 250};
1162 int encoder_sent_rate3[] = {250, 250, 250, 250, 250};
1163 int incoming_frame_rate3[] = {20, 20, 20, 20, 120};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001164 uint8_t fraction_lost3[] = {10, 10, 10, 10, 10};
1165 UpdateQmRateData(target_rate3, encoder_sent_rate3, incoming_frame_rate3,
1166 fraction_lost3, 5);
1167
1168 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1169 EXPECT_EQ(1, qm_resolution_->ComputeContentClass());
1170 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001171 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 1.0f, 1.0f, 2.0f / 3.0f, 480,
1172 360, 30.0f));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001173
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001174 // Go up spatial.
1175 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1176 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001177 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001178 int target_rate4[] = {500, 500, 500, 500, 500};
1179 int encoder_sent_rate4[] = {500, 500, 500, 500, 500};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001180 int incoming_frame_rate4[] = {30, 30, 30, 30, 30};
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001181 uint8_t fraction_lost4[] = {30, 30, 30, 30, 30};
1182 UpdateQmRateData(target_rate4, encoder_sent_rate4, incoming_frame_rate4,
1183 fraction_lost4, 5);
1184
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001185 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001186 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001187 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 3.0f / 4.0f, 3.0f / 4.0f,
1188 1.0f, 640, 480, 30.0f));
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001189}
1190
1191// Two stages of 3/4x3/4 converted to one stage of 1/2x1/2.
1192TEST_F(QmSelectTest, ConvertThreeQuartersToOneHalf) {
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001193 // Initialize with bitrate, frame rate, native system width/height, and
1194 // number of temporal layers.
1195 InitQmNativeData(150, 30, 640, 480, 1);
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001196
1197 // Update with encoder frame size.
1198 uint16_t codec_width = 640;
1199 uint16_t codec_height = 480;
1200 qm_resolution_->UpdateCodecParameters(30.0f, codec_width, codec_height);
1201 EXPECT_EQ(5, qm_resolution_->GetImageType(codec_width, codec_height));
1202
1203 // Go down 3/4x3/4 spatial.
1204 // Update rates for a sequence of intervals.
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001205 int target_rate[] = {150, 150, 150};
1206 int encoder_sent_rate[] = {150, 150, 150};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001207 int incoming_frame_rate[] = {30, 30, 30};
1208 uint8_t fraction_lost[] = {10, 10, 10};
1209 UpdateQmRateData(target_rate, encoder_sent_rate, incoming_frame_rate,
1210 fraction_lost, 3);
1211
1212 // Update content: motion level, and 3 spatial prediction errors.
1213 // Medium motion, low spatial.
1214 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1215 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1216 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1217 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1218 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 4.0f / 3.0f, 4.0f / 3.0f,
1219 1.0f, 480, 360, 30.0f));
1220
1221 // Set rates to go down another 3/4 spatial. Should be converted ton 1/2.
1222 qm_resolution_->UpdateCodecParameters(30.0f, 480, 360);
1223 EXPECT_EQ(4, qm_resolution_->GetImageType(480, 360));
1224 qm_resolution_->ResetRates();
marpan@webrtc.orgc5b392e2012-06-29 21:44:55 +00001225 int target_rate2[] = {100, 100, 100, 100, 100};
1226 int encoder_sent_rate2[] = {100, 100, 100, 100, 100};
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001227 int incoming_frame_rate2[] = {30, 30, 30, 30, 30};
1228 uint8_t fraction_lost2[] = {10, 10, 10, 10, 10};
1229 UpdateQmRateData(target_rate2, encoder_sent_rate2, incoming_frame_rate2,
1230 fraction_lost2, 5);
1231
1232 // Update content: motion level, and 3 spatial prediction errors.
1233 // Medium motion, low spatial.
1234 UpdateQmContentData(kTemporalMedium, kSpatialLow, kSpatialLow, kSpatialLow);
1235 EXPECT_EQ(0, qm_resolution_->SelectResolution(&qm_scale_));
1236 EXPECT_EQ(6, qm_resolution_->ComputeContentClass());
1237 EXPECT_EQ(kStableEncoding, qm_resolution_->GetEncoderState());
1238 EXPECT_TRUE(IsSelectedActionCorrect(qm_scale_, 2.0f, 2.0f, 1.0f, 320, 240,
1239 30.0f));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001240}
1241
1242void QmSelectTest::InitQmNativeData(float initial_bit_rate,
1243 int user_frame_rate,
1244 int native_width,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001245 int native_height,
1246 int num_layers) {
1247 EXPECT_EQ(0, qm_resolution_->Initialize(initial_bit_rate,
1248 user_frame_rate,
1249 native_width,
1250 native_height,
1251 num_layers));
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001252}
1253
1254void QmSelectTest::UpdateQmContentData(float motion_metric,
1255 float spatial_metric,
1256 float spatial_metric_horiz,
1257 float spatial_metric_vert) {
1258 content_metrics_->motion_magnitude = motion_metric;
1259 content_metrics_->spatial_pred_err = spatial_metric;
1260 content_metrics_->spatial_pred_err_h = spatial_metric_horiz;
1261 content_metrics_->spatial_pred_err_v = spatial_metric_vert;
1262 qm_resolution_->UpdateContent(content_metrics_);
1263}
1264
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001265void QmSelectTest::UpdateQmEncodedFrame(size_t* encoded_size,
1266 size_t num_updates) {
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001267 for (size_t i = 0; i < num_updates; ++i) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001268 // Convert to bytes.
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001269 size_t encoded_size_update = 1000 * encoded_size[i] / 8;
pbos@webrtc.org273a4142014-12-01 15:23:21 +00001270 qm_resolution_->UpdateEncodedSize(encoded_size_update);
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001271 }
1272}
1273
1274void QmSelectTest::UpdateQmRateData(int* target_rate,
1275 int* encoder_sent_rate,
1276 int* incoming_frame_rate,
1277 uint8_t* fraction_lost,
1278 int num_updates) {
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001279 for (int i = 0; i < num_updates; ++i) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001280 float target_rate_update = target_rate[i];
1281 float encoder_sent_rate_update = encoder_sent_rate[i];
1282 float incoming_frame_rate_update = incoming_frame_rate[i];
1283 uint8_t fraction_lost_update = fraction_lost[i];
1284 qm_resolution_->UpdateRates(target_rate_update,
1285 encoder_sent_rate_update,
1286 incoming_frame_rate_update,
1287 fraction_lost_update);
1288 }
1289}
1290
1291// Check is the selected action from the QmResolution class is the same
1292// as the expected scales from |fac_width|, |fac_height|, |fac_temp|.
1293bool QmSelectTest::IsSelectedActionCorrect(VCMResolutionScale* qm_scale,
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001294 float fac_width,
1295 float fac_height,
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001296 float fac_temp,
1297 uint16_t new_width,
1298 uint16_t new_height,
1299 float new_frame_rate) {
marpan@webrtc.orgaccf6072012-03-07 17:16:10 +00001300 if (qm_scale->spatial_width_fact == fac_width &&
1301 qm_scale->spatial_height_fact == fac_height &&
marpan@webrtc.orge22d81c2012-03-20 18:21:53 +00001302 qm_scale->temporal_fact == fac_temp &&
1303 qm_scale->codec_width == new_width &&
1304 qm_scale->codec_height == new_height &&
1305 qm_scale->frame_rate == new_frame_rate) {
marpan@webrtc.org9d76b4e2012-02-28 23:39:31 +00001306 return true;
1307 } else {
1308 return false;
1309 }
1310}
1311} // namespace webrtc