ref: b19b16cfa1fe0275c82dadc78c4dcbb8a1f8da36
parent: e67d45d4ce92468ba193288b59093fef0a502662
parent: 668e804504021aee1ad1c6ee095b746885596135
author: Paul Wilkins <[email protected]>
date: Mon Jun 8 10:26:05 EDT 2015
Merge "Animation and dead zone detection."
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -113,8 +113,8 @@
fpfile = fopen("firstpass.stt", "a");
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.0lf %12.0lf %12.0lf %12.4lf\n",
+ "%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",
stats->frame,
stats->weight,
stats->intra_error,
@@ -124,6 +124,8 @@
stats->pcnt_motion,
stats->pcnt_second_ref,
stats->pcnt_neutral,
+ stats->ul_intra_pct,
+ stats->image_start_row,
stats->MVr,
stats->mvr_abs,
stats->MVc,
@@ -160,7 +162,9 @@
section->pcnt_motion = 0.0;
section->pcnt_second_ref = 0.0;
section->pcnt_neutral = 0.0;
- section->MVr = 0.0;
+ section->ul_intra_pct = 0.0;
+ section->image_start_row = 0.0;
+ section->MVr = 0.0;
section->mvr_abs = 0.0;
section->MVc = 0.0;
section->mvc_abs = 0.0;
@@ -185,7 +189,9 @@
section->pcnt_motion += frame->pcnt_motion;
section->pcnt_second_ref += frame->pcnt_second_ref;
section->pcnt_neutral += frame->pcnt_neutral;
- section->MVr += frame->MVr;
+ section->ul_intra_pct += frame->ul_intra_pct;
+ section->image_start_row += frame->image_start_row;
+ section->MVr += frame->MVr;
section->mvr_abs += frame->mvr_abs;
section->MVc += frame->MVc;
section->mvc_abs += frame->mvc_abs;
@@ -208,7 +214,9 @@
section->pcnt_motion -= frame->pcnt_motion;
section->pcnt_second_ref -= frame->pcnt_second_ref;
section->pcnt_neutral -= frame->pcnt_neutral;
- section->MVr -= frame->MVr;
+ section->ul_intra_pct -= frame->ul_intra_pct;
+ section->image_start_row -= frame->image_start_row;
+ section->MVr -= frame->MVr;
section->mvr_abs -= frame->mvr_abs;
section->MVc -= frame->MVc;
section->mvc_abs -= frame->mvc_abs;
@@ -453,6 +461,8 @@
cpi->rc.frames_to_key = INT_MAX;
}
+#define UL_INTRA_THRESH 50
+#define INVALID_ROW -1
void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
int mb_row, mb_col;
MACROBLOCK *const x = &cpi->td.mb;
@@ -477,6 +487,8 @@
int second_ref_count = 0;
const int intrapenalty = INTRA_MODE_PENALTY;
double neutral_count;
+ int ul_intra_count = 0;
+ int image_data_start_row = INVALID_ROW;
int new_mv_count = 0;
int sum_in_vectors = 0;
MV lastmv = {0, 0};
@@ -636,6 +648,18 @@
(bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4;
vp9_encode_intra_block_plane(x, bsize, 0);
this_error = vpx_get_mb_ss(x->plane[0].src_diff);
+
+ // Keep a record of blocks that have almost no intra error residual
+ // (i.e. are in effect completely flat and untextured in the intra
+ // 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 (this_error < UL_INTRA_THRESH) {
+ ++ul_intra_count;
+ } else if ((mb_col > 0) && (image_data_start_row == INVALID_ROW)) {
+ image_data_start_row = mb_row;
+ }
+
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth) {
switch (cm->bit_depth) {
@@ -963,6 +987,18 @@
vp9_clear_system_state();
}
+ // Clamp the image start to rows/2. This number of rows is discarded top
+ // and bottom as dead data so rows / 2 means the frame is blank.
+ if ((image_data_start_row > cm->mb_rows / 2) ||
+ (image_data_start_row == INVALID_ROW)) {
+ image_data_start_row = cm->mb_rows / 2;
+ }
+ // Exclude any image dead zone
+ if (image_data_start_row > 0) {
+ ul_intra_count =
+ MAX(0, ul_intra_count - (image_data_start_row * cm->mb_cols * 2));
+ }
+
{
FIRSTPASS_STATS fps;
// The minimum error here insures some bit allocation to frames even
@@ -987,6 +1023,8 @@
fps.pcnt_inter = (double)intercount / num_mbs;
fps.pcnt_second_ref = (double)second_ref_count / num_mbs;
fps.pcnt_neutral = (double)neutral_count / num_mbs;
+ fps.ul_intra_pct = (double)ul_intra_count / num_mbs;
+ fps.image_start_row = (double)image_data_start_row;
if (mvcount > 0) {
fps.MVr = (double)sum_mvr / mvcount;
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -51,6 +51,8 @@
double pcnt_motion;
double pcnt_second_ref;
double pcnt_neutral;
+ double ul_intra_pct;
+ double image_start_row;
double MVr;
double mvr_abs;
double MVc;
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -19,6 +19,28 @@
return frame_is_kf_gf_arf(cpi) || vp9_is_upper_layer_key_frame(cpi);
}
+// Sets a partition size down to which the auto partition code will always
+// search (can go lower), based on the image dimensions. The logic here
+// is that the extent to which ringing artefacts are offensive, depends
+// partly on the screen area that over which they propogate. Propogation is
+// limited by transform block size but the screen area take up by a given block
+// size will be larger for a small image format stretched to full screen.
+static BLOCK_SIZE set_partition_min_limit(VP9_COMMON *const cm) {
+ unsigned int screen_area = (cm->width * cm->height);
+
+ // Select block size based on image format size.
+ if (screen_area < 1280 * 720) {
+ // Formats smaller in area than 720P
+ return BLOCK_4X4;
+ } else if (screen_area < 1920 * 1080) {
+ // Format >= 720P and < 1080P
+ return BLOCK_8X8;
+ } else {
+ // Formats 1080P and up
+ return BLOCK_16X16;
+ }
+}
+
static void set_good_speed_feature_framesize_dependent(VP9_COMMON *cm,
SPEED_FEATURES *sf,
int speed) {
@@ -45,6 +67,7 @@
sf->partition_search_breakout_dist_thr = (1 << 22);
sf->partition_search_breakout_rate_thr = 100;
}
+ sf->rd_auto_partition_min_limit = set_partition_min_limit(cm);
}
if (speed >= 3) {
@@ -72,29 +95,6 @@
}
}
-// Sets a partition size down to which the auto partition code will always
-// search (can go lower), based on the image dimensions. The logic here
-// is that the extent to which ringing artefacts are offensive, depends
-// partly on the screen area that over which they propogate. Propogation is
-// limited by transform block size but the screen area take up by a given block
-// size will be larger for a small image format stretched to full screen.
-static BLOCK_SIZE set_partition_min_limit(VP9_COMP *cpi) {
- VP9_COMMON *const cm = &cpi->common;
- unsigned int screen_area = (cm->width * cm->height);
-
- // Select block size based on image format size.
- if (screen_area < 1280 * 720) {
- // Formats smaller in area than 720P
- return BLOCK_4X4;
- } else if (screen_area < 1920 * 1080) {
- // Format >= 720P and < 1080P
- return BLOCK_8X8;
- } else {
- // Formats 1080P and up
- return BLOCK_16X16;
- }
-}
-
static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
SPEED_FEATURES *sf, int speed) {
const int boosted = frame_is_boosted(cpi);
@@ -139,7 +139,6 @@
sf->disable_filter_search_var_thresh = 100;
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
- sf->rd_auto_partition_min_limit = set_partition_min_limit(cpi);
sf->allow_partition_search_skip = 1;
}