vp9_onyx_if.c 133 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
/*
 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
#include "vpx_config.h"
#include "vp9/common/vp9_filter.h"
#include "vp9/common/vp9_onyxc_int.h"
#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/encoder/vp9_firstpass.h"
#include "vp9/encoder/vp9_psnr.h"
Johann's avatar
Johann committed
#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_segmentation.h"
#include "./vp9_rtcd.h"
#include "./vpx_scale_rtcd.h"
#if CONFIG_VP9_POSTPROC
#include "vp9/common/vp9_postproc.h"
John Koleszar's avatar
John Koleszar committed
#include "vpx_mem/vpx_mem.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"
John Koleszar's avatar
John Koleszar committed
#include <math.h>
#include <stdio.h>
#include <limits.h>

extern void print_tree_update_probs();
static void set_default_lf_deltas(struct loopfilter *lf);
John Koleszar's avatar
John Koleszar committed

Adrian Grange's avatar
Adrian Grange committed
#define DEFAULT_INTERP_FILTER SWITCHABLE

#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 */
#if CONFIG_INTERNAL_STATS
John Koleszar's avatar
John Koleszar committed
#include "math.h"

extern double vp9_calc_ssim(YV12_BUFFER_CONFIG *source,
                            YV12_BUFFER_CONFIG *dest, int lumamask,
                            double *weight);
John Koleszar's avatar
John Koleszar committed

extern double vp9_calc_ssimg(YV12_BUFFER_CONFIG *source,
                             YV12_BUFFER_CONFIG *dest, double *ssim_y,
                             double *ssim_u, double *ssim_v);
John Koleszar's avatar
John Koleszar committed
// #define OUTPUT_YUV_REC
John Koleszar's avatar
John Koleszar committed

#ifdef OUTPUT_YUV_SRC
FILE *yuv_file;
#endif
#ifdef OUTPUT_YUV_REC
FILE *yuv_rec_file;
#endif
John Koleszar's avatar
John Koleszar committed

#if 0
FILE *framepsnr;
Yaowu Xu's avatar
Yaowu Xu committed
FILE *kf_list;
John Koleszar's avatar
John Koleszar committed
FILE *keyfile;
#endif


#ifdef ENTROPY_STATS
extern int intra_mode_stats[INTRA_MODES]
                           [INTRA_MODES]
                           [INTRA_MODES];
John Koleszar's avatar
John Koleszar committed
#endif

#ifdef MODE_STATS
extern void init_tx_count_stats();
extern void write_tx_count_stats();
extern void init_switchable_interp_stats();
extern void write_switchable_interp_stats();
John Koleszar's avatar
John Koleszar committed
#ifdef SPEEDSTATS
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)
extern unsigned __int64 Sectionbits[500];
#endif
extern void vp9_init_quantizer(VP9_COMP *cpi);
// Tables relating active max Q to active min Q
static int kf_low_motion_minq[QINDEX_RANGE];
static int kf_high_motion_minq[QINDEX_RANGE];
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) {
    case NORMAL:
      *hr = 1;
      *hs = 1;
      break;
    case FOURFIVE:
      *hr = 4;
      *hs = 5;
      break;
    case THREEFIVE:
      *hr = 3;
      *hs = 5;
    break;
    case ONETWO:
      *hr = 1;
      *hs = 2;
    break;
    default:
      *hr = 1;
      *hs = 1;
       assert(0);
      break;
  }
}

