encodeframe.c 77.3 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.
John Koleszar's avatar
John Koleszar committed
 */


#include "vpx_ports/config.h"
#include "encodemb.h"
#include "encodemv.h"
#include "vp8/common/common.h"
John Koleszar's avatar
John Koleszar committed
#include "onyx_int.h"
#include "vp8/common/extend.h"
#include "vp8/common/entropymode.h"
#include "vp8/common/quant_common.h"
#include "segmentation.h"
#include "vp8/common/setupintrarecon.h"
#include "vp8/common/reconintra4x4.h"
John Koleszar's avatar
John Koleszar committed
#include "encodeintra.h"
#include "vp8/common/reconinter.h"
#include "vp8/common/invtrans.h"
John Koleszar's avatar
John Koleszar committed
#include "rdopt.h"
#include "vp8/common/findnearmv.h"
#include "vp8/common/reconintra.h"
Christian Duvivier's avatar
Christian Duvivier committed
#include "vp8/common/seg_common.h"
#include "vpx_rtcd.h"
John Koleszar's avatar
John Koleszar committed
#include <stdio.h>
#include <math.h>
John Koleszar's avatar
John Koleszar committed
#include <limits.h>
#include "vp8/common/subpixel.h"
John Koleszar's avatar
John Koleszar committed
#include "vpx_ports/vpx_timer.h"
#include "vp8/common/pred_common.h"
John Koleszar's avatar
John Koleszar committed

#define DBG_PRNT_SEGMAP 0
#if CONFIG_NEWBESTREFMV
#include "vp8/common/mvref_common.h"
#endif

John Koleszar's avatar
John Koleszar committed
#if CONFIG_RUNTIME_CPU_DETECT
#define RTCD(x)     &cpi->common.rtcd.x
#define IF_RTCD(x)  (x)
#else
#define RTCD(x)     NULL
#define IF_RTCD(x)  NULL
#endif
#ifdef ENC_DEBUG
John Koleszar's avatar
John Koleszar committed
int enc_debug = 0;
int mb_row_debug, mb_col_debug;
#endif

extern void vp9cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
extern void vp9_auto_select_speed(VP8_COMP *cpi);
John Koleszar's avatar
John Koleszar committed
extern void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
                                      MACROBLOCK *x,
                                      MB_ROW_COMP *mbr_ei,
                                      int mb_row,
                                      int count);
int64_t vp9_rd_pick_inter_mode_sb(VP8_COMP *cpi, MACROBLOCK *x,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
                              int recon_yoffset, int recon_uvoffset,
                              int *returnrate, int *returndistortion);
extern void vp9cx_pick_mode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x,
Adrian Grange's avatar
Adrian Grange committed
                                            int recon_yoffset,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
                                            int recon_uvoffset, int *r, int *d);
void vp9_build_block_offsets(MACROBLOCK *x);
void vp9_setup_block_ptrs(MACROBLOCK *x);
void vp9cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
Adrian Grange's avatar
Adrian Grange committed
                                   int recon_yoffset, int recon_uvoffset,
                                   int output_enabled);
void vp9cx_encode_inter_superblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
                                   int recon_yoffset, int recon_uvoffset, int mb_col, int mb_row);
void vp9cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x,
Adrian Grange's avatar
Adrian Grange committed
                                    TOKENEXTRA **t, int output_enabled);
void vp9cx_encode_intra_super_block(VP8_COMP *cpi,
Ronald S. Bultje's avatar
Ronald S. Bultje committed
                                    MACROBLOCK *x,
                                    TOKENEXTRA **t, int mb_col);
John Koleszar's avatar
John Koleszar committed
static void adjust_act_zbin(VP8_COMP *cpi, MACROBLOCK *x);
John Koleszar's avatar
John Koleszar committed
#ifdef MODE_STATS
unsigned int inter_y_modes[MB_MODE_COUNT];
unsigned int inter_uv_modes[VP8_UV_MODES];
unsigned int inter_b_modes[B_MODE_COUNT];
unsigned int y_modes[VP8_YMODES];
unsigned int i8x8_modes[VP8_I8X8_MODES];
unsigned int uv_modes[VP8_UV_MODES];
unsigned int uv_modes_y[VP8_YMODES][VP8_UV_MODES];
unsigned int b_modes[B_MODE_COUNT];
John Koleszar's avatar
John Koleszar committed
#endif


