| @@ -4201,6 +4201,134 @@ static int get_qstep_adj(int rate_excess, int rate_limit) { · 4200 unmodified lines |
| 4201 | return VPXMIN(qstep, MAX_QSTEP_ADJ); | 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 | static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, | 4332 | static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, |
| 4205 | uint8_t *dest) { | 4333 | uint8_t *dest) { |
| 4206 | const VP9EncoderConfig *const oxcf = &cpi->oxcf; | 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 | int qrange_adj = 1; | 4348 | int qrange_adj = 1; |
| 4221 | #endif | 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 | if (cm->show_existing_frame) { | 4360 | if (cm->show_existing_frame) { |
| 4224 | rc->this_frame_target = 0; | 4361 | rc->this_frame_target = 0; |
| 4225 | if (is_psnr_calc_enabled(cpi)) set_raw_source_frame(cpi); | 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 | loop_at_this_size = 0; | 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 | // Decide frame size bounds first time through. | 4415 | // Decide frame size bounds first time through. |
| 4270 | if (loop_count == 0) { | 4416 | if (loop_count == 0) { |
| 4271 | vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target, | 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 | if (cpi->encode_command.use_external_quantize_index) { | 4505 | if (cpi->encode_command.use_external_quantize_index) { |
| 4360 | break; | 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 | if (oxcf->rc_mode == VPX_Q) { | 4531 | if (oxcf->rc_mode == VPX_Q) { |
| 4365 | loop = 0; | 4532 | loop = 0; |