// Functions to compute the active minq lookup table entries based on a
// formulaic approach to facilitate easier adjustment of the Q tables.
// The formulae were derived from computing a 3rd order polynomial best
// fit to the original data (after plotting real maxq vs minq (not q index))
static int calculate_minq_index(double maxq,
Dmitry Kovalev's avatar
Dmitry Kovalev committed
                                double x3, double x2, double x1, double c) {
John Koleszar's avatar
John Koleszar committed
  int i;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  const double minqtarget = MIN(((x3 * maxq + x2) * maxq + x1) * maxq + c,
                                maxq);
John Koleszar's avatar
John Koleszar committed

Paul Wilkins's avatar
Paul Wilkins committed
  // Special case handling to deal with the step from q2.0
  // down to lossless mode represented by q 1.0.
  if (minqtarget <= 2.0)
    return 0;

John Koleszar's avatar
John Koleszar committed
  for (i = 0; i < QINDEX_RANGE; i++) {
    if (minqtarget <= vp9_convert_qindex_to_q(i))
John Koleszar's avatar
John Koleszar committed
      return i;
  }
John Koleszar's avatar
John Koleszar committed
  return QINDEX_RANGE - 1;
John Koleszar's avatar
John Koleszar committed
  int i;

  for (i = 0; i < QINDEX_RANGE; i++) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
    const double maxq = vp9_convert_qindex_to_q(i);
John Koleszar's avatar
John Koleszar committed


    kf_low_motion_minq[i] = calculate_minq_index(maxq,
                                                 0.000001,
                                                 -0.0004,
                                                 0.15,
John Koleszar's avatar
John Koleszar committed
                                                 0.0);
    kf_high_motion_minq[i] = calculate_minq_index(maxq,
                                                  0.000002,
                                                  -0.0012,
                                                  0.5,
John Koleszar's avatar
John Koleszar committed
                                                  0.0);
John Koleszar's avatar
John Koleszar committed
    gf_low_motion_minq[i] = calculate_minq_index(maxq,
                                                 0.0000015,
                                                 -0.0009,
John Koleszar's avatar
John Koleszar committed
                                                 0.0);
    gf_high_motion_minq[i] = calculate_minq_index(maxq,
                                                  0.0000021,
                                                  -0.00125,
John Koleszar's avatar
John Koleszar committed
                                                  0.0);
    inter_minq[i] = calculate_minq_index(maxq,
                                         0.00000271,
                                         -0.00113,
John Koleszar's avatar
John Koleszar committed
                                         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,
John Koleszar's avatar
John Koleszar committed
  }
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) {
    mb->mvcost = mb->nmvcost_hp;
    mb->mvsadcost = mb->nmvsadcost_hp;
  } else {
    mb->mvcost = mb->nmvcost;
    mb->mvsadcost = mb->nmvsadcost;
  }
}
John Koleszar's avatar
John Koleszar committed
  static int init_done = 0;

  if (!init_done) {
    vp9_initialize_common();
    vp9_init_quant_tables();
John Koleszar's avatar
John Koleszar committed
    init_minq_luts();
Deb Mukherjee's avatar
Deb Mukherjee committed
    // init_base_skip_probs();
John Koleszar's avatar
John Koleszar committed
    init_done = 1;
  }
