1347 lines · 46.0 KB · C
RawDownload
/* *  Copyright (c) 2010 The WebM project authors. All Rights Reserved. * *  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 <assert.h>#include <limits.h>#include "vpx_config.h"#include "./vpx_dsp_rtcd.h"#include "onyx_int.h"#include "modecosts.h"#include "encodeintra.h"#include "vp8/common/common.h"#include "vp8/common/entropymode.h"#include "pickinter.h"#include "vp8/common/findnearmv.h"#include "encodemb.h"#include "vp8/common/reconinter.h"#include "vp8/common/reconintra.h"#include "vp8/common/reconintra4x4.h"#include "vpx_dsp/variance.h"#include "mcomp.h"#include "vp8/common/vp8_skin_detection.h"#include "rdopt.h"#include "vpx_dsp/vpx_dsp_common.h"#include "vpx_mem/vpx_mem.h"#if CONFIG_TEMPORAL_DENOISING#include "denoising.h"#endif #ifdef SPEEDSTATSextern unsigned int cnt_pm;#endif extern const int vp8_ref_frame_order[MAX_MODES];extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES]; static int macroblock_corner_grad(unsigned char *signal, int stride,                                  int offsetx, int offsety, int sgnx,                                  int sgny) {  int y1 = signal[offsetx * stride + offsety];  int y2 = signal[offsetx * stride + offsety + sgny];  int y3 = signal[(offsetx + sgnx) * stride + offsety];  int y4 = signal[(offsetx + sgnx) * stride + offsety + sgny];  return VPXMAX(VPXMAX(abs(y1 - y2), abs(y1 - y3)), abs(y1 - y4));} static int check_dot_artifact_candidate(VP8_COMP *cpi, MACROBLOCK *x,                                        unsigned char *target_last, int stride,                                        unsigned char *last_ref, int mb_row,                                        int mb_col, int channel) {  int threshold1 = 6;  int threshold2 = 3;  unsigned int max_num = (cpi->common.MBs) / 10;  int grad_last = 0;  int grad_source = 0;  int index = mb_row * cpi->common.mb_cols + mb_col;  // Threshold for #consecutive (base layer) frames using zero_last mode.  int num_frames = 30;  int shift = 15;  if (channel > 0) {    shift = 7;  }  if (cpi->oxcf.number_of_layers > 1) {    num_frames = 20;  }  x->zero_last_dot_suppress = 0;  // Blocks on base layer frames that have been using ZEROMV_LAST repeatedly  // (i.e, at least |x| consecutive frames are candidates for increasing the  // rd adjustment for zero_last mode.  // Only allow this for at most |max_num| blocks per frame.  // Don't allow this for screen content input.  if (cpi->current_layer == 0 &&      cpi->consec_zero_last_mvbias[index] > num_frames &&      x->mbs_zero_last_dot_suppress < max_num &&      !cpi->oxcf.screen_content_mode) {    // If this block is checked here, label it so we don't check it again until    // ~|x| framaes later.    x->zero_last_dot_suppress = 1;    // Dot artifact is noticeable as strong gradient at corners of macroblock,    // for flat areas. As a simple detector for now, we look for a high    // corner gradient on last ref, and a smaller gradient on source.    // Check 4 corners, return if any satisfy condition.    // Top-left:    grad_last = macroblock_corner_grad(last_ref, stride, 0, 0, 1, 1);    grad_source = macroblock_corner_grad(target_last, stride, 0, 0, 1, 1);    if (grad_last >= threshold1 && grad_source <= threshold2) {      x->mbs_zero_last_dot_suppress++;      return 1;    }    // Top-right:    grad_last = macroblock_corner_grad(last_ref, stride, 0, shift, 1, -1);    grad_source = macroblock_corner_grad(target_last, stride, 0, shift, 1, -1);    if (grad_last >= threshold1 && grad_source <= threshold2) {      x->mbs_zero_last_dot_suppress++;      return 1;    }    // Bottom-left:    grad_last = macroblock_corner_grad(last_ref, stride, shift, 0, -1, 1);    grad_source = macroblock_corner_grad(target_last, stride, shift, 0, -1, 1);    if (grad_last >= threshold1 && grad_source <= threshold2) {      x->mbs_zero_last_dot_suppress++;      return 1;    }    // Bottom-right:    grad_last = macroblock_corner_grad(last_ref, stride, shift, shift, -1, -1);    grad_source =        macroblock_corner_grad(target_last, stride, shift, shift, -1, -1);    if (grad_last >= threshold1 && grad_source <= threshold2) {      x->mbs_zero_last_dot_suppress++;      return 1;    }    return 0;  }  return 0;} int vp8_skip_fractional_mv_step(MACROBLOCK *mb, BLOCK *b, BLOCKD *d,                                int_mv *bestmv, int_mv *ref_mv,                                int error_per_bit,                                const vp8_variance_fn_ptr_t *vfp,                                int *mvcost[2], int *distortion,                                unsigned int *sse) {  (void)b;  (void)d;  (void)ref_mv;  (void)error_per_bit;  (void)vfp;  (void)mb;  (void)mvcost;  (void)distortion;  (void)sse;  bestmv->as_mv.row *= 8;  bestmv->as_mv.col *= 8;  return 0;} int vp8_get_inter_mbpred_error(MACROBLOCK *mb, const vp8_variance_fn_ptr_t *vfp,                               unsigned int *sse, int_mv this_mv) {  BLOCK *b = &mb->block[0];  BLOCKD *d = &mb->e_mbd.block[0];  unsigned char *what = (*(b->base_src) + b->src);  int what_stride = b->src_stride;  int pre_stride = mb->e_mbd.pre.y_stride;  unsigned char *in_what = mb->e_mbd.pre.y_buffer + d->offset;  int in_what_stride = pre_stride;  int xoffset = this_mv.as_mv.col & 7;  int yoffset = this_mv.as_mv.row & 7;   in_what += (this_mv.as_mv.row >> 3) * pre_stride + (this_mv.as_mv.col >> 3);   if (xoffset | yoffset) {    return vfp->svf(in_what, in_what_stride, xoffset, yoffset, what,                    what_stride, sse);  } else {    return vfp->vf(what, what_stride, in_what, in_what_stride, sse);  }} static int get_prediction_error(BLOCK *be, BLOCKD *b) {  unsigned char *sptr;  unsigned char *dptr;  sptr = (*(be->base_src) + be->src);  dptr = b->predictor;   return vpx_get4x4sse_cs(sptr, be->src_stride, dptr, 16);} static int pick_intra4x4block(MACROBLOCK *x, int ib,                              B_PREDICTION_MODE *best_mode,                              const int *mode_costs, int *bestrate,                              int *bestdistortion) {  BLOCKD *b = &x->e_mbd.block[ib];  BLOCK *be = &x->block[ib];  int dst_stride = x->e_mbd.dst.y_stride;  unsigned char *dst = x->e_mbd.dst.y_buffer + b->offset;  B_PREDICTION_MODE mode;  int best_rd = INT_MAX;  int rate;  int distortion;   unsigned char *Above = dst - dst_stride;  unsigned char *yleft = dst - 1;  unsigned char top_left = Above[-1];   for (mode = B_DC_PRED; mode <= B_HE_PRED; ++mode) {    int this_rd;     rate = mode_costs[mode];     vp8_intra4x4_predict(Above, yleft, dst_stride, mode, b->predictor, 16,                         top_left);    distortion = get_prediction_error(be, b);    this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);     if (this_rd < best_rd) {      *bestrate = rate;      *bestdistortion = distortion;      best_rd = this_rd;      *best_mode = mode;    }  }   b->bmi.as_mode = *best_mode;  vp8_encode_intra4x4block(x, ib);  return best_rd;} static int pick_intra4x4mby_modes(MACROBLOCK *mb, int *Rate, int *best_dist) {  MACROBLOCKD *const xd = &mb->e_mbd;  int i;  int cost = mb->mbmode_cost[xd->frame_type][B_PRED];  int error;  int distortion = 0;  const int *bmode_costs;   intra_prediction_down_copy(xd, xd->dst.y_buffer - xd->dst.y_stride + 16);   bmode_costs = mb->inter_bmode_costs;   for (i = 0; i < 16; ++i) {    MODE_INFO *const mic = xd->mode_info_context;    const int mis = xd->mode_info_stride;     B_PREDICTION_MODE best_mode = B_MODE_COUNT;    int r = 0, d = 0;     if (mb->e_mbd.frame_type == KEY_FRAME) {      const B_PREDICTION_MODE A = above_block_mode(mic, i, mis);      const B_PREDICTION_MODE L = left_block_mode(mic, i);       bmode_costs = mb->bmode_costs[A][L];    }     pick_intra4x4block(mb, i, &best_mode, bmode_costs, &r, &d);     cost += r;    distortion += d;    assert(best_mode != B_MODE_COUNT);    mic->bmi[i].as_mode = best_mode;     /* Break out case where we have already exceeded best so far value     * that was passed in     */    if (distortion > *best_dist) break;  }   *Rate = cost;   if (i == 16) {    *best_dist = distortion;    error = RDCOST(mb->rdmult, mb->rddiv, cost, distortion);  } else {    *best_dist = INT_MAX;    error = INT_MAX;  }   return error;} static void pick_intra_mbuv_mode(MACROBLOCK *mb) {  MACROBLOCKD *x = &mb->e_mbd;  unsigned char *uabove_row = x->dst.u_buffer - x->dst.uv_stride;  unsigned char *vabove_row = x->dst.v_buffer - x->dst.uv_stride;  unsigned char *usrc_ptr = (mb->block[16].src + *mb->block[16].base_src);  unsigned char *vsrc_ptr = (mb->block[20].src + *mb->block[20].base_src);  int uvsrc_stride = mb->block[16].src_stride;  unsigned char uleft_col[8];  unsigned char vleft_col[8];  unsigned char utop_left = uabove_row[-1];  unsigned char vtop_left = vabove_row[-1];  int i, j;  int expected_udc;  int expected_vdc;  int shift;  int Uaverage = 0;  int Vaverage = 0;  int diff;  int pred_error[4] = { 0, 0, 0, 0 }, best_error = INT_MAX;  MB_PREDICTION_MODE best_mode = MB_MODE_COUNT;   for (i = 0; i < 8; ++i) {    uleft_col[i] = x->dst.u_buffer[i * x->dst.uv_stride - 1];    vleft_col[i] = x->dst.v_buffer[i * x->dst.uv_stride - 1];  }   if (!x->up_available && !x->left_available) {    expected_udc = 128;    expected_vdc = 128;  } else {    shift = 2;     if (x->up_available) {      for (i = 0; i < 8; ++i) {        Uaverage += uabove_row[i];        Vaverage += vabove_row[i];      }       shift++;    }     if (x->left_available) {      for (i = 0; i < 8; ++i) {        Uaverage += uleft_col[i];        Vaverage += vleft_col[i];      }       shift++;    }     expected_udc = (Uaverage + (1 << (shift - 1))) >> shift;    expected_vdc = (Vaverage + (1 << (shift - 1))) >> shift;  }   for (i = 0; i < 8; ++i) {    for (j = 0; j < 8; ++j) {      int predu = uleft_col[i] + uabove_row[j] - utop_left;      int predv = vleft_col[i] + vabove_row[j] - vtop_left;      int u_p, v_p;       u_p = usrc_ptr[j];      v_p = vsrc_ptr[j];       if (predu < 0) predu = 0;       if (predu > 255) predu = 255;       if (predv < 0) predv = 0;       if (predv > 255) predv = 255;       diff = u_p - expected_udc;      pred_error[DC_PRED] += diff * diff;      diff = v_p - expected_vdc;      pred_error[DC_PRED] += diff * diff;       diff = u_p - uabove_row[j];      pred_error[V_PRED] += diff * diff;      diff = v_p - vabove_row[j];      pred_error[V_PRED] += diff * diff;       diff = u_p - uleft_col[i];      pred_error[H_PRED] += diff * diff;      diff = v_p - vleft_col[i];      pred_error[H_PRED] += diff * diff;       diff = u_p - predu;      pred_error[TM_PRED] += diff * diff;      diff = v_p - predv;      pred_error[TM_PRED] += diff * diff;    }     usrc_ptr += uvsrc_stride;    vsrc_ptr += uvsrc_stride;     if (i == 3) {      usrc_ptr = (mb->block[18].src + *mb->block[18].base_src);      vsrc_ptr = (mb->block[22].src + *mb->block[22].base_src);    }  }   for (i = DC_PRED; i <= TM_PRED; ++i) {    if (best_error > pred_error[i]) {      best_error = pred_error[i];      best_mode = (MB_PREDICTION_MODE)i;    }  }   assert(best_mode != MB_MODE_COUNT);  mb->e_mbd.mode_info_context->mbmi.uv_mode = best_mode;} static void update_mvcount(MACROBLOCK *x, int_mv *best_ref_mv) {  MACROBLOCKD *xd = &x->e_mbd;  /* Split MV modes currently not supported when RD is nopt enabled,   * therefore, only need to modify MVcount in NEWMV mode. */  if (xd->mode_info_context->mbmi.mode == NEWMV) {    x->MVcount[0][mv_max + ((xd->mode_info_context->mbmi.mv.as_mv.row -                             best_ref_mv->as_mv.row) >>                            1)]++;    x->MVcount[1][mv_max + ((xd->mode_info_context->mbmi.mv.as_mv.col -                             best_ref_mv->as_mv.col) >>                            1)]++;  }} #if CONFIG_MULTI_RES_ENCODINGstatic void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd,                                      int *dissim, int *parent_ref_frame,                                      MB_PREDICTION_MODE *parent_mode,                                      int_mv *parent_ref_mv, int mb_row,                                      int mb_col) {  LOWER_RES_MB_INFO *store_mode_info =      ((LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info)->mb_info;  unsigned int parent_mb_index;   /* Consider different down_sampling_factor.  */  {    /* TODO: Removed the loop that supports special down_sampling_factor     * such as 2, 4, 8. Will revisit it if needed.     * Should also try using a look-up table to see if it helps     * performance. */    int parent_mb_row, parent_mb_col;     parent_mb_row = mb_row * cpi->oxcf.mr_down_sampling_factor.den /                    cpi->oxcf.mr_down_sampling_factor.num;    parent_mb_col = mb_col * cpi->oxcf.mr_down_sampling_factor.den /                    cpi->oxcf.mr_down_sampling_factor.num;    parent_mb_index = parent_mb_row * cpi->mr_low_res_mb_cols + parent_mb_col;  }   /* Read lower-resolution mode & motion result from memory.*/  *parent_ref_frame = store_mode_info[parent_mb_index].ref_frame;  *parent_mode = store_mode_info[parent_mb_index].mode;  *dissim = store_mode_info[parent_mb_index].dissim;   /* For highest-resolution encoder, adjust dissim value. Lower its quality   * for good performance. */  if (cpi->oxcf.mr_encoder_id == (cpi->oxcf.mr_total_resolutions - 1))    *dissim >>= 1;   if (*parent_ref_frame != INTRA_FRAME) {    /* Consider different down_sampling_factor.     * The result can be rounded to be more precise, but it takes more time.     */    (*parent_ref_mv).as_mv.row = store_mode_info[parent_mb_index].mv.as_mv.row *                                 cpi->oxcf.mr_down_sampling_factor.num /                                 cpi->oxcf.mr_down_sampling_factor.den;    (*parent_ref_mv).as_mv.col = store_mode_info[parent_mb_index].mv.as_mv.col *                                 cpi->oxcf.mr_down_sampling_factor.num /                                 cpi->oxcf.mr_down_sampling_factor.den;     vp8_clamp_mv2(parent_ref_mv, xd);  }}#endif static void check_for_encode_breakout(unsigned int sse, MACROBLOCK *x) {  MACROBLOCKD *xd = &x->e_mbd;   unsigned int threshold =      (xd->block[0].dequant[1] * xd->block[0].dequant[1] >> 4);   if (threshold < x->encode_breakout) threshold = x->encode_breakout;   if (sse < threshold) {    /* Check u and v to make sure skip is ok */    unsigned int sse2 = 0;     sse2 = VP8_UVSSE(x);     if (sse2 * 2 < x->encode_breakout) {      x->skip = 1;    } else {      x->skip = 0;    }  }} static int evaluate_inter_mode(unsigned int *sse, int rate2, int *distortion2,                               VP8_COMP *cpi, MACROBLOCK *x, int rd_adj) {  MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;  int_mv mv = x->e_mbd.mode_info_context->mbmi.mv;  int this_rd;  int denoise_aggressive = 0;  /* Exit early and don't compute the distortion if this macroblock   * is marked inactive. */  if (cpi->active_map_enabled && x->active_ptr[0] == 0) {    *sse = 0;    *distortion2 = 0;    x->skip = 1;    return INT_MAX;  }   if ((this_mode != NEWMV) || !(cpi->sf.half_pixel_search) ||      cpi->common.full_pixel == 1) {    *distortion2 =        vp8_get_inter_mbpred_error(x, &cpi->fn_ptr[BLOCK_16X16], sse, mv);  }   this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2); #if CONFIG_TEMPORAL_DENOISING  if (cpi->oxcf.noise_sensitivity > 0) {    denoise_aggressive =        (cpi->denoiser.denoiser_mode == kDenoiserOnYUVAggressive) ? 1 : 0;  }#endif   // Adjust rd for ZEROMV and LAST, if LAST is the closest reference frame.  // TODO: We should also add condition on distance of closest to current.  if (!cpi->oxcf.screen_content_mode && this_mode == ZEROMV &&      x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME &&      (denoise_aggressive || (cpi->closest_reference_frame == LAST_FRAME))) {    // No adjustment if block is considered to be skin area.

Lines 1–500 of 1347.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t