1 /*
2 * Copyright (c) 2020 The WebM 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 <cstdint>
12 #include <new>
13
14 #include "test/codec_factory.h"
15 #include "test/encode_test_driver.h"
16 #include "test/util.h"
17 #include "test/yuv_video_source.h"
18 #include "third_party/googletest/src/include/gtest/gtest.h"
19 #include "vp9/simple_encode.h"
20 #include "vpx/vpx_ext_ratectrl.h"
21 #include "vpx/vpx_tpl.h"
22 #include "vpx_dsp/vpx_dsp_common.h"
23
24 namespace {
25
26 constexpr int kModelMagicNumber = 51396;
27 constexpr uintptr_t PrivMagicNumber = 5566;
28 constexpr int kFrameNum = 5;
29 constexpr int kFrameNumGOP = 30;
30 constexpr int kFrameNumGOPShort = 4;
31 constexpr int kLosslessCodingIndex = 2;
32 constexpr int kFixedGOPSize = 9;
33 // The range check in vp9_cx_iface.c shows that the max
34 // lag in buffer is MAX_LAG_BUFFERS (25):
35 // RANGE_CHECK_HI(cfg, g_lag_in_frames, MAX_LAG_BUFFERS);
36 constexpr int kMaxLagInFrames = 25;
37 constexpr int kDefaultMinGfInterval = 4;
38 constexpr int kDefaultMaxGfInterval = 16;
39 // The active gf interval might change for each GOP
40 // See function "get_active_gf_inverval_range".
41 // The numbers below are from manual inspection.
42 constexpr int kReadMinGfInterval = 5;
43 constexpr int kReadMaxGfInterval = 13;
44 const char kTestFileName[] = "bus_352x288_420_f20_b8.yuv";
45 const double kPsnrThreshold = 30.4;
46
47 struct ToyRateCtrl {
48 int magic_number;
49 int coding_index;
50
51 int gop_global_index;
52 int frames_since_key;
53 int show_index;
54 };
55
rc_create_model(void * priv,const vpx_rc_config_t * ratectrl_config,vpx_rc_model_t * rate_ctrl_model_ptr)56 vpx_rc_status_t rc_create_model(void *priv,
57 const vpx_rc_config_t *ratectrl_config,
58 vpx_rc_model_t *rate_ctrl_model_ptr) {
59 ToyRateCtrl *toy_rate_ctrl = new (std::nothrow) ToyRateCtrl;
60 if (toy_rate_ctrl == nullptr) return VPX_RC_ERROR;
61 toy_rate_ctrl->magic_number = kModelMagicNumber;
62 toy_rate_ctrl->coding_index = -1;
63 *rate_ctrl_model_ptr = toy_rate_ctrl;
64 EXPECT_EQ(priv, reinterpret_cast<void *>(PrivMagicNumber));
65 EXPECT_EQ(ratectrl_config->frame_width, 352);
66 EXPECT_EQ(ratectrl_config->frame_height, 288);
67 EXPECT_EQ(ratectrl_config->show_frame_count, kFrameNum);
68 EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 24000);
69 EXPECT_EQ(ratectrl_config->frame_rate_num, 30);
70 EXPECT_EQ(ratectrl_config->frame_rate_den, 1);
71 return VPX_RC_OK;
72 }
73
rc_create_model_gop(void * priv,const vpx_rc_config_t * ratectrl_config,vpx_rc_model_t * rate_ctrl_model_ptr)74 vpx_rc_status_t rc_create_model_gop(void *priv,
75 const vpx_rc_config_t *ratectrl_config,
76 vpx_rc_model_t *rate_ctrl_model_ptr) {
77 ToyRateCtrl *toy_rate_ctrl = new (std::nothrow) ToyRateCtrl;
78 if (toy_rate_ctrl == nullptr) return VPX_RC_ERROR;
79 toy_rate_ctrl->magic_number = kModelMagicNumber;
80 toy_rate_ctrl->gop_global_index = 0;
81 toy_rate_ctrl->frames_since_key = 0;
82 toy_rate_ctrl->show_index = 0;
83 toy_rate_ctrl->coding_index = 0;
84 *rate_ctrl_model_ptr = toy_rate_ctrl;
85 EXPECT_EQ(priv, reinterpret_cast<void *>(PrivMagicNumber));
86 EXPECT_EQ(ratectrl_config->frame_width, 640);
87 EXPECT_EQ(ratectrl_config->frame_height, 360);
88 EXPECT_EQ(ratectrl_config->show_frame_count, kFrameNumGOP);
89 EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 4000);
90 EXPECT_EQ(ratectrl_config->frame_rate_num, 30);
91 EXPECT_EQ(ratectrl_config->frame_rate_den, 1);
92 return VPX_RC_OK;
93 }
94
rc_create_model_gop_short(void * priv,const vpx_rc_config_t * ratectrl_config,vpx_rc_model_t * rate_ctrl_model_ptr)95 vpx_rc_status_t rc_create_model_gop_short(
96 void *priv, const vpx_rc_config_t *ratectrl_config,
97 vpx_rc_model_t *rate_ctrl_model_ptr) {
98 ToyRateCtrl *toy_rate_ctrl = new (std::nothrow) ToyRateCtrl;
99 if (toy_rate_ctrl == nullptr) return VPX_RC_ERROR;
100 toy_rate_ctrl->magic_number = kModelMagicNumber;
101 toy_rate_ctrl->gop_global_index = 0;
102 toy_rate_ctrl->frames_since_key = 0;
103 toy_rate_ctrl->show_index = 0;
104 toy_rate_ctrl->coding_index = 0;
105 *rate_ctrl_model_ptr = toy_rate_ctrl;
106 EXPECT_EQ(priv, reinterpret_cast<void *>(PrivMagicNumber));
107 EXPECT_EQ(ratectrl_config->frame_width, 352);
108 EXPECT_EQ(ratectrl_config->frame_height, 288);
109 EXPECT_EQ(ratectrl_config->show_frame_count, kFrameNumGOPShort);
110 EXPECT_EQ(ratectrl_config->target_bitrate_kbps, 500);
111 EXPECT_EQ(ratectrl_config->frame_rate_num, 30);
112 EXPECT_EQ(ratectrl_config->frame_rate_den, 1);
113 return VPX_RC_OK;
114 }
115
rc_send_firstpass_stats(vpx_rc_model_t rate_ctrl_model,const vpx_rc_firstpass_stats_t * first_pass_stats)116 vpx_rc_status_t rc_send_firstpass_stats(
117 vpx_rc_model_t rate_ctrl_model,
118 const vpx_rc_firstpass_stats_t *first_pass_stats) {
119 const ToyRateCtrl *toy_rate_ctrl =
120 static_cast<ToyRateCtrl *>(rate_ctrl_model);
121 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
122 EXPECT_EQ(first_pass_stats->num_frames, kFrameNum);
123 for (int i = 0; i < first_pass_stats->num_frames; ++i) {
124 EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i);
125 }
126 return VPX_RC_OK;
127 }
128
rc_send_firstpass_stats_gop(vpx_rc_model_t rate_ctrl_model,const vpx_rc_firstpass_stats_t * first_pass_stats)129 vpx_rc_status_t rc_send_firstpass_stats_gop(
130 vpx_rc_model_t rate_ctrl_model,
131 const vpx_rc_firstpass_stats_t *first_pass_stats) {
132 const ToyRateCtrl *toy_rate_ctrl =
133 static_cast<ToyRateCtrl *>(rate_ctrl_model);
134 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
135 EXPECT_EQ(first_pass_stats->num_frames, kFrameNumGOP);
136 for (int i = 0; i < first_pass_stats->num_frames; ++i) {
137 EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i);
138 }
139 return VPX_RC_OK;
140 }
141
rc_send_firstpass_stats_gop_short(vpx_rc_model_t rate_ctrl_model,const vpx_rc_firstpass_stats_t * first_pass_stats)142 vpx_rc_status_t rc_send_firstpass_stats_gop_short(
143 vpx_rc_model_t rate_ctrl_model,
144 const vpx_rc_firstpass_stats_t *first_pass_stats) {
145 const ToyRateCtrl *toy_rate_ctrl =
146 static_cast<ToyRateCtrl *>(rate_ctrl_model);
147 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
148 EXPECT_EQ(first_pass_stats->num_frames, kFrameNumGOPShort);
149 for (int i = 0; i < first_pass_stats->num_frames; ++i) {
150 EXPECT_DOUBLE_EQ(first_pass_stats->frame_stats[i].frame, i);
151 }
152 return VPX_RC_OK;
153 }
154
rc_send_tpl_gop_stats(vpx_rc_model_t rate_ctrl_model,const VpxTplGopStats * tpl_gop_stats)155 vpx_rc_status_t rc_send_tpl_gop_stats(vpx_rc_model_t rate_ctrl_model,
156 const VpxTplGopStats *tpl_gop_stats) {
157 const ToyRateCtrl *toy_rate_ctrl =
158 static_cast<ToyRateCtrl *>(rate_ctrl_model);
159 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
160 EXPECT_GT(tpl_gop_stats->size, 0);
161
162 for (int i = 0; i < tpl_gop_stats->size; ++i) {
163 EXPECT_GT(tpl_gop_stats->frame_stats_list[i].num_blocks, 0);
164 }
165 return VPX_RC_OK;
166 }
167
rc_get_encodeframe_decision(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_info_t * encode_frame_info,vpx_rc_encodeframe_decision_t * frame_decision)168 vpx_rc_status_t rc_get_encodeframe_decision(
169 vpx_rc_model_t rate_ctrl_model,
170 const vpx_rc_encodeframe_info_t *encode_frame_info,
171 vpx_rc_encodeframe_decision_t *frame_decision) {
172 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
173 toy_rate_ctrl->coding_index += 1;
174
175 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
176
177 EXPECT_LT(encode_frame_info->show_index, kFrameNum);
178 EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
179
180 if (encode_frame_info->coding_index == 0) {
181 EXPECT_EQ(encode_frame_info->show_index, 0);
182 EXPECT_EQ(encode_frame_info->gop_index, 0);
183 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
184 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
185 0); // kRefFrameTypeLast
186 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
187 0); // kRefFrameTypePast
188 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
189 0); // kRefFrameTypeFuture
190 } else if (encode_frame_info->coding_index == 1) {
191 EXPECT_EQ(encode_frame_info->show_index, 4);
192 EXPECT_EQ(encode_frame_info->gop_index, 1);
193 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeAltRef);
194 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
195 1); // kRefFrameTypeLast
196 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
197 0); // kRefFrameTypePast
198 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
199 0); // kRefFrameTypeFuture
200 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
201 0); // kRefFrameTypeLast
202 } else if (encode_frame_info->coding_index >= 2 &&
203 encode_frame_info->coding_index < 5) {
204 // In the first group of pictures, coding_index and gop_index are equal.
205 EXPECT_EQ(encode_frame_info->gop_index, encode_frame_info->coding_index);
206 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
207 } else if (encode_frame_info->coding_index == 5) {
208 EXPECT_EQ(encode_frame_info->show_index, 4);
209 EXPECT_EQ(encode_frame_info->gop_index, 0);
210 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeOverlay);
211 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
212 1); // kRefFrameTypeLast
213 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
214 1); // kRefFrameTypePast
215 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
216 1); // kRefFrameTypeFuture
217 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
218 4); // kRefFrameTypeLast
219 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[1],
220 0); // kRefFrameTypePast
221 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[2],
222 1); // kRefFrameTypeFuture
223 }
224 if (encode_frame_info->coding_index == kLosslessCodingIndex) {
225 // We should get sse == 0 at rc_update_encodeframe_result()
226 frame_decision->q_index = 0;
227 } else {
228 frame_decision->q_index = 100;
229 }
230 frame_decision->max_frame_size = 0;
231 return VPX_RC_OK;
232 }
233
rc_get_encodeframe_decision_gop(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_info_t * encode_frame_info,vpx_rc_encodeframe_decision_t * frame_decision)234 vpx_rc_status_t rc_get_encodeframe_decision_gop(
235 vpx_rc_model_t rate_ctrl_model,
236 const vpx_rc_encodeframe_info_t *encode_frame_info,
237 vpx_rc_encodeframe_decision_t *frame_decision) {
238 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
239 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
240 EXPECT_LT(encode_frame_info->show_index, kFrameNumGOP);
241 EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
242
243 if (encode_frame_info->coding_index == 0) {
244 EXPECT_EQ(encode_frame_info->show_index, 0);
245 EXPECT_EQ(encode_frame_info->gop_index, 0);
246 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
247 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
248 0); // kRefFrameTypeLast
249 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
250 0); // kRefFrameTypePast
251 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
252 0); // kRefFrameTypeFuture
253 } else if (encode_frame_info->coding_index == 1) {
254 EXPECT_EQ(encode_frame_info->show_index, 1);
255 EXPECT_EQ(encode_frame_info->gop_index, 1);
256 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
257 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
258 1); // kRefFrameTypeLast
259 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
260 0); // kRefFrameTypePast
261 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
262 0); // kRefFrameTypeFuture
263 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
264 0); // kRefFrameTypeLast
265 } else if (encode_frame_info->coding_index == 2) {
266 EXPECT_EQ(encode_frame_info->show_index, 2);
267 EXPECT_EQ(encode_frame_info->gop_index, 0);
268 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
269 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
270 0); // kRefFrameTypeLast
271 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
272 0); // kRefFrameTypePast
273 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
274 0); // kRefFrameTypeFuture
275 } else if (encode_frame_info->coding_index == 3 ||
276 encode_frame_info->coding_index == 12 ||
277 encode_frame_info->coding_index == 21) {
278 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeAltRef);
279 EXPECT_EQ(encode_frame_info->gop_index, 1);
280 } else if (encode_frame_info->coding_index == 11 ||
281 encode_frame_info->coding_index == 20 ||
282 encode_frame_info->coding_index == 29) {
283 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeOverlay);
284 EXPECT_EQ(encode_frame_info->gop_index, 0);
285 } else if (encode_frame_info->coding_index >= 30) {
286 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
287 }
288
289 // When the model recommends an invalid q, valid range [0, 255],
290 // the encoder will ignore it and use the default q selected
291 // by libvpx rate control strategy.
292 frame_decision->q_index = VPX_DEFAULT_Q;
293 frame_decision->max_frame_size = 0;
294
295 toy_rate_ctrl->coding_index += 1;
296 return VPX_RC_OK;
297 }
298
rc_get_encodeframe_decision_gop_short(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_info_t * encode_frame_info,vpx_rc_encodeframe_decision_t * frame_decision)299 vpx_rc_status_t rc_get_encodeframe_decision_gop_short(
300 vpx_rc_model_t rate_ctrl_model,
301 const vpx_rc_encodeframe_info_t *encode_frame_info,
302 vpx_rc_encodeframe_decision_t *frame_decision) {
303 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
304 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
305 EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
306 EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
307
308 if (encode_frame_info->coding_index == 0) {
309 EXPECT_EQ(encode_frame_info->show_index, 0);
310 EXPECT_EQ(encode_frame_info->gop_index, 0);
311 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
312 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
313 0); // kRefFrameTypeLast
314 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
315 0); // kRefFrameTypePast
316 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
317 0); // kRefFrameTypeFuture
318 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
319 } else if (encode_frame_info->coding_index == 1) {
320 EXPECT_EQ(encode_frame_info->show_index, 1);
321 EXPECT_EQ(encode_frame_info->gop_index, 1);
322 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
323 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
324 1); // kRefFrameTypeLast
325 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
326 0); // kRefFrameTypePast
327 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
328 0); // kRefFrameTypeFuture
329 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
330 0); // kRefFrameTypeLast
331 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
332 } else if (encode_frame_info->coding_index == 2) {
333 EXPECT_EQ(encode_frame_info->show_index, 2);
334 EXPECT_EQ(encode_frame_info->gop_index, 2);
335 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
336 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
337 } else if (encode_frame_info->coding_index == 3) {
338 EXPECT_EQ(encode_frame_info->show_index, 3);
339 EXPECT_EQ(encode_frame_info->gop_index, 0);
340 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeGolden);
341 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 2);
342 }
343
344 // When the model recommends an invalid q, valid range [0, 255],
345 // the encoder will ignore it and use the default q selected
346 // by libvpx rate control strategy.
347 frame_decision->q_index = VPX_DEFAULT_Q;
348 frame_decision->max_frame_size = 0;
349
350 toy_rate_ctrl->coding_index += 1;
351 return VPX_RC_OK;
352 }
353
rc_get_encodeframe_decision_gop_short_overlay(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_info_t * encode_frame_info,vpx_rc_encodeframe_decision_t * frame_decision)354 vpx_rc_status_t rc_get_encodeframe_decision_gop_short_overlay(
355 vpx_rc_model_t rate_ctrl_model,
356 const vpx_rc_encodeframe_info_t *encode_frame_info,
357 vpx_rc_encodeframe_decision_t *frame_decision) {
358 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
359 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
360 EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
361 EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
362
363 if (encode_frame_info->coding_index == 0) {
364 EXPECT_EQ(encode_frame_info->show_index, 0);
365 EXPECT_EQ(encode_frame_info->gop_index, 0);
366 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
367 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
368 0); // kRefFrameTypeLast
369 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
370 0); // kRefFrameTypePast
371 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
372 0); // kRefFrameTypeFuture
373 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
374 } else if (encode_frame_info->coding_index == 1) {
375 EXPECT_EQ(encode_frame_info->show_index, 3);
376 EXPECT_EQ(encode_frame_info->gop_index, 1);
377 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeAltRef);
378 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
379 1); // kRefFrameTypeLast
380 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
381 0); // kRefFrameTypePast
382 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
383 0); // kRefFrameTypeFuture
384 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
385 0); // kRefFrameTypeLast
386 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
387 } else if (encode_frame_info->coding_index == 2) {
388 EXPECT_EQ(encode_frame_info->show_index, 1);
389 EXPECT_EQ(encode_frame_info->gop_index, 2);
390 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
391 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
392 } else if (encode_frame_info->coding_index == 3) {
393 EXPECT_EQ(encode_frame_info->show_index, 2);
394 EXPECT_EQ(encode_frame_info->gop_index, 3);
395 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
396 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
397 } else if (encode_frame_info->coding_index == 4) {
398 EXPECT_EQ(encode_frame_info->show_index, 3);
399 EXPECT_EQ(encode_frame_info->gop_index, 0);
400 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeOverlay);
401 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
402 }
403
404 // When the model recommends an invalid q, valid range [0, 255],
405 // the encoder will ignore it and use the default q selected
406 // by libvpx rate control strategy.
407 frame_decision->q_index = VPX_DEFAULT_Q;
408 frame_decision->max_frame_size = 0;
409
410 toy_rate_ctrl->coding_index += 1;
411 return VPX_RC_OK;
412 }
413
rc_get_encodeframe_decision_gop_short_no_arf(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_info_t * encode_frame_info,vpx_rc_encodeframe_decision_t * frame_decision)414 vpx_rc_status_t rc_get_encodeframe_decision_gop_short_no_arf(
415 vpx_rc_model_t rate_ctrl_model,
416 const vpx_rc_encodeframe_info_t *encode_frame_info,
417 vpx_rc_encodeframe_decision_t *frame_decision) {
418 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
419 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
420 EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
421 EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
422
423 if (encode_frame_info->coding_index == 0) {
424 EXPECT_EQ(encode_frame_info->show_index, 0);
425 EXPECT_EQ(encode_frame_info->gop_index, 0);
426 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeKey);
427 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
428 0); // kRefFrameTypeLast
429 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
430 0); // kRefFrameTypePast
431 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
432 0); // kRefFrameTypeFuture
433 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
434 } else if (encode_frame_info->coding_index == 1) {
435 EXPECT_EQ(encode_frame_info->show_index, 1);
436 EXPECT_EQ(encode_frame_info->gop_index, 1);
437 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
438 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[0],
439 1); // kRefFrameTypeLast
440 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[1],
441 0); // kRefFrameTypePast
442 EXPECT_EQ(encode_frame_info->ref_frame_valid_list[2],
443 0); // kRefFrameTypeFuture
444 EXPECT_EQ(encode_frame_info->ref_frame_coding_indexes[0],
445 0); // kRefFrameTypeLast
446 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
447 } else if (encode_frame_info->coding_index == 2) {
448 EXPECT_EQ(encode_frame_info->show_index, 2);
449 EXPECT_EQ(encode_frame_info->gop_index, 2);
450 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
451 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
452 } else if (encode_frame_info->coding_index == 3) {
453 EXPECT_EQ(encode_frame_info->show_index, 3);
454 EXPECT_EQ(encode_frame_info->gop_index, 3);
455 EXPECT_EQ(encode_frame_info->frame_type, vp9::kFrameTypeInter);
456 EXPECT_EQ(toy_rate_ctrl->gop_global_index, 1);
457 }
458
459 // When the model recommends an invalid q, valid range [0, 255],
460 // the encoder will ignore it and use the default q selected
461 // by libvpx rate control strategy.
462 frame_decision->q_index = VPX_DEFAULT_Q;
463 frame_decision->max_frame_size = 0;
464
465 toy_rate_ctrl->coding_index += 1;
466 return VPX_RC_OK;
467 }
468
rc_get_gop_decision(vpx_rc_model_t rate_ctrl_model,const vpx_rc_gop_info_t * gop_info,vpx_rc_gop_decision_t * gop_decision)469 vpx_rc_status_t rc_get_gop_decision(vpx_rc_model_t rate_ctrl_model,
470 const vpx_rc_gop_info_t *gop_info,
471 vpx_rc_gop_decision_t *gop_decision) {
472 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
473 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
474 EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames);
475 EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
476 EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
477 EXPECT_EQ(gop_info->active_min_gf_interval, kReadMinGfInterval);
478 EXPECT_EQ(gop_info->active_max_gf_interval, kReadMaxGfInterval);
479 EXPECT_EQ(gop_info->allow_alt_ref, 1);
480 if (gop_info->is_key_frame) {
481 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
482 EXPECT_EQ(gop_info->frames_since_key, 0);
483 EXPECT_EQ(gop_info->gop_global_index, 0);
484 toy_rate_ctrl->gop_global_index = 0;
485 toy_rate_ctrl->frames_since_key = 0;
486 } else {
487 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 1);
488 }
489 EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
490 EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
491 EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
492 EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
493
494 gop_decision->gop_coding_frames =
495 VPXMIN(kFixedGOPSize, gop_info->frames_to_key);
496 gop_decision->use_alt_ref = gop_decision->gop_coding_frames == kFixedGOPSize;
497 toy_rate_ctrl->frames_since_key +=
498 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
499 toy_rate_ctrl->show_index +=
500 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
501 ++toy_rate_ctrl->gop_global_index;
502 return VPX_RC_OK;
503 }
504
505 // Test on a 4 frame video.
506 // Test a setting of 2 GOPs.
507 // The first GOP has 3 coding frames, no alt ref.
508 // The second GOP has 1 coding frame, no alt ref.
rc_get_gop_decision_short(vpx_rc_model_t rate_ctrl_model,const vpx_rc_gop_info_t * gop_info,vpx_rc_gop_decision_t * gop_decision)509 vpx_rc_status_t rc_get_gop_decision_short(vpx_rc_model_t rate_ctrl_model,
510 const vpx_rc_gop_info_t *gop_info,
511 vpx_rc_gop_decision_t *gop_decision) {
512 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
513 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
514 EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames - 1);
515 EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
516 EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
517 EXPECT_EQ(gop_info->allow_alt_ref, 1);
518 if (gop_info->is_key_frame) {
519 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
520 EXPECT_EQ(gop_info->frames_since_key, 0);
521 EXPECT_EQ(gop_info->gop_global_index, 0);
522 toy_rate_ctrl->gop_global_index = 0;
523 toy_rate_ctrl->frames_since_key = 0;
524 } else {
525 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
526 }
527 EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
528 EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
529 EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
530 EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
531
532 gop_decision->gop_coding_frames = gop_info->gop_global_index == 0 ? 3 : 1;
533 gop_decision->use_alt_ref = 0;
534 toy_rate_ctrl->frames_since_key +=
535 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
536 toy_rate_ctrl->show_index +=
537 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
538 ++toy_rate_ctrl->gop_global_index;
539 return VPX_RC_OK;
540 }
541
542 // Test on a 4 frame video.
543 // Test a setting of 2 GOPs.
544 // The first GOP has 4 coding frames. Use alt ref.
545 // The second GOP only contains the overlay frame of the first GOP's alt ref
546 // frame.
rc_get_gop_decision_short_overlay(vpx_rc_model_t rate_ctrl_model,const vpx_rc_gop_info_t * gop_info,vpx_rc_gop_decision_t * gop_decision)547 vpx_rc_status_t rc_get_gop_decision_short_overlay(
548 vpx_rc_model_t rate_ctrl_model, const vpx_rc_gop_info_t *gop_info,
549 vpx_rc_gop_decision_t *gop_decision) {
550 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
551 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
552 EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames - 1);
553 EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
554 EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
555 EXPECT_EQ(gop_info->allow_alt_ref, 1);
556 if (gop_info->is_key_frame) {
557 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
558 EXPECT_EQ(gop_info->frames_since_key, 0);
559 EXPECT_EQ(gop_info->gop_global_index, 0);
560 toy_rate_ctrl->gop_global_index = 0;
561 toy_rate_ctrl->frames_since_key = 0;
562 } else {
563 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 1);
564 }
565 EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
566 EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
567 EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
568 EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
569
570 gop_decision->gop_coding_frames = gop_info->gop_global_index == 0 ? 4 : 1;
571 gop_decision->use_alt_ref = gop_info->is_key_frame ? 1 : 0;
572 toy_rate_ctrl->frames_since_key +=
573 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
574 toy_rate_ctrl->show_index +=
575 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
576 ++toy_rate_ctrl->gop_global_index;
577 return VPX_RC_OK;
578 }
579
580 // Test on a 4 frame video.
581 // Test a setting of 1 GOP.
582 // The GOP has 4 coding frames. Do not use alt ref.
rc_get_gop_decision_short_no_arf(vpx_rc_model_t rate_ctrl_model,const vpx_rc_gop_info_t * gop_info,vpx_rc_gop_decision_t * gop_decision)583 vpx_rc_status_t rc_get_gop_decision_short_no_arf(
584 vpx_rc_model_t rate_ctrl_model, const vpx_rc_gop_info_t *gop_info,
585 vpx_rc_gop_decision_t *gop_decision) {
586 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
587 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
588 EXPECT_EQ(gop_info->lag_in_frames, kMaxLagInFrames - 1);
589 EXPECT_EQ(gop_info->min_gf_interval, kDefaultMinGfInterval);
590 EXPECT_EQ(gop_info->max_gf_interval, kDefaultMaxGfInterval);
591 EXPECT_EQ(gop_info->allow_alt_ref, 1);
592 if (gop_info->is_key_frame) {
593 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
594 EXPECT_EQ(gop_info->frames_since_key, 0);
595 EXPECT_EQ(gop_info->gop_global_index, 0);
596 toy_rate_ctrl->gop_global_index = 0;
597 toy_rate_ctrl->frames_since_key = 0;
598 } else {
599 EXPECT_EQ(gop_info->last_gop_use_alt_ref, 0);
600 }
601 EXPECT_EQ(gop_info->gop_global_index, toy_rate_ctrl->gop_global_index);
602 EXPECT_EQ(gop_info->frames_since_key, toy_rate_ctrl->frames_since_key);
603 EXPECT_EQ(gop_info->show_index, toy_rate_ctrl->show_index);
604 EXPECT_EQ(gop_info->coding_index, toy_rate_ctrl->coding_index);
605
606 gop_decision->gop_coding_frames = gop_info->gop_global_index == 0 ? 4 : 1;
607 gop_decision->use_alt_ref = 0;
608 toy_rate_ctrl->frames_since_key +=
609 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
610 toy_rate_ctrl->show_index +=
611 gop_decision->gop_coding_frames - gop_decision->use_alt_ref;
612 ++toy_rate_ctrl->gop_global_index;
613 return VPX_RC_OK;
614 }
615
rc_update_encodeframe_result(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_result_t * encode_frame_result)616 vpx_rc_status_t rc_update_encodeframe_result(
617 vpx_rc_model_t rate_ctrl_model,
618 const vpx_rc_encodeframe_result_t *encode_frame_result) {
619 const ToyRateCtrl *toy_rate_ctrl =
620 static_cast<ToyRateCtrl *>(rate_ctrl_model);
621 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
622
623 const int64_t ref_pixel_count = 352 * 288 * 3 / 2;
624 EXPECT_EQ(encode_frame_result->pixel_count, ref_pixel_count);
625 if (toy_rate_ctrl->coding_index == kLosslessCodingIndex) {
626 EXPECT_EQ(encode_frame_result->sse, 0);
627 }
628 if (toy_rate_ctrl->coding_index == kLosslessCodingIndex) {
629 EXPECT_EQ(encode_frame_result->actual_encoding_qindex, 0);
630 } else {
631 EXPECT_EQ(encode_frame_result->actual_encoding_qindex, 100);
632 }
633 return VPX_RC_OK;
634 }
635
rc_update_encodeframe_result_gop(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_result_t * encode_frame_result)636 vpx_rc_status_t rc_update_encodeframe_result_gop(
637 vpx_rc_model_t rate_ctrl_model,
638 const vpx_rc_encodeframe_result_t *encode_frame_result) {
639 const ToyRateCtrl *toy_rate_ctrl =
640 static_cast<ToyRateCtrl *>(rate_ctrl_model);
641 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
642
643 const int64_t ref_pixel_count = 640 * 360 * 3 / 2;
644 EXPECT_EQ(encode_frame_result->pixel_count, ref_pixel_count);
645 return VPX_RC_OK;
646 }
647
rc_update_encodeframe_result_gop_short(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_result_t * encode_frame_result)648 vpx_rc_status_t rc_update_encodeframe_result_gop_short(
649 vpx_rc_model_t rate_ctrl_model,
650 const vpx_rc_encodeframe_result_t *encode_frame_result) {
651 const ToyRateCtrl *toy_rate_ctrl =
652 static_cast<ToyRateCtrl *>(rate_ctrl_model);
653 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
654
655 const int64_t ref_pixel_count = 352 * 288 * 3 / 2;
656 EXPECT_EQ(encode_frame_result->pixel_count, ref_pixel_count);
657 return VPX_RC_OK;
658 }
659
rc_get_default_frame_rdmult(vpx_rc_model_t rate_ctrl_model,const vpx_rc_encodeframe_info_t * encode_frame_info,int * rdmult)660 vpx_rc_status_t rc_get_default_frame_rdmult(
661 vpx_rc_model_t rate_ctrl_model,
662 const vpx_rc_encodeframe_info_t *encode_frame_info, int *rdmult) {
663 const ToyRateCtrl *toy_rate_ctrl =
664 static_cast<ToyRateCtrl *>(rate_ctrl_model);
665 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
666 EXPECT_LT(encode_frame_info->show_index, kFrameNumGOPShort);
667 EXPECT_EQ(encode_frame_info->coding_index, toy_rate_ctrl->coding_index);
668
669 *rdmult = VPX_DEFAULT_RDMULT;
670 return VPX_RC_OK;
671 }
672
rc_delete_model(vpx_rc_model_t rate_ctrl_model)673 vpx_rc_status_t rc_delete_model(vpx_rc_model_t rate_ctrl_model) {
674 ToyRateCtrl *toy_rate_ctrl = static_cast<ToyRateCtrl *>(rate_ctrl_model);
675 EXPECT_EQ(toy_rate_ctrl->magic_number, kModelMagicNumber);
676 delete toy_rate_ctrl;
677 return VPX_RC_OK;
678 }
679
680 class ExtRateCtrlTest : public ::libvpx_test::EncoderTest,
681 public ::testing::Test {
682 protected:
ExtRateCtrlTest()683 ExtRateCtrlTest() : EncoderTest(&::libvpx_test::kVP9) {}
684
685 ~ExtRateCtrlTest() override = default;
686
SetUp()687 void SetUp() override {
688 InitializeConfig();
689 SetMode(::libvpx_test::kTwoPassGood);
690 }
691
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)692 void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
693 ::libvpx_test::Encoder *encoder) override {
694 if (video->frame() == 0) {
695 vpx_rc_funcs_t rc_funcs = {};
696 rc_funcs.rc_type = VPX_RC_QP;
697 rc_funcs.create_model = rc_create_model;
698 rc_funcs.send_firstpass_stats = rc_send_firstpass_stats;
699 rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision;
700 rc_funcs.update_encodeframe_result = rc_update_encodeframe_result;
701 rc_funcs.delete_model = rc_delete_model;
702 rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
703 encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
704 }
705 }
706 };
707
TEST_F(ExtRateCtrlTest,EncodeTest)708 TEST_F(ExtRateCtrlTest, EncodeTest) {
709 cfg_.rc_target_bitrate = 24000;
710
711 std::unique_ptr<libvpx_test::VideoSource> video;
712 video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
713 "bus_352x288_420_f20_b8.yuv", VPX_IMG_FMT_I420, 352, 288, 30, 1, 0,
714 kFrameNum));
715
716 ASSERT_NE(video, nullptr);
717 ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
718 }
719
720 class ExtRateCtrlTestGOP : public ::libvpx_test::EncoderTest,
721 public ::libvpx_test::CodecTestWithParam<int> {
722 protected:
ExtRateCtrlTestGOP()723 ExtRateCtrlTestGOP() : EncoderTest(&::libvpx_test::kVP9) {}
724
725 ~ExtRateCtrlTestGOP() override = default;
726
SetUp()727 void SetUp() override {
728 InitializeConfig();
729 SetMode(::libvpx_test::kTwoPassGood);
730 }
731
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)732 void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
733 ::libvpx_test::Encoder *encoder) override {
734 if (video->frame() == 0) {
735 encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
736 encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
737
738 vpx_rc_funcs_t rc_funcs = {};
739 rc_funcs.rc_type = VPX_RC_GOP_QP;
740 rc_funcs.create_model = rc_create_model_gop;
741 rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop;
742 rc_funcs.send_tpl_gop_stats = rc_send_tpl_gop_stats;
743 rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision_gop;
744 rc_funcs.get_gop_decision = rc_get_gop_decision;
745 rc_funcs.update_encodeframe_result = rc_update_encodeframe_result_gop;
746 rc_funcs.delete_model = rc_delete_model;
747 rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
748 encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
749 }
750 }
751 };
752
TEST_F(ExtRateCtrlTestGOP,EncodeTest)753 TEST_F(ExtRateCtrlTestGOP, EncodeTest) {
754 cfg_.rc_target_bitrate = 4000;
755 cfg_.g_lag_in_frames = kMaxLagInFrames;
756 cfg_.rc_end_usage = VPX_VBR;
757
758 std::unique_ptr<libvpx_test::VideoSource> video;
759 video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
760 "noisy_clip_640_360.y4m", VPX_IMG_FMT_I420, 640, 360, 30, 1, 0,
761 kFrameNumGOP));
762
763 ASSERT_NE(video, nullptr);
764 ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
765 }
766
767 class ExtRateCtrlTestGOPShort : public ::libvpx_test::EncoderTest,
768 public ::libvpx_test::CodecTestWithParam<int> {
769 protected:
ExtRateCtrlTestGOPShort()770 ExtRateCtrlTestGOPShort() : EncoderTest(&::libvpx_test::kVP9) {}
771
772 ~ExtRateCtrlTestGOPShort() override = default;
773
SetUp()774 void SetUp() override {
775 InitializeConfig();
776 SetMode(::libvpx_test::kTwoPassGood);
777 }
778
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)779 void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
780 ::libvpx_test::Encoder *encoder) override {
781 if (video->frame() == 0) {
782 encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
783 encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
784 encoder->Control(VP9E_SET_TARGET_LEVEL, vp9::LEVEL_AUTO);
785
786 vpx_rc_funcs_t rc_funcs = {};
787 rc_funcs.rc_type = VPX_RC_GOP_QP;
788 rc_funcs.create_model = rc_create_model_gop_short;
789 rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
790 rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision_gop_short;
791 rc_funcs.get_gop_decision = rc_get_gop_decision_short;
792 rc_funcs.update_encodeframe_result =
793 rc_update_encodeframe_result_gop_short;
794 rc_funcs.delete_model = rc_delete_model;
795 rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
796 encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
797 }
798 }
799 };
800
TEST_F(ExtRateCtrlTestGOPShort,EncodeTest)801 TEST_F(ExtRateCtrlTestGOPShort, EncodeTest) {
802 cfg_.rc_target_bitrate = 500;
803 cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
804 cfg_.rc_end_usage = VPX_VBR;
805
806 std::unique_ptr<libvpx_test::VideoSource> video;
807 video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
808 kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
809
810 ASSERT_NE(video, nullptr);
811 ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
812 }
813
814 class ExtRateCtrlTestGOPShortOverlay
815 : public ::libvpx_test::EncoderTest,
816 public ::libvpx_test::CodecTestWithParam<int> {
817 protected:
ExtRateCtrlTestGOPShortOverlay()818 ExtRateCtrlTestGOPShortOverlay() : EncoderTest(&::libvpx_test::kVP9) {}
819
820 ~ExtRateCtrlTestGOPShortOverlay() override = default;
821
SetUp()822 void SetUp() override {
823 InitializeConfig();
824 SetMode(::libvpx_test::kTwoPassGood);
825 }
826
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)827 void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
828 ::libvpx_test::Encoder *encoder) override {
829 if (video->frame() == 0) {
830 encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
831 encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
832 encoder->Control(VP9E_SET_TARGET_LEVEL, vp9::LEVEL_AUTO);
833
834 vpx_rc_funcs_t rc_funcs = {};
835 rc_funcs.rc_type = VPX_RC_GOP_QP;
836 rc_funcs.create_model = rc_create_model_gop_short;
837 rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
838 rc_funcs.get_encodeframe_decision =
839 rc_get_encodeframe_decision_gop_short_overlay;
840 rc_funcs.get_gop_decision = rc_get_gop_decision_short_overlay;
841 rc_funcs.update_encodeframe_result =
842 rc_update_encodeframe_result_gop_short;
843 rc_funcs.delete_model = rc_delete_model;
844 rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
845 encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
846 }
847 }
848 };
849
TEST_F(ExtRateCtrlTestGOPShortOverlay,EncodeTest)850 TEST_F(ExtRateCtrlTestGOPShortOverlay, EncodeTest) {
851 cfg_.rc_target_bitrate = 500;
852 cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
853 cfg_.rc_end_usage = VPX_VBR;
854
855 std::unique_ptr<libvpx_test::VideoSource> video;
856 video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
857 kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
858
859 ASSERT_NE(video, nullptr);
860 ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
861 }
862
863 class ExtRateCtrlTestGOPShortNoARF
864 : public ::libvpx_test::EncoderTest,
865 public ::libvpx_test::CodecTestWithParam<int> {
866 protected:
ExtRateCtrlTestGOPShortNoARF()867 ExtRateCtrlTestGOPShortNoARF() : EncoderTest(&::libvpx_test::kVP9) {}
868
869 ~ExtRateCtrlTestGOPShortNoARF() override = default;
870
SetUp()871 void SetUp() override {
872 InitializeConfig();
873 SetMode(::libvpx_test::kTwoPassGood);
874 }
875
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)876 void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
877 ::libvpx_test::Encoder *encoder) override {
878 if (video->frame() == 0) {
879 encoder->Control(VP9E_SET_MIN_GF_INTERVAL, kDefaultMinGfInterval);
880 encoder->Control(VP9E_SET_MAX_GF_INTERVAL, kDefaultMaxGfInterval);
881 encoder->Control(VP9E_SET_TARGET_LEVEL, vp9::LEVEL_AUTO);
882
883 vpx_rc_funcs_t rc_funcs = {};
884 rc_funcs.rc_type = VPX_RC_GOP_QP;
885 rc_funcs.create_model = rc_create_model_gop_short;
886 rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
887 rc_funcs.get_encodeframe_decision =
888 rc_get_encodeframe_decision_gop_short_no_arf;
889 rc_funcs.get_gop_decision = rc_get_gop_decision_short_no_arf;
890 rc_funcs.update_encodeframe_result =
891 rc_update_encodeframe_result_gop_short;
892 rc_funcs.delete_model = rc_delete_model;
893 rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
894 encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
895 }
896 }
897 };
898
TEST_F(ExtRateCtrlTestGOPShortNoARF,EncodeTest)899 TEST_F(ExtRateCtrlTestGOPShortNoARF, EncodeTest) {
900 cfg_.rc_target_bitrate = 500;
901 cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
902 cfg_.rc_end_usage = VPX_VBR;
903
904 std::unique_ptr<libvpx_test::VideoSource> video;
905 video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
906 kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
907
908 ASSERT_NE(video, nullptr);
909 ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
910 }
911
912 class ExtRateCtrlTestRdmult : public ::libvpx_test::EncoderTest,
913 public ::testing::Test {
914 protected:
ExtRateCtrlTestRdmult()915 ExtRateCtrlTestRdmult() : EncoderTest(&::libvpx_test::kVP9) {}
916
917 ~ExtRateCtrlTestRdmult() override = default;
918
SetUp()919 void SetUp() override {
920 InitializeConfig();
921 SetMode(::libvpx_test::kTwoPassGood);
922 }
923
BeginPassHook(unsigned int)924 void BeginPassHook(unsigned int) override {
925 psnr_ = 0.0;
926 nframes_ = 0;
927 }
928
PSNRPktHook(const vpx_codec_cx_pkt_t * pkt)929 void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) override {
930 psnr_ += pkt->data.psnr.psnr[0];
931 nframes_++;
932 }
933
PreEncodeFrameHook(::libvpx_test::VideoSource * video,::libvpx_test::Encoder * encoder)934 void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
935 ::libvpx_test::Encoder *encoder) override {
936 if (video->frame() == 0) {
937 vpx_rc_funcs_t rc_funcs = {};
938 rc_funcs.rc_type = VPX_RC_GOP_QP_RDMULT;
939 rc_funcs.create_model = rc_create_model_gop_short;
940 rc_funcs.send_firstpass_stats = rc_send_firstpass_stats_gop_short;
941 rc_funcs.get_encodeframe_decision = rc_get_encodeframe_decision_gop_short;
942 rc_funcs.get_gop_decision = rc_get_gop_decision_short;
943 rc_funcs.update_encodeframe_result =
944 rc_update_encodeframe_result_gop_short;
945 rc_funcs.get_frame_rdmult = rc_get_default_frame_rdmult;
946 rc_funcs.delete_model = rc_delete_model;
947 rc_funcs.priv = reinterpret_cast<void *>(PrivMagicNumber);
948 encoder->Control(VP9E_SET_EXTERNAL_RATE_CONTROL, &rc_funcs);
949 }
950 }
951
GetAveragePsnr() const952 double GetAveragePsnr() const {
953 if (nframes_) return psnr_ / nframes_;
954 return 0.0;
955 }
956
957 private:
958 double psnr_;
959 unsigned int nframes_;
960 };
961
TEST_F(ExtRateCtrlTestRdmult,DefaultRdmult)962 TEST_F(ExtRateCtrlTestRdmult, DefaultRdmult) {
963 cfg_.rc_target_bitrate = 500;
964 cfg_.g_lag_in_frames = kMaxLagInFrames - 1;
965 cfg_.rc_end_usage = VPX_VBR;
966 init_flags_ = VPX_CODEC_USE_PSNR;
967
968 std::unique_ptr<libvpx_test::VideoSource> video;
969 video.reset(new (std::nothrow) libvpx_test::YUVVideoSource(
970 kTestFileName, VPX_IMG_FMT_I420, 352, 288, 30, 1, 0, kFrameNumGOPShort));
971
972 ASSERT_NE(video, nullptr);
973 ASSERT_NO_FATAL_FAILURE(RunLoop(video.get()));
974
975 const double psnr = GetAveragePsnr();
976 EXPECT_GT(psnr, kPsnrThreshold);
977 }
978
979 } // namespace
980