static void setup_features(VP9_COMMON *cm) {
  struct loopfilter *const lf = &cm->lf;
  struct segmentation *const seg = &cm->seg;
John Koleszar's avatar
John Koleszar committed
  // Set up default state for MB feature flags
  seg->update_map = 0;
  seg->update_data = 0;
  vpx_memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
  vp9_clearall_segfeatures(seg);
  lf->mode_ref_delta_enabled = 0;
  lf->mode_ref_delta_update = 0;
  vp9_zero(lf->ref_deltas);
  vp9_zero(lf->mode_deltas);
  vp9_zero(lf->last_ref_deltas);
  vp9_zero(lf->last_mode_deltas);
  set_default_lf_deltas(lf);
static void dealloc_compressor_data(VP9_COMP *cpi) {
John Koleszar's avatar
John Koleszar committed
  // Delete sementation map
  vpx_free(cpi->segmentation_map);
  cpi->segmentation_map = 0;
  vpx_free(cpi->common.last_frame_seg_map);
  cpi->common.last_frame_seg_map = 0;
  vpx_free(cpi->coding_context.last_frame_seg_map_copy);
  cpi->coding_context.last_frame_seg_map_copy = 0;
John Koleszar's avatar
John Koleszar committed
  vpx_free(cpi->active_map);
  cpi->active_map = 0;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  vp9_free_frame_buffers(&cpi->common);
  vp9_free_frame_buffer(&cpi->last_frame_uf);
  vp9_free_frame_buffer(&cpi->scaled_source);
  vp9_free_frame_buffer(&cpi->alt_ref_buffer);
  vp9_lookahead_destroy(cpi->lookahead);
John Koleszar's avatar
John Koleszar committed
  vpx_free(cpi->tok);
  cpi->tok = 0;
John Koleszar's avatar
John Koleszar committed
  // Activity mask based per mb zbin adjustments
  vpx_free(cpi->mb_activity_map);
  cpi->mb_activity_map = 0;
  vpx_free(cpi->mb_norm_activity_map);
  cpi->mb_norm_activity_map = 0;
John Koleszar's avatar
John Koleszar committed
  vpx_free(cpi->mb.pip);
  cpi->mb.pip = 0;
// 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) {
John Koleszar's avatar
John Koleszar committed
  int i;
  int start_index = cpi->worst_quality;
  int target_index = cpi->worst_quality;

  // Convert the average q value to an index.
  for (i = cpi->best_quality; i < cpi->worst_quality; i++) {
    start_index = i;
    if (vp9_convert_qindex_to_q(i) >= qstart)
John Koleszar's avatar
John Koleszar committed
      break;
  }

  // Convert the q target to an index
  for (i = cpi->best_quality; i < cpi->worst_quality; i++) {
    target_index = i;
    if (vp9_convert_qindex_to_q(i) >= qtarget)
John Koleszar's avatar
John Koleszar committed
      break;
  }

  return target_index - start_index;
static void configure_static_seg_features(VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;
  struct segmentation *seg = &cm->seg;
John Koleszar's avatar
John Koleszar committed
  int high_q = (int)(cpi->avg_q > 48.0);
  int qi_delta;
John Koleszar's avatar
John Koleszar committed
  // Disable and clear down for KF
  if (cm->frame_type == KEY_FRAME) {
    // Clear down the global segmentation map
    vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
    seg->update_map = 0;
    seg->update_data = 0;
John Koleszar's avatar
John Koleszar committed
    cpi->static_mb_pct = 0;
John Koleszar's avatar
John Koleszar committed
    // Disable segmentation
    vp9_disable_segmentation((VP9_PTR)cpi);
John Koleszar's avatar
John Koleszar committed
    // Clear down the segment features.
    vp9_clearall_segfeatures(seg);
  } else if (cpi->refresh_alt_ref_frame) {
    // If this is an alt ref frame
John Koleszar's avatar
John Koleszar committed
    // Clear down the global segmentation map
    vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
    seg->update_map = 0;
    seg->update_data = 0;
John Koleszar's avatar
John Koleszar committed
    cpi->static_mb_pct = 0;
John Koleszar's avatar
John Koleszar committed
    // Disable segmentation and individual segment features by default
    vp9_disable_segmentation((VP9_PTR)cpi);
    vp9_clearall_segfeatures(seg);
John Koleszar's avatar
John Koleszar committed
    // Scan frames from current to arf frame.
    // This function re-enables segmentation if appropriate.
    vp9_update_mbgraph_stats(cpi);
John Koleszar's avatar
John Koleszar committed
    // If segmentation was enabled set those features needed for the
    // arf itself.
    if (seg->enabled) {
      seg->update_map = 1;
      seg->update_data = 1;
John Koleszar's avatar
John Koleszar committed
      qi_delta = 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);
      vp9_enable_segfeature(seg, 1, SEG_LVL_ALT_Q);
      vp9_enable_segfeature(seg, 1, SEG_LVL_ALT_LF);
John Koleszar's avatar
John Koleszar committed
      // 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

John Koleszar's avatar
John Koleszar committed
    // First normal frame in a valid gf or alt ref group
    if (cpi->frames_since_golden == 0) {
Paul Wilkins's avatar
Paul Wilkins committed
      // Set up segment features for normal frames in an arf group
John Koleszar's avatar
John Koleszar committed
      if (cpi->source_alt_ref_active) {
        seg->update_map = 0;
        seg->update_data = 1;
        seg->abs_delta = SEGMENT_DELTADATA;
John Koleszar's avatar
John Koleszar committed
        qi_delta = 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);
        vp9_set_segdata(seg, 1, SEG_LVL_ALT_LF, -2);
        vp9_enable_segfeature(seg, 1, SEG_LVL_ALT_LF);
John Koleszar's avatar
John Koleszar committed
        // Segment coding disabled for compred testing
        if (high_q || (cpi->static_mb_pct == 100)) {
          vp9_set_segdata(seg, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME);
          vp9_enable_segfeature(seg, 1, SEG_LVL_REF_FRAME);
          vp9_enable_segfeature(seg, 1, SEG_LVL_SKIP);
John Koleszar's avatar
John Koleszar committed
        }
      } else {
        // Disable segmentation and clear down features if alt ref
        // is not active for this group

        vp9_disable_segmentation((VP9_PTR)cpi);
        vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
        seg->update_map = 0;
        seg->update_data = 0;
        vp9_clearall_segfeatures(seg);
John Koleszar's avatar
John Koleszar committed
      }
    } else if (cpi->is_src_frame_alt_ref) {
      // Special case where we are coding over the top of a previous
      // alt ref frame.
      // Segment coding disabled for compred testing
John Koleszar's avatar
John Koleszar committed

Paul Wilkins's avatar
Paul Wilkins committed
      // Enable ref frame features for segment 0 as well
      vp9_enable_segfeature(seg, 0, SEG_LVL_REF_FRAME);
      vp9_enable_segfeature(seg, 1, SEG_LVL_REF_FRAME);
John Koleszar's avatar
John Koleszar committed

Paul Wilkins's avatar
Paul Wilkins committed
      // All mbs should use ALTREF_FRAME
      vp9_clear_segdata(seg, 0, SEG_LVL_REF_FRAME);
      vp9_set_segdata(seg, 0, SEG_LVL_REF_FRAME, ALTREF_FRAME);
      vp9_clear_segdata(seg, 1, SEG_LVL_REF_FRAME);
      vp9_set_segdata(seg, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME);
John Koleszar's avatar
John Koleszar committed

Paul Wilkins's avatar
Paul Wilkins committed
      // Skip all MBs if high Q (0,0 mv and skip coeffs)
John Koleszar's avatar
John Koleszar committed
      if (high_q) {
          vp9_enable_segfeature(seg, 0, SEG_LVL_SKIP);
          vp9_enable_segfeature(seg, 1, SEG_LVL_SKIP);
John Koleszar's avatar
John Koleszar committed
      }
Adrian Grange's avatar
Adrian Grange committed
      // Enable data update
    } else {
      // All other frames.

John Koleszar's avatar
John Koleszar committed
      // No updates.. leave things as they are.
      seg->update_map = 0;
      seg->update_data = 0;
John Koleszar's avatar
John Koleszar committed
    }
  }
Paul Wilkins's avatar
Paul Wilkins committed
#ifdef ENTROPY_STATS
void vp9_update_mode_context_stats(VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;
  int i, j;
  unsigned int (*inter_mode_counts)[INTER_MODES - 1][2] =
      cm->fc.inter_mode_counts;
  int64_t (*mv_ref_stats)[INTER_MODES - 1][2] = cpi->mv_ref_stats;
Paul Wilkins's avatar
Paul Wilkins committed
  FILE *f;

  // Read the past stats counters
  f = fopen("mode_context.bin",  "rb");
  if (!f) {
    vpx_memset(cpi->mv_ref_stats, 0, sizeof(cpi->mv_ref_stats));
  } else {
    fread(cpi->mv_ref_stats, sizeof(cpi->mv_ref_stats), 1, f);
    fclose(f);
  }

  // Add in the values for this frame
  for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
    for (j = 0; j < INTER_MODES - 1; j++) {
      mv_ref_stats[i][j][0] += (int64_t)inter_mode_counts[i][j][0];
      mv_ref_stats[i][j][1] += (int64_t)inter_mode_counts[i][j][1];
Paul Wilkins's avatar
Paul Wilkins committed
    }
  }

  // Write back the accumulated stats
  f = fopen("mode_context.bin",  "wb");
  fwrite(cpi->mv_ref_stats, sizeof(cpi->mv_ref_stats), 1, f);
  fclose(f);
}

void print_mode_context(VP9_COMP *cpi) {
  FILE *f = fopen("vp9_modecont.c", "a");
  int i, j;

  fprintf(f, "#include \"vp9_entropy.h\"\n");
      "const int inter_mode_probs[INTER_MODE_CONTEXTS][INTER_MODES - 1] =");
Paul Wilkins's avatar
Paul Wilkins committed
  fprintf(f, "{\n");
  for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
    fprintf(f, "  {/* %d */ ", j);
    fprintf(f, "    ");
    for (i = 0; i < INTER_MODES - 1; i++) {
Paul Wilkins's avatar
Paul Wilkins committed
      int this_prob;
      int64_t count = cpi->mv_ref_stats[j][i][0] + cpi->mv_ref_stats[j][i][1];
      if (count)
        this_prob = ((cpi->mv_ref_stats[j][i][0] * 256) + (count >> 1)) / count;
      else
        this_prob = 128;

      // context probs
      fprintf(f, "%5d, ", this_prob);
    }
    fprintf(f, "  },\n");
  }

  fprintf(f, "};\n");
  fclose(f);
}
#endif  // ENTROPY_STATS

