Superres adjustements Add a criteria on the overall fraction of the AC energy to determine the superres denominator, Also adjust the q down lower if superres was used in CQ or Q modes in the non-keyframe only coding case. Change-Id: I1bc2984db51db9a15dd3c62e9a9a4dbc1406bba0
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index b49790d..95d57c8 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -269,7 +269,7 @@ // by calculuating the 16x4 Horizontal DCT. This is to be used to // decide the superresolution parameters. void analyze_hor_freq(const AV1_COMP *cpi, double *energy) { - uint64_t freq_energy[8] = { 0 }; + uint64_t freq_energy[16] = { 0 }; const YV12_BUFFER_CONFIG *buf = cpi->source; const int bd = cpi->td.mb.e_mbd.bd; const int width = buf->y_crop_width; @@ -283,14 +283,13 @@ for (int j = 0; j < width - 16; j += 16) { av1_fwd_txfm2d_16x4(src16 + i * buf->y_stride + j, coeff, buf->y_stride, H_DCT, bd); - for (int k = 8; k < 16; ++k) { + for (int k = 1; k < 16; ++k) { const uint64_t this_energy = ((int64_t)coeff[k] * coeff[k]) + ((int64_t)coeff[k + 16] * coeff[k + 16]) + ((int64_t)coeff[k + 32] * coeff[k + 32]) + ((int64_t)coeff[k + 48] * coeff[k + 48]); - freq_energy[k - 8] += - ROUND_POWER_OF_TWO(this_energy, 2 + 2 * (bd - 8)); + freq_energy[k] += ROUND_POWER_OF_TWO(this_energy, 2 + 2 * (bd - 8)); } n++; } @@ -305,24 +304,24 @@ src16[ii * 16 + jj] = buf->y_buffer[(i + ii) * buf->y_stride + (j + jj)]; av1_fwd_txfm2d_16x4(src16, coeff, 16, H_DCT, bd); - for (int k = 8; k < 16; ++k) { + for (int k = 1; k < 16; ++k) { const uint64_t this_energy = ((int64_t)coeff[k] * coeff[k]) + ((int64_t)coeff[k + 16] * coeff[k + 16]) + ((int64_t)coeff[k + 32] * coeff[k + 32]) + ((int64_t)coeff[k + 48] * coeff[k + 48]); - freq_energy[k - 8] += ROUND_POWER_OF_TWO(this_energy, 2); + freq_energy[k] += ROUND_POWER_OF_TWO(this_energy, 2); } n++; } } } if (n) { - for (int k = 0; k < 8; ++k) energy[k] = (double)freq_energy[k] / n; + for (int k = 1; k < 16; ++k) energy[k] = (double)freq_energy[k] / n; // Convert to cumulative energy - for (int k = 6; k >= 0; --k) energy[k] += energy[k + 1]; + for (int k = 14; k > 0; --k) energy[k] += energy[k + 1]; } else { - for (int k = 0; k < 8; ++k) energy[k] = 1e+20; + for (int k = 1; k < 16; ++k) energy[k] = 1e+20; } } @@ -4164,23 +4163,32 @@ } #define ENERGY_BY_Q2_THRESH 0.01 +#define ENERGY_BY_AC_THRESH 0.2 static uint8_t get_superres_denom_from_qindex_energy(int qindex, double *energy, - double thresh) { + double threshq, + double threshp) { const double q = av1_convert_qindex_to_q(qindex, AOM_BITS_8); - const double threshq2 = thresh * q * q; + const double tq = threshq * q * q; + const double tp = threshp * energy[1]; + const double thresh = AOMMIN(tq, tp); int k; - for (k = 8; k > 0; --k) { - if (energy[k - 1] > threshq2) break; + for (k = 16; k > 8; --k) { + if (energy[k - 1] > thresh) break; } - return 2 * SCALE_NUMERATOR - k; + return 3 * SCALE_NUMERATOR - k; } static uint8_t get_superres_denom_for_qindex(const AV1_COMP *cpi, int qindex) { - double energy[8]; + double energy[16]; analyze_hor_freq(cpi, energy); - return get_superres_denom_from_qindex_energy(qindex, energy, - ENERGY_BY_Q2_THRESH); + /* + printf("\nenergy = ["); + for (int k = 1; k < 16; ++k) printf("%f, ", energy[k]); + printf("]\n"); + */ + return get_superres_denom_from_qindex_energy( + qindex, energy, ENERGY_BY_Q2_THRESH, ENERGY_BY_AC_THRESH); } static uint8_t calculate_next_superres_scale(AV1_COMP *cpi) {
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c index 1dc4b17..6635304 100644 --- a/av1/encoder/ratectrl.c +++ b/av1/encoder/ratectrl.c
@@ -756,10 +756,28 @@ return q; } +static int gf_group_pyramid_level(const AV1_COMP *cpi) { + const GF_GROUP *gf_group = &cpi->twopass.gf_group; + int this_height = gf_group->pyramid_level[gf_group->index]; + return this_height; +} + static int get_active_cq_level(const RATE_CONTROL *rc, - const AV1EncoderConfig *const oxcf) { + const AV1EncoderConfig *const oxcf, + int intra_only, int superres_denom) { static const double cq_adjust_threshold = 0.1; int active_cq_level = oxcf->cq_level; + (void)intra_only; + if (oxcf->rc_mode == AOM_CQ || oxcf->rc_mode == AOM_Q) { + // printf("Superres %d %d %d = %d\n", superres_denom, intra_only, + // rc->frames_to_key, !(intra_only && rc->frames_to_key <= 1)); + if (oxcf->superres_mode == SUPERRES_QTHRESH && + superres_denom != SCALE_NUMERATOR && + !(intra_only && rc->frames_to_key <= 1)) { + active_cq_level = + AOMMAX(active_cq_level - ((superres_denom - SCALE_NUMERATOR) * 4), 0); + } + } if (oxcf->rc_mode == AOM_CQ && rc->total_target_bits > 0) { const double x = (double)rc->total_actual_bits / rc->total_target_bits; if (x < cq_adjust_threshold) { @@ -776,7 +794,8 @@ const RATE_CONTROL *const rc = &cpi->rc; const CurrentFrame *const current_frame = &cm->current_frame; const AV1EncoderConfig *const oxcf = &cpi->oxcf; - const int cq_level = get_active_cq_level(rc, oxcf); + const int cq_level = get_active_cq_level(rc, oxcf, frame_is_intra_only(cm), + cm->superres_scale_denominator); int active_best_quality; int active_worst_quality = calc_active_worst_quality_one_pass_vbr(cpi); int q; @@ -937,7 +956,8 @@ const RATE_CONTROL *const rc = &cpi->rc; const AV1EncoderConfig *const oxcf = &cpi->oxcf; const GF_GROUP *gf_group = &cpi->twopass.gf_group; - const int cq_level = get_active_cq_level(rc, oxcf); + const int cq_level = get_active_cq_level(rc, oxcf, frame_is_intra_only(cm), + cm->superres_scale_denominator); int active_best_quality; int active_worst_quality = cpi->twopass.active_worst_quality; int q; @@ -1048,7 +1068,7 @@ } else if (cpi->new_bwdref_update_rule && is_intrl_arf_boost) { assert(rc->arf_q >= 0); // Ensure it is set to a valid value. active_best_quality = rc->arf_q; - int this_height = gf_group->pyramid_level[gf_group->index]; + int this_height = gf_group_pyramid_level(cpi); while (this_height < gf_group->pyramid_height) { active_best_quality = (active_best_quality + cq_level + 1) / 2; ++this_height; @@ -1074,7 +1094,7 @@ } #if USE_SYMM_MULTI_LAYER if (cpi->new_bwdref_update_rule && is_intrl_arf_boost) { - int this_height = gf_group->pyramid_level[gf_group->index]; + int this_height = gf_group_pyramid_level(cpi); while (this_height < gf_group->pyramid_height) { active_best_quality = (active_best_quality + cq_level + 1) / 2; ++this_height; @@ -1099,7 +1119,7 @@ #endif #if USE_SYMM_MULTI_LAYER if (cpi->new_bwdref_update_rule && is_intrl_arf_boost) { - int this_height = gf_group->pyramid_level[gf_group->index]; + int this_height = gf_group_pyramid_level(cpi); while (this_height < gf_group->pyramid_height) { active_best_quality = (active_best_quality + active_worst_quality + 1) / 2;