Ejemplo n.º 1
0
static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
                                 int speed, vp9e_tune_content content) {
  VP9_COMMON *const cm = &cpi->common;
  const int is_keyframe = cm->frame_type == KEY_FRAME;
  const int frames_since_key = is_keyframe ? 0 : cpi->rc.frames_since_key;
  sf->static_segmentation = 0;
  sf->adaptive_rd_thresh = 1;
  sf->use_fast_coef_costing = 1;
  sf->allow_exhaustive_searches = 0;
  sf->exhaustive_searches_thresh = INT_MAX;

  if (speed >= 1) {
    sf->txfm_domain_distortion = 1;
    sf->quant_coeff_opt = 0;
    sf->use_square_partition_only = !frame_is_intra_only(cm);
    sf->less_rectangular_check = 1;
    sf->tx_size_search_method = frame_is_intra_only(cm) ? USE_FULL_RD
                                                        : USE_LARGESTALL;

    sf->use_rd_breakout = 1;

    sf->adaptive_motion_search = 1;
    sf->adaptive_pred_interp_filter = 1;
    sf->mv.auto_mv_step_size = 1;
    sf->adaptive_rd_thresh = 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->mode_search_skip_flags = (cm->frame_type == KEY_FRAME) ? 0 :
                                 FLAG_SKIP_INTRA_DIRMISMATCH |
                                 FLAG_SKIP_INTRA_BESTINTER |
                                 FLAG_SKIP_COMP_BESTINTRA |
                                 FLAG_SKIP_INTRA_LOWVAR;
    sf->adaptive_pred_interp_filter = 2;

    // Reference masking only enabled for 1 spatial layer, and if none of the
    // references have been scaled. The latter condition needs to be checked
    // for external or internal dynamic resize.
    sf->reference_masking = (cpi->svc.number_spatial_layers == 1);
    if (sf->reference_masking == 1 &&
        (cpi->external_resize == 1 ||
         cpi->oxcf.resize_mode == RESIZE_DYNAMIC)) {
      MV_REFERENCE_FRAME ref_frame;
      static const int flag_list[4] =
          {0, VP9_LAST_FLAG, VP9_GOLD_FLAG, VP9_ALT_FLAG};
      for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
        const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, ref_frame);
        if (yv12 != NULL && (cpi->ref_frame_flags & flag_list[ref_frame])) {
          const struct scale_factors *const scale_fac =
              &cm->frame_refs[ref_frame - 1].sf;
          if (vp9_is_scaled(scale_fac))
            sf->reference_masking = 0;
        }
      }
    }

    sf->disable_filter_search_var_thresh = 50;
    sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
    sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
    sf->lf_motion_threshold = LOW_MOTION_THRESHOLD;
    sf->adjust_partitioning_from_last_frame = 1;
    sf->last_partitioning_redo_frequency = 3;
    sf->use_lp32x32fdct = 1;
    sf->mode_skip_start = 11;
    sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
  }

  if (speed >= 3) {
    sf->use_square_partition_only = 1;
    sf->disable_filter_search_var_thresh = 100;
    sf->use_uv_intra_rd_estimate = 1;
    sf->skip_encode_sb = 1;
    sf->mv.subpel_iters_per_step = 1;
    sf->adaptive_rd_thresh = 4;
    sf->mode_skip_start = 6;
    sf->allow_skip_recode = 0;
    sf->optimize_coefficients = 0;
    sf->disable_split_mask = DISABLE_ALL_SPLIT;
    sf->lpf_pick = LPF_PICK_FROM_Q;
  }

  if (speed >= 4) {
    int i;
    sf->last_partitioning_redo_frequency = 4;
    sf->adaptive_rd_thresh = 5;
    sf->use_fast_coef_costing = 0;
    sf->auto_min_max_partition_size = STRICT_NEIGHBORING_MIN_MAX;
    sf->adjust_partitioning_from_last_frame =
        cm->last_frame_type != cm->frame_type || (0 ==
        (frames_since_key + 1) % sf->last_partitioning_redo_frequency);
    sf->mv.subpel_force_stop = 1;
    for (i = 0; i < TX_SIZES; i++) {
      sf->intra_y_mode_mask[i] = INTRA_DC_H_V;
      sf->intra_uv_mode_mask[i] = INTRA_DC;
    }
    sf->intra_y_mode_mask[TX_32X32] = INTRA_DC;
    sf->frame_parameter_update = 0;
    sf->mv.search_method = FAST_HEX;

    sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEAR_NEW;
    sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST;
    sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST;
    sf->inter_mode_mask[BLOCK_64X64] = INTER_NEAREST;
    sf->max_intra_bsize = BLOCK_32X32;
    sf->allow_skip_recode = 1;
  }

  if (speed >= 5) {
    sf->use_quant_fp = !is_keyframe;
    sf->auto_min_max_partition_size = is_keyframe ? RELAXED_NEIGHBORING_MIN_MAX
                                                  : STRICT_NEIGHBORING_MIN_MAX;
    sf->default_max_partition_size = BLOCK_32X32;
    sf->default_min_partition_size = BLOCK_8X8;
    sf->force_frame_boost = is_keyframe ||
        (frames_since_key % (sf->last_partitioning_redo_frequency << 1) == 1);
    sf->max_delta_qindex = is_keyframe ? 20 : 15;
    sf->partition_search_type = REFERENCE_PARTITION;
    sf->use_nonrd_pick_mode = 1;
    sf->allow_skip_recode = 0;
    sf->inter_mode_mask[BLOCK_32X32] = INTER_NEAREST_NEW_ZERO;
    sf->inter_mode_mask[BLOCK_32X64] = INTER_NEAREST_NEW_ZERO;
    sf->inter_mode_mask[BLOCK_64X32] = INTER_NEAREST_NEW_ZERO;
    sf->inter_mode_mask[BLOCK_64X64] = INTER_NEAREST_NEW_ZERO;
    sf->adaptive_rd_thresh = 2;
    // This feature is only enabled when partition search is disabled.
    sf->reuse_inter_pred_sby = 1;
    sf->partition_search_breakout_rate_thr = 200;
    sf->coeff_prob_appx_step = 4;
    sf->use_fast_coef_updates = is_keyframe ? TWO_LOOP : ONE_LOOP_REDUCED;
    sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH;
    sf->tx_size_search_method = is_keyframe ? USE_LARGESTALL : USE_TX_8X8;
    sf->simple_model_rd_from_var = 1;
    if (cpi->oxcf.rc_mode == VPX_VBR)
      sf->mv.search_method = NSTEP;

    if (!is_keyframe) {
      int i;
      if (content == VP9E_CONTENT_SCREEN) {
        for (i = 0; i < BLOCK_SIZES; ++i)
          sf->intra_y_mode_bsize_mask[i] = INTRA_DC_TM_H_V;
      } else {
        for (i = 0; i < BLOCK_SIZES; ++i)
          if (i > BLOCK_16X16)
            sf->intra_y_mode_bsize_mask[i] = INTRA_DC;
          else
            // Use H and V intra mode for block sizes <= 16X16.
            sf->intra_y_mode_bsize_mask[i] = INTRA_DC_H_V;
      }
    }
    if (content == VP9E_CONTENT_SCREEN) {
      sf->short_circuit_flat_blocks = 1;
    }
  }

  if (speed >= 6) {
    sf->partition_search_type = VAR_BASED_PARTITION;
    // Turn on this to use non-RD key frame coding mode.
    sf->use_nonrd_pick_mode = 1;
    sf->mv.search_method = NSTEP;
    sf->mv.reduce_first_step_size = 1;
    sf->skip_encode_sb = 0;
    if (!cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR &&
        content != VP9E_CONTENT_SCREEN) {
      // Enable short circuit for low temporal variance.
      sf->short_circuit_low_temp_var = 1;
    }
  }

  if (speed >= 7) {
    sf->adaptive_rd_thresh = 3;
    sf->mv.search_method = FAST_DIAMOND;
    sf->mv.fullpel_search_step_param = 10;
    if (cpi->svc.number_temporal_layers > 2 &&
        cpi->svc.temporal_layer_id == 0) {
      sf->mv.search_method = NSTEP;
      sf->mv.fullpel_search_step_param = 6;
    }
  }
  if (speed >= 8) {
    sf->adaptive_rd_thresh = 4;
    sf->mv.subpel_force_stop = (content == VP9E_CONTENT_SCREEN) ? 3 : 2;
    sf->lpf_pick = LPF_PICK_MINIMAL_LPF;
    // Only keep INTRA_DC mode for speed 8.
    if (!is_keyframe) {
      int i = 0;
      for (i = 0; i < BLOCK_SIZES; ++i)
        sf->intra_y_mode_bsize_mask[i] = INTRA_DC;
    }
    if (!cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR &&
        content != VP9E_CONTENT_SCREEN) {
      // More aggressive short circuit for speed 8.
      sf->short_circuit_low_temp_var = 2;
    }
  }
}
Ejemplo n.º 2
0
void vp9_setup_scale_factors_for_frame(struct scale_factors *sf,
                                       int other_w, int other_h,
                                       int this_w, int this_h) {
  if (!check_scale_factors(other_w, other_h, this_w, this_h)) {
    sf->x_scale_fp = REF_INVALID_SCALE;
    sf->y_scale_fp = REF_INVALID_SCALE;
    return;
  }

  sf->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
  sf->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);
  sf->x_step_q4 = scaled_x(16, sf);
  sf->y_step_q4 = scaled_y(16, sf);

  if (vp9_is_scaled(sf)) {
    sf->scale_value_x = scaled_x;
    sf->scale_value_y = scaled_y;
  } else {
    sf->scale_value_x = unscaled_value;
    sf->scale_value_y = unscaled_value;
  }

  // TODO(agrange): Investigate the best choice of functions to use here
  // for EIGHTTAP_SMOOTH. Since it is not interpolating, need to choose what
  // to do at full-pel offsets. The current selection, where the filter is
  // applied in one direction only, and not at all for 0,0, seems to give the
  // best quality, but it may be worth trying an additional mode that does
  // do the filtering on full-pel.
  if (sf->x_step_q4 == 16) {
    if (sf->y_step_q4 == 16) {
      // No scaling in either direction.
      sf->predict[0][0][0] = vp9_convolve_copy;
      sf->predict[0][0][1] = vp9_convolve_avg;
      sf->predict[0][1][0] = vp9_convolve8_vert;
      sf->predict[0][1][1] = vp9_convolve8_avg_vert;
      sf->predict[1][0][0] = vp9_convolve8_horiz;
      sf->predict[1][0][1] = vp9_convolve8_avg_horiz;
    } else {
      // No scaling in x direction. Must always scale in the y direction.
      sf->predict[0][0][0] = vp9_convolve8_vert;
      sf->predict[0][0][1] = vp9_convolve8_avg_vert;
      sf->predict[0][1][0] = vp9_convolve8_vert;
      sf->predict[0][1][1] = vp9_convolve8_avg_vert;
      sf->predict[1][0][0] = vp9_convolve8;
      sf->predict[1][0][1] = vp9_convolve8_avg;
    }
  } else {
    if (sf->y_step_q4 == 16) {
      // No scaling in the y direction. Must always scale in the x direction.
      sf->predict[0][0][0] = vp9_convolve8_horiz;
      sf->predict[0][0][1] = vp9_convolve8_avg_horiz;
      sf->predict[0][1][0] = vp9_convolve8;
      sf->predict[0][1][1] = vp9_convolve8_avg;
      sf->predict[1][0][0] = vp9_convolve8_horiz;
      sf->predict[1][0][1] = vp9_convolve8_avg_horiz;
    } else {
      // Must always scale in both directions.
      sf->predict[0][0][0] = vp9_convolve8;
      sf->predict[0][0][1] = vp9_convolve8_avg;
      sf->predict[0][1][0] = vp9_convolve8;
      sf->predict[0][1][1] = vp9_convolve8_avg;
      sf->predict[1][0][0] = vp9_convolve8;
      sf->predict[1][0][1] = vp9_convolve8_avg;
    }
  }
  // 2D subpel motion always gets filtered in both directions
  sf->predict[1][1][0] = vp9_convolve8;
  sf->predict[1][1][1] = vp9_convolve8_avg;
}