• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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