// DEBUG: Print out the segment id of each MB in the current frame.
static void print_seg_map(VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;
John Koleszar's avatar
John Koleszar committed
  int row, col;
  int map_index = 0;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  FILE *statsfile = fopen("segmap.stt", "a");
Dmitry Kovalev's avatar
Dmitry Kovalev committed
  fprintf(statsfile, "%10d\n", cm->current_video_frame);
  for (row = 0; row < cpi->common.mi_rows; row++) {
    for (col = 0; col < cpi->common.mi_cols; col++) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
      fprintf(statsfile, "%10d", cpi->segmentation_map[map_index]);
John Koleszar's avatar
John Koleszar committed
      map_index++;
    }
    fprintf(statsfile, "\n");
John Koleszar's avatar
John Koleszar committed
  }
  fprintf(statsfile, "\n");
John Koleszar's avatar
John Koleszar committed
  fclose(statsfile);
static void update_reference_segmentation_map(VP9_COMP *cpi) {
  VP9_COMMON *const cm = &cpi->common;
  int row, col;
  MODE_INFO **mi_8x8, **mi_8x8_ptr = cm->mi_grid_visible;
  uint8_t *cache_ptr = cm->last_frame_seg_map, *cache;

  for (row = 0; row < cm->mi_rows; row++) {
    mi_8x8 = mi_8x8_ptr;
    cache = cache_ptr;
    for (col = 0; col < cm->mi_cols; col++, mi_8x8++, cache++)
      cache[0] = mi_8x8[0]->mbmi.segment_id;
    mi_8x8_ptr += cm->mode_info_stride;
    cache_ptr += cm->mi_cols;
static void set_default_lf_deltas(struct loopfilter *lf) {
  lf->mode_ref_delta_enabled = 1;
  lf->mode_ref_delta_update = 1;

  vp9_zero(lf->ref_deltas);
  vp9_zero(lf->mode_deltas);
John Koleszar's avatar
John Koleszar committed
  // Test of ref frame deltas
  lf->ref_deltas[INTRA_FRAME] = 2;
  lf->ref_deltas[LAST_FRAME] = 0;
  lf->ref_deltas[GOLDEN_FRAME] = -2;
  lf->ref_deltas[ALTREF_FRAME] = -2;
  lf->mode_deltas[0] = 0;   // Zero
  lf->mode_deltas[1] = 0;   // New mv
static void set_rd_speed_thresholds(VP9_COMP *cpi, int mode) {
  SPEED_FEATURES *sf = &cpi->sf;
  int i;

  // Set baseline threshold values
  for (i = 0; i < MAX_MODES; ++i)
    sf->thresh_mult[i] = mode == 0 ? -500 : 0;

  sf->thresh_mult[THR_NEARESTMV] = 0;
  sf->thresh_mult[THR_NEARESTG] = 0;
  sf->thresh_mult[THR_NEARESTA] = 0;

  sf->thresh_mult[THR_DC] += 1000;

Paul Wilkins's avatar
Paul Wilkins committed
  sf->thresh_mult[THR_NEWMV] += 1000;
  sf->thresh_mult[THR_NEWA] += 1000;
Paul Wilkins's avatar
Paul Wilkins committed
  sf->thresh_mult[THR_NEWG] += 1000;

  sf->thresh_mult[THR_NEARMV] += 1000;
  sf->thresh_mult[THR_NEARA] += 1000;
Paul Wilkins's avatar
Paul Wilkins committed
  sf->thresh_mult[THR_COMP_NEARESTLA] += 1000;
  sf->thresh_mult[THR_COMP_NEARESTGA] += 1000;

  sf->thresh_mult[THR_TM] += 1000;

  sf->thresh_mult[THR_COMP_NEARLA] += 1500;
  sf->thresh_mult[THR_COMP_NEWLA] += 2000;
  sf->thresh_mult[THR_NEARG] += 1000;
  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;
  sf->thresh_mult[THR_D135_PRED] += 2500;
  sf->thresh_mult[THR_D117_PRED] += 2500;
  sf->thresh_mult[THR_D153_PRED] += 2500;
  sf->thresh_mult[THR_D207_PRED] += 2500;
  sf->thresh_mult[THR_D63_PRED] += 2500;
  /* disable frame modes if flags not set */
  if (!(cpi->ref_frame_flags & VP9_LAST_FLAG)) {
    sf->thresh_mult[THR_NEWMV    ] = INT_MAX;
    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)) !=
      (VP9_LAST_FLAG | VP9_ALT_FLAG)) {
    sf->thresh_mult[THR_COMP_ZEROLA   ] = INT_MAX;
    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)) {
    sf->thresh_mult[THR_COMP_ZEROGA   ] = INT_MAX;
    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;

    sf->thresh_mult[THR_COMP_SPLITLA  ] = INT_MAX;
    sf->thresh_mult[THR_COMP_SPLITGA  ] = INT_MAX;
  }
void vp9_set_speed_features(VP9_COMP *cpi) {
John Koleszar's avatar
John Koleszar committed
  SPEED_FEATURES *sf = &cpi->sf;
  int mode = cpi->compressor_speed;
  int speed = cpi->speed;
John Koleszar's avatar
John Koleszar committed
  int i;
John Koleszar's avatar
John Koleszar committed
  // Only modes 0 and 1 supported for now in experimental code basae
  if (mode > 1)
    mode = 1;
John Koleszar's avatar
John Koleszar committed

  for (i = 0; i < MAX_MODES; ++i)
John Koleszar's avatar
John Koleszar committed
    cpi->mode_chosen_counts[i] = 0;

  // best quality defaults
  sf->RD = 1;
  sf->search_method = NSTEP;
  sf->auto_filter = 1;
  sf->recode_loop = 1;
  sf->subpel_search_method = SUBPEL_TREE;
  sf->subpel_iters_per_step = 2;
  sf->optimize_coefficients = !cpi->oxcf.lossless;
  sf->reduce_first_step_size = 0;
  sf->auto_mv_step_size = 0;
John Koleszar's avatar
John Koleszar committed
  sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
  sf->comp_inter_joint_search_thresh = BLOCK_4X4;
  sf->adaptive_rd_thresh = 0;
Paul Wilkins's avatar
Paul Wilkins committed
  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->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->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->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;
  sf->use_rd_breakout = 0;
  sf->skip_encode_sb = 0;
  sf->use_uv_intra_rd_estimate = 0;
  sf->use_fast_lpf_pick = 0;
  sf->use_fast_coef_updates = 0;
  sf->using_small_partition_info = 0;
  sf->mode_skip_start = MAX_MODES;  // Mode index at which mode skip mask set

#if CONFIG_MULTIPLE_ARF
  // Switch segmentation off.
  sf->static_segmentation = 0;
#else
  sf->static_segmentation = 0;
  switch (mode) {
John Koleszar's avatar
John Koleszar committed
    case 0: // best quality mode
John Koleszar's avatar
John Koleszar committed
      break;

#if CONFIG_MULTIPLE_ARF
      // Switch segmentation off.
      sf->static_segmentation = 0;
Paul Wilkins's avatar
Paul Wilkins committed
      sf->static_segmentation = 0;
      sf->use_avoid_tested_higherror = 1;
Paul Wilkins's avatar
Paul Wilkins committed
      sf->adaptive_rd_thresh = 1;
      if (speed == 1) {
Paul Wilkins's avatar
Paul Wilkins committed
        sf->use_square_partition_only = !(cpi->common.frame_type == KEY_FRAME ||
                                          cpi->common.intra_only);
        sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
Paul Wilkins's avatar
Paul Wilkins committed
                                      cpi->common.intra_only)
                                     ? USE_FULL_RD : USE_LARGESTALL);
        sf->disable_splitmv =
          (MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;

        sf->use_rd_breakout = 1;
        sf->adaptive_motion_search = 1;
        sf->auto_mv_step_size = 1;
        sf->adaptive_rd_thresh = 2;
      }
      if (speed == 2) {
        sf->use_square_partition_only = !(cpi->common.frame_type == KEY_FRAME ||
Paul Wilkins's avatar
Paul Wilkins committed
                                          cpi->common.intra_only);
        sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
                                      cpi->common.intra_only)
                                     ? USE_FULL_RD : USE_LARGESTALL);
        sf->disable_splitmv =
Paul Wilkins's avatar
Paul Wilkins committed
          (MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;

        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;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->comp_inter_joint_search_thresh = BLOCK_SIZES;

        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;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->adaptive_rd_thresh = 2;
        sf->mode_skip_start = 11;
Paul Wilkins's avatar
Paul Wilkins committed
      if (speed == 3) {
        sf->use_square_partition_only = 1;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->tx_size_search_method = USE_LARGESTALL;
        sf->disable_splitmv =
          (MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;

        sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
                                     FLAG_SKIP_INTRA_BESTINTER |
                                     FLAG_SKIP_COMP_BESTINTRA |
Paul Wilkins's avatar
Paul Wilkins committed
                                     FLAG_SKIP_INTRA_LOWVAR;

        sf->use_rd_breakout = 1;
        sf->adaptive_motion_search = 1;
        sf->auto_mv_step_size = 1;
Paul Wilkins's avatar
Paul Wilkins committed

        sf->disable_filter_search_var_thresh = 16;
        sf->comp_inter_joint_search_thresh = BLOCK_SIZES;

        sf->auto_min_max_partition_size = 1;
Paul Wilkins's avatar
Paul Wilkins committed
        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->subpel_iters_per_step = 1;
        sf->use_fast_coef_updates = 2;
Paul Wilkins's avatar
Paul Wilkins committed

        sf->adaptive_rd_thresh = 4;
        sf->mode_skip_start = 6;
Paul Wilkins's avatar
Paul Wilkins committed
      if (speed == 4) {
Paul Wilkins's avatar
Paul Wilkins committed
        sf->less_rectangular_check  = 1;
        sf->use_square_partition_only = 1;
        sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
Paul Wilkins's avatar
Paul Wilkins committed
        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;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->intra_y_mode_mask = INTRA_DC_ONLY;
        sf->intra_uv_mode_mask = INTRA_DC_ONLY;
        sf->use_uv_intra_rd_estimate = 1;
        sf->use_rd_breakout = 1;
        sf->skip_encode_sb = 1;
        sf->use_lp32x32fdct = 1;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->adaptive_motion_search = 1;
        sf->using_small_partition_info = 0;
        sf->disable_splitmv = 1;
        sf->auto_mv_step_size = 1;
        sf->search_method = BIGDIA;
        sf->subpel_iters_per_step = 1;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->use_fast_lpf_pick = 1;
        sf->auto_min_max_partition_size = 1;
        sf->disable_split_var_thresh = 64;
        sf->disable_filter_search_var_thresh = 64;
        sf->use_fast_coef_updates = 2;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->adaptive_rd_thresh = 4;
        sf->mode_skip_start = 6;
Paul Wilkins's avatar
Paul Wilkins committed
      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->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->use_lp32x32fdct = 1;
        sf->optimize_coefficients = 0;
        sf->auto_mv_step_size = 1;
        // sf->reduce_first_step_size = 1;
        // sf->reference_masking = 1;

        sf->disable_splitmv = 1;
        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;
        sf->use_fast_coef_updates = 2;
Paul Wilkins's avatar
Paul Wilkins committed
        sf->adaptive_rd_thresh = 4;
        sf->mode_skip_start = 6;
John Koleszar's avatar
John Koleszar committed
  }; /* switch */
  // Set rd thresholds based on mode and speed setting
  set_rd_speed_thresholds(cpi, mode);
John Koleszar's avatar
John Koleszar committed

  // Slow quant, dct and trellis not worthwhile for first pass
  // so make sure they are always turned off.
  if (cpi->pass == 1) {
    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;
Yaowu Xu's avatar
Yaowu Xu committed
  if (cpi->oxcf.lossless || cpi->mb.e_mbd.lossless) {
    cpi->mb.fwd_txm8x4    = vp9_short_walsh8x4;
    cpi->mb.fwd_txm4x4    = vp9_short_walsh4x4;
John Koleszar's avatar
John Koleszar committed
  }
  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;
  } else if (cpi->sf.subpel_search_method == SUBPEL_TREE) {
    cpi->find_fractional_mv_step = vp9_find_best_sub_pixel_tree;
    cpi->find_fractional_mv_step_comp = vp9_find_best_sub_pixel_comp_tree;
John Koleszar's avatar
John Koleszar committed
  }
  cpi->mb.optimize = cpi->sf.optimize_coefficients == 1 && cpi->pass != 1;
John Koleszar's avatar
John Koleszar committed

#ifdef SPEEDSTATS
  frames_at_speed[cpi->speed]++;
John Koleszar's avatar
John Koleszar committed
#endif
}
static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;

  cpi->lookahead = vp9_lookahead_init(cpi->oxcf.width, cpi->oxcf.height,
                                      cm->subsampling_x, cm->subsampling_y,
John Koleszar's avatar
John Koleszar committed
                                      cpi->oxcf.lag_in_frames);
  if (!cpi->lookahead)
    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                       "Failed to allocate lag buffers");
  if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
                               cpi->oxcf.width, cpi->oxcf.height,
                               cm->subsampling_x, cm->subsampling_y,
                               VP9BORDERINPIXELS))
