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