fprintf(fpfile, "%12.0lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf %12.4lf"
"%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf"
- "%12.4lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf\n",
+ "%12.4lf %12.4lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf\n",
stats->frame,
stats->weight,
stats->intra_error,
stats->pcnt_second_ref,
stats->pcnt_neutral,
stats->intra_skip_pct,
+ stats->intra_smooth_pct,
stats->inactive_zone_rows,
stats->inactive_zone_cols,
stats->MVr,
section->pcnt_second_ref = 0.0;
section->pcnt_neutral = 0.0;
section->intra_skip_pct = 0.0;
+ section->intra_smooth_pct = 0.0;
section->inactive_zone_rows = 0.0;
section->inactive_zone_cols = 0.0;
section->MVr = 0.0;
section->pcnt_second_ref += frame->pcnt_second_ref;
section->pcnt_neutral += frame->pcnt_neutral;
section->intra_skip_pct += frame->intra_skip_pct;
+ section->intra_smooth_pct += frame->intra_smooth_pct;
section->inactive_zone_rows += frame->inactive_zone_rows;
section->inactive_zone_cols += frame->inactive_zone_cols;
section->MVr += frame->MVr;
section->pcnt_second_ref -= frame->pcnt_second_ref;
section->pcnt_neutral -= frame->pcnt_neutral;
section->intra_skip_pct -= frame->intra_skip_pct;
+ section->intra_smooth_pct -= frame->intra_smooth_pct;
section->inactive_zone_rows -= frame->inactive_zone_rows;
section->inactive_zone_cols -= frame->inactive_zone_cols;
section->MVr -= frame->MVr;
// This threshold is used to track blocks where to all intents and purposes
// the intra prediction error 0. Though the metric we test against
// is technically a sse we are mainly interested in blocks where all the pixels
-// int he 8 bit domain have an error of <= 1 (where error = sse) so a
+// in the 8 bit domain have an error of <= 1 (where error = sse) so a
// linear scaling for 10 and 12 bit gives similar results.
#define UL_INTRA_THRESH 50
-#if CONFIG_VP9_HIGHBITDEPTH
static int get_ul_intra_threshold(VP9_COMMON *cm) {
int ret_val = UL_INTRA_THRESH;
+#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
switch (cm->bit_depth) {
case VPX_BITS_8:
"VPX_BITS_10 or VPX_BITS_12");
}
}
+#else
+ (void) cm;
+#endif // CONFIG_VP9_HIGHBITDEPTH
return ret_val;
}
+
+#define SMOOTH_INTRA_THRESH 4000
+static int get_smooth_intra_threshold(VP9_COMMON *cm) {
+ int ret_val = SMOOTH_INTRA_THRESH;
+#if CONFIG_VP9_HIGHBITDEPTH
+ if (cm->use_highbitdepth) {
+ switch (cm->bit_depth) {
+ case VPX_BITS_8:
+ ret_val = SMOOTH_INTRA_THRESH;
+ break;
+ case VPX_BITS_10:
+ ret_val = SMOOTH_INTRA_THRESH >> 2;
+ break;
+ case VPX_BITS_12:
+ ret_val = SMOOTH_INTRA_THRESH >> 4;
+ break;
+ default:
+ assert(0 && "cm->bit_depth should be VPX_BITS_8, "
+ "VPX_BITS_10 or VPX_BITS_12");
+ }
+ }
+#else
+ (void) cm;
#endif // CONFIG_VP9_HIGHBITDEPTH
+ return ret_val;
+}
#define INVALID_ROW -1
void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
const int intrapenalty = INTRA_MODE_PENALTY;
double neutral_count;
int intra_skip_count = 0;
+ int intra_smooth_count = 0;
int image_data_start_row = INVALID_ROW;
int new_mv_count = 0;
int sum_in_vectors = 0;
// domain). In natural videos this is uncommon, but it is much more
// common in animations, graphics and screen content, so may be used
// as a signal to detect these types of content.
-#if CONFIG_VP9_HIGHBITDEPTH
if (this_error < get_ul_intra_threshold(cm)) {
-#else
- if (this_error < UL_INTRA_THRESH) {
-#endif
++intra_skip_count;
} else if ((mb_col > 0) && (image_data_start_row == INVALID_ROW)) {
image_data_start_row = mb_row;
}
+ if (this_error < get_smooth_intra_threshold(cm)) {
+ ++intra_smooth_count;
+ }
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
fps.pcnt_second_ref = (double)second_ref_count / num_mbs;
fps.pcnt_neutral = (double)neutral_count / num_mbs;
fps.intra_skip_pct = (double)intra_skip_count / num_mbs;
+ fps.intra_smooth_pct = (double)intra_smooth_count / num_mbs;
fps.inactive_zone_rows = (double)image_data_start_row;
fps.inactive_zone_cols = (double)0; // TODO(paulwilkins): fix
// applied when combining MB error values for the frame.
twopass->mb_av_energy =
log(((this_frame.intra_error * 256.0) / num_mbs) + 1.0);
+ twopass->mb_smooth_pct = this_frame.intra_smooth_pct;
}
// Update the total stats remaining structure.
return q;
}
-static int get_active_cq_level(const RATE_CONTROL *rc,
- const VP9EncoderConfig *const oxcf) {
+static int get_active_cq_level_one_pass(
+ const RATE_CONTROL *rc, const VP9EncoderConfig *const oxcf) {
static const double cq_adjust_threshold = 0.1;
int active_cq_level = oxcf->cq_level;
if (oxcf->rc_mode == VPX_CQ &&
return active_cq_level;
}
+#define SMOOTH_PCT_MIN 0.1
+#define SMOOTH_PCT_DIV 0.05
+static int get_active_cq_level_two_pass(
+ const TWO_PASS *twopass, const RATE_CONTROL *rc,
+ const VP9EncoderConfig *const oxcf) {
+ static const double cq_adjust_threshold = 0.1;
+ int active_cq_level = oxcf->cq_level;
+ if (oxcf->rc_mode == VPX_CQ) {
+ if (twopass->mb_smooth_pct > SMOOTH_PCT_MIN) {
+ active_cq_level -= (twopass->mb_smooth_pct - SMOOTH_PCT_MIN) /
+ SMOOTH_PCT_DIV;
+ active_cq_level = VPXMAX(active_cq_level, 0);
+ }
+ if (rc->total_target_bits > 0) {
+ const double x = (double)rc->total_actual_bits / rc->total_target_bits;
+ if (x < cq_adjust_threshold) {
+ active_cq_level = (int)(active_cq_level * x / cq_adjust_threshold);
+ }
+ }
+ }
+ return active_cq_level;
+}
+
static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
int *bottom_index,
int *top_index) {
const VP9_COMMON *const cm = &cpi->common;
const RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
- const int cq_level = get_active_cq_level(rc, oxcf);
+ const int cq_level = get_active_cq_level_one_pass(rc, oxcf);
int active_best_quality;
int active_worst_quality = calc_active_worst_quality_one_pass_vbr(cpi);
int q;
const RATE_CONTROL *const rc = &cpi->rc;
const VP9EncoderConfig *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_two_pass(&cpi->twopass, rc, oxcf);
int active_best_quality;
int active_worst_quality = cpi->twopass.active_worst_quality;
int q;