Index: source/libvpx/vp9/encoder/vp9_onyx_if.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_onyx_if.c (revision 232232) |
+++ source/libvpx/vp9/encoder/vp9_onyx_if.c (working copy) |
@@ -8,45 +8,36 @@ |
* be found in the AUTHORS file in the root of the source tree. |
*/ |
+#include <math.h> |
+#include <stdio.h> |
+#include <limits.h> |
-#include "vpx_config.h" |
+#include "./vpx_config.h" |
+#include "./vpx_scale_rtcd.h" |
+ |
+#include "vp9/common/vp9_alloccommon.h" |
#include "vp9/common/vp9_filter.h" |
-#include "vp9/common/vp9_onyxc_int.h" |
+#include "vp9/common/vp9_idct.h" |
+#if CONFIG_VP9_POSTPROC |
+#include "vp9/common/vp9_postproc.h" |
+#endif |
#include "vp9/common/vp9_reconinter.h" |
-#include "vp9/encoder/vp9_onyx_int.h" |
#include "vp9/common/vp9_systemdependent.h" |
-#include "vp9/encoder/vp9_quantize.h" |
-#include "vp9/common/vp9_alloccommon.h" |
-#include "vp9/encoder/vp9_mcomp.h" |
+#include "vp9/common/vp9_tile_common.h" |
#include "vp9/encoder/vp9_firstpass.h" |
+#include "vp9/encoder/vp9_mbgraph.h" |
+#include "vp9/encoder/vp9_onyx_int.h" |
+#include "vp9/encoder/vp9_picklpf.h" |
#include "vp9/encoder/vp9_psnr.h" |
-#include "vpx_scale/vpx_scale.h" |
-#include "vp9/common/vp9_extend.h" |
#include "vp9/encoder/vp9_ratectrl.h" |
-#include "vp9/common/vp9_quant_common.h" |
-#include "vp9/common/vp9_tile_common.h" |
+#include "vp9/encoder/vp9_rdopt.h" |
#include "vp9/encoder/vp9_segmentation.h" |
-#include "./vp9_rtcd.h" |
-#include "./vpx_scale_rtcd.h" |
-#if CONFIG_VP9_POSTPROC |
-#include "vp9/common/vp9_postproc.h" |
-#endif |
-#include "vpx_mem/vpx_mem.h" |
+#include "vp9/encoder/vp9_temporal_filter.h" |
+#include "vp9/encoder/vp9_vaq.h" |
+ |
#include "vpx_ports/vpx_timer.h" |
-#include "vp9/common/vp9_seg_common.h" |
-#include "vp9/encoder/vp9_mbgraph.h" |
-#include "vp9/common/vp9_pred_common.h" |
-#include "vp9/encoder/vp9_rdopt.h" |
-#include "vp9/encoder/vp9_bitstream.h" |
-#include "vp9/encoder/vp9_picklpf.h" |
-#include "vp9/common/vp9_mvref_common.h" |
-#include "vp9/encoder/vp9_temporal_filter.h" |
-#include <math.h> |
-#include <stdio.h> |
-#include <limits.h> |
- |
extern void print_tree_update_probs(); |
static void set_default_lf_deltas(struct loopfilter *lf); |
@@ -55,16 +46,20 @@ |
#define SHARP_FILTER_QTHRESH 0 /* Q threshold for 8-tap sharp filter */ |
-#define ALTREF_HIGH_PRECISION_MV 1 /* whether to use high precision mv |
- for altref computation */ |
-#define HIGH_PRECISION_MV_QTHRESH 200 /* Q threshold for use of high precision |
- mv. Choose a very high value for |
- now so that HIGH_PRECISION is always |
- chosen */ |
+#define ALTREF_HIGH_PRECISION_MV 1 // Whether to use high precision mv |
+ // for altref computation. |
+#define HIGH_PRECISION_MV_QTHRESH 200 // Q threshold for high precision |
+ // mv. Choose a very high value for |
+ // now so that HIGH_PRECISION is always |
+ // chosen. |
+// Masks for partially or completely disabling split mode |
+#define DISABLE_ALL_SPLIT 0x3F |
+#define DISABLE_ALL_INTER_SPLIT 0x1F |
+#define DISABLE_COMPOUND_SPLIT 0x18 |
+#define LAST_AND_INTRA_SPLIT_ONLY 0x1E |
+ |
#if CONFIG_INTERNAL_STATS |
-#include "math.h" |
- |
extern double vp9_calc_ssim(YV12_BUFFER_CONFIG *source, |
YV12_BUFFER_CONFIG *dest, int lumamask, |
double *weight); |
@@ -107,7 +102,8 @@ |
#endif |
#ifdef SPEEDSTATS |
-unsigned int frames_at_speed[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
+unsigned int frames_at_speed[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
+ 0, 0, 0}; |
#endif |
#if defined(SECTIONBITS_OUTPUT) |
@@ -122,6 +118,8 @@ |
static int gf_low_motion_minq[QINDEX_RANGE]; |
static int gf_high_motion_minq[QINDEX_RANGE]; |
static int inter_minq[QINDEX_RANGE]; |
+static int afq_low_motion_minq[QINDEX_RANGE]; |
+static int afq_high_motion_minq[QINDEX_RANGE]; |
static INLINE void Scale2Ratio(int mode, int *hr, int *hs) { |
switch (mode) { |
@@ -193,24 +191,55 @@ |
gf_low_motion_minq[i] = calculate_minq_index(maxq, |
0.0000015, |
-0.0009, |
- 0.33, |
+ 0.32, |
0.0); |
gf_high_motion_minq[i] = calculate_minq_index(maxq, |
0.0000021, |
-0.00125, |
- 0.45, |
+ 0.50, |
0.0); |
inter_minq[i] = calculate_minq_index(maxq, |
0.00000271, |
-0.00113, |
- 0.697, |
+ 0.75, |
0.0); |
+ afq_low_motion_minq[i] = calculate_minq_index(maxq, |
+ 0.0000015, |
+ -0.0009, |
+ 0.33, |
+ 0.0); |
+ afq_high_motion_minq[i] = calculate_minq_index(maxq, |
+ 0.0000021, |
+ -0.00125, |
+ 0.55, |
+ 0.0); |
+ } |
+} |
+static int get_active_quality(int q, |
+ int gfu_boost, |
+ int low, |
+ int high, |
+ int *low_motion_minq, |
+ int *high_motion_minq) { |
+ int active_best_quality; |
+ if (gfu_boost > high) { |
+ active_best_quality = low_motion_minq[q]; |
+ } else if (gfu_boost < low) { |
+ active_best_quality = high_motion_minq[q]; |
+ } else { |
+ const int gap = high - low; |
+ const int offset = high - gfu_boost; |
+ const int qdiff = high_motion_minq[q] - low_motion_minq[q]; |
+ const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap; |
+ active_best_quality = low_motion_minq[q] + adjustment; |
} |
+ return active_best_quality; |
} |
-static void set_mvcost(MACROBLOCK *mb) { |
- if (mb->e_mbd.allow_high_precision_mv) { |
+static void set_mvcost(VP9_COMP *cpi) { |
+ MACROBLOCK *const mb = &cpi->mb; |
+ if (cpi->common.allow_high_precision_mv) { |
mb->mvcost = mb->nmvcost_hp; |
mb->mvsadcost = mb->nmvsadcost_hp; |
} else { |
@@ -284,14 +313,17 @@ |
vpx_free(cpi->mb_norm_activity_map); |
cpi->mb_norm_activity_map = 0; |
- vpx_free(cpi->mb.pip); |
- cpi->mb.pip = 0; |
+ vpx_free(cpi->above_context[0]); |
+ cpi->above_context[0] = NULL; |
+ |
+ vpx_free(cpi->above_seg_context); |
+ cpi->above_seg_context = NULL; |
} |
// Computes a q delta (in "q index" terms) to get from a starting q value |
// to a target value |
// target q value |
-static int compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) { |
+int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) { |
int i; |
int start_index = cpi->worst_quality; |
int target_index = cpi->worst_quality; |
@@ -355,7 +387,7 @@ |
seg->update_map = 1; |
seg->update_data = 1; |
- qi_delta = compute_qdelta(cpi, cpi->avg_q, (cpi->avg_q * 0.875)); |
+ qi_delta = vp9_compute_qdelta(cpi, cpi->avg_q, (cpi->avg_q * 0.875)); |
vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, (qi_delta - 2)); |
vp9_set_segdata(seg, 1, SEG_LVL_ALT_LF, -2); |
@@ -364,7 +396,6 @@ |
// Where relevant assume segment data is delta data |
seg->abs_delta = SEGMENT_DELTADATA; |
- |
} |
} else if (seg->enabled) { |
// All other frames if segmentation has been enabled |
@@ -377,8 +408,8 @@ |
seg->update_data = 1; |
seg->abs_delta = SEGMENT_DELTADATA; |
- qi_delta = compute_qdelta(cpi, cpi->avg_q, |
- (cpi->avg_q * 1.125)); |
+ qi_delta = vp9_compute_qdelta(cpi, cpi->avg_q, |
+ (cpi->avg_q * 1.125)); |
vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, (qi_delta + 2)); |
vp9_enable_segfeature(seg, 1, SEG_LVL_ALT_Q); |
@@ -421,8 +452,8 @@ |
// Skip all MBs if high Q (0,0 mv and skip coeffs) |
if (high_q) { |
- vp9_enable_segfeature(seg, 0, SEG_LVL_SKIP); |
- vp9_enable_segfeature(seg, 1, SEG_LVL_SKIP); |
+ vp9_enable_segfeature(seg, 0, SEG_LVL_SKIP); |
+ vp9_enable_segfeature(seg, 1, SEG_LVL_SKIP); |
} |
// Enable data update |
seg->update_data = 1; |
@@ -584,19 +615,12 @@ |
sf->thresh_mult[THR_COMP_NEARGA] += 1500; |
sf->thresh_mult[THR_COMP_NEWGA] += 2000; |
- sf->thresh_mult[THR_SPLITMV] += 2500; |
- sf->thresh_mult[THR_SPLITG] += 2500; |
- sf->thresh_mult[THR_SPLITA] += 2500; |
- sf->thresh_mult[THR_COMP_SPLITLA] += 4500; |
- sf->thresh_mult[THR_COMP_SPLITGA] += 4500; |
- |
sf->thresh_mult[THR_ZEROMV] += 2000; |
sf->thresh_mult[THR_ZEROG] += 2000; |
sf->thresh_mult[THR_ZEROA] += 2000; |
sf->thresh_mult[THR_COMP_ZEROLA] += 2500; |
sf->thresh_mult[THR_COMP_ZEROGA] += 2500; |
- sf->thresh_mult[THR_B_PRED] += 2500; |
sf->thresh_mult[THR_H_PRED] += 2000; |
sf->thresh_mult[THR_V_PRED] += 2000; |
sf->thresh_mult[THR_D45_PRED ] += 2500; |
@@ -612,21 +636,18 @@ |
sf->thresh_mult[THR_NEARESTMV] = INT_MAX; |
sf->thresh_mult[THR_ZEROMV ] = INT_MAX; |
sf->thresh_mult[THR_NEARMV ] = INT_MAX; |
- sf->thresh_mult[THR_SPLITMV ] = INT_MAX; |
} |
if (!(cpi->ref_frame_flags & VP9_GOLD_FLAG)) { |
sf->thresh_mult[THR_NEARESTG ] = INT_MAX; |
sf->thresh_mult[THR_ZEROG ] = INT_MAX; |
sf->thresh_mult[THR_NEARG ] = INT_MAX; |
sf->thresh_mult[THR_NEWG ] = INT_MAX; |
- sf->thresh_mult[THR_SPLITG ] = INT_MAX; |
} |
if (!(cpi->ref_frame_flags & VP9_ALT_FLAG)) { |
sf->thresh_mult[THR_NEARESTA ] = INT_MAX; |
sf->thresh_mult[THR_ZEROA ] = INT_MAX; |
sf->thresh_mult[THR_NEARA ] = INT_MAX; |
sf->thresh_mult[THR_NEWA ] = INT_MAX; |
- sf->thresh_mult[THR_SPLITA ] = INT_MAX; |
} |
if ((cpi->ref_frame_flags & (VP9_LAST_FLAG | VP9_ALT_FLAG)) != |
@@ -635,7 +656,6 @@ |
sf->thresh_mult[THR_COMP_NEARESTLA] = INT_MAX; |
sf->thresh_mult[THR_COMP_NEARLA ] = INT_MAX; |
sf->thresh_mult[THR_COMP_NEWLA ] = INT_MAX; |
- sf->thresh_mult[THR_COMP_SPLITLA ] = INT_MAX; |
} |
if ((cpi->ref_frame_flags & (VP9_GOLD_FLAG | VP9_ALT_FLAG)) != |
(VP9_GOLD_FLAG | VP9_ALT_FLAG)) { |
@@ -643,17 +663,42 @@ |
sf->thresh_mult[THR_COMP_NEARESTGA] = INT_MAX; |
sf->thresh_mult[THR_COMP_NEARGA ] = INT_MAX; |
sf->thresh_mult[THR_COMP_NEWGA ] = INT_MAX; |
- sf->thresh_mult[THR_COMP_SPLITGA ] = INT_MAX; |
} |
+} |
- if (sf->disable_splitmv == 1) { |
- sf->thresh_mult[THR_SPLITMV ] = INT_MAX; |
- sf->thresh_mult[THR_SPLITG ] = INT_MAX; |
- sf->thresh_mult[THR_SPLITA ] = INT_MAX; |
+static void set_rd_speed_thresholds_sub8x8(VP9_COMP *cpi, int mode) { |
+ SPEED_FEATURES *sf = &cpi->sf; |
+ int i; |
- sf->thresh_mult[THR_COMP_SPLITLA ] = INT_MAX; |
- sf->thresh_mult[THR_COMP_SPLITGA ] = INT_MAX; |
+ for (i = 0; i < MAX_REFS; ++i) |
+ sf->thresh_mult_sub8x8[i] = mode == 0 ? -500 : 0; |
+ |
+ sf->thresh_mult_sub8x8[THR_LAST] += 2500; |
+ sf->thresh_mult_sub8x8[THR_GOLD] += 2500; |
+ sf->thresh_mult_sub8x8[THR_ALTR] += 2500; |
+ sf->thresh_mult_sub8x8[THR_INTRA] += 2500; |
+ sf->thresh_mult_sub8x8[THR_COMP_LA] += 4500; |
+ sf->thresh_mult_sub8x8[THR_COMP_GA] += 4500; |
+ |
+ // Check for masked out split cases. |
+ for (i = 0; i < MAX_REFS; i++) { |
+ if (sf->disable_split_mask & (1 << i)) |
+ sf->thresh_mult_sub8x8[i] = INT_MAX; |
} |
+ |
+ // disable mode test if frame flag is not set |
+ if (!(cpi->ref_frame_flags & VP9_LAST_FLAG)) |
+ sf->thresh_mult_sub8x8[THR_LAST] = INT_MAX; |
+ if (!(cpi->ref_frame_flags & VP9_GOLD_FLAG)) |
+ sf->thresh_mult_sub8x8[THR_GOLD] = INT_MAX; |
+ if (!(cpi->ref_frame_flags & VP9_ALT_FLAG)) |
+ sf->thresh_mult_sub8x8[THR_ALTR] = INT_MAX; |
+ if ((cpi->ref_frame_flags & (VP9_LAST_FLAG | VP9_ALT_FLAG)) != |
+ (VP9_LAST_FLAG | VP9_ALT_FLAG)) |
+ sf->thresh_mult_sub8x8[THR_COMP_LA] = INT_MAX; |
+ if ((cpi->ref_frame_flags & (VP9_GOLD_FLAG | VP9_ALT_FLAG)) != |
+ (VP9_GOLD_FLAG | VP9_ALT_FLAG)) |
+ sf->thresh_mult_sub8x8[THR_COMP_GA] = INT_MAX; |
} |
void vp9_set_speed_features(VP9_COMP *cpi) { |
@@ -666,12 +711,8 @@ |
if (mode > 1) |
mode = 1; |
- // Initialise default mode frequency sampling variables |
- for (i = 0; i < MAX_MODES; i ++) { |
- cpi->mode_check_freq[i] = 0; |
- cpi->mode_test_hit_counts[i] = 0; |
+ for (i = 0; i < MAX_MODES; ++i) |
cpi->mode_chosen_counts[i] = 0; |
- } |
// best quality defaults |
sf->RD = 1; |
@@ -686,29 +727,28 @@ |
sf->max_step_search_steps = MAX_MVSEARCH_STEPS; |
sf->comp_inter_joint_search_thresh = BLOCK_4X4; |
sf->adaptive_rd_thresh = 0; |
- sf->use_lastframe_partitioning = 0; |
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_OFF; |
sf->tx_size_search_method = USE_FULL_RD; |
sf->use_lp32x32fdct = 0; |
sf->adaptive_motion_search = 0; |
sf->use_avoid_tested_higherror = 0; |
sf->reference_masking = 0; |
- sf->partition_by_variance = 0; |
sf->use_one_partition_size_always = 0; |
sf->less_rectangular_check = 0; |
sf->use_square_partition_only = 0; |
sf->auto_min_max_partition_size = 0; |
- sf->auto_min_max_partition_interval = 0; |
- sf->auto_min_max_partition_count = 0; |
sf->max_partition_size = BLOCK_64X64; |
sf->min_partition_size = BLOCK_4X4; |
sf->adjust_partitioning_from_last_frame = 0; |
sf->last_partitioning_redo_frequency = 4; |
- sf->disable_splitmv = 0; |
+ sf->disable_split_mask = 0; |
sf->mode_search_skip_flags = 0; |
sf->disable_split_var_thresh = 0; |
sf->disable_filter_search_var_thresh = 0; |
- sf->intra_y_mode_mask = ALL_INTRA_MODES; |
- sf->intra_uv_mode_mask = ALL_INTRA_MODES; |
+ for (i = 0; i < TX_SIZES; i++) { |
+ sf->intra_y_mode_mask[i] = ALL_INTRA_MODES; |
+ sf->intra_uv_mode_mask[i] = ALL_INTRA_MODES; |
+ } |
sf->use_rd_breakout = 0; |
sf->skip_encode_sb = 0; |
sf->use_uv_intra_rd_estimate = 0; |
@@ -724,8 +764,10 @@ |
sf->static_segmentation = 0; |
#endif |
+ sf->variance_adaptive_quantization = 0; |
+ |
switch (mode) { |
- case 0: // best quality mode |
+ case 0: // This is the best quality mode. |
break; |
case 1: |
@@ -736,121 +778,148 @@ |
sf->static_segmentation = 0; |
#endif |
sf->use_avoid_tested_higherror = 1; |
- sf->adaptive_rd_thresh = MIN((speed + 1), 4); |
+ sf->adaptive_rd_thresh = 1; |
+ sf->recode_loop = (speed < 1); |
if (speed == 1) { |
- sf->comp_inter_joint_search_thresh = BLOCK_SIZES; |
+ sf->use_square_partition_only = !frame_is_intra_only(&cpi->common); |
sf->less_rectangular_check = 1; |
- sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME || |
- cpi->common.intra_only || |
- cpi->common.show_frame == 0) ? |
- USE_FULL_RD : |
- USE_LARGESTALL); |
- sf->use_square_partition_only = !(cpi->common.frame_type == KEY_FRAME || |
- cpi->common.intra_only || |
- cpi->common.show_frame == 0); |
- sf->disable_splitmv = |
- (MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0; |
+ sf->tx_size_search_method = frame_is_intra_only(&cpi->common) |
+ ? USE_FULL_RD : USE_LARGESTALL; |
+ |
+ if (MIN(cpi->common.width, cpi->common.height) >= 720) |
+ sf->disable_split_mask = cpi->common.show_frame ? |
+ DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT; |
+ else |
+ sf->disable_split_mask = DISABLE_COMPOUND_SPLIT; |
+ |
+ sf->use_rd_breakout = 1; |
+ sf->adaptive_motion_search = 1; |
+ sf->auto_mv_step_size = 1; |
+ sf->adaptive_rd_thresh = 2; |
+ sf->recode_loop = 2; |
+ sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V; |
+ sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V; |
+ sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V; |
+ } |
+ if (speed == 2) { |
+ sf->use_square_partition_only = !frame_is_intra_only(&cpi->common); |
+ sf->less_rectangular_check = 1; |
+ sf->tx_size_search_method = frame_is_intra_only(&cpi->common) |
+ ? USE_FULL_RD : USE_LARGESTALL; |
+ |
+ if (MIN(cpi->common.width, cpi->common.height) >= 720) |
+ sf->disable_split_mask = cpi->common.show_frame ? |
+ DISABLE_ALL_SPLIT : DISABLE_ALL_INTER_SPLIT; |
+ else |
+ sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY; |
+ |
+ |
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | |
FLAG_SKIP_INTRA_BESTINTER | |
FLAG_SKIP_COMP_BESTINTRA | |
FLAG_SKIP_INTRA_LOWVAR; |
- sf->use_uv_intra_rd_estimate = 1; |
+ |
sf->use_rd_breakout = 1; |
- sf->skip_encode_sb = 1; |
- sf->use_lp32x32fdct = 1; |
sf->adaptive_motion_search = 1; |
sf->auto_mv_step_size = 1; |
- sf->auto_min_max_partition_size = 1; |
- sf->auto_min_max_partition_interval = 1; |
- // FIXME(jingning): temporarily turn off disable_split_var_thresh |
- // during refactoring process. will get this back after finishing |
- // the main framework of partition search type. |
- sf->disable_split_var_thresh = 0; |
sf->disable_filter_search_var_thresh = 16; |
+ sf->comp_inter_joint_search_thresh = BLOCK_SIZES; |
- sf->intra_y_mode_mask = INTRA_DC_TM_H_V; |
- sf->intra_uv_mode_mask = INTRA_DC_TM_H_V; |
- sf->use_fast_coef_updates = 1; |
+ sf->auto_min_max_partition_size = 1; |
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION; |
+ sf->adjust_partitioning_from_last_frame = 1; |
+ sf->last_partitioning_redo_frequency = 3; |
+ |
+ sf->adaptive_rd_thresh = 2; |
+ sf->recode_loop = 2; |
sf->mode_skip_start = 11; |
+ sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V; |
+ sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V; |
+ sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V; |
+ sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V; |
} |
- if (speed == 2) { |
- sf->less_rectangular_check = 1; |
+ if (speed == 3) { |
sf->use_square_partition_only = 1; |
+ sf->tx_size_search_method = USE_LARGESTALL; |
+ |
+ if (MIN(cpi->common.width, cpi->common.height) >= 720) |
+ sf->disable_split_mask = DISABLE_ALL_SPLIT; |
+ else |
+ sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT; |
+ |
+ sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | |
+ FLAG_SKIP_INTRA_BESTINTER | |
+ FLAG_SKIP_COMP_BESTINTRA | |
+ FLAG_SKIP_INTRA_LOWVAR; |
+ |
+ sf->use_rd_breakout = 1; |
+ sf->adaptive_motion_search = 1; |
+ sf->auto_mv_step_size = 1; |
+ |
+ sf->disable_filter_search_var_thresh = 16; |
sf->comp_inter_joint_search_thresh = BLOCK_SIZES; |
- sf->use_lastframe_partitioning = 1; |
+ |
+ sf->auto_min_max_partition_size = 1; |
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL; |
sf->adjust_partitioning_from_last_frame = 1; |
sf->last_partitioning_redo_frequency = 3; |
- sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME || |
- cpi->common.intra_only || |
- cpi->common.show_frame == 0) ? |
- USE_FULL_RD : |
- USE_LARGESTALL); |
- sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | |
- FLAG_SKIP_INTRA_BESTINTER | |
- FLAG_SKIP_COMP_BESTINTRA | |
- FLAG_SKIP_COMP_REFMISMATCH | |
- FLAG_SKIP_INTRA_LOWVAR | |
- FLAG_EARLY_TERMINATE; |
- sf->intra_y_mode_mask = INTRA_DC_TM; |
- sf->intra_uv_mode_mask = INTRA_DC_TM; |
+ |
sf->use_uv_intra_rd_estimate = 1; |
- sf->use_rd_breakout = 1; |
sf->skip_encode_sb = 1; |
sf->use_lp32x32fdct = 1; |
- sf->adaptive_motion_search = 1; |
- sf->using_small_partition_info = 0; |
- sf->disable_splitmv = |
- (MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0; |
- sf->auto_mv_step_size = 1; |
- sf->search_method = SQUARE; |
sf->subpel_iters_per_step = 1; |
- sf->use_fast_lpf_pick = 1; |
- sf->auto_min_max_partition_size = 1; |
- sf->auto_min_max_partition_interval = 2; |
- sf->disable_split_var_thresh = 32; |
- sf->disable_filter_search_var_thresh = 32; |
sf->use_fast_coef_updates = 2; |
+ |
+ sf->adaptive_rd_thresh = 4; |
sf->mode_skip_start = 6; |
} |
- if (speed == 3) { |
- sf->comp_inter_joint_search_thresh = BLOCK_SIZES; |
- sf->partition_by_variance = 1; |
- sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME || |
- cpi->common.intra_only || |
- cpi->common.show_frame == 0) ? |
- USE_FULL_RD : |
- USE_LARGESTALL); |
+ if (speed == 4) { |
+ sf->use_square_partition_only = 1; |
+ sf->tx_size_search_method = USE_LARGESTALL; |
+ sf->disable_split_mask = DISABLE_ALL_SPLIT; |
+ |
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | |
FLAG_SKIP_INTRA_BESTINTER | |
FLAG_SKIP_COMP_BESTINTRA | |
FLAG_SKIP_COMP_REFMISMATCH | |
FLAG_SKIP_INTRA_LOWVAR | |
FLAG_EARLY_TERMINATE; |
+ |
sf->use_rd_breakout = 1; |
+ sf->adaptive_motion_search = 1; |
+ sf->auto_mv_step_size = 1; |
+ |
+ sf->disable_filter_search_var_thresh = 16; |
+ sf->comp_inter_joint_search_thresh = BLOCK_SIZES; |
+ |
+ sf->auto_min_max_partition_size = 1; |
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL; |
+ sf->adjust_partitioning_from_last_frame = 1; |
+ sf->last_partitioning_redo_frequency = 3; |
+ |
+ sf->use_uv_intra_rd_estimate = 1; |
sf->skip_encode_sb = 1; |
sf->use_lp32x32fdct = 1; |
- sf->disable_splitmv = 1; |
- sf->auto_mv_step_size = 1; |
- sf->search_method = BIGDIA; |
sf->subpel_iters_per_step = 1; |
- sf->disable_split_var_thresh = 64; |
- sf->disable_filter_search_var_thresh = 64; |
- sf->intra_y_mode_mask = INTRA_DC_ONLY; |
- sf->intra_uv_mode_mask = INTRA_DC_ONLY; |
sf->use_fast_coef_updates = 2; |
+ |
+ sf->adaptive_rd_thresh = 4; |
sf->mode_skip_start = 6; |
+ |
+ /* sf->intra_y_mode_mask = INTRA_DC_ONLY; |
+ sf->intra_uv_mode_mask = INTRA_DC_ONLY; |
+ sf->search_method = BIGDIA; |
+ sf->disable_split_var_thresh = 64; |
+ sf->disable_filter_search_var_thresh = 64; */ |
} |
- if (speed == 4) { |
+ if (speed == 5) { |
sf->comp_inter_joint_search_thresh = BLOCK_SIZES; |
sf->use_one_partition_size_always = 1; |
sf->always_this_block_size = BLOCK_16X16; |
- sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME || |
- cpi->common.intra_only || |
- cpi->common.show_frame == 0) ? |
- USE_FULL_RD : |
- USE_LARGESTALL); |
+ sf->tx_size_search_method = frame_is_intra_only(&cpi->common) ? |
+ USE_FULL_RD : USE_LARGESTALL; |
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH | |
FLAG_SKIP_INTRA_BESTINTER | |
FLAG_SKIP_COMP_BESTINTRA | |
@@ -864,22 +933,25 @@ |
// sf->reduce_first_step_size = 1; |
// sf->reference_masking = 1; |
- sf->disable_splitmv = 1; |
+ sf->disable_split_mask = DISABLE_ALL_SPLIT; |
sf->search_method = HEX; |
sf->subpel_iters_per_step = 1; |
sf->disable_split_var_thresh = 64; |
sf->disable_filter_search_var_thresh = 96; |
- sf->intra_y_mode_mask = INTRA_DC_ONLY; |
- sf->intra_uv_mode_mask = INTRA_DC_ONLY; |
+ for (i = 0; i < TX_SIZES; i++) { |
+ sf->intra_y_mode_mask[i] = INTRA_DC_ONLY; |
+ sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY; |
+ } |
sf->use_fast_coef_updates = 2; |
+ sf->adaptive_rd_thresh = 4; |
sf->mode_skip_start = 6; |
} |
break; |
- |
}; /* switch */ |
// Set rd thresholds based on mode and speed setting |
set_rd_speed_thresholds(cpi, mode); |
+ set_rd_speed_thresholds_sub8x8(cpi, mode); |
// Slow quant, dct and trellis not worthwhile for first pass |
// so make sure they are always turned off. |
@@ -887,17 +959,17 @@ |
sf->optimize_coefficients = 0; |
} |
- cpi->mb.fwd_txm16x16 = vp9_short_fdct16x16; |
- cpi->mb.fwd_txm8x8 = vp9_short_fdct8x8; |
- cpi->mb.fwd_txm8x4 = vp9_short_fdct8x4; |
- cpi->mb.fwd_txm4x4 = vp9_short_fdct4x4; |
+ // No recode for 1 pass. |
+ if (cpi->pass == 0) { |
+ sf->recode_loop = 0; |
+ sf->optimize_coefficients = 0; |
+ } |
+ |
+ cpi->mb.fwd_txm4x4 = vp9_fdct4x4; |
if (cpi->oxcf.lossless || cpi->mb.e_mbd.lossless) { |
- cpi->mb.fwd_txm8x4 = vp9_short_walsh8x4; |
- cpi->mb.fwd_txm4x4 = vp9_short_walsh4x4; |
+ cpi->mb.fwd_txm4x4 = vp9_fwht4x4; |
} |
- cpi->mb.quantize_b_4x4 = vp9_regular_quantize_b_4x4; |
- |
if (cpi->sf.subpel_search_method == SUBPEL_ITERATIVE) { |
cpi->find_fractional_mv_step = vp9_find_best_sub_pixel_iterative; |
cpi->find_fractional_mv_step_comp = vp9_find_best_sub_pixel_comp_iterative; |
@@ -931,20 +1003,6 @@ |
"Failed to allocate altref buffer"); |
} |
-static int alloc_partition_data(VP9_COMP *cpi) { |
- vpx_free(cpi->mb.pip); |
- |
- cpi->mb.pip = vpx_calloc(cpi->common.mode_info_stride * |
- (cpi->common.mi_rows + MI_BLOCK_SIZE), |
- sizeof(PARTITION_INFO)); |
- if (!cpi->mb.pip) |
- return 1; |
- |
- cpi->mb.pi = cpi->mb.pip + cpi->common.mode_info_stride + 1; |
- |
- return 0; |
-} |
- |
void vp9_alloc_compressor_data(VP9_COMP *cpi) { |
VP9_COMMON *cm = &cpi->common; |
@@ -952,10 +1010,6 @@ |
vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, |
"Failed to allocate frame buffers"); |
- if (alloc_partition_data(cpi)) |
- vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, |
- "Failed to allocate partition data"); |
- |
if (vp9_alloc_frame_buffer(&cpi->last_frame_uf, |
cm->width, cm->height, |
cm->subsampling_x, cm->subsampling_y, |
@@ -992,6 +1046,19 @@ |
CHECK_MEM_ERROR(cm, cpi->mb_norm_activity_map, |
vpx_calloc(sizeof(unsigned int), |
cm->mb_rows * cm->mb_cols)); |
+ |
+ // 2 contexts per 'mi unit', so that we have one context per 4x4 txfm |
+ // block where mi unit size is 8x8. |
+ vpx_free(cpi->above_context[0]); |
+ CHECK_MEM_ERROR(cm, cpi->above_context[0], |
+ vpx_calloc(2 * mi_cols_aligned_to_sb(cm->mi_cols) * |
+ MAX_MB_PLANE, |
+ sizeof(*cpi->above_context[0]))); |
+ |
+ vpx_free(cpi->above_seg_context); |
+ CHECK_MEM_ERROR(cm, cpi->above_seg_context, |
+ vpx_calloc(mi_cols_aligned_to_sb(cm->mi_cols), |
+ sizeof(*cpi->above_seg_context))); |
} |
@@ -1024,13 +1091,18 @@ |
vp9_init_dsmotion_compensation(&cpi->mb, y_stride); |
} |
} |
+ |
+ { |
+ int i; |
+ for (i = 1; i < MAX_MB_PLANE; ++i) { |
+ cpi->above_context[i] = cpi->above_context[0] + |
+ i * sizeof(*cpi->above_context[0]) * 2 * |
+ mi_cols_aligned_to_sb(cm->mi_cols); |
+ } |
+ } |
} |
-// TODO perhaps change number of steps expose to outside world when setting |
-// max and min limits. Also this will likely want refining for the extended Q |
-// range. |
-// |
// Table that converts 0-63 Q range values passed in outside to the Qindex |
// range used internally. |
static const int q_trans[] = { |
@@ -1057,11 +1129,14 @@ |
if (framerate < 0.1) |
framerate = 30; |
- cpi->oxcf.framerate = framerate; |
- cpi->output_framerate = cpi->oxcf.framerate; |
- cpi->per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_framerate); |
- cpi->av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth / cpi->output_framerate); |
- cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth * cpi->oxcf.two_pass_vbrmin_section / 100); |
+ cpi->oxcf.framerate = framerate; |
+ cpi->output_framerate = cpi->oxcf.framerate; |
+ cpi->per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth |
+ / cpi->output_framerate); |
+ cpi->av_per_frame_bandwidth = (int)(cpi->oxcf.target_bandwidth |
+ / cpi->output_framerate); |
+ cpi->min_frame_bandwidth = (int)(cpi->av_per_frame_bandwidth * |
+ cpi->oxcf.two_pass_vbrmin_section / 100); |
cpi->min_frame_bandwidth = MAX(cpi->min_frame_bandwidth, FRAME_OVERHEAD_BITS); |
@@ -1172,6 +1247,12 @@ |
switch (cpi->oxcf.Mode) { |
// Real time and one pass deprecated in test code base |
+ case MODE_GOODQUALITY: |
+ cpi->pass = 0; |
+ cpi->compressor_speed = 2; |
+ cpi->oxcf.cpu_used = clamp(cpi->oxcf.cpu_used, -5, 5); |
+ break; |
+ |
case MODE_FIRSTPASS: |
cpi->pass = 1; |
cpi->compressor_speed = 1; |
@@ -1194,14 +1275,8 @@ |
cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level]; |
cpi->oxcf.lossless = oxcf->lossless; |
- if (cpi->oxcf.lossless) { |
- cpi->mb.e_mbd.inv_txm4x4_1_add = vp9_short_iwalsh4x4_1_add; |
- cpi->mb.e_mbd.inv_txm4x4_add = vp9_short_iwalsh4x4_add; |
- } else { |
- cpi->mb.e_mbd.inv_txm4x4_1_add = vp9_short_idct4x4_1_add; |
- cpi->mb.e_mbd.inv_txm4x4_add = vp9_short_idct4x4_add; |
- } |
- |
+ cpi->mb.e_mbd.itxm_add = cpi->oxcf.lossless ? vp9_iwht4x4_add |
+ : vp9_idct4x4_add; |
cpi->baseline_gf_interval = DEFAULT_GF_INTERVAL; |
cpi->ref_frame_flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG; |
@@ -1214,8 +1289,8 @@ |
cm->reset_frame_context = 0; |
setup_features(cm); |
- cpi->mb.e_mbd.allow_high_precision_mv = 0; // Default mv precision adaptation |
- set_mvcost(&cpi->mb); |
+ cpi->common.allow_high_precision_mv = 0; // Default mv precision |
+ set_mvcost(cpi); |
{ |
int i; |
@@ -1367,6 +1442,94 @@ |
} while (++i <= MV_MAX); |
} |
+static void init_pick_mode_context(VP9_COMP *cpi) { |
+ int i; |
+ MACROBLOCK *x = &cpi->mb; |
+ MACROBLOCKD *xd = &x->e_mbd; |
+ VP9_COMMON *cm = &cpi->common; |
+ |
+ for (i = 0; i < BLOCK_SIZES; ++i) { |
+ const int num_4x4_w = num_4x4_blocks_wide_lookup[i]; |
+ const int num_4x4_h = num_4x4_blocks_high_lookup[i]; |
+ const int num_4x4_blk = MAX(4, num_4x4_w * num_4x4_h); |
+ if (i < BLOCK_16X16) { |
+ for (xd->sb_index = 0; xd->sb_index < 4; ++xd->sb_index) { |
+ for (xd->mb_index = 0; xd->mb_index < 4; ++xd->mb_index) { |
+ for (xd->b_index = 0; xd->b_index < 16 / num_4x4_blk; ++xd->b_index) { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ ctx->num_4x4_blk = num_4x4_blk; |
+ CHECK_MEM_ERROR(cm, ctx->zcoeff_blk, |
+ vpx_calloc(num_4x4_blk, sizeof(uint8_t))); |
+ } |
+ } |
+ } |
+ } else if (i < BLOCK_32X32) { |
+ for (xd->sb_index = 0; xd->sb_index < 4; ++xd->sb_index) { |
+ for (xd->mb_index = 0; xd->mb_index < 64 / num_4x4_blk; |
+ ++xd->mb_index) { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ ctx->num_4x4_blk = num_4x4_blk; |
+ CHECK_MEM_ERROR(cm, ctx->zcoeff_blk, |
+ vpx_calloc(num_4x4_blk, sizeof(uint8_t))); |
+ } |
+ } |
+ } else if (i < BLOCK_64X64) { |
+ for (xd->sb_index = 0; xd->sb_index < 256 / num_4x4_blk; ++xd->sb_index) { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ ctx->num_4x4_blk = num_4x4_blk; |
+ CHECK_MEM_ERROR(cm, ctx->zcoeff_blk, |
+ vpx_calloc(num_4x4_blk, sizeof(uint8_t))); |
+ } |
+ } else { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ ctx->num_4x4_blk = num_4x4_blk; |
+ CHECK_MEM_ERROR(cm, ctx->zcoeff_blk, |
+ vpx_calloc(num_4x4_blk, sizeof(uint8_t))); |
+ } |
+ } |
+} |
+ |
+static void free_pick_mode_context(MACROBLOCK *x) { |
+ int i; |
+ MACROBLOCKD *xd = &x->e_mbd; |
+ |
+ for (i = 0; i < BLOCK_SIZES; ++i) { |
+ const int num_4x4_w = num_4x4_blocks_wide_lookup[i]; |
+ const int num_4x4_h = num_4x4_blocks_high_lookup[i]; |
+ const int num_4x4_blk = MAX(4, num_4x4_w * num_4x4_h); |
+ if (i < BLOCK_16X16) { |
+ for (xd->sb_index = 0; xd->sb_index < 4; ++xd->sb_index) { |
+ for (xd->mb_index = 0; xd->mb_index < 4; ++xd->mb_index) { |
+ for (xd->b_index = 0; xd->b_index < 16 / num_4x4_blk; ++xd->b_index) { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ vpx_free(ctx->zcoeff_blk); |
+ ctx->zcoeff_blk = 0; |
+ } |
+ } |
+ } |
+ } else if (i < BLOCK_32X32) { |
+ for (xd->sb_index = 0; xd->sb_index < 4; ++xd->sb_index) { |
+ for (xd->mb_index = 0; xd->mb_index < 64 / num_4x4_blk; |
+ ++xd->mb_index) { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ vpx_free(ctx->zcoeff_blk); |
+ ctx->zcoeff_blk = 0; |
+ } |
+ } |
+ } else if (i < BLOCK_64X64) { |
+ for (xd->sb_index = 0; xd->sb_index < 256 / num_4x4_blk; ++xd->sb_index) { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ vpx_free(ctx->zcoeff_blk); |
+ ctx->zcoeff_blk = 0; |
+ } |
+ } else { |
+ PICK_MODE_CONTEXT *ctx = get_block_context(x, i); |
+ vpx_free(ctx->zcoeff_blk); |
+ ctx->zcoeff_blk = 0; |
+ } |
+ } |
+} |
+ |
VP9_PTR vp9_create_compressor(VP9_CONFIG *oxcf) { |
int i, j; |
volatile union { |
@@ -1403,6 +1566,8 @@ |
init_config((VP9_PTR)cpi, oxcf); |
+ init_pick_mode_context(cpi); |
+ |
cm->current_video_frame = 0; |
cpi->kf_overspend_bits = 0; |
cpi->kf_bitrate_adjustment = 0; |
@@ -1455,7 +1620,7 @@ |
/*Initialize the feed-forward activity masking.*/ |
cpi->activity_avg = 90 << 12; |
- cpi->frames_since_key = 8; // Give a sensible default for the first frame. |
+ cpi->frames_since_key = 8; // Sensible default for first frame. |
cpi->key_frame_frequency = cpi->oxcf.key_freq; |
cpi->this_key_frame_forced = 0; |
cpi->next_key_frame_forced = 0; |
@@ -1576,9 +1741,12 @@ |
vp9_set_speed_features(cpi); |
// Default rd threshold factors for mode selection |
- for (i = 0; i < BLOCK_SIZES; ++i) |
+ for (i = 0; i < BLOCK_SIZES; ++i) { |
for (j = 0; j < MAX_MODES; ++j) |
cpi->rd_thresh_freq_fact[i][j] = 32; |
+ for (j = 0; j < MAX_REFS; ++j) |
+ cpi->rd_thresh_freq_sub8x8[i][j] = 32; |
+ } |
#define BFP(BT, SDF, SDAF, VF, SVF, SVAF, SVFHH, SVFHV, SVFHHV, \ |
SDX3F, SDX8F, SDX4DF)\ |
@@ -1689,10 +1857,10 @@ |
cpi->common.error.setjmp = 0; |
- vp9_zero(cpi->y_uv_mode_count) |
+ vp9_zero(cpi->y_uv_mode_count); |
#ifdef MODE_TEST_HIT_STATS |
- vp9_zero(cpi->mode_test_hits) |
+ vp9_zero(cpi->mode_test_hits); |
#endif |
return (VP9_PTR) cpi; |
@@ -1734,8 +1902,10 @@ |
FILE *f = fopen("opsnr.stt", "a"); |
double time_encoded = (cpi->last_end_time_stamp_seen |
- cpi->first_time_stamp_ever) / 10000000.000; |
- double total_encode_time = (cpi->time_receive_data + cpi->time_compress_data) / 1000.000; |
- double dr = (double)cpi->bytes * (double) 8 / (double)1000 / time_encoded; |
+ double total_encode_time = (cpi->time_receive_data + |
+ cpi->time_compress_data) / 1000.000; |
+ double dr = (double)cpi->bytes * (double) 8 / (double)1000 |
+ / time_encoded; |
if (cpi->b_calculate_psnr) { |
YV12_BUFFER_CONFIG *lst_yv12 = |
@@ -1755,20 +1925,15 @@ |
dr, cpi->total / cpi->count, total_psnr, |
cpi->totalp / cpi->count, total_psnr2, total_ssim, total_ssimp, |
total_encode_time); |
-// fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f %10ld\n", |
-// dr, cpi->total / cpi->count, total_psnr, |
-// cpi->totalp / cpi->count, total_psnr2, total_ssim, |
-// total_encode_time, cpi->tot_recode_hits); |
} |
if (cpi->b_calculate_ssimg) { |
fprintf(f, "BitRate\tSSIM_Y\tSSIM_U\tSSIM_V\tSSIM_A\t Time(ms)\n"); |
fprintf(f, "%7.2f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr, |
- cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count, |
- cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time); |
-// fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f %10ld\n", dr, |
-// cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count, |
-// cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time, cpi->tot_recode_hits); |
+ cpi->total_ssimg_y / cpi->count, |
+ cpi->total_ssimg_u / cpi->count, |
+ cpi->total_ssimg_v / cpi->count, |
+ cpi->total_ssimg_all / cpi->count, total_encode_time); |
} |
fclose(f); |
@@ -1815,11 +1980,9 @@ |
"[INTRA_MODES] =\n{\n"); |
for (i = 0; i < INTRA_MODES; i++) { |
- |
fprintf(fmode, " { // Above Mode : %d\n", i); |
for (j = 0; j < INTRA_MODES; j++) { |
- |
fprintf(fmode, " {"); |
for (k = 0; k < INTRA_MODES; k++) { |
@@ -1830,11 +1993,9 @@ |
} |
fprintf(fmode, "}, // left_mode %d\n", j); |
- |
} |
fprintf(fmode, " },\n"); |
- |
} |
fprintf(fmode, "};\n"); |
@@ -1868,14 +2029,15 @@ |
(cpi->time_receive_data + cpi->time_compress_data) / 1000); |
} |
#endif |
- |
} |
+ free_pick_mode_context(&cpi->mb); |
dealloc_compressor_data(cpi); |
vpx_free(cpi->mb.ss); |
vpx_free(cpi->tok); |
- for (i = 0; i < sizeof(cpi->mbgraph_stats) / sizeof(cpi->mbgraph_stats[0]); i++) { |
+ for (i = 0; i < sizeof(cpi->mbgraph_stats) / |
+ sizeof(cpi->mbgraph_stats[0]); ++i) { |
vpx_free(cpi->mbgraph_stats[i].mb_stats); |
} |
@@ -1902,7 +2064,6 @@ |
fclose(kf_list); |
#endif |
- |
} |
@@ -2223,14 +2384,15 @@ |
cpi->frames_since_golden = 0; |
// ******** Fixed Q test code only ************ |
- // If we are going to use the ALT reference for the next group of frames set a flag to say so. |
+ // If we are going to use the ALT reference for the next group of frames |
+ // set a flag to say so. |
if (cpi->oxcf.fixed_q >= 0 && |
cpi->oxcf.play_alternate && !cpi->refresh_alt_ref_frame) { |
cpi->source_alt_ref_pending = 1; |
cpi->frames_till_gf_update_due = cpi->baseline_gf_interval; |
- // TODO(ivan): for SVC encoder, GF automatic update is disabled by using a |
- // large GF_interval |
+ // TODO(ivan): For SVC encoder, GF automatic update is disabled by using |
+ // a large GF_interval. |
if (cpi->use_svc) { |
cpi->frames_till_gf_update_due = INT_MAX; |
} |
@@ -2270,12 +2432,12 @@ |
return i; |
} |
-static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, unsigned int *frame_flags) { |
+static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest, |
+ unsigned int *frame_flags) { |
(void) size; |
(void) dest; |
(void) frame_flags; |
- |
vp9_set_quantizer(cpi, find_fp_qindex()); |
vp9_first_pass(cpi); |
} |
@@ -2283,13 +2445,11 @@ |
#define WRITE_RECON_BUFFER 0 |
#if WRITE_RECON_BUFFER |
void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) { |
- |
- // write the frame |
FILE *yframe; |
int i; |
char filename[255]; |
- sprintf(filename, "cx\\y%04d.raw", this_frame); |
+ snprintf(filename, sizeof(filename), "cx\\y%04d.raw", this_frame); |
yframe = fopen(filename, "wb"); |
for (i = 0; i < frame->y_height; i++) |
@@ -2297,7 +2457,7 @@ |
frame->y_width, 1, yframe); |
fclose(yframe); |
- sprintf(filename, "cx\\u%04d.raw", this_frame); |
+ snprintf(filename, sizeof(filename), "cx\\u%04d.raw", this_frame); |
yframe = fopen(filename, "wb"); |
for (i = 0; i < frame->uv_height; i++) |
@@ -2305,7 +2465,7 @@ |
frame->uv_width, 1, yframe); |
fclose(yframe); |
- sprintf(filename, "cx\\v%04d.raw", this_frame); |
+ snprintf(filename, sizeof(filename), "cx\\v%04d.raw", this_frame); |
yframe = fopen(filename, "wb"); |
for (i = 0; i < frame->uv_height; i++) |
@@ -2327,8 +2487,10 @@ |
for (i = 1; i < frame->y_height - 1; i++) { |
for (j = 1; j < frame->y_width - 1; j++) { |
/* Sobel hor and ver gradients */ |
- int v = 2 * (curr[1] - curr[-1]) + (prev[1] - prev[-1]) + (next[1] - next[-1]); |
- int h = 2 * (prev[0] - next[0]) + (prev[1] - next[1]) + (prev[-1] - next[-1]); |
+ int v = 2 * (curr[1] - curr[-1]) + (prev[1] - prev[-1]) + |
+ (next[1] - next[-1]); |
+ int h = 2 * (prev[0] - next[0]) + (prev[1] - next[1]) + |
+ (prev[-1] - next[-1]); |
h = (h < 0 ? -h : h); |
v = (v < 0 ? -v : v); |
if (h > EDGE_THRESH || v > EDGE_THRESH) |
@@ -2364,10 +2526,9 @@ |
if (((cpi->projected_frame_size > high_limit) && (q < maxq)) || |
((cpi->projected_frame_size < low_limit) && (q > minq))) { |
force_recode = 1; |
- } |
- // Special Constrained quality tests |
- else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) { |
- // Undershoot and below auto cq level |
+ } else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) { |
+ // Deal with frame undershoot and whether or not we are |
+ // below the automatically set cq level. |
if (q > cpi->cq_target_quality && |
cpi->projected_frame_size < ((cpi->this_frame_target * 7) >> 3)) { |
force_recode = 1; |
@@ -2528,159 +2689,81 @@ |
} |
} |
+#if 0 && CONFIG_INTERNAL_STATS |
+static void output_frame_level_debug_stats(VP9_COMP *cpi) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ FILE *const f = fopen("tmp.stt", cm->current_video_frame ? "a" : "w"); |
+ int recon_err; |
-static void encode_frame_to_data_rate(VP9_COMP *cpi, |
- unsigned long *size, |
- unsigned char *dest, |
- unsigned int *frame_flags) { |
- VP9_COMMON *cm = &cpi->common; |
- MACROBLOCKD *xd = &cpi->mb.e_mbd; |
- TX_SIZE t; |
- int q; |
- int frame_over_shoot_limit; |
- int frame_under_shoot_limit; |
+ vp9_clear_system_state(); // __asm emms; |
- int loop = 0; |
- int loop_count; |
+ recon_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm)); |
- int q_low; |
- int q_high; |
+ if (cpi->twopass.total_left_stats.coded_error != 0.0) |
+ fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d" |
+ "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f" |
+ "%6d %6d %5d %5d %5d %8.2f %10d %10.3f" |
+ "%10.3f %8d %10d %10d %10d\n", |
+ cpi->common.current_video_frame, cpi->this_frame_target, |
+ cpi->projected_frame_size, 0, |
+ (cpi->projected_frame_size - cpi->this_frame_target), |
+ (int)cpi->total_target_vs_actual, |
+ (int)(cpi->oxcf.starting_buffer_level - cpi->bits_off_target), |
+ (int)cpi->total_actual_bits, cm->base_qindex, |
+ vp9_convert_qindex_to_q(cm->base_qindex), |
+ (double)vp9_dc_quant(cm->base_qindex, 0) / 4.0, |
+ vp9_convert_qindex_to_q(cpi->active_best_quality), |
+ vp9_convert_qindex_to_q(cpi->active_worst_quality), cpi->avg_q, |
+ vp9_convert_qindex_to_q(cpi->ni_av_qi), |
+ vp9_convert_qindex_to_q(cpi->cq_target_quality), |
+ cpi->refresh_last_frame, cpi->refresh_golden_frame, |
+ cpi->refresh_alt_ref_frame, cm->frame_type, cpi->gfu_boost, |
+ cpi->twopass.est_max_qcorrection_factor, (int)cpi->twopass.bits_left, |
+ cpi->twopass.total_left_stats.coded_error, |
+ (double)cpi->twopass.bits_left / |
+ (1 + cpi->twopass.total_left_stats.coded_error), |
+ cpi->tot_recode_hits, recon_err, cpi->kf_boost, cpi->kf_zeromotion_pct); |
- int top_index; |
- int bottom_index; |
- int active_worst_qchanged = 0; |
+ fclose(f); |
- int overshoot_seen = 0; |
- int undershoot_seen = 0; |
+ if (0) { |
+ FILE *const fmodes = fopen("Modes.stt", "a"); |
+ int i; |
- SPEED_FEATURES *sf = &cpi->sf; |
- unsigned int max_mv_def = MIN(cpi->common.width, cpi->common.height); |
- struct segmentation *seg = &cm->seg; |
+ fprintf(fmodes, "%6d:%1d:%1d:%1d ", cpi->common.current_video_frame, |
+ cm->frame_type, cpi->refresh_golden_frame, |
+ cpi->refresh_alt_ref_frame); |
- /* Scale the source buffer, if required */ |
- if (cm->mi_cols * 8 != cpi->un_scaled_source->y_width || |
- cm->mi_rows * 8 != cpi->un_scaled_source->y_height) { |
- scale_and_extend_frame(cpi->un_scaled_source, &cpi->scaled_source); |
- cpi->Source = &cpi->scaled_source; |
- } else { |
- cpi->Source = cpi->un_scaled_source; |
- } |
+ for (i = 0; i < MAX_MODES; ++i) |
+ fprintf(fmodes, "%5d ", cpi->mode_chosen_counts[i]); |
+ for (i = 0; i < MAX_REFS; ++i) |
+ fprintf(fmodes, "%5d ", cpi->sub8x8_mode_chosen_counts[i]); |
- scale_references(cpi); |
+ fprintf(fmodes, "\n"); |
- // Clear down mmx registers to allow floating point in what follows |
- vp9_clear_system_state(); |
- |
- |
- // For an alt ref frame in 2 pass we skip the call to the second |
- // pass function that sets the target bandwidth so must set it here |
- if (cpi->refresh_alt_ref_frame) { |
- // Per frame bit target for the alt ref frame |
- cpi->per_frame_bandwidth = cpi->twopass.gf_bits; |
- // per second target bitrate |
- cpi->target_bandwidth = (int)(cpi->twopass.gf_bits * |
- cpi->output_framerate); |
+ fclose(fmodes); |
} |
+} |
+#endif |
- // Clear zbin over-quant value and mode boost values. |
- cpi->zbin_mode_boost = 0; |
- |
- // Enable or disable mode based tweaking of the zbin |
- // For 2 Pass Only used where GF/ARF prediction quality |
- // is above a threshold |
- cpi->zbin_mode_boost = 0; |
- |
- // if (cpi->oxcf.lossless) |
- cpi->zbin_mode_boost_enabled = 0; |
- // else |
- // cpi->zbin_mode_boost_enabled = 1; |
- |
- // Current default encoder behaviour for the altref sign bias |
- cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = cpi->source_alt_ref_active; |
- |
- // Check to see if a key frame is signaled |
- // For two pass with auto key frame enabled cm->frame_type may already be set, but not for one pass. |
- if ((cm->current_video_frame == 0) || |
- (cm->frame_flags & FRAMEFLAGS_KEY) || |
- (cpi->oxcf.auto_key && (cpi->frames_since_key % cpi->key_frame_frequency == 0))) { |
- // Key frame from VFW/auto-keyframe/first frame |
- cm->frame_type = KEY_FRAME; |
- } |
- |
- // Set default state for segment based loop filter update flags |
- cm->lf.mode_ref_delta_update = 0; |
- |
- // Initialize cpi->mv_step_param to default based on max resolution |
- cpi->mv_step_param = vp9_init_search_range(cpi, max_mv_def); |
- // Initialize cpi->max_mv_magnitude and cpi->mv_step_param if appropriate. |
- if (sf->auto_mv_step_size) { |
- if ((cpi->common.frame_type == KEY_FRAME) || cpi->common.intra_only) { |
- // initialize max_mv_magnitude for use in the first INTER frame |
- // after a key/intra-only frame |
- cpi->max_mv_magnitude = max_mv_def; |
- } else { |
- if (cm->show_frame) |
- // allow mv_steps to correspond to twice the max mv magnitude found |
- // in the previous frame, capped by the default max_mv_magnitude based |
- // on resolution |
- cpi->mv_step_param = vp9_init_search_range( |
- cpi, MIN(max_mv_def, 2 * cpi->max_mv_magnitude)); |
- cpi->max_mv_magnitude = 0; |
- } |
- } |
- |
- // Set various flags etc to special state if it is a key frame |
- if (cm->frame_type == KEY_FRAME) { |
- // Reset the loop filter deltas and segmentation map |
- setup_features(cm); |
- |
- // If segmentation is enabled force a map update for key frames |
- if (seg->enabled) { |
- seg->update_map = 1; |
- seg->update_data = 1; |
- } |
- |
- // The alternate reference frame cannot be active for a key frame |
- cpi->source_alt_ref_active = 0; |
- |
- cm->error_resilient_mode = (cpi->oxcf.error_resilient_mode != 0); |
- cm->frame_parallel_decoding_mode = |
- (cpi->oxcf.frame_parallel_decoding_mode != 0); |
- if (cm->error_resilient_mode) { |
- cm->frame_parallel_decoding_mode = 1; |
- cm->reset_frame_context = 0; |
- cm->refresh_frame_context = 0; |
- } |
- } |
- |
- // Configure experimental use of segmentation for enhanced coding of |
- // static regions if indicated. |
- // Only allowed for now in second pass of two pass (as requires lagged coding) |
- // and if the relevant speed feature flag is set. |
- if ((cpi->pass == 2) && (cpi->sf.static_segmentation)) { |
- configure_static_seg_features(cpi); |
- } |
- |
- // Decide how big to make the frame |
- vp9_pick_frame_size(cpi); |
- |
- vp9_clear_system_state(); |
- |
+static int pick_q_and_adjust_q_bounds(VP9_COMP *cpi, |
+ int * bottom_index, int * top_index) { |
// Set an active best quality and if necessary active worst quality |
- q = cpi->active_worst_quality; |
+ int q = cpi->active_worst_quality; |
+ VP9_COMMON *const cm = &cpi->common; |
- if (cm->frame_type == KEY_FRAME) { |
+ if (frame_is_intra_only(cm)) { |
#if !CONFIG_MULTIPLE_ARF |
- // Special case for key frames forced because we have reached |
- // the maximum key frame interval. Here force the Q to a range |
- // based on the ambient Q to reduce the risk of popping |
+ // Handle the special case for key frames forced when we have75 reached |
+ // the maximum key frame interval. Here force the Q to a range |
+ // based on the ambient Q to reduce the risk of popping. |
if (cpi->this_key_frame_forced) { |
int delta_qindex; |
int qindex = cpi->last_boosted_qindex; |
double last_boosted_q = vp9_convert_qindex_to_q(qindex); |
- delta_qindex = compute_qdelta(cpi, last_boosted_q, |
- (last_boosted_q * 0.75)); |
+ delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q, |
+ (last_boosted_q * 0.75)); |
cpi->active_best_quality = MAX(qindex + delta_qindex, |
cpi->best_quality); |
@@ -2691,19 +2774,11 @@ |
double q_val; |
// Baseline value derived from cpi->active_worst_quality and kf boost |
- if (cpi->kf_boost > high) { |
- cpi->active_best_quality = kf_low_motion_minq[q]; |
- } else if (cpi->kf_boost < low) { |
- cpi->active_best_quality = kf_high_motion_minq[q]; |
- } else { |
- const int gap = high - low; |
- const int offset = high - cpi->kf_boost; |
- const int qdiff = kf_high_motion_minq[q] - kf_low_motion_minq[q]; |
- const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap; |
+ cpi->active_best_quality = get_active_quality(q, cpi->kf_boost, |
+ low, high, |
+ kf_low_motion_minq, |
+ kf_high_motion_minq); |
- cpi->active_best_quality = kf_low_motion_minq[q] + adjustment; |
- } |
- |
// Allow somewhat lower kf minq with small image formats. |
if ((cm->width * cm->height) <= (352 * 288)) { |
q_adj_factor -= 0.25; |
@@ -2716,68 +2791,66 @@ |
// on active_best_quality. |
q_val = vp9_convert_qindex_to_q(cpi->active_best_quality); |
cpi->active_best_quality += |
- compute_qdelta(cpi, q_val, (q_val * q_adj_factor)); |
+ vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor)); |
} |
#else |
double current_q; |
// Force the KF quantizer to be 30% of the active_worst_quality. |
current_q = vp9_convert_qindex_to_q(cpi->active_worst_quality); |
cpi->active_best_quality = cpi->active_worst_quality |
- + compute_qdelta(cpi, current_q, current_q * 0.3); |
+ + vp9_compute_qdelta(cpi, current_q, current_q * 0.3); |
#endif |
- } else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) { |
+ } else if (!cpi->is_src_frame_alt_ref && |
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) { |
int high = 2000; |
int low = 400; |
// Use the lower of cpi->active_worst_quality and recent |
- // average Q as basis for GF/ARF Q limit unless last frame was |
+ // average Q as basis for GF/ARF best Q limit unless last frame was |
// a key frame. |
if (cpi->frames_since_key > 1 && |
cpi->avg_frame_qindex < cpi->active_worst_quality) { |
q = cpi->avg_frame_qindex; |
} |
// For constrained quality dont allow Q less than the cq level |
- if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY && |
- q < cpi->cq_target_quality) { |
- q = cpi->cq_target_quality; |
- } |
- if (cpi->gfu_boost > high) { |
- cpi->active_best_quality = gf_low_motion_minq[q]; |
- } else if (cpi->gfu_boost < low) { |
- cpi->active_best_quality = gf_high_motion_minq[q]; |
- } else { |
- const int gap = high - low; |
- const int offset = high - cpi->gfu_boost; |
- const int qdiff = gf_high_motion_minq[q] - gf_low_motion_minq[q]; |
- const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap; |
- |
- cpi->active_best_quality = gf_low_motion_minq[q] + adjustment; |
- } |
- |
- // Constrained quality use slightly lower active best. |
- if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) |
+ if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) { |
+ if (q < cpi->cq_target_quality) |
+ q = cpi->cq_target_quality; |
+ if (cpi->frames_since_key > 1) { |
+ cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost, |
+ low, high, |
+ afq_low_motion_minq, |
+ afq_high_motion_minq); |
+ } else { |
+ cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost, |
+ low, high, |
+ gf_low_motion_minq, |
+ gf_high_motion_minq); |
+ } |
+ // Constrained quality use slightly lower active best. |
cpi->active_best_quality = cpi->active_best_quality * 15 / 16; |
- // TODO(debargha): Refine the logic below |
- if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { |
+ } else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { |
if (!cpi->refresh_alt_ref_frame) { |
cpi->active_best_quality = cpi->cq_target_quality; |
} else { |
if (cpi->frames_since_key > 1) { |
- if (cpi->gfu_boost > high) { |
- cpi->active_best_quality = cpi->cq_target_quality * 6 / 16; |
- } else if (cpi->gfu_boost < low) { |
- cpi->active_best_quality = cpi->cq_target_quality * 11 / 16; |
- } else { |
- const int gap = high - low; |
- const int offset = high - cpi->gfu_boost; |
- const int qdiff = cpi->cq_target_quality * 5 / 16; |
- const int adjustment = ((offset * qdiff) + (gap >> 1)) / gap; |
- cpi->active_best_quality = cpi->cq_target_quality * 6 / 16 |
- + adjustment; |
- } |
+ cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost, |
+ low, high, |
+ afq_low_motion_minq, |
+ afq_high_motion_minq); |
+ } else { |
+ cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost, |
+ low, high, |
+ gf_low_motion_minq, |
+ gf_high_motion_minq); |
} |
} |
+ } else { |
+ cpi->active_best_quality = get_active_quality(q, cpi->gfu_boost, |
+ low, high, |
+ gf_low_motion_minq, |
+ gf_high_motion_minq); |
} |
} else { |
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { |
@@ -2791,9 +2864,13 @@ |
#endif |
#else |
cpi->active_best_quality = inter_minq[q]; |
+ // 1-pass: for now, use the average Q for the active_best, if its lower |
+ // than active_worst. |
+ if (cpi->pass == 0 && (cpi->avg_frame_qindex < q)) |
+ cpi->active_best_quality = inter_minq[cpi->avg_frame_qindex]; |
#endif |
- // For the constant/constrained quality mode we don't want |
+ // For the constrained quality mode we don't want |
// q to fall below the cq level. |
if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && |
(cpi->active_best_quality < cpi->cq_target_quality)) { |
@@ -2821,16 +2898,189 @@ |
if (cpi->active_worst_quality < cpi->active_best_quality) |
cpi->active_worst_quality = cpi->active_best_quality; |
- // Special case code to try and match quality with forced key frames |
+ // Limit Q range for the adaptive loop. |
+ if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) { |
+ *top_index = |
+ (cpi->active_worst_quality + cpi->active_best_quality * 3) / 4; |
+ // If this is the first (key) frame in 1-pass, active best is the user |
+ // best-allowed, and leave the top_index to active_worst. |
+ if (cpi->pass == 0 && cpi->common.current_video_frame == 0) { |
+ cpi->active_best_quality = cpi->oxcf.best_allowed_q; |
+ *top_index = cpi->oxcf.worst_allowed_q; |
+ } |
+ } else if (!cpi->is_src_frame_alt_ref && |
+ (cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) && |
+ (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) { |
+ *top_index = |
+ (cpi->active_worst_quality + cpi->active_best_quality) / 2; |
+ } else { |
+ *top_index = cpi->active_worst_quality; |
+ } |
+ *bottom_index = cpi->active_best_quality; |
+ |
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { |
q = cpi->active_best_quality; |
+ // Special case code to try and match quality with forced key frames |
} else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) { |
q = cpi->last_boosted_qindex; |
} else { |
- // Determine initial Q to try |
- q = vp9_regulate_q(cpi, cpi->this_frame_target); |
+ // Determine initial Q to try. |
+ if (cpi->pass == 0) { |
+ // 1-pass: for now, use per-frame-bw for target size of frame, scaled |
+ // by |x| for key frame. |
+ int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1; |
+ q = vp9_regulate_q(cpi, scale * cpi->av_per_frame_bandwidth); |
+ } else { |
+ q = vp9_regulate_q(cpi, cpi->this_frame_target); |
+ } |
+ if (q > *top_index) |
+ q = *top_index; |
} |
+ return q; |
+} |
+static void encode_frame_to_data_rate(VP9_COMP *cpi, |
+ unsigned long *size, |
+ unsigned char *dest, |
+ unsigned int *frame_flags) { |
+ VP9_COMMON *const cm = &cpi->common; |
+ TX_SIZE t; |
+ int q; |
+ int frame_over_shoot_limit; |
+ int frame_under_shoot_limit; |
+ |
+ int loop = 0; |
+ int loop_count; |
+ |
+ int q_low; |
+ int q_high; |
+ |
+ int top_index; |
+ int bottom_index; |
+ int active_worst_qchanged = 0; |
+ |
+ int overshoot_seen = 0; |
+ int undershoot_seen = 0; |
+ |
+ SPEED_FEATURES *const sf = &cpi->sf; |
+ unsigned int max_mv_def = MIN(cpi->common.width, cpi->common.height); |
+ struct segmentation *const seg = &cm->seg; |
+ |
+ /* Scale the source buffer, if required. */ |
+ if (cm->mi_cols * 8 != cpi->un_scaled_source->y_width || |
+ cm->mi_rows * 8 != cpi->un_scaled_source->y_height) { |
+ scale_and_extend_frame(cpi->un_scaled_source, &cpi->scaled_source); |
+ cpi->Source = &cpi->scaled_source; |
+ } else { |
+ cpi->Source = cpi->un_scaled_source; |
+ } |
+ scale_references(cpi); |
+ |
+ // Clear down mmx registers to allow floating point in what follows. |
+ vp9_clear_system_state(); |
+ |
+ // For an alt ref frame in 2 pass we skip the call to the second |
+ // pass function that sets the target bandwidth so we must set it here. |
+ if (cpi->refresh_alt_ref_frame) { |
+ // Set a per frame bit target for the alt ref frame. |
+ cpi->per_frame_bandwidth = cpi->twopass.gf_bits; |
+ // Set a per second target bitrate. |
+ cpi->target_bandwidth = (int)(cpi->twopass.gf_bits * cpi->output_framerate); |
+ } |
+ |
+ // Clear zbin over-quant value and mode boost values. |
+ cpi->zbin_mode_boost = 0; |
+ |
+ // Enable or disable mode based tweaking of the zbin. |
+ // For 2 pass only used where GF/ARF prediction quality |
+ // is above a threshold. |
+ cpi->zbin_mode_boost = 0; |
+ cpi->zbin_mode_boost_enabled = 0; |
+ |
+ // Current default encoder behavior for the altref sign bias. |
+ cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = cpi->source_alt_ref_active; |
+ |
+ // Check to see if a key frame is signaled. |
+ // For two pass with auto key frame enabled cm->frame_type may already be |
+ // set, but not for one pass. |
+ if ((cm->current_video_frame == 0) || |
+ (cm->frame_flags & FRAMEFLAGS_KEY) || |
+ (cpi->oxcf.auto_key && (cpi->frames_since_key % |
+ cpi->key_frame_frequency == 0))) { |
+ // Set frame type to key frame for the force key frame, if we exceed the |
+ // maximum distance in an automatic keyframe selection or for the first |
+ // frame. |
+ cm->frame_type = KEY_FRAME; |
+ } |
+ |
+ // Set default state for segment based loop filter update flags. |
+ cm->lf.mode_ref_delta_update = 0; |
+ |
+ // Initialize cpi->mv_step_param to default based on max resolution. |
+ cpi->mv_step_param = vp9_init_search_range(cpi, max_mv_def); |
+ // Initialize cpi->max_mv_magnitude and cpi->mv_step_param if appropriate. |
+ if (sf->auto_mv_step_size) { |
+ if (frame_is_intra_only(&cpi->common)) { |
+ // Initialize max_mv_magnitude for use in the first INTER frame |
+ // after a key/intra-only frame. |
+ cpi->max_mv_magnitude = max_mv_def; |
+ } else { |
+ if (cm->show_frame) |
+ // Allow mv_steps to correspond to twice the max mv magnitude found |
+ // in the previous frame, capped by the default max_mv_magnitude based |
+ // on resolution. |
+ cpi->mv_step_param = vp9_init_search_range( |
+ cpi, MIN(max_mv_def, 2 * cpi->max_mv_magnitude)); |
+ cpi->max_mv_magnitude = 0; |
+ } |
+ } |
+ |
+ // Set various flags etc to special state if it is a key frame. |
+ if (frame_is_intra_only(cm)) { |
+ vp9_setup_key_frame(cpi); |
+ // Reset the loop filter deltas and segmentation map. |
+ setup_features(cm); |
+ |
+ // If segmentation is enabled force a map update for key frames. |
+ if (seg->enabled) { |
+ seg->update_map = 1; |
+ seg->update_data = 1; |
+ } |
+ |
+ // The alternate reference frame cannot be active for a key frame. |
+ cpi->source_alt_ref_active = 0; |
+ |
+ cm->error_resilient_mode = (cpi->oxcf.error_resilient_mode != 0); |
+ cm->frame_parallel_decoding_mode = |
+ (cpi->oxcf.frame_parallel_decoding_mode != 0); |
+ if (cm->error_resilient_mode) { |
+ cm->frame_parallel_decoding_mode = 1; |
+ cm->reset_frame_context = 0; |
+ cm->refresh_frame_context = 0; |
+ } else if (cm->intra_only) { |
+ // Only reset the current context. |
+ cm->reset_frame_context = 2; |
+ } |
+ } |
+ |
+ // Configure experimental use of segmentation for enhanced coding of |
+ // static regions if indicated. |
+ // Only allowed in second pass of two pass (as requires lagged coding) |
+ // and if the relevant speed feature flag is set. |
+ if ((cpi->pass == 2) && (cpi->sf.static_segmentation)) { |
+ configure_static_seg_features(cpi); |
+ } |
+ |
+ // Decide how big to make the frame. |
+ vp9_pick_frame_size(cpi); |
+ |
+ vp9_clear_system_state(); |
+ |
+ q = pick_q_and_adjust_q_bounds(cpi, &bottom_index, &top_index); |
+ |
+ q_high = top_index; |
+ q_low = bottom_index; |
+ |
vp9_compute_frame_size_bounds(cpi, &frame_under_shoot_limit, |
&frame_over_shoot_limit); |
@@ -2845,7 +3095,7 @@ |
// Set quantizer steps at 10% increments. |
new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level))); |
- q = cpi->active_worst_quality + compute_qdelta(cpi, current_q, new_q); |
+ q = cpi->active_worst_quality + vp9_compute_qdelta(cpi, current_q, new_q); |
bottom_index = q; |
top_index = q; |
@@ -2853,24 +3103,17 @@ |
q_high = q; |
printf("frame:%d q:%d\n", cm->current_video_frame, q); |
- } else { |
-#endif |
- // Limit Q range for the adaptive loop. |
- bottom_index = cpi->active_best_quality; |
- top_index = cpi->active_worst_quality; |
- q_low = cpi->active_best_quality; |
- q_high = cpi->active_worst_quality; |
-#if CONFIG_MULTIPLE_ARF |
} |
#endif |
+ |
loop_count = 0; |
vp9_zero(cpi->rd_tx_select_threshes); |
- if (cm->frame_type != KEY_FRAME) { |
+ if (!frame_is_intra_only(cm)) { |
cm->mcomp_filter_type = DEFAULT_INTERP_FILTER; |
/* TODO: Decide this more intelligently */ |
- xd->allow_high_precision_mv = q < HIGH_PRECISION_MV_QTHRESH; |
- set_mvcost(&cpi->mb); |
+ cm->allow_high_precision_mv = q < HIGH_PRECISION_MV_QTHRESH; |
+ set_mvcost(cpi); |
} |
#if CONFIG_VP9_POSTPROC |
@@ -2912,25 +3155,25 @@ |
vp9_set_quantizer(cpi, q); |
if (loop_count == 0) { |
- |
- // Set up entropy depending on frame type. |
+ // Set up entropy context depending on frame type. The decoder mandates |
+ // the use of the default context, index 0, for keyframes and inter |
+ // frames where the error_resilient_mode or intra_only flag is set. For |
+ // other inter-frames the encoder currently uses only two contexts; |
+ // context 1 for ALTREF frames and context 0 for the others. |
if (cm->frame_type == KEY_FRAME) { |
- /* Choose which entropy context to use. When using a forward reference |
- * frame, it immediately follows the keyframe, and thus benefits from |
- * using the same entropy context established by the keyframe. |
- * Otherwise, use the default context 0. |
- */ |
- cm->frame_context_idx = cpi->oxcf.play_alternate; |
vp9_setup_key_frame(cpi); |
} else { |
- /* Choose which entropy context to use. Currently there are only two |
- * contexts used, one for normal frames and one for alt ref frames. |
- */ |
- cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame; |
+ if (!cm->intra_only && !cm->error_resilient_mode) { |
+ cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame; |
+ } |
vp9_setup_inter_frame(cpi); |
} |
} |
+ if (cpi->sf.variance_adaptive_quantization) { |
+ vp9_vaq_frame_setup(cpi); |
+ } |
+ |
// transform / motion compensation build reconstruction frame |
vp9_encode_frame(cpi); |
@@ -2954,14 +3197,13 @@ |
frame_over_shoot_limit = 1; |
active_worst_qchanged = 0; |
- // Special case handling for forced key frames |
if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) { |
loop = 0; |
} else { |
+ // Special case handling for forced key frames |
if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) { |
int last_q = q; |
- int kf_err = vp9_calc_ss_err(cpi->Source, |
- &cm->yv12_fb[cm->new_fb_idx]); |
+ int kf_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm)); |
int high_err_target = cpi->ambient_err; |
int low_err_target = cpi->ambient_err >> 1; |
@@ -3097,14 +3339,13 @@ |
// fixed interval. Note the reconstruction error if it is the frame before |
// the force key frame |
if (cpi->next_key_frame_forced && (cpi->twopass.frames_to_key == 0)) { |
- cpi->ambient_err = vp9_calc_ss_err(cpi->Source, |
- &cm->yv12_fb[cm->new_fb_idx]); |
+ cpi->ambient_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm)); |
} |
if (cm->frame_type == KEY_FRAME) |
cpi->refresh_last_frame = 1; |
- cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx]; |
+ cm->frame_to_show = get_frame_new_buffer(cm); |
#if WRITE_RECON_BUFFER |
if (cm->show_frame) |
@@ -3145,7 +3386,7 @@ |
vp9_adapt_coef_probs(&cpi->common); |
} |
- if (cpi->common.frame_type != KEY_FRAME) { |
+ if (!frame_is_intra_only(&cpi->common)) { |
FRAME_COUNTS *counts = &cpi->common.counts; |
vp9_copy(counts->y_mode, cpi->y_mode_count); |
@@ -3159,7 +3400,7 @@ |
if (!cpi->common.error_resilient_mode && |
!cpi->common.frame_parallel_decoding_mode) { |
vp9_adapt_mode_probs(&cpi->common); |
- vp9_adapt_mv_probs(&cpi->common, cpi->mb.e_mbd.allow_high_precision_mv); |
+ vp9_adapt_mv_probs(&cpi->common, cpi->common.allow_high_precision_mv); |
} |
} |
@@ -3175,8 +3416,9 @@ |
cpi->total_byte_count += (*size); |
cpi->projected_frame_size = (*size) << 3; |
+ // Post encode loop adjustment of Q prediction. |
if (!active_worst_qchanged) |
- vp9_update_rate_correction_factors(cpi, 2); |
+ vp9_update_rate_correction_factors(cpi, (cpi->sf.recode_loop) ? 2 : 0); |
cpi->last_q[cm->frame_type] = cm->base_qindex; |
@@ -3199,9 +3441,11 @@ |
// Keep a record of ambient average Q. |
if (cm->frame_type != KEY_FRAME) |
- cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex + cm->base_qindex) >> 2; |
+ cpi->avg_frame_qindex = (2 + 3 * cpi->avg_frame_qindex + |
+ cm->base_qindex) >> 2; |
- // Keep a record from which we can calculate the average Q excluding GF updates and key frames |
+ // Keep a record from which we can calculate the average Q excluding GF |
+ // updates and key frames. |
if (cm->frame_type != KEY_FRAME && |
!cpi->refresh_golden_frame && |
!cpi->refresh_alt_ref_frame) { |
@@ -3219,7 +3463,8 @@ |
if (!cm->show_frame) |
cpi->bits_off_target -= cpi->projected_frame_size; |
else |
- cpi->bits_off_target += cpi->av_per_frame_bandwidth - cpi->projected_frame_size; |
+ cpi->bits_off_target += cpi->av_per_frame_bandwidth - |
+ cpi->projected_frame_size; |
// Clip the buffer level at the maximum buffer size |
if (cpi->bits_off_target > cpi->oxcf.maximum_buffer_size) |
@@ -3243,125 +3488,30 @@ |
cpi->total_actual_bits += cpi->projected_frame_size; |
// Debug stats |
- cpi->total_target_vs_actual += (cpi->this_frame_target - cpi->projected_frame_size); |
+ cpi->total_target_vs_actual += (cpi->this_frame_target - |
+ cpi->projected_frame_size); |
cpi->buffer_level = cpi->bits_off_target; |
- // Update bits left to the kf and gf groups to account for overshoot or undershoot on these frames |
+#ifndef DISABLE_RC_LONG_TERM_MEM |
+ // Update bits left to the kf and gf groups to account for overshoot or |
+ // undershoot on these frames |
if (cm->frame_type == KEY_FRAME) { |
- cpi->twopass.kf_group_bits += cpi->this_frame_target - cpi->projected_frame_size; |
+ cpi->twopass.kf_group_bits += cpi->this_frame_target - |
+ cpi->projected_frame_size; |
cpi->twopass.kf_group_bits = MAX(cpi->twopass.kf_group_bits, 0); |
} else if (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) { |
- cpi->twopass.gf_group_bits += cpi->this_frame_target - cpi->projected_frame_size; |
+ cpi->twopass.gf_group_bits += cpi->this_frame_target - |
+ cpi->projected_frame_size; |
cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0); |
} |
- |
- // Update the skip mb flag probabilities based on the distribution seen |
- // in this frame. |
- // update_base_skip_probs(cpi); |
- |
-#if CONFIG_INTERNAL_STATS |
- { |
- FILE *f = fopen("tmp.stt", cm->current_video_frame ? "a" : "w"); |
- int recon_err; |
- |
- vp9_clear_system_state(); // __asm emms; |
- |
- recon_err = vp9_calc_ss_err(cpi->Source, |
- &cm->yv12_fb[cm->new_fb_idx]); |
- |
- if (cpi->twopass.total_left_stats.coded_error != 0.0) |
- fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d" |
- "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f" |
- "%6d %6d %5d %5d %5d %8.2f %10d %10.3f" |
- "%10.3f %8d %10d %10d %10d\n", |
- cpi->common.current_video_frame, cpi->this_frame_target, |
- cpi->projected_frame_size, 0, //loop_size_estimate, |
- (cpi->projected_frame_size - cpi->this_frame_target), |
- (int)cpi->total_target_vs_actual, |
- (int)(cpi->oxcf.starting_buffer_level - cpi->bits_off_target), |
- (int)cpi->total_actual_bits, |
- cm->base_qindex, |
- vp9_convert_qindex_to_q(cm->base_qindex), |
- (double)vp9_dc_quant(cm->base_qindex, 0) / 4.0, |
- vp9_convert_qindex_to_q(cpi->active_best_quality), |
- vp9_convert_qindex_to_q(cpi->active_worst_quality), |
- cpi->avg_q, |
- vp9_convert_qindex_to_q(cpi->ni_av_qi), |
- vp9_convert_qindex_to_q(cpi->cq_target_quality), |
- cpi->refresh_last_frame, |
- cpi->refresh_golden_frame, cpi->refresh_alt_ref_frame, |
- cm->frame_type, cpi->gfu_boost, |
- cpi->twopass.est_max_qcorrection_factor, |
- (int)cpi->twopass.bits_left, |
- cpi->twopass.total_left_stats.coded_error, |
- (double)cpi->twopass.bits_left / |
- cpi->twopass.total_left_stats.coded_error, |
- cpi->tot_recode_hits, recon_err, cpi->kf_boost, |
- cpi->kf_zeromotion_pct); |
- else |
- fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d" |
- "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f" |
- "%5d %5d %5d %8d %8d %8.2f %10d %10.3f" |
- "%8d %10d %10d %10d\n", |
- cpi->common.current_video_frame, |
- cpi->this_frame_target, cpi->projected_frame_size, |
- 0, //loop_size_estimate, |
- (cpi->projected_frame_size - cpi->this_frame_target), |
- (int)cpi->total_target_vs_actual, |
- (int)(cpi->oxcf.starting_buffer_level - cpi->bits_off_target), |
- (int)cpi->total_actual_bits, |
- cm->base_qindex, |
- vp9_convert_qindex_to_q(cm->base_qindex), |
- (double)vp9_dc_quant(cm->base_qindex, 0) / 4.0, |
- vp9_convert_qindex_to_q(cpi->active_best_quality), |
- vp9_convert_qindex_to_q(cpi->active_worst_quality), |
- cpi->avg_q, |
- vp9_convert_qindex_to_q(cpi->ni_av_qi), |
- vp9_convert_qindex_to_q(cpi->cq_target_quality), |
- cpi->refresh_last_frame, |
- cpi->refresh_golden_frame, cpi->refresh_alt_ref_frame, |
- cm->frame_type, cpi->gfu_boost, |
- cpi->twopass.est_max_qcorrection_factor, |
- (int)cpi->twopass.bits_left, |
- cpi->twopass.total_left_stats.coded_error, |
- cpi->tot_recode_hits, recon_err, cpi->kf_boost, |
- cpi->kf_zeromotion_pct); |
- |
- fclose(f); |
- |
- if (0) { |
- FILE *fmodes = fopen("Modes.stt", "a"); |
- int i; |
- |
- fprintf(fmodes, "%6d:%1d:%1d:%1d ", |
- cpi->common.current_video_frame, |
- cm->frame_type, cpi->refresh_golden_frame, |
- cpi->refresh_alt_ref_frame); |
- |
- for (i = 0; i < MAX_MODES; i++) |
- fprintf(fmodes, "%5d ", cpi->mode_chosen_counts[i]); |
- |
- fprintf(fmodes, "\n"); |
- |
- fclose(fmodes); |
- } |
- } |
- |
#endif |
#if 0 |
- // Debug stats for segment feature experiments. |
- print_seg_map(cpi); |
+ output_frame_level_debug_stats(cpi); |
#endif |
- |
- // If this was a kf or Gf note the Q |
- if ((cm->frame_type == KEY_FRAME) |
- || cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame) |
- cm->last_kf_gf_q = cm->base_qindex; |
- |
if (cpi->refresh_golden_frame == 1) |
cm->frame_flags = cm->frame_flags | FRAMEFLAGS_GOLDEN; |
else |
@@ -3440,7 +3590,8 @@ |
#endif |
} |
- // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas. |
+ // Clear the one shot update flags for segmentation map and mode/ref loop |
+ // filter deltas. |
cm->seg.update_map = 0; |
cm->seg.update_data = 0; |
cm->lf.mode_ref_delta_update = 0; |
@@ -3464,6 +3615,9 @@ |
cm->mi = cm->mip + cm->mode_info_stride + 1; |
cm->mi_grid_visible = cm->mi_grid_base + cm->mode_info_stride + 1; |
+ cpi->mb.e_mbd.mi_8x8 = cm->mi_grid_visible; |
+ cpi->mb.e_mbd.mi_8x8[0] = cm->mi; |
+ |
// Don't increment frame counters if this was an altref buffer |
// update not a real frame |
++cm->current_video_frame; |
@@ -3472,28 +3626,10 @@ |
// restore prev_mi |
cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1; |
cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1; |
- |
- #if 0 |
- { |
- char filename[512]; |
- FILE *recon_file; |
- sprintf(filename, "enc%04d.yuv", (int) cm->current_video_frame); |
- recon_file = fopen(filename, "wb"); |
- fwrite(cm->yv12_fb[cm->ref_frame_map[cpi->lst_fb_idx]].buffer_alloc, |
- cm->yv12_fb[cm->ref_frame_map[cpi->lst_fb_idx]].frame_size, |
- 1, recon_file); |
- fclose(recon_file); |
- } |
-#endif |
-#ifdef OUTPUT_YUV_REC |
- vp9_write_yuv_rec_frame(cm); |
-#endif |
- |
} |
static void Pass2Encode(VP9_COMP *cpi, unsigned long *size, |
unsigned char *dest, unsigned int *frame_flags) { |
- |
cpi->enable_encode_breakout = 1; |
if (!cpi->refresh_alt_ref_frame) |
@@ -3510,12 +3646,14 @@ |
if (!cpi->refresh_alt_ref_frame) { |
double lower_bounds_min_rate = FRAME_OVERHEAD_BITS * cpi->oxcf.framerate; |
double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth |
- * cpi->oxcf.two_pass_vbrmin_section / 100); |
+ * cpi->oxcf.two_pass_vbrmin_section |
+ / 100); |
if (two_pass_min_rate < lower_bounds_min_rate) |
two_pass_min_rate = lower_bounds_min_rate; |
- cpi->twopass.bits_left += (int64_t)(two_pass_min_rate / cpi->oxcf.framerate); |
+ cpi->twopass.bits_left += (int64_t)(two_pass_min_rate |
+ / cpi->oxcf.framerate); |
} |
} |
@@ -3589,8 +3727,8 @@ |
cpi->source = NULL; |
- cpi->mb.e_mbd.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV; |
- set_mvcost(&cpi->mb); |
+ cpi->common.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV; |
+ set_mvcost(cpi); |
// Should we code an alternate reference frame. |
if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) { |
@@ -3628,7 +3766,6 @@ |
} |
cm->show_frame = 0; |
- cm->intra_only = 0; |
cpi->refresh_alt_ref_frame = 1; |
cpi->refresh_golden_frame = 0; |
cpi->refresh_last_frame = 0; |
@@ -3650,6 +3787,7 @@ |
#endif |
if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) { |
cm->show_frame = 1; |
+ cm->intra_only = 0; |
#if CONFIG_MULTIPLE_ARF |
// Is this frame the ARF overlay. |
@@ -3806,7 +3944,7 @@ |
cm->frame_flags = *frame_flags; |
// Reset the frame pointers to the current frame size |
- vp9_realloc_frame_buffer(&cm->yv12_fb[cm->new_fb_idx], |
+ vp9_realloc_frame_buffer(get_frame_new_buffer(cm), |
cm->width, cm->height, |
cm->subsampling_x, cm->subsampling_y, |
VP9BORDERINPIXELS); |
@@ -3817,6 +3955,10 @@ |
vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm); |
+ if (cpi->sf.variance_adaptive_quantization) { |
+ vp9_vaq_init(); |
+ } |
+ |
if (cpi->pass == 1) { |
Pass1Encode(cpi, size, dest, frame_flags); |
} else if (cpi->pass == 2) { |
@@ -3853,7 +3995,6 @@ |
cpi->bytes += *size; |
if (cm->show_frame) { |
- |
cpi->count++; |
if (cpi->b_calculate_psnr) { |
@@ -3963,9 +4104,9 @@ |
vp9_ppflags_t *flags) { |
VP9_COMP *cpi = (VP9_COMP *) comp; |
- if (!cpi->common.show_frame) |
+ if (!cpi->common.show_frame) { |
return -1; |
- else { |
+ } else { |
int ret; |
#if CONFIG_VP9_POSTPROC |
ret = vp9_post_proc_frame(&cpi->common, dest, flags); |