John Koleszar's avatar
John Koleszar committed
    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                       "Failed to allocate altref buffer");
John Koleszar's avatar
John Koleszar committed
}
static int alloc_partition_data(VP9_COMP *cpi) {
John Koleszar's avatar
John Koleszar committed
  vpx_free(cpi->mb.pip);
  cpi->mb.pip = vpx_calloc(cpi->common.mode_info_stride *
                           (cpi->common.mi_rows + MI_BLOCK_SIZE),
John Koleszar's avatar
John Koleszar committed
                           sizeof(PARTITION_INFO));
  if (!cpi->mb.pip)
    return 1;
John Koleszar's avatar
John Koleszar committed
  cpi->mb.pi = cpi->mb.pip + cpi->common.mode_info_stride + 1;
John Koleszar's avatar
John Koleszar committed
  return 0;
void vp9_alloc_compressor_data(VP9_COMP *cpi) {
  VP9_COMMON *cm = &cpi->common;
  if (vp9_alloc_frame_buffers(cm, cm->width, cm->height))
John Koleszar's avatar
John Koleszar committed
    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                       "Failed to allocate frame buffers");
  if (alloc_partition_data(cpi))
John Koleszar's avatar
John Koleszar committed
    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,
                             VP9BORDERINPIXELS))
John Koleszar's avatar
John Koleszar committed
    vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR,
                       "Failed to allocate last frame buffer");