3151 lines · 107.6 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 <math.h>#include <limits.h>#include <stdio.h> #include "./vpx_dsp_rtcd.h"#include "./vpx_scale_rtcd.h"#include "block.h"#include "onyx_int.h"#include "vpx_dsp/variance.h"#include "encodeintra.h"#include "vp8/common/common.h"#include "vp8/common/setupintrarecon.h"#include "vp8/common/systemdependent.h"#include "mcomp.h"#include "firstpass.h"#include "vpx_scale/vpx_scale.h"#include "encodemb.h"#include "vp8/common/extend.h"#include "vpx_ports/system_state.h"#include "vpx_mem/vpx_mem.h"#include "vp8/common/swapyv12buffer.h"#include "rdopt.h"#include "vp8/common/quant_common.h"#include "encodemv.h"#include "encodeframe.h" #define OUTPUT_FPF 0 extern void vp8cx_frame_init_quantizer(VP8_COMP *cpi); #define GFQ_ADJUSTMENT vp8_gf_boost_qadjustment[Q]extern int vp8_kf_boost_qadjustment[QINDEX_RANGE]; extern const int vp8_gf_boost_qadjustment[QINDEX_RANGE]; #define IIFACTOR 1.5#define IIKFACTOR1 1.40#define IIKFACTOR2 1.5#define RMAX 14.0#define GF_RMAX 48.0 #define KF_MB_INTRA_MIN 300#define GF_MB_INTRA_MIN 200 #define DOUBLE_DIVIDE_CHECK(X) ((X) < 0 ? (X)-.000001 : (X) + .000001) #define POW1 (double)cpi->oxcf.two_pass_vbrbias / 100.0#define POW2 (double)cpi->oxcf.two_pass_vbrbias / 100.0 #define NEW_BOOST 1 static int vscale_lookup[7] = { 0, 1, 1, 2, 2, 3, 3 };static int hscale_lookup[7] = { 0, 0, 1, 1, 2, 2, 3 }; static const int cq_level[QINDEX_RANGE] = {  0,  0,  1,  1,  2,  3,  3,  4,  4,  5,  6,  6,  7,  8,  8,  9,  9,  10, 11,  11, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24,  24, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38,  39, 39, 40, 41, 42, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 50, 51, 52, 53,  54, 55, 55, 56, 57, 58, 59, 60, 60, 61, 62, 63, 64, 65, 66, 67, 67, 68, 69,  70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86,  87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100}; static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame); /* Resets the first pass file to the given position using a relative seek * from the current position */static void reset_fpf_position(VP8_COMP *cpi, FIRSTPASS_STATS *Position) {  cpi->twopass.stats_in = Position;} static int lookup_next_frame_stats(VP8_COMP *cpi, FIRSTPASS_STATS *next_frame) {  if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end) return EOF;   *next_frame = *cpi->twopass.stats_in;  return 1;} /* Read frame stats at an offset from the current position */static int read_frame_stats(VP8_COMP *cpi, FIRSTPASS_STATS *frame_stats,                            int offset) {  FIRSTPASS_STATS *fps_ptr = cpi->twopass.stats_in;   /* Check legality of offset */  if (offset >= 0) {    if (&fps_ptr[offset] >= cpi->twopass.stats_in_end) return EOF;  } else if (offset < 0) {    if (&fps_ptr[offset] < cpi->twopass.stats_in_start) return EOF;  }   *frame_stats = fps_ptr[offset];  return 1;} static int input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps) {  if (cpi->twopass.stats_in >= cpi->twopass.stats_in_end) return EOF;   *fps = *cpi->twopass.stats_in;  cpi->twopass.stats_in =      (void *)((char *)cpi->twopass.stats_in + sizeof(FIRSTPASS_STATS));  return 1;} static void output_stats(struct vpx_codec_pkt_list *pktlist,                         FIRSTPASS_STATS *stats) {  struct vpx_codec_cx_pkt pkt;  pkt.kind = VPX_CODEC_STATS_PKT;  pkt.data.twopass_stats.buf = stats;  pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);  vpx_codec_pkt_list_add(pktlist, &pkt); /* TEMP debug code */#if OUTPUT_FPF   {    FILE *fpfile;    fpfile = fopen("firstpass.stt", "a");     fprintf(fpfile,            "%12.0f %12.0f %12.0f %12.4f %12.4f %12.4f %12.4f"            " %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f"            " %12.0f %12.0f %12.4f\n",            stats->frame, stats->intra_error, stats->coded_error,            stats->ssim_weighted_pred_err, stats->pcnt_inter,            stats->pcnt_motion, stats->pcnt_second_ref, stats->pcnt_neutral,            stats->MVr, stats->mvr_abs, stats->MVc, stats->mvc_abs, stats->MVrv,            stats->MVcv, stats->mv_in_out_count, stats->new_mv_count,            stats->count, stats->duration);    fclose(fpfile);  }#endif} static void zero_stats(FIRSTPASS_STATS *section) {  section->frame = 0.0;  section->intra_error = 0.0;  section->coded_error = 0.0;  section->ssim_weighted_pred_err = 0.0;  section->pcnt_inter = 0.0;  section->pcnt_motion = 0.0;  section->pcnt_second_ref = 0.0;  section->pcnt_neutral = 0.0;  section->MVr = 0.0;  section->mvr_abs = 0.0;  section->MVc = 0.0;  section->mvc_abs = 0.0;  section->MVrv = 0.0;  section->MVcv = 0.0;  section->mv_in_out_count = 0.0;  section->new_mv_count = 0.0;  section->count = 0.0;  section->duration = 1.0;} static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) {  section->frame += frame->frame;  section->intra_error += frame->intra_error;  section->coded_error += frame->coded_error;  section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err;  section->pcnt_inter += frame->pcnt_inter;  section->pcnt_motion += frame->pcnt_motion;  section->pcnt_second_ref += frame->pcnt_second_ref;  section->pcnt_neutral += frame->pcnt_neutral;  section->MVr += frame->MVr;  section->mvr_abs += frame->mvr_abs;  section->MVc += frame->MVc;  section->mvc_abs += frame->mvc_abs;  section->MVrv += frame->MVrv;  section->MVcv += frame->MVcv;  section->mv_in_out_count += frame->mv_in_out_count;  section->new_mv_count += frame->new_mv_count;  section->count += frame->count;  section->duration += frame->duration;} static void subtract_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) {  section->frame -= frame->frame;  section->intra_error -= frame->intra_error;  section->coded_error -= frame->coded_error;  section->ssim_weighted_pred_err -= frame->ssim_weighted_pred_err;  section->pcnt_inter -= frame->pcnt_inter;  section->pcnt_motion -= frame->pcnt_motion;  section->pcnt_second_ref -= frame->pcnt_second_ref;  section->pcnt_neutral -= frame->pcnt_neutral;  section->MVr -= frame->MVr;  section->mvr_abs -= frame->mvr_abs;  section->MVc -= frame->MVc;  section->mvc_abs -= frame->mvc_abs;  section->MVrv -= frame->MVrv;  section->MVcv -= frame->MVcv;  section->mv_in_out_count -= frame->mv_in_out_count;  section->new_mv_count -= frame->new_mv_count;  section->count -= frame->count;  section->duration -= frame->duration;} static void avg_stats(FIRSTPASS_STATS *section) {  if (section->count < 1.0) return;   section->intra_error /= section->count;  section->coded_error /= section->count;  section->ssim_weighted_pred_err /= section->count;  section->pcnt_inter /= section->count;  section->pcnt_second_ref /= section->count;  section->pcnt_neutral /= section->count;  section->pcnt_motion /= section->count;  section->MVr /= section->count;  section->mvr_abs /= section->count;  section->MVc /= section->count;  section->mvc_abs /= section->count;  section->MVrv /= section->count;  section->MVcv /= section->count;  section->mv_in_out_count /= section->count;  section->duration /= section->count;} /* Calculate a modified Error used in distributing bits between easier * and harder frames */static double calculate_modified_err(VP8_COMP *cpi,                                     FIRSTPASS_STATS *this_frame) {  double av_err = (cpi->twopass.total_stats.ssim_weighted_pred_err /                   cpi->twopass.total_stats.count);  double this_err = this_frame->ssim_weighted_pred_err;  double modified_err;   if (this_err > av_err) {    modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW1);  } else {    modified_err = av_err * pow((this_err / DOUBLE_DIVIDE_CHECK(av_err)), POW2);  }   return modified_err;} static const double weight_table[256] = {  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.031250, 0.062500,  0.093750, 0.125000, 0.156250, 0.187500, 0.218750, 0.250000, 0.281250,  0.312500, 0.343750, 0.375000, 0.406250, 0.437500, 0.468750, 0.500000,  0.531250, 0.562500, 0.593750, 0.625000, 0.656250, 0.687500, 0.718750,  0.750000, 0.781250, 0.812500, 0.843750, 0.875000, 0.906250, 0.937500,  0.968750, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,  1.000000, 1.000000, 1.000000, 1.000000}; static double simple_weight(YV12_BUFFER_CONFIG *source) {  int i, j;   unsigned char *src = source->y_buffer;  double sum_weights = 0.0;   /* Loop throught the Y plane raw examining levels and creating a weight   * for the image   */  i = source->y_height;  do {    j = source->y_width;    do {      sum_weights += weight_table[*src];      src++;    } while (--j);    src -= source->y_width;    src += source->y_stride;  } while (--i);   sum_weights /= (source->y_height * source->y_width);   return sum_weights;} /* This function returns the current per frame maximum bitrate target */static int frame_max_bits(VP8_COMP *cpi) {  /* Max allocation for a single frame based on the max section guidelines   * passed in and how many bits are left   */  int max_bits;   /* For CBR we need to also consider buffer fullness.   * If we are running below the optimal level then we need to gradually   * tighten up on max_bits.   */  if (cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) {    double buffer_fullness_ratio =        (double)cpi->buffer_level /        DOUBLE_DIVIDE_CHECK((double)cpi->oxcf.optimal_buffer_level);     /* For CBR base this on the target average bits per frame plus the     * maximum sedction rate passed in by the user     */    max_bits = (int)(cpi->av_per_frame_bandwidth *                     ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));     /* If our buffer is below the optimum level */    if (buffer_fullness_ratio < 1.0) {      /* The lower of max_bits / 4 or cpi->av_per_frame_bandwidth / 4. */      int min_max_bits = ((cpi->av_per_frame_bandwidth >> 2) < (max_bits >> 2))                             ? cpi->av_per_frame_bandwidth >> 2                             : max_bits >> 2;       max_bits = (int)(max_bits * buffer_fullness_ratio);       /* Lowest value we will set ... which should allow the buffer to       * refill.       */      if (max_bits < min_max_bits) max_bits = min_max_bits;    }  }  /* VBR */  else {    /* For VBR base this on the bits and frames left plus the     * two_pass_vbrmax_section rate passed in by the user     */    max_bits = (int)(((double)cpi->twopass.bits_left /                      (cpi->twopass.total_stats.count -                       (double)cpi->common.current_video_frame)) *                     ((double)cpi->oxcf.two_pass_vbrmax_section / 100.0));  }   /* Trap case where we are out of bits */  if (max_bits < 0) max_bits = 0;   return max_bits;} void vp8_init_first_pass(VP8_COMP *cpi) {  zero_stats(&cpi->twopass.total_stats);} void vp8_end_first_pass(VP8_COMP *cpi) {  output_stats(cpi->output_pkt_list, &cpi->twopass.total_stats);} static void zz_motion_search(MACROBLOCK *x, YV12_BUFFER_CONFIG *raw_buffer,                             int *raw_motion_err,                             YV12_BUFFER_CONFIG *recon_buffer,                             int *best_motion_err, int recon_yoffset) {  MACROBLOCKD *const xd = &x->e_mbd;  BLOCK *b = &x->block[0];  BLOCKD *d = &x->e_mbd.block[0];   unsigned char *src_ptr = (*(b->base_src) + b->src);  int src_stride = b->src_stride;  unsigned char *raw_ptr;  int raw_stride = raw_buffer->y_stride;  unsigned char *ref_ptr;  int ref_stride = x->e_mbd.pre.y_stride;   /* Set up pointers for this macro block raw buffer */  raw_ptr = (unsigned char *)(raw_buffer->y_buffer + recon_yoffset + d->offset);  vpx_mse16x16(src_ptr, src_stride, raw_ptr, raw_stride,               (unsigned int *)(raw_motion_err));   /* Set up pointers for this macro block recon buffer */  xd->pre.y_buffer = recon_buffer->y_buffer + recon_yoffset;  ref_ptr = (unsigned char *)(xd->pre.y_buffer + d->offset);  vpx_mse16x16(src_ptr, src_stride, ref_ptr, ref_stride,               (unsigned int *)(best_motion_err));} static void first_pass_motion_search(VP8_COMP *cpi, MACROBLOCK *x,                                     int_mv *ref_mv, MV *best_mv,                                     YV12_BUFFER_CONFIG *recon_buffer,                                     int *best_motion_err, int recon_yoffset) {  MACROBLOCKD *const xd = &x->e_mbd;  BLOCK *b = &x->block[0];  BLOCKD *d = &x->e_mbd.block[0];  int num00;   int_mv tmp_mv;  int_mv ref_mv_full;   int tmp_err;  int step_param = 3; /* Dont search over full range for first pass */  int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;  int n;  vp8_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[BLOCK_16X16];  int new_mv_mode_penalty = 256;   /* override the default variance function to use MSE */  v_fn_ptr.vf = vpx_mse16x16;   /* Set up pointers for this macro block recon buffer */  xd->pre.y_buffer = recon_buffer->y_buffer + recon_yoffset;   /* Initial step/diamond search centred on best mv */  tmp_mv.as_int = 0;  ref_mv_full.as_mv.col = ref_mv->as_mv.col >> 3;  ref_mv_full.as_mv.row = ref_mv->as_mv.row >> 3;  tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv, step_param,                                    x->sadperbit16, &num00, &v_fn_ptr,                                    x->mvcost, ref_mv);  if (tmp_err < INT_MAX - new_mv_mode_penalty) tmp_err += new_mv_mode_penalty;   if (tmp_err < *best_motion_err) {    *best_motion_err = tmp_err;    best_mv->row = tmp_mv.as_mv.row;    best_mv->col = tmp_mv.as_mv.col;  }   /* Further step/diamond searches as necessary */  n = num00;  num00 = 0;   while (n < further_steps) {    n++;     if (num00) {      num00--;    } else {      tmp_err = cpi->diamond_search_sad(x, b, d, &ref_mv_full, &tmp_mv,                                        step_param + n, x->sadperbit16, &num00,                                        &v_fn_ptr, x->mvcost, ref_mv);      if (tmp_err < INT_MAX - new_mv_mode_penalty) {        tmp_err += new_mv_mode_penalty;      }       if (tmp_err < *best_motion_err) {        *best_motion_err = tmp_err;        best_mv->row = tmp_mv.as_mv.row;        best_mv->col = tmp_mv.as_mv.col;      }    }  }} void vp8_first_pass(VP8_COMP *cpi) {  int mb_row, mb_col;  MACROBLOCK *const x = &cpi->mb;  VP8_COMMON *const cm = &cpi->common;  MACROBLOCKD *const xd = &x->e_mbd;   int recon_yoffset, recon_uvoffset;  YV12_BUFFER_CONFIG *lst_yv12 = &cm->yv12_fb[cm->lst_fb_idx];  YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];  YV12_BUFFER_CONFIG *gld_yv12 = &cm->yv12_fb[cm->gld_fb_idx];  int recon_y_stride = lst_yv12->y_stride;  int recon_uv_stride = lst_yv12->uv_stride;  int64_t intra_error = 0;  int64_t coded_error = 0;   int sum_mvr = 0, sum_mvc = 0;  int sum_mvr_abs = 0, sum_mvc_abs = 0;  int sum_mvrs = 0, sum_mvcs = 0;  int mvcount = 0;  int intercount = 0;  int second_ref_count = 0;  int intrapenalty = 256;  int neutral_count = 0;  int new_mv_count = 0;  int sum_in_vectors = 0;  uint32_t lastmv_as_int = 0;   int_mv zero_ref_mv;   zero_ref_mv.as_int = 0;   vpx_clear_system_state(); 

Lines 1–500 of 3151.

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