| @@ -4201,6 +4201,134 @@ static int get_qstep_adj(int rate_excess, int rate_limit) { · 4200 unmodified lines |
| 4201 | 4201 | return VPXMIN(qstep, MAX_QSTEP_ADJ); |
| 4202 | 4202 | } |
| 4203 | 4203 | |
| 4204 | +#if CONFIG_RATE_CTRL |
| 4205 | +#define RATE_CTRL_MAX_RECODE_NUM 7 |
| 4206 | + |
| 4207 | +typedef struct RATE_QINDEX_HISTORY { |
| 4208 | + int recode_count; |
| 4209 | + int q_index_history[RATE_CTRL_MAX_RECODE_NUM]; |
| 4210 | + int rate_history[RATE_CTRL_MAX_RECODE_NUM]; |
| 4211 | + int q_index_high; |
| 4212 | + int q_index_low; |
| 4213 | +} RATE_QINDEX_HISTORY; |
| 4214 | + |
| 4215 | +static void init_rq_history(RATE_QINDEX_HISTORY *rq_history) { |
| 4216 | + rq_history->recode_count = 0; |
| 4217 | + rq_history->q_index_high = 255; |
| 4218 | + rq_history->q_index_low = 0; |
| 4219 | +} |
| 4220 | + |
| 4221 | +static void update_rq_history(RATE_QINDEX_HISTORY *rq_history, int target_bits, |
| 4222 | + int actual_bits, int q_index) { |
| 4223 | + rq_history->q_index_history[rq_history->recode_count] = q_index; |
| 4224 | + rq_history->rate_history[rq_history->recode_count] = actual_bits; |
| 4225 | + if (actual_bits <= target_bits) { |
| 4226 | + rq_history->q_index_high = q_index; |
| 4227 | + } |
| 4228 | + if (actual_bits >= target_bits) { |
| 4229 | + rq_history->q_index_low = q_index; |
| 4230 | + } |
| 4231 | + rq_history->recode_count += 1; |
| 4232 | +} |
| 4233 | + |
| 4234 | +static int guess_q_index_from_model(const RATE_QSTEP_MODEL *rq_model, |
| 4235 | + int target_bits) { |
| 4236 | + // The model predicts bits as follows. |
| 4237 | + // target_bits = bias - ratio * log2(q_step) |
| 4238 | + // Given the target_bits, we compute the q_step as follows. |
| 4239 | + const double q_step = |
| 4240 | + pow(2.0, (rq_model->bias - target_bits) / rq_model->ratio); |
| 4241 | + // TODO(angiebird): Make this function support highbitdepth. |
| 4242 | + return vp9_convert_q_to_qindex(q_step, VPX_BITS_8); |
| 4243 | +} |
| 4244 | + |
| 4245 | +static int guess_q_index_linear(int prev_q_index, int target_bits, |
| 4246 | + int actual_bits, int gap) { |
| 4247 | + int q_index = prev_q_index; |
| 4248 | + if (actual_bits < target_bits) { |
| 4249 | + q_index -= gap; |
| 4250 | + q_index = VPXMAX(q_index, 0); |
| 4251 | + } else { |
| 4252 | + q_index += gap; |
| 4253 | + q_index = VPXMIN(q_index, 255); |
| 4254 | + } |
| 4255 | + return q_index; |
| 4256 | +} |
| 4257 | + |
| 4258 | +static double get_bits_percent_diff(int target_bits, int actual_bits) { |
| 4259 | + double diff = abs(target_bits - actual_bits) * 1. / target_bits; |
| 4260 | + diff *= 100; |
| 4261 | + return diff; |
| 4262 | +} |
| 4263 | + |
| 4264 | +static int rq_model_predict_q_index(const RATE_QSTEP_MODEL *rq_model, |
| 4265 | + const RATE_QINDEX_HISTORY *rq_history, |
| 4266 | + int target_bits) { |
| 4267 | + int q_index = -1; |
| 4268 | + if (rq_history->recode_count > 0) { |
| 4269 | + const int actual_bits = |
| 4270 | + rq_history->rate_history[rq_history->recode_count - 1]; |
| 4271 | + const int prev_q_index = |
| 4272 | + rq_history->q_index_history[rq_history->recode_count - 1]; |
| 4273 | + const double percent_diff = get_bits_percent_diff(target_bits, actual_bits); |
| 4274 | + if (percent_diff > 50) { |
| 4275 | + // Binary search. |
| 4276 | + // When the actual_bits and target_bits are far apart, binary search |
| 4277 | + // q_index is faster. |
| 4278 | + q_index = (rq_history->q_index_low + rq_history->q_index_high) / 2; |
| 4279 | + } else { |
| 4280 | + if (rq_model->ready) { |
| 4281 | + q_index = guess_q_index_from_model(rq_model, target_bits); |
| 4282 | + } else { |
| 4283 | + // TODO(angiebird): Find a better way to set the gap. |
| 4284 | + q_index = |
| 4285 | + guess_q_index_linear(prev_q_index, target_bits, actual_bits, 20); |
| 4286 | + } |
| 4287 | + } |
| 4288 | + } else { |
| 4289 | + if (rq_model->ready) { |
| 4290 | + q_index = guess_q_index_from_model(rq_model, target_bits); |
| 4291 | + } |
| 4292 | + } |
| 4293 | + |
| 4294 | + assert(rq_history->q_index_low <= rq_history->q_index_high); |
| 4295 | + if (q_index <= rq_history->q_index_low) { |
| 4296 | + q_index = rq_history->q_index_low + 1; |
| 4297 | + } |
| 4298 | + if (q_index >= rq_history->q_index_high) { |
| 4299 | + q_index = rq_history->q_index_high - 1; |
| 4300 | + } |
| 4301 | + return q_index; |
| 4302 | +} |
| 4303 | + |
| 4304 | +static void rq_model_update(const RATE_QINDEX_HISTORY *rq_history, |
| 4305 | + int target_bits, RATE_QSTEP_MODEL *rq_model) { |
| 4306 | + const int recode_count = rq_history->recode_count; |
| 4307 | + if (recode_count >= 2) { |
| 4308 | + // Fit the ratio and bias of rq_model based on last two recode histories. |
| 4309 | + const double s1 = vp9_convert_qindex_to_q( |
| 4310 | + rq_history->q_index_history[recode_count - 2], VPX_BITS_8); |
| 4311 | + const double s2 = vp9_convert_qindex_to_q( |
| 4312 | + rq_history->q_index_history[recode_count - 1], VPX_BITS_8); |
| 4313 | + const double r1 = rq_history->rate_history[recode_count - 2]; |
| 4314 | + const double r2 = rq_history->rate_history[recode_count - 1]; |
| 4315 | + rq_model->ratio = (r2 - r1) / (log2(s1) - log2(s2)); |
| 4316 | + rq_model->bias = r1 + (rq_model->ratio) * log2(s1); |
| 4317 | + rq_model->ready = 1; |
| 4318 | + } else if (recode_count == 1) { |
| 4319 | + if (rq_model->ready) { |
| 4320 | + // Update the ratio only when the initial model exists and we only have |
| 4321 | + // one recode history. |
| 4322 | + const int prev_q = rq_history->q_index_history[recode_count - 1]; |
| 4323 | + const double prev_q_step = vp9_convert_qindex_to_q(prev_q, VPX_BITS_8); |
| 4324 | + const int actual_bits = rq_history->rate_history[recode_count - 1]; |
| 4325 | + rq_model->ratio = |
| 4326 | + rq_model->ratio - (target_bits - actual_bits) / log2(prev_q_step); |
| 4327 | + } |
| 4328 | + } |
| 4329 | +} |
| 4330 | +#endif // CONFIG_RATE_CTRL |
| 4331 | + |
| 4204 | 4332 | static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, |
| 4205 | 4333 | uint8_t *dest) { |
| 4206 | 4334 | const VP9EncoderConfig *const oxcf = &cpi->oxcf; |
| @@ -4220,6 +4348,15 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, · 13 unmodified lines |
| 4220 | 4348 | int qrange_adj = 1; |
| 4221 | 4349 | #endif |
| 4222 | 4350 | |
| 4351 | +#if CONFIG_RATE_CTRL |
| 4352 | + const FRAME_UPDATE_TYPE update_type = |
| 4353 | + cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index]; |
| 4354 | + const ENCODE_FRAME_TYPE frame_type = get_encode_frame_type(update_type); |
| 4355 | + RATE_QSTEP_MODEL *rq_model = &cpi->rq_model[frame_type]; |
| 4356 | + RATE_QINDEX_HISTORY rq_history; |
| 4357 | + init_rq_history(&rq_history); |
| 4358 | +#endif // CONFIG_RATE_CTRL |
| 4359 | + |
| 4223 | 4360 | if (cm->show_existing_frame) { |
| 4224 | 4361 | rc->this_frame_target = 0; |
| 4225 | 4362 | if (is_psnr_calc_enabled(cpi)) set_raw_source_frame(cpi); |
| @@ -4266,6 +4403,15 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, · 40 unmodified lines |
| 4266 | 4403 | loop_at_this_size = 0; |
| 4267 | 4404 | } |
| 4268 | 4405 | |
| 4406 | +#if CONFIG_RATE_CTRL |
| 4407 | + { |
| 4408 | + const int suggested_q_index = rq_model_predict_q_index( |
| 4409 | + rq_model, &rq_history, rc->this_frame_target); |
| 4410 | + if (suggested_q_index != -1) { |
| 4411 | + q = suggested_q_index; |
| 4412 | + } |
| 4413 | + } |
| 4414 | +#endif // CONFIG_RATE_CTRL |
| 4269 | 4415 | // Decide frame size bounds first time through. |
| 4270 | 4416 | if (loop_count == 0) { |
| 4271 | 4417 | vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, |
| @@ -4359,7 +4505,28 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, · 87 unmodified lines |
| 4359 | 4505 | if (cpi->encode_command.use_external_quantize_index) { |
| 4360 | 4506 | break; |
| 4361 | 4507 | } |
| 4362 | | −#endif |
| 4508 | + |
| 4509 | + if (cpi->encode_command.use_external_target_frame_bits) { |
| 4510 | + const double percent_diff = get_bits_percent_diff( |
| 4511 | + rc->this_frame_target, rc->projected_frame_size); |
| 4512 | + update_rq_history(&rq_history, rc->this_frame_target, |
| 4513 | + rc->projected_frame_size, q); |
| 4514 | + loop_count += 1; |
| 4515 | + |
| 4516 | + rq_model_update(&rq_history, rc->this_frame_target, rq_model); |
| 4517 | + |
| 4518 | + // Check if we hit the target bitrate. |
| 4519 | + if (percent_diff <= 15 || |
| 4520 | + rq_history.recode_count >= RATE_CTRL_MAX_RECODE_NUM || |
| 4521 | + rq_history.q_index_low >= rq_history.q_index_high) { |
| 4522 | + break; |
| 4523 | + } |
| 4524 | + |
| 4525 | + loop = 1; |
| 4526 | + restore_coding_context(cpi); |
| 4527 | + continue; |
| 4528 | + } |
| 4529 | +#endif // CONFIG_RATE_CTRL |
| 4363 | 4530 | |
| 4364 | 4531 | if (oxcf->rc_mode == VPX_Q) { |
| 4365 | 4532 | loop = 0; |