History

Merge "Add recode loop logics for rate_ctrl experiment"

Angie Chiang committed 6 years ago

Commit 8a8e7802 parents bdbf872 566905e2 files · +205 −1Browse files

Unified · Split

2 files
  1. vp9/encoder/vp9_encoder.c +168 −1
  2. vp9/encoder/vp9_encoder.h +37 −0
vp9/encoder/vp9_encoder.c+168−1
@@ -4201,6 +4201,134 @@ static int get_qstep_adj(int rate_excess, int rate_limit) { · 4200 unmodified lines
42014201 return VPXMIN(qstep, MAX_QSTEP_ADJ);
42024202 }
42034203
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+
42044332 static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size,
42054333 uint8_t *dest) {
42064334 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
42204348 int qrange_adj = 1;
42214349 #endif
42224350
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+
42234360 if (cm->show_existing_frame) {
42244361 rc->this_frame_target = 0;
42254362 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
42664403 loop_at_this_size = 0;
42674404 }
42684405
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
42694415 // Decide frame size bounds first time through.
42704416 if (loop_count == 0) {
42714417 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
43594505 if (cpi->encode_command.use_external_quantize_index) {
43604506 break;
43614507 }
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
43634530
43644531 if (oxcf->rc_mode == VPX_Q) {
43654532 loop = 0;
vp9/encoder/vp9_encoder.h+37−0
@@ -560,6 +560,41 @@ static INLINE int gop_command_coding_frame_count( · 559 unmodified lines
560560 return gop_command->show_frame_count + gop_command->use_alt_ref;
561561 }
562562
563+// TODO(angiebird): See if we can merge this one with FrameType in
564+// simple_encode.h
565+typedef enum ENCODE_FRAME_TYPE {
566+ ENCODE_FRAME_TYPE_KEY,
567+ ENCODE_FRAME_TYPE_INTER,
568+ ENCODE_FRAME_TYPE_ALTREF,
569+ ENCODE_FRAME_TYPE_OVERLAY,
570+ ENCODE_FRAME_TYPE_GOLDEN,
571+ ENCODE_FRAME_TYPES,
572+} ENCODE_FRAME_TYPE;
573+
574+// TODO(angiebird): Merge this function with get_frame_type_from_update_type()
575+static INLINE ENCODE_FRAME_TYPE
576+get_encode_frame_type(FRAME_UPDATE_TYPE update_type) {
577+ switch (update_type) {
578+ case KF_UPDATE: return ENCODE_FRAME_TYPE_KEY;
579+ case ARF_UPDATE: return ENCODE_FRAME_TYPE_ALTREF;
580+ case GF_UPDATE: return ENCODE_FRAME_TYPE_GOLDEN;
581+ case OVERLAY_UPDATE: return ENCODE_FRAME_TYPE_OVERLAY;
582+ case LF_UPDATE: return ENCODE_FRAME_TYPE_INTER;
583+ default:
584+ fprintf(stderr, "Unsupported update_type %d\n", update_type);
585+ abort();
586+ return ENCODE_FRAME_TYPE_INTER;
587+ }
588+}
589+
590+typedef struct RATE_QSTEP_MODEL {
591+ // The rq model predict the bit usage as follows.
592+ // rate = bias - ratio * log2(q_step)
593+ int ready;
594+ double bias;
595+ double ratio;
596+} RATE_QSTEP_MODEL;
597+
563598 typedef struct ENCODE_COMMAND {
564599 int use_external_quantize_index;
565600 int external_quantize_index;
@@ -917,6 +952,8 @@ typedef struct VP9_COMP { · 351 unmodified lines
917952 ENCODE_COMMAND encode_command;
918953 PARTITION_INFO *partition_info;
919954 MOTION_VECTOR_INFO *motion_vector_info;
955+
956+ RATE_QSTEP_MODEL rq_model[ENCODE_FRAME_TYPES];
920957 #endif
921958 } VP9_COMP;
922959

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t