/* activity_avg must be positive, or flat regions could get a zero weight
 *  (infinite lambda), which confounds analysis.
 * This also avoids the need for divide by zero checks in
 */
#define VP8_ACTIVITY_AVG_MIN (64)

/* This is used as a reference when computing the source variance for the
 *  purposes of activity masking.
 * Eventually this should be replaced by custom no-reference routines,
 *  which will be faster.
 */
John Koleszar's avatar
John Koleszar committed
static const unsigned char VP8_VAR_OFFS[16] = {
  128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128

// Original activity measure from Tim T's code.
John Koleszar's avatar
John Koleszar committed
static unsigned int tt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x) {
  unsigned int act;
  unsigned int sse;
  /* TODO: This could also be done over smaller areas (8x8), but that would
   *  require extensive changes elsewhere, as lambda is assumed to be fixed
   *  over an entire MB in most of the code.
   * Another option is to compute four 8x8 variances, and pick a single
   *  lambda using a non-linear combination (e.g., the smallest, or second
   *  smallest, etc.).
   */
  act = vp9_variance16x16(x->src.y_buffer, x->src.y_stride, VP8_VAR_OFFS, 0,
John Koleszar's avatar
John Koleszar committed
  act = act << 4;

  /* If the region is flat, lower the activity some more. */
  if (act < 8 << 12)
    act = act < 5 << 12 ? act : 5 << 12;

  return act;
// Stub for alternative experimental activity measures.
John Koleszar's avatar
John Koleszar committed
static unsigned int alt_activity_measure(VP8_COMP *cpi,
                                         MACROBLOCK *x, int use_dc_pred) {
  return vp9_encode_intra(cpi, x, use_dc_pred);
}


// Measure the activity of the current macroblock
// What we measure here is TBD so abstracted to this function
#define ALT_ACT_MEASURE 1
John Koleszar's avatar
John Koleszar committed
static unsigned int mb_activity_measure(VP8_COMP *cpi, MACROBLOCK *x,
                                        int mb_row, int mb_col) {
  unsigned int mb_activity;
John Koleszar's avatar
John Koleszar committed
  if (ALT_ACT_MEASURE) {
    int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
John Koleszar's avatar
John Koleszar committed
    // Or use and alternative.
    mb_activity = alt_activity_measure(cpi, x, use_dc_pred);
  } else {
    // Original activity measure from Tim T's code.
    mb_activity = tt_activity_measure(cpi, x);
  }
John Koleszar's avatar
John Koleszar committed
  if (mb_activity < VP8_ACTIVITY_AVG_MIN)
    mb_activity = VP8_ACTIVITY_AVG_MIN;
John Koleszar's avatar
John Koleszar committed
  return mb_activity;
}

// Calculate an "average" mb activity value for the frame
#define ACT_MEDIAN 0
John Koleszar's avatar
John Koleszar committed
static void calc_av_activity(VP8_COMP *cpi, int64_t activity_sum) {
#if ACT_MEDIAN
John Koleszar's avatar
John Koleszar committed
  // Find median: Simple n^2 algorithm for experimentation
  {
    unsigned int median;
    unsigned int i, j;
    unsigned int *sortlist;
    unsigned int tmp;

    // Create a list to sort to
    CHECK_MEM_ERROR(sortlist,
    vpx_calloc(sizeof(unsigned int),
    cpi->common.MBs));

    // Copy map to sort list
    vpx_memcpy(sortlist, cpi->mb_activity_map,
    sizeof(unsigned int) * cpi->common.MBs);


    // Ripple each value down to its correct position
    for (i = 1; i < cpi->common.MBs; i ++) {
      for (j = i; j > 0; j --) {
        if (sortlist[j] < sortlist[j - 1]) {
          // Swap values
          tmp = sortlist[j - 1];
          sortlist[j - 1] = sortlist[j];
          sortlist[j] = tmp;
        } else
          break;
      }
    }
John Koleszar's avatar
John Koleszar committed
    // Even number MBs so estimate median as mean of two either side.
    median = (1 + sortlist[cpi->common.MBs >> 1] +
Loading full blame...