/src/aom/av1/encoder/rc_utils.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2020, Alliance for Open Media. All rights reserved. |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
10 | | */ |
11 | | |
12 | | #ifndef AOM_AV1_ENCODER_RC_UTILS_H_ |
13 | | #define AOM_AV1_ENCODER_RC_UTILS_H_ |
14 | | |
15 | | #include "av1/encoder/encoder.h" |
16 | | #include "aom_dsp/psnr.h" |
17 | | |
18 | | #ifdef __cplusplus |
19 | | extern "C" { |
20 | | #endif |
21 | | |
22 | 0 | static inline void check_reset_rc_flag(AV1_COMP *cpi) { |
23 | 0 | RATE_CONTROL *rc = &cpi->rc; |
24 | 0 | PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; |
25 | 0 | if (cpi->common.current_frame.frame_number > |
26 | 0 | (unsigned int)cpi->svc.number_spatial_layers) { |
27 | 0 | if (cpi->ppi->use_svc) { |
28 | 0 | av1_svc_check_reset_layer_rc_flag(cpi); |
29 | 0 | } else { |
30 | 0 | if (rc->avg_frame_bandwidth / 3 > (rc->prev_avg_frame_bandwidth >> 1) || |
31 | 0 | rc->avg_frame_bandwidth < (rc->prev_avg_frame_bandwidth >> 1)) { |
32 | 0 | rc->rc_1_frame = 0; |
33 | 0 | rc->rc_2_frame = 0; |
34 | 0 | p_rc->bits_off_target = p_rc->optimal_buffer_level; |
35 | 0 | p_rc->buffer_level = p_rc->optimal_buffer_level; |
36 | 0 | } |
37 | 0 | } |
38 | 0 | } |
39 | 0 | } Unexecuted instantiation: av1_cx_iface.c:check_reset_rc_flag Unexecuted instantiation: encoder.c:check_reset_rc_flag Unexecuted instantiation: encoder_utils.c:check_reset_rc_flag Unexecuted instantiation: pass2_strategy.c:check_reset_rc_flag |
40 | | |
41 | | static inline void set_primary_rc_buffer_sizes(const AV1EncoderConfig *oxcf, |
42 | 0 | AV1_PRIMARY *ppi) { |
43 | 0 | PRIMARY_RATE_CONTROL *p_rc = &ppi->p_rc; |
44 | 0 | const RateControlCfg *const rc_cfg = &oxcf->rc_cfg; |
45 | |
|
46 | 0 | const int64_t bandwidth = rc_cfg->target_bandwidth; |
47 | 0 | const int64_t starting = rc_cfg->starting_buffer_level_ms; |
48 | 0 | const int64_t optimal = rc_cfg->optimal_buffer_level_ms; |
49 | 0 | const int64_t maximum = rc_cfg->maximum_buffer_size_ms; |
50 | |
|
51 | 0 | p_rc->starting_buffer_level = starting * bandwidth / 1000; |
52 | 0 | p_rc->optimal_buffer_level = |
53 | 0 | (optimal == 0) ? bandwidth / 8 : optimal * bandwidth / 1000; |
54 | 0 | p_rc->maximum_buffer_size = |
55 | 0 | (maximum == 0) ? bandwidth / 8 : maximum * bandwidth / 1000; |
56 | | |
57 | | // Under a configuration change, where maximum_buffer_size may change, |
58 | | // keep buffer level clipped to the maximum allowed buffer size. |
59 | 0 | p_rc->bits_off_target = |
60 | 0 | AOMMIN(p_rc->bits_off_target, p_rc->maximum_buffer_size); |
61 | 0 | p_rc->buffer_level = AOMMIN(p_rc->buffer_level, p_rc->maximum_buffer_size); |
62 | 0 | } Unexecuted instantiation: av1_cx_iface.c:set_primary_rc_buffer_sizes Unexecuted instantiation: encoder.c:set_primary_rc_buffer_sizes Unexecuted instantiation: encoder_utils.c:set_primary_rc_buffer_sizes Unexecuted instantiation: pass2_strategy.c:set_primary_rc_buffer_sizes |
63 | | |
64 | | static inline void config_target_level(AV1_COMP *const cpi, |
65 | 0 | AV1_LEVEL target_level, int tier) { |
66 | 0 | AV1EncoderConfig *const oxcf = &cpi->oxcf; |
67 | 0 | SequenceHeader *const seq_params = cpi->common.seq_params; |
68 | 0 | TileConfig *const tile_cfg = &oxcf->tile_cfg; |
69 | 0 | RateControlCfg *const rc_cfg = &oxcf->rc_cfg; |
70 | | |
71 | | // Adjust target bitrate to be no larger than 70% of level limit. |
72 | 0 | const BITSTREAM_PROFILE profile = seq_params->profile; |
73 | 0 | const double level_bitrate_limit = |
74 | 0 | av1_get_max_bitrate_for_level(target_level, tier, profile); |
75 | 0 | const int64_t max_bitrate = (int64_t)(level_bitrate_limit * 0.70); |
76 | 0 | rc_cfg->target_bandwidth = AOMMIN(rc_cfg->target_bandwidth, max_bitrate); |
77 | | // Also need to update cpi->ppi->twopass.bits_left. |
78 | 0 | TWO_PASS *const twopass = &cpi->ppi->twopass; |
79 | 0 | FIRSTPASS_STATS *stats = twopass->stats_buf_ctx->total_stats; |
80 | 0 | if (stats != NULL) |
81 | 0 | cpi->ppi->twopass.bits_left = |
82 | 0 | (int64_t)(stats->duration * rc_cfg->target_bandwidth / 10000000.0); |
83 | | |
84 | | // Adjust max over-shoot percentage. |
85 | 0 | rc_cfg->over_shoot_pct = 0; |
86 | | |
87 | | // Adjust max quantizer. |
88 | 0 | rc_cfg->worst_allowed_q = 255; |
89 | | |
90 | | // Adjust number of tiles and tile columns to be under level limit. |
91 | 0 | int max_tiles, max_tile_cols; |
92 | 0 | av1_get_max_tiles_for_level(target_level, &max_tiles, &max_tile_cols); |
93 | 0 | while (tile_cfg->tile_columns > 0 && |
94 | 0 | (1 << tile_cfg->tile_columns) > max_tile_cols) { |
95 | 0 | --tile_cfg->tile_columns; |
96 | 0 | } |
97 | 0 | const int tile_cols = (1 << tile_cfg->tile_columns); |
98 | 0 | while (tile_cfg->tile_rows > 0 && |
99 | 0 | tile_cols * (1 << tile_cfg->tile_rows) > max_tiles) { |
100 | 0 | --tile_cfg->tile_rows; |
101 | 0 | } |
102 | | |
103 | | // Adjust min compression ratio. |
104 | 0 | const int still_picture = seq_params->still_picture; |
105 | 0 | const double min_cr = |
106 | 0 | av1_get_min_cr_for_level(target_level, tier, still_picture); |
107 | 0 | rc_cfg->min_cr = AOMMAX(rc_cfg->min_cr, (unsigned int)(min_cr * 100)); |
108 | 0 | } Unexecuted instantiation: av1_cx_iface.c:config_target_level Unexecuted instantiation: encoder.c:config_target_level Unexecuted instantiation: encoder_utils.c:config_target_level Unexecuted instantiation: pass2_strategy.c:config_target_level |
109 | | |
110 | | #if !CONFIG_REALTIME_ONLY |
111 | | |
112 | | /*!\brief Function to test for conditions that indicate we should loop |
113 | | * back and recode a frame. |
114 | | * |
115 | | * \ingroup rate_control |
116 | | * |
117 | | * \param[in] cpi Top-level encoder structure |
118 | | * \param[in] high_limit Upper rate threshold |
119 | | * \param[in] low_limit Lower rate threshold |
120 | | * \param[in] q Current q index |
121 | | * \param[in] maxq Maximum allowed q index |
122 | | * \param[in] minq Minimum allowed q index |
123 | | * |
124 | | * \return Indicates if a recode is required. |
125 | | * \retval 1 Recode Required |
126 | | * \retval 0 No Recode required |
127 | | */ |
128 | | static inline int recode_loop_test(AV1_COMP *cpi, int high_limit, int low_limit, |
129 | 0 | int q, int maxq, int minq) { |
130 | 0 | const RATE_CONTROL *const rc = &cpi->rc; |
131 | 0 | const AV1EncoderConfig *const oxcf = &cpi->oxcf; |
132 | 0 | const int frame_is_kfgfarf = frame_is_kf_gf_arf(cpi); |
133 | 0 | int force_recode = 0; |
134 | |
|
135 | 0 | if ((rc->projected_frame_size >= rc->max_frame_bandwidth) || |
136 | 0 | (cpi->sf.hl_sf.recode_loop == ALLOW_RECODE) || |
137 | 0 | (frame_is_kfgfarf && |
138 | 0 | (cpi->sf.hl_sf.recode_loop == ALLOW_RECODE_KFARFGF))) { |
139 | | // TODO(agrange) high_limit could be greater than the scale-down threshold. |
140 | 0 | if ((rc->projected_frame_size > high_limit && q < maxq) || |
141 | 0 | (rc->projected_frame_size < low_limit && q > minq)) { |
142 | 0 | force_recode = 1; |
143 | 0 | } else if (cpi->oxcf.rc_cfg.mode == AOM_CQ) { |
144 | | // Deal with frame undershoot and whether or not we are |
145 | | // below the automatically set cq level. |
146 | 0 | if (q > oxcf->rc_cfg.cq_level && |
147 | 0 | rc->projected_frame_size < |
148 | 0 | (((int64_t)rc->this_frame_target * 7) >> 3)) { |
149 | 0 | force_recode = 1; |
150 | 0 | } |
151 | 0 | } |
152 | 0 | } |
153 | 0 | return force_recode; |
154 | 0 | } Unexecuted instantiation: av1_cx_iface.c:recode_loop_test Unexecuted instantiation: encoder.c:recode_loop_test Unexecuted instantiation: encoder_utils.c:recode_loop_test Unexecuted instantiation: pass2_strategy.c:recode_loop_test |
155 | | |
156 | | static inline double av1_get_gfu_boost_projection_factor(double min_factor, |
157 | | double max_factor, |
158 | 0 | int frame_count) { |
159 | 0 | double factor = sqrt((double)frame_count); |
160 | 0 | factor = AOMMIN(factor, max_factor); |
161 | 0 | factor = AOMMAX(factor, min_factor); |
162 | 0 | factor = (200.0 + 10.0 * factor); |
163 | 0 | return factor; |
164 | 0 | } Unexecuted instantiation: av1_cx_iface.c:av1_get_gfu_boost_projection_factor Unexecuted instantiation: encoder.c:av1_get_gfu_boost_projection_factor Unexecuted instantiation: encoder_utils.c:av1_get_gfu_boost_projection_factor Unexecuted instantiation: pass2_strategy.c:av1_get_gfu_boost_projection_factor |
165 | | |
166 | | static inline int get_gfu_boost_from_r0_lap(double min_factor, |
167 | | double max_factor, double r0, |
168 | 0 | int frames_to_key) { |
169 | 0 | double factor = av1_get_gfu_boost_projection_factor(min_factor, max_factor, |
170 | 0 | frames_to_key); |
171 | 0 | const int boost = (int)rint(factor / r0); |
172 | 0 | return boost; |
173 | 0 | } Unexecuted instantiation: av1_cx_iface.c:get_gfu_boost_from_r0_lap Unexecuted instantiation: encoder.c:get_gfu_boost_from_r0_lap Unexecuted instantiation: encoder_utils.c:get_gfu_boost_from_r0_lap Unexecuted instantiation: pass2_strategy.c:get_gfu_boost_from_r0_lap |
174 | | |
175 | 0 | static inline double av1_get_kf_boost_projection_factor(int frame_count) { |
176 | 0 | double factor = sqrt((double)frame_count); |
177 | 0 | factor = AOMMIN(factor, 10.0); |
178 | 0 | factor = AOMMAX(factor, 4.0); |
179 | 0 | factor = (75.0 + 14.0 * factor); |
180 | 0 | return factor; |
181 | 0 | } Unexecuted instantiation: av1_cx_iface.c:av1_get_kf_boost_projection_factor Unexecuted instantiation: encoder.c:av1_get_kf_boost_projection_factor Unexecuted instantiation: encoder_utils.c:av1_get_kf_boost_projection_factor Unexecuted instantiation: pass2_strategy.c:av1_get_kf_boost_projection_factor |
182 | | |
183 | | static inline int get_regulated_q_overshoot(AV1_COMP *const cpi, |
184 | | int is_encode_stage, int q_low, |
185 | | int q_high, int top_index, |
186 | 0 | int bottom_index) { |
187 | 0 | const AV1_COMMON *const cm = &cpi->common; |
188 | 0 | const RATE_CONTROL *const rc = &cpi->rc; |
189 | |
|
190 | 0 | av1_rc_update_rate_correction_factors(cpi, is_encode_stage, cm->width, |
191 | 0 | cm->height); |
192 | |
|
193 | 0 | int q_regulated = |
194 | 0 | av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index, |
195 | 0 | AOMMAX(q_high, top_index), cm->width, cm->height); |
196 | |
|
197 | 0 | int retries = 0; |
198 | 0 | while (q_regulated < q_low && retries < 10) { |
199 | 0 | av1_rc_update_rate_correction_factors(cpi, is_encode_stage, cm->width, |
200 | 0 | cm->height); |
201 | 0 | q_regulated = |
202 | 0 | av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index, |
203 | 0 | AOMMAX(q_high, top_index), cm->width, cm->height); |
204 | 0 | retries++; |
205 | 0 | } |
206 | 0 | return q_regulated; |
207 | 0 | } Unexecuted instantiation: av1_cx_iface.c:get_regulated_q_overshoot Unexecuted instantiation: encoder.c:get_regulated_q_overshoot Unexecuted instantiation: encoder_utils.c:get_regulated_q_overshoot Unexecuted instantiation: pass2_strategy.c:get_regulated_q_overshoot |
208 | | |
209 | | static inline int get_regulated_q_undershoot(AV1_COMP *const cpi, |
210 | | int is_encode_stage, int q_high, |
211 | 0 | int top_index, int bottom_index) { |
212 | 0 | const AV1_COMMON *const cm = &cpi->common; |
213 | 0 | const RATE_CONTROL *const rc = &cpi->rc; |
214 | |
|
215 | 0 | av1_rc_update_rate_correction_factors(cpi, is_encode_stage, cm->width, |
216 | 0 | cm->height); |
217 | 0 | int q_regulated = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index, |
218 | 0 | top_index, cm->width, cm->height); |
219 | |
|
220 | 0 | int retries = 0; |
221 | 0 | while (q_regulated > q_high && retries < 10) { |
222 | 0 | av1_rc_update_rate_correction_factors(cpi, is_encode_stage, cm->width, |
223 | 0 | cm->height); |
224 | 0 | q_regulated = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index, |
225 | 0 | top_index, cm->width, cm->height); |
226 | 0 | retries++; |
227 | 0 | } |
228 | 0 | return q_regulated; |
229 | 0 | } Unexecuted instantiation: av1_cx_iface.c:get_regulated_q_undershoot Unexecuted instantiation: encoder.c:get_regulated_q_undershoot Unexecuted instantiation: encoder_utils.c:get_regulated_q_undershoot Unexecuted instantiation: pass2_strategy.c:get_regulated_q_undershoot |
230 | | |
231 | | /*!\brief Called after encode_with_recode_loop() has just encoded a frame. |
232 | | * This function works out whether we undershot or overshot our bitrate |
233 | | * target and adjusts q as appropriate. It also decides whether or not |
234 | | * we need to recode the frame to get closer to the target rate. |
235 | | * |
236 | | * \ingroup rate_control |
237 | | * |
238 | | * \param[in] cpi Top-level encoder structure |
239 | | * \param[out] loop Should we go around the recode loop again |
240 | | * \param[in,out] q New q index value |
241 | | * \param[in,out] q_low Low q index limit for this loop itteration |
242 | | * \param[in,out] q_high High q index limit for this loop itteration |
243 | | * \param[in] top_index Max permited new value for q index |
244 | | * \param[in] bottom_index Min permited new value for q index |
245 | | * \param[in,out] undershoot_seen Have we seen undershoot on this frame |
246 | | * \param[in,out] overshoot_seen Have we seen overshoot on this frame |
247 | | * \param[in,out] low_cr_seen Have we previously trriggered recode |
248 | | * because the compression ration was less |
249 | | * than a given minimum threshold. |
250 | | * \param[in] loop_count Loop itterations so far. |
251 | | * |
252 | | */ |
253 | | static inline void recode_loop_update_q( |
254 | | AV1_COMP *const cpi, int *const loop, int *const q, int *const q_low, |
255 | | int *const q_high, const int top_index, const int bottom_index, |
256 | | int *const undershoot_seen, int *const overshoot_seen, |
257 | 0 | int *const low_cr_seen, const int loop_count) { |
258 | 0 | AV1_COMMON *const cm = &cpi->common; |
259 | 0 | RATE_CONTROL *const rc = &cpi->rc; |
260 | 0 | PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc; |
261 | 0 | const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg; |
262 | 0 | *loop = 0; |
263 | | |
264 | | // Special case for overlay frame. |
265 | 0 | if (rc->is_src_frame_alt_ref && |
266 | 0 | rc->projected_frame_size < rc->max_frame_bandwidth) |
267 | 0 | return; |
268 | | |
269 | 0 | const int min_cr = rc_cfg->min_cr; |
270 | 0 | if (min_cr > 0) { |
271 | 0 | const double compression_ratio = |
272 | 0 | av1_get_compression_ratio(cm, rc->projected_frame_size >> 3); |
273 | 0 | const double target_cr = min_cr / 100.0; |
274 | 0 | if (compression_ratio < target_cr) { |
275 | 0 | *low_cr_seen = 1; |
276 | 0 | if (*q < rc->worst_quality) { |
277 | 0 | const double cr_ratio = target_cr / compression_ratio; |
278 | 0 | const int projected_q = AOMMAX(*q + 1, (int)(*q * cr_ratio * cr_ratio)); |
279 | 0 | *q = AOMMIN(AOMMIN(projected_q, *q + 32), rc->worst_quality); |
280 | 0 | *q_low = AOMMAX(*q, *q_low); |
281 | 0 | *q_high = AOMMAX(*q, *q_high); |
282 | 0 | *loop = 1; |
283 | 0 | } |
284 | 0 | } |
285 | 0 | if (*low_cr_seen) return; |
286 | 0 | } |
287 | | |
288 | 0 | if (cpi->ppi->level_params.keep_level_stats && |
289 | 0 | !is_stat_generation_stage(cpi)) { |
290 | | // Initialize level info. at the beginning of each sequence. |
291 | 0 | if (cm->current_frame.frame_type == KEY_FRAME && |
292 | 0 | cpi->ppi->gf_group.refbuf_state[cpi->gf_frame_index] == REFBUF_RESET) { |
293 | 0 | av1_init_level_info(cpi); |
294 | 0 | } |
295 | 0 | const AV1LevelParams *const level_params = &cpi->ppi->level_params; |
296 | | // TODO(any): currently only checking operating point 0 |
297 | 0 | const AV1LevelInfo *const level_info = level_params->level_info[0]; |
298 | 0 | const DECODER_MODEL *const decoder_models = level_info->decoder_models; |
299 | 0 | const AV1_LEVEL target_level = level_params->target_seq_level_idx[0]; |
300 | |
|
301 | 0 | if (target_level < SEQ_LEVELS && |
302 | 0 | decoder_models[target_level].status == DECODER_MODEL_OK) { |
303 | 0 | DECODER_MODEL_STATUS status = av1_decoder_model_try_smooth_buf( |
304 | 0 | cpi, rc->projected_frame_size, &decoder_models[target_level]); |
305 | |
|
306 | 0 | if ((status == SMOOTHING_BUFFER_UNDERFLOW || |
307 | 0 | status == SMOOTHING_BUFFER_OVERFLOW) && |
308 | 0 | *q < rc->worst_quality) { |
309 | 0 | *q = AOMMIN(*q + 10, rc->worst_quality); |
310 | 0 | *q_low = AOMMAX(*q, *q_low); |
311 | 0 | *q_high = AOMMAX(*q, *q_high); |
312 | 0 | *loop = 1; |
313 | 0 | return; |
314 | 0 | } |
315 | 0 | } |
316 | 0 | } |
317 | | |
318 | 0 | if (rc_cfg->mode == AOM_Q) return; |
319 | | |
320 | 0 | const int last_q = *q; |
321 | 0 | int frame_over_shoot_limit = 0, frame_under_shoot_limit = 0; |
322 | 0 | av1_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, |
323 | 0 | &frame_under_shoot_limit, |
324 | 0 | &frame_over_shoot_limit); |
325 | 0 | if (frame_over_shoot_limit == 0) frame_over_shoot_limit = 1; |
326 | |
|
327 | 0 | if (cm->current_frame.frame_type == KEY_FRAME && |
328 | 0 | p_rc->this_key_frame_forced && |
329 | 0 | rc->projected_frame_size < rc->max_frame_bandwidth) { |
330 | 0 | int64_t kf_err; |
331 | 0 | const int64_t high_err_target = cpi->ambient_err; |
332 | 0 | const int64_t low_err_target = cpi->ambient_err >> 1; |
333 | |
|
334 | 0 | #if CONFIG_AV1_HIGHBITDEPTH |
335 | 0 | if (cm->seq_params->use_highbitdepth) { |
336 | 0 | kf_err = aom_highbd_get_y_sse(cpi->source, &cm->cur_frame->buf); |
337 | 0 | } else { |
338 | 0 | kf_err = aom_get_y_sse(cpi->source, &cm->cur_frame->buf); |
339 | 0 | } |
340 | | #else |
341 | | kf_err = aom_get_y_sse(cpi->source, &cm->cur_frame->buf); |
342 | | #endif |
343 | | // Prevent possible divide by zero error below for perfect KF |
344 | 0 | kf_err += !kf_err; |
345 | | |
346 | | // The key frame is not good enough or we can afford |
347 | | // to make it better without undue risk of popping. |
348 | 0 | if ((kf_err > high_err_target && |
349 | 0 | rc->projected_frame_size <= frame_over_shoot_limit) || |
350 | 0 | (kf_err > low_err_target && |
351 | 0 | rc->projected_frame_size <= frame_under_shoot_limit)) { |
352 | | // Lower q_high |
353 | 0 | *q_high = AOMMAX(*q - 1, *q_low); |
354 | | |
355 | | // Adjust Q |
356 | 0 | *q = (int)((*q * high_err_target) / kf_err); |
357 | 0 | *q = AOMMIN(*q, (*q_high + *q_low) >> 1); |
358 | 0 | } else if (kf_err < low_err_target && |
359 | 0 | rc->projected_frame_size >= frame_under_shoot_limit) { |
360 | | // The key frame is much better than the previous frame |
361 | | // Raise q_low |
362 | 0 | *q_low = AOMMIN(*q + 1, *q_high); |
363 | | |
364 | | // Adjust Q |
365 | 0 | *q = (int)((*q * low_err_target) / kf_err); |
366 | 0 | *q = AOMMIN(*q, (*q_high + *q_low + 1) >> 1); |
367 | 0 | } |
368 | | |
369 | | // Clamp Q to upper and lower limits: |
370 | 0 | *q = clamp(*q, *q_low, *q_high); |
371 | 0 | *loop = (*q != last_q); |
372 | 0 | return; |
373 | 0 | } |
374 | | |
375 | 0 | if (recode_loop_test(cpi, frame_over_shoot_limit, frame_under_shoot_limit, *q, |
376 | 0 | AOMMAX(*q_high, top_index), bottom_index)) { |
377 | | // Is the projected frame size out of range and are we allowed |
378 | | // to attempt to recode. |
379 | | |
380 | | // Frame size out of permitted range: |
381 | | // Update correction factor & compute new Q to try... |
382 | | // Frame is too large |
383 | 0 | if (rc->projected_frame_size > rc->this_frame_target) { |
384 | | // Special case if the projected size is > the max allowed. |
385 | 0 | if (*q == *q_high && |
386 | 0 | rc->projected_frame_size >= rc->max_frame_bandwidth) { |
387 | 0 | const double q_val_high_current = |
388 | 0 | av1_convert_qindex_to_q(*q_high, cm->seq_params->bit_depth); |
389 | 0 | const double q_val_high_new = |
390 | 0 | q_val_high_current * |
391 | 0 | ((double)rc->projected_frame_size / rc->max_frame_bandwidth); |
392 | 0 | *q_high = av1_find_qindex(q_val_high_new, cm->seq_params->bit_depth, |
393 | 0 | rc->best_quality, rc->worst_quality); |
394 | 0 | } |
395 | | |
396 | | // Raise Qlow as to at least the current value |
397 | 0 | *q_low = AOMMIN(*q + 1, *q_high); |
398 | |
|
399 | 0 | if (*undershoot_seen || loop_count > 2 || |
400 | 0 | (loop_count == 2 && !frame_is_intra_only(cm))) { |
401 | 0 | av1_rc_update_rate_correction_factors(cpi, 1, cm->width, cm->height); |
402 | |
|
403 | 0 | *q = (*q_high + *q_low + 1) / 2; |
404 | 0 | } else if (loop_count == 2 && frame_is_intra_only(cm)) { |
405 | 0 | const int q_mid = (*q_high + *q_low + 1) / 2; |
406 | 0 | const int q_regulated = get_regulated_q_overshoot( |
407 | 0 | cpi, 1, *q_low, *q_high, top_index, bottom_index); |
408 | | // Get 'q' in-between 'q_mid' and 'q_regulated' for a smooth |
409 | | // transition between loop_count < 2 and loop_count > 2. |
410 | 0 | *q = (q_mid + q_regulated + 1) / 2; |
411 | 0 | } else { |
412 | 0 | *q = get_regulated_q_overshoot(cpi, 1, *q_low, *q_high, top_index, |
413 | 0 | bottom_index); |
414 | 0 | } |
415 | |
|
416 | 0 | *overshoot_seen = 1; |
417 | 0 | } else { |
418 | | // Frame is too small |
419 | 0 | *q_high = AOMMAX(*q - 1, *q_low); |
420 | |
|
421 | 0 | if (*overshoot_seen || loop_count > 2 || |
422 | 0 | (loop_count == 2 && !frame_is_intra_only(cm))) { |
423 | 0 | av1_rc_update_rate_correction_factors(cpi, 1, cm->width, cm->height); |
424 | 0 | *q = (*q_high + *q_low) / 2; |
425 | 0 | } else if (loop_count == 2 && frame_is_intra_only(cm)) { |
426 | 0 | const int q_mid = (*q_high + *q_low) / 2; |
427 | 0 | const int q_regulated = get_regulated_q_undershoot( |
428 | 0 | cpi, 1, *q_high, top_index, bottom_index); |
429 | | // Get 'q' in-between 'q_mid' and 'q_regulated' for a smooth |
430 | | // transition between loop_count < 2 and loop_count > 2. |
431 | 0 | *q = (q_mid + q_regulated) / 2; |
432 | | |
433 | | // Special case reset for qlow for constrained quality. |
434 | | // This should only trigger where there is very substantial |
435 | | // undershoot on a frame and the auto cq level is above |
436 | | // the user passsed in value. |
437 | 0 | if (rc_cfg->mode == AOM_CQ && q_regulated < *q_low) { |
438 | 0 | *q_low = *q; |
439 | 0 | } |
440 | 0 | } else { |
441 | 0 | *q = get_regulated_q_undershoot(cpi, 1, *q_high, top_index, |
442 | 0 | bottom_index); |
443 | | |
444 | | // Special case reset for qlow for constrained quality. |
445 | | // This should only trigger where there is very substantial |
446 | | // undershoot on a frame and the auto cq level is above |
447 | | // the user passsed in value. |
448 | 0 | if (rc_cfg->mode == AOM_CQ && *q < *q_low) { |
449 | 0 | *q_low = *q; |
450 | 0 | } |
451 | 0 | } |
452 | |
|
453 | 0 | *undershoot_seen = 1; |
454 | 0 | } |
455 | | |
456 | | // Clamp Q to upper and lower limits: |
457 | 0 | *q = clamp(*q, *q_low, *q_high); |
458 | 0 | } |
459 | |
|
460 | 0 | *loop = (*q != last_q); |
461 | 0 | } Unexecuted instantiation: av1_cx_iface.c:recode_loop_update_q Unexecuted instantiation: encoder.c:recode_loop_update_q Unexecuted instantiation: encoder_utils.c:recode_loop_update_q Unexecuted instantiation: pass2_strategy.c:recode_loop_update_q |
462 | | #endif |
463 | | |
464 | | #ifdef __cplusplus |
465 | | } // extern "C" |
466 | | #endif |
467 | | |
468 | | #endif // AOM_AV1_ENCODER_RC_UTILS_H_ |