Add SetupDeltaQ to Qmode RC SetupDeltaQ is a simplified version of setup_delta_q and it adds all the qp indices. It doesn't follow the rule of restricting to max_distinct_q_indices_per_frame. K-means will be added as a separate CL. Bug: b/256852795 Change-Id: Ic9848631fad189ed1fbfa0d43d6d08485eb22cd2
diff --git a/av1/qmode_rc/ratectrl_qmode.cc b/av1/qmode_rc/ratectrl_qmode.cc index 725a01f..40fcab0 100644 --- a/av1/qmode_rc/ratectrl_qmode.cc +++ b/av1/qmode_rc/ratectrl_qmode.cc
@@ -1243,6 +1243,64 @@ return tpl_gop_dep_stats; } +static std::vector<uint8_t> SetupDeltaQ(const TplFrameDepStats &frame_dep_stats, + int frame_width, int frame_height, + int base_qindex, + double frame_importance) { + // TODO(jianj) : Add support to various superblock sizes. + const int sb_size = 64; + const int delta_q_res = 4; + const int num_unit_per_sb = sb_size / frame_dep_stats.unit_size; + const int sb_rows = (frame_height + sb_size - 1) / sb_size; + const int sb_cols = (frame_width + sb_size - 1) / sb_size; + const int unit_rows = (frame_height + frame_dep_stats.unit_size - 1) / + frame_dep_stats.unit_size; + const int unit_cols = + (frame_width + frame_dep_stats.unit_size - 1) / frame_dep_stats.unit_size; + double intra_cost = 0; + double mc_dep_cost = 0; + std::vector<uint8_t> superblock_q_indices; + // Calculate delta_q offset for each superblock. + for (int sb_row = 0; sb_row < sb_rows; ++sb_row) { + for (int sb_col = 0; sb_col < sb_cols; ++sb_col) { + const int unit_row_start = sb_row * num_unit_per_sb; + const int unit_row_end = + std::min((sb_row + 1) * num_unit_per_sb, unit_rows); + const int unit_col_start = sb_col * num_unit_per_sb; + const int unit_col_end = + std::min((sb_col + 1) * num_unit_per_sb, unit_cols); + // A simplified version of av1_get_q_for_deltaq_objective() + for (int unit_row = unit_row_start; unit_row < unit_row_end; ++unit_row) { + for (int unit_col = unit_col_start; unit_col < unit_col_end; + ++unit_col) { + const TplUnitDepStats &unit_dep_stat = + frame_dep_stats.unit_stats[unit_row][unit_col]; + intra_cost += unit_dep_stat.intra_cost; + mc_dep_cost += unit_dep_stat.intra_cost; + } + } + + double beta = 1.0; + if (mc_dep_cost > 0 && intra_cost > 0) { + const double r0 = 1 / frame_importance; + const double rk = intra_cost / mc_dep_cost; + beta = r0 / rk; + assert(beta > 0.0); + } + int offset = av1_get_deltaq_offset(AOM_BITS_8, base_qindex, beta); + offset = std::min(offset, delta_q_res * 9 - 1); + offset = std::max(offset, -delta_q_res * 9 + 1); + int qindex = offset + base_qindex; + qindex = std::min(qindex, MAXQ); + qindex = std::max(qindex, MINQ); + qindex = av1_adjust_q_from_delta_q_res(delta_q_res, base_qindex, qindex); + superblock_q_indices.push_back(static_cast<uint8_t>(qindex)); + } + } + + return superblock_q_indices; +} + int AV1RateControlQMode::GetRDMult(const GopFrame &gop_frame, int q_index) const { // TODO(angiebird): @@ -1352,6 +1410,14 @@ qstep_ratio, AOM_BITS_8); if (rc_param_.base_q_index) param.q_index = AOMMAX(param.q_index, 1); active_best_quality = param.q_index; + + if (rc_param_.max_distinct_q_indices_per_frame > 1) { + param.superblock_q_indices = SetupDeltaQ( + frame_dep_stats, rc_param_.frame_width, rc_param_.frame_height, + param.q_index, frame_importance); + // TODO(b/256852795): Implement K-means to restrict the numbers of q + // indices to rc_param_.max_distinct_q_indices_per_frame + } } else { // Intermediate ARFs assert(gop_frame.layer_depth >= 1);