Jeremy LeconteFix nullptr with offset.ffc179d5 years agoHistory
1294 lines · 38.8 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 "vpx_config.h"#include "vp8_rtcd.h"#include "./vpx_dsp_rtcd.h"#include "bitstream.h"#include "encodemb.h"#include "encodemv.h"#if CONFIG_MULTITHREAD#include "ethreading.h"#endif#include "vp8/common/common.h"#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 "encodeintra.h"#include "vp8/common/reconinter.h"#include "rdopt.h"#include "pickinter.h"#include "vp8/common/findnearmv.h"#include <stdio.h>#include <limits.h>#include "vp8/common/invtrans.h"#include "vpx_ports/vpx_timer.h"#if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING#include "bitstream.h"#endif#include "encodeframe.h" extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t);static void adjust_act_zbin(VP8_COMP *cpi, MACROBLOCK *x); #ifdef MODE_STATSunsigned int inter_y_modes[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };unsigned int inter_uv_modes[4] = { 0, 0, 0, 0 };unsigned int inter_b_modes[15] = {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};unsigned int y_modes[5] = { 0, 0, 0, 0, 0 };unsigned int uv_modes[4] = { 0, 0, 0, 0 };unsigned int b_modes[14] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };#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 *  vp8_activity_masking(). */#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. */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. */static unsigned int tt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x) {  unsigned int act;  unsigned int sse;  (void)cpi;  /* 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 = vpx_variance16x16(x->src.y_buffer, x->src.y_stride, VP8_VAR_OFFS, 0,                          &sse);  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. */static unsigned int alt_activity_measure(VP8_COMP *cpi, MACROBLOCK *x,                                         int use_dc_pred) {  return vp8_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 1static unsigned int mb_activity_measure(VP8_COMP *cpi, MACROBLOCK *x,                                        int mb_row, int mb_col) {  unsigned int mb_activity;   if (ALT_ACT_MEASURE) {    int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);     /* 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);  }   if (mb_activity < VP8_ACTIVITY_AVG_MIN) mb_activity = VP8_ACTIVITY_AVG_MIN;   return mb_activity;} /* Calculate an "average" mb activity value for the frame */#define ACT_MEDIAN 0static void calc_av_activity(VP8_COMP *cpi, int64_t activity_sum) {#if ACT_MEDIAN  /* 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 */    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;      }    }     /* Even number MBs so estimate median as mean of two either side. */    median = (1 + sortlist[cpi->common.MBs >> 1] +              sortlist[(cpi->common.MBs >> 1) + 1]) >>             1;     cpi->activity_avg = median;     vpx_free(sortlist);  }#else  /* Simple mean for now */  cpi->activity_avg = (unsigned int)(activity_sum / cpi->common.MBs);#endif   if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN) {    cpi->activity_avg = VP8_ACTIVITY_AVG_MIN;  }   /* Experimental code: return fixed value normalized for several clips */  if (ALT_ACT_MEASURE) cpi->activity_avg = 100000;} #define USE_ACT_INDEX 0#define OUTPUT_NORM_ACT_STATS 0 #if USE_ACT_INDEX/* Calculate and activity index for each mb */static void calc_activity_index(VP8_COMP *cpi, MACROBLOCK *x) {  VP8_COMMON *const cm = &cpi->common;  int mb_row, mb_col;   int64_t act;  int64_t a;  int64_t b; #if OUTPUT_NORM_ACT_STATS  FILE *f = fopen("norm_act.stt", "a");  fprintf(f, "\n%12d\n", cpi->activity_avg);#endif   /* Reset pointers to start of activity map */  x->mb_activity_ptr = cpi->mb_activity_map;   /* Calculate normalized mb activity number. */  for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {    /* for each macroblock col in image */    for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {      /* Read activity from the map */      act = *(x->mb_activity_ptr);       /* Calculate a normalized activity number */      a = act + 4 * cpi->activity_avg;      b = 4 * act + cpi->activity_avg;       if (b >= a)        *(x->activity_ptr) = (int)((b + (a >> 1)) / a) - 1;      else        *(x->activity_ptr) = 1 - (int)((a + (b >> 1)) / b); #if OUTPUT_NORM_ACT_STATS      fprintf(f, " %6d", *(x->mb_activity_ptr));#endif      /* Increment activity map pointers */      x->mb_activity_ptr++;    } #if OUTPUT_NORM_ACT_STATS    fprintf(f, "\n");#endif  } #if OUTPUT_NORM_ACT_STATS  fclose(f);#endif}#endif /* Loop through all MBs. Note activity of each, average activity and * calculate a normalized activity for each */static void build_activity_map(VP8_COMP *cpi) {  MACROBLOCK *const x = &cpi->mb;  MACROBLOCKD *xd = &x->e_mbd;  VP8_COMMON *const cm = &cpi->common; #if ALT_ACT_MEASURE  YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];  int recon_yoffset;  int recon_y_stride = new_yv12->y_stride;#endif   int mb_row, mb_col;  unsigned int mb_activity;  int64_t activity_sum = 0;   /* for each macroblock row in image */  for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {#if ALT_ACT_MEASURE    /* reset above block coeffs */    xd->up_available = (mb_row != 0);    recon_yoffset = (mb_row * recon_y_stride * 16);#endif    /* for each macroblock col in image */    for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {#if ALT_ACT_MEASURE      xd->dst.y_buffer = new_yv12->y_buffer + recon_yoffset;      xd->left_available = (mb_col != 0);      recon_yoffset += 16;#endif      /* Copy current mb to a buffer */      vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);       /* measure activity */      mb_activity = mb_activity_measure(cpi, x, mb_row, mb_col);       /* Keep frame sum */      activity_sum += mb_activity;       /* Store MB level activity details. */      *x->mb_activity_ptr = mb_activity;       /* Increment activity map pointer */      x->mb_activity_ptr++;       /* adjust to the next column of source macroblocks */      x->src.y_buffer += 16;    }     /* adjust to the next row of mbs */    x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols; #if ALT_ACT_MEASURE    /* extend the recon for intra prediction */    vp8_extend_mb_row(new_yv12, xd->dst.y_buffer + 16, xd->dst.u_buffer + 8,                      xd->dst.v_buffer + 8);#endif  }   /* Calculate an "average" MB activity */  calc_av_activity(cpi, activity_sum); #if USE_ACT_INDEX  /* Calculate an activity index number of each mb */  calc_activity_index(cpi, x);#endif} /* Macroblock activity masking */void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x) {#if USE_ACT_INDEX  x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);  x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);  x->errorperbit += (x->errorperbit == 0);#else  int64_t a;  int64_t b;  int64_t act = *(x->mb_activity_ptr);   /* Apply the masking to the RD multiplier. */  a = act + (2 * cpi->activity_avg);  b = (2 * act) + cpi->activity_avg;   x->rdmult = (unsigned int)(((int64_t)x->rdmult * b + (a >> 1)) / a);  x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);  x->errorperbit += (x->errorperbit == 0);#endif   /* Activity based Zbin adjustment */  adjust_act_zbin(cpi, x);} static void encode_mb_row(VP8_COMP *cpi, VP8_COMMON *cm, int mb_row,                          MACROBLOCK *x, MACROBLOCKD *xd, TOKENEXTRA **tp,                          int *segment_counts, int *totalrate) {  int recon_yoffset, recon_uvoffset;  int mb_col;  int ref_fb_idx = cm->lst_fb_idx;  int dst_fb_idx = cm->new_fb_idx;  int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;  int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;  int map_index = (mb_row * cpi->common.mb_cols); #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)  const int num_part = (1 << cm->multi_token_partition);  TOKENEXTRA *tp_start = cpi->tok;  vp8_writer *w;#endif #if CONFIG_MULTITHREAD  const int nsync = cpi->mt_sync_range;  vpx_atomic_int rightmost_col = VPX_ATOMIC_INIT(cm->mb_cols + nsync);  const vpx_atomic_int *last_row_current_mb_col;  vpx_atomic_int *current_mb_col = NULL;   if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {    current_mb_col = &cpi->mt_current_mb_col[mb_row];  }  if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0 && mb_row != 0) {    last_row_current_mb_col = &cpi->mt_current_mb_col[mb_row - 1];  } else {    last_row_current_mb_col = &rightmost_col;  }#endif #if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)  if (num_part > 1)    w = &cpi->bc[1 + (mb_row % num_part)];  else    w = &cpi->bc[1];#endif   /* reset above block coeffs */  xd->above_context = cm->above_context;   xd->up_available = (mb_row != 0);  recon_yoffset = (mb_row * recon_y_stride * 16);  recon_uvoffset = (mb_row * recon_uv_stride * 8);   cpi->tplist[mb_row].start = *tp;  /* printf("Main mb_row = %d\n", mb_row); */   /* Distance of Mb to the top & bottom edges, specified in 1/8th pel   * units as they are always compared to values that are in 1/8th pel   */  xd->mb_to_top_edge = -((mb_row * 16) << 3);  xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;   /* Set up limit values for vertical motion vector components   * to prevent them extending beyond the UMV borders   */  x->mv_row_min = -((mb_row * 16) + (VP8BORDERINPIXELS - 16));  x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + (VP8BORDERINPIXELS - 16);   /* Set the mb activity pointer to the start of the row. */  x->mb_activity_ptr = &cpi->mb_activity_map[map_index];   /* for each macroblock col in image */  for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {#if (CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING)    *tp = cpi->tok;#endif    /* Distance of Mb to the left & right edges, specified in     * 1/8th pel units as they are always compared to values     * that are in 1/8th pel units     */    xd->mb_to_left_edge = -((mb_col * 16) << 3);    xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;     /* Set up limit values for horizontal motion vector components     * to prevent them extending beyond the UMV borders     */    x->mv_col_min = -((mb_col * 16) + (VP8BORDERINPIXELS - 16));    x->mv_col_max =        ((cm->mb_cols - 1 - mb_col) * 16) + (VP8BORDERINPIXELS - 16);     xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;    xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;    xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;    xd->left_available = (mb_col != 0);     x->rddiv = cpi->RDDIV;    x->rdmult = cpi->RDMULT;     /* Copy current mb to a buffer */    vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16); #if CONFIG_MULTITHREAD    if (vpx_atomic_load_acquire(&cpi->b_multi_threaded) != 0) {      if (((mb_col - 1) % nsync) == 0) {        vpx_atomic_store_release(current_mb_col, mb_col - 1);      }       if (mb_row && !(mb_col & (nsync - 1))) {        vp8_atomic_spin_wait(mb_col, last_row_current_mb_col, nsync);      }    }#endif     if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp8_activity_masking(cpi, x);     /* Is segmentation enabled */    /* MB level adjustment to quantizer */    if (xd->segmentation_enabled) {      /* Code to set segment id in xd->mbmi.segment_id for current MB       * (with range checking)       */      if (cpi->segmentation_map[map_index + mb_col] <= 3) {        xd->mode_info_context->mbmi.segment_id =            cpi->segmentation_map[map_index + mb_col];      } else {        xd->mode_info_context->mbmi.segment_id = 0;      }       vp8cx_mb_init_quantizer(cpi, x, 1);    } else {      /* Set to Segment 0 by default */      xd->mode_info_context->mbmi.segment_id = 0;    }     x->active_ptr = cpi->active_map + map_index + mb_col;     if (cm->frame_type == KEY_FRAME) {      *totalrate += vp8cx_encode_intra_macroblock(cpi, x, tp);#ifdef MODE_STATS      y_modes[xd->mbmi.mode]++;#endif    } else {      *totalrate += vp8cx_encode_inter_macroblock(          cpi, x, tp, recon_yoffset, recon_uvoffset, mb_row, mb_col); #ifdef MODE_STATS      inter_y_modes[xd->mbmi.mode]++;       if (xd->mbmi.mode == SPLITMV) {        int b;         for (b = 0; b < xd->mbmi.partition_count; ++b) {          inter_b_modes[x->partition->bmi[b].mode]++;        }      } #endif       // Keep track of how many (consecutive) times a  block is coded      // as ZEROMV_LASTREF, for base layer frames.      // Reset to 0 if its coded as anything else.      if (cpi->current_layer == 0) {        if (xd->mode_info_context->mbmi.mode == ZEROMV &&            xd->mode_info_context->mbmi.ref_frame == LAST_FRAME) {          // Increment, check for wrap-around.          if (cpi->consec_zero_last[map_index + mb_col] < 255) {            cpi->consec_zero_last[map_index + mb_col] += 1;          }          if (cpi->consec_zero_last_mvbias[map_index + mb_col] < 255) {            cpi->consec_zero_last_mvbias[map_index + mb_col] += 1;          }        } else {          cpi->consec_zero_last[map_index + mb_col] = 0;          cpi->consec_zero_last_mvbias[map_index + mb_col] = 0;        }        if (x->zero_last_dot_suppress) {          cpi->consec_zero_last_mvbias[map_index + mb_col] = 0;        }      }       /* Special case code for cyclic refresh       * If cyclic update enabled then copy xd->mbmi.segment_id; (which

Lines 1–500 of 1294.

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