firstpass.c 108 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Jingning Han's avatar
Jingning Han committed
10 11 12 13 14 15
 */

#include <limits.h>
#include <math.h>
#include <stdio.h>

Yaowu Xu's avatar
Yaowu Xu committed
16 17
#include "./aom_dsp_rtcd.h"
#include "./aom_scale_rtcd.h"
Jingning Han's avatar
Jingning Han committed
18

Yaowu Xu's avatar
Yaowu Xu committed
19 20
#include "aom_dsp/aom_dsp_common.h"
#include "aom_mem/aom_mem.h"
21 22
#include "aom_ports/mem.h"
#include "aom_ports/system_state.h"
Yaowu Xu's avatar
Yaowu Xu committed
23
#include "aom_scale/aom_scale.h"
24
#include "aom_scale/yv12config.h"
Jingning Han's avatar
Jingning Han committed
25

Zoe Liu's avatar
Zoe Liu committed
26
#include "aom_dsp/variance.h"
27 28
#include "av1/common/entropymv.h"
#include "av1/common/quant_common.h"
Yaowu Xu's avatar
Yaowu Xu committed
29
#include "av1/common/reconinter.h"  // av1_setup_dst_planes()
30 31 32 33 34 35 36 37 38 39 40
#include "av1/encoder/aq_variance.h"
#include "av1/encoder/block.h"
#include "av1/encoder/encodeframe.h"
#include "av1/encoder/encodemb.h"
#include "av1/encoder/encodemv.h"
#include "av1/encoder/encoder.h"
#include "av1/encoder/extend.h"
#include "av1/encoder/firstpass.h"
#include "av1/encoder/mcomp.h"
#include "av1/encoder/quantize.h"
#include "av1/encoder/rd.h"
Jingning Han's avatar
Jingning Han committed
41

42 43
#define OUTPUT_FPF 0
#define ARF_STATS_OUTPUT 0
Jingning Han's avatar
Jingning Han committed
44 45 46

#define GROUP_ADAPTIVE_MAXQ 1

47 48 49 50 51 52 53 54 55 56 57
#define BOOST_BREAKOUT 12.5
#define BOOST_FACTOR 12.5
#define FACTOR_PT_LOW 0.70
#define FACTOR_PT_HIGH 0.90
#define FIRST_PASS_Q 10.0
#define GF_MAX_BOOST 96.0
#define INTRA_MODE_PENALTY 1024
#define KF_MAX_BOOST 128.0
#define MIN_ARF_GF_BOOST 240
#define MIN_DECAY_FACTOR 0.01
#define MIN_KF_BOOST 300
Jingning Han's avatar
Jingning Han committed
58
#define NEW_MV_MODE_PENALTY 32
59 60 61 62
#define DARK_THRESH 64
#define DEFAULT_GRP_WEIGHT 1.0
#define RC_FACTOR_MIN 0.75
#define RC_FACTOR_MAX 1.75
Jingning Han's avatar
Jingning Han committed
63 64 65 66 67

#define NCOUNT_INTRA_THRESH 8192
#define NCOUNT_INTRA_FACTOR 3
#define NCOUNT_FRAME_II_THRESH 5.0

68
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x)-0.000001 : (x) + 0.000001)
Jingning Han's avatar
Jingning Han committed
69 70 71 72 73 74 75

#if ARF_STATS_OUTPUT
unsigned int arf_count = 0;
#endif

// Resets the first pass file to the given position using a relative seek from
// the current position.
76
static void reset_fpf_position(TWO_PASS *p, const FIRSTPASS_STATS *position) {
Jingning Han's avatar
Jingning Han committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90
  p->stats_in = position;
}

// Read frame stats at an offset from the current position.
static const FIRSTPASS_STATS *read_frame_stats(const TWO_PASS *p, int offset) {
  if ((offset >= 0 && p->stats_in + offset >= p->stats_in_end) ||
      (offset < 0 && p->stats_in + offset < p->stats_in_start)) {
    return NULL;
  }

  return &p->stats_in[offset];
}

static int input_stats(TWO_PASS *p, FIRSTPASS_STATS *fps) {
91
  if (p->stats_in >= p->stats_in_end) return EOF;
Jingning Han's avatar
Jingning Han committed
92 93 94 95 96 97 98

  *fps = *p->stats_in;
  ++p->stats_in;
  return 1;
}

static void output_stats(FIRSTPASS_STATS *stats,
Yaowu Xu's avatar
Yaowu Xu committed
99 100 101
                         struct aom_codec_pkt_list *pktlist) {
  struct aom_codec_cx_pkt pkt;
  pkt.kind = AOM_CODEC_STATS_PKT;
Jingning Han's avatar
Jingning Han committed
102 103
  pkt.data.twopass_stats.buf = stats;
  pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);
Yaowu Xu's avatar
Yaowu Xu committed
104
  aom_codec_pkt_list_add(pktlist, &pkt);
Jingning Han's avatar
Jingning Han committed
105 106 107 108 109 110 111

// TEMP debug code
#if OUTPUT_FPF
  {
    FILE *fpfile;
    fpfile = fopen("firstpass.stt", "a");

112 113
    fprintf(fpfile,
            "%12.0lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf %12.4lf"
Jingning Han's avatar
Jingning Han committed
114 115
            "%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf"
            "%12.4lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf\n",
116 117 118 119 120 121 122
            stats->frame, stats->weight, stats->intra_error, stats->coded_error,
            stats->sr_coded_error, stats->pcnt_inter, stats->pcnt_motion,
            stats->pcnt_second_ref, stats->pcnt_neutral, stats->intra_skip_pct,
            stats->inactive_zone_rows, stats->inactive_zone_cols, 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);
Jingning Han's avatar
Jingning Han committed
123 124 125 126 127 128
    fclose(fpfile);
  }
#endif
}

#if CONFIG_FP_MB_STATS
129
static void output_fpmb_stats(uint8_t *this_frame_mb_stats, int stats_size,
Yaowu Xu's avatar
Yaowu Xu committed
130 131 132
                              struct aom_codec_pkt_list *pktlist) {
  struct aom_codec_cx_pkt pkt;
  pkt.kind = AOM_CODEC_FPMB_STATS_PKT;
Jingning Han's avatar
Jingning Han committed
133
  pkt.data.firstpass_mb_stats.buf = this_frame_mb_stats;
134
  pkt.data.firstpass_mb_stats.sz = stats_size * sizeof(*this_frame_mb_stats);
Yaowu Xu's avatar
Yaowu Xu committed
135
  aom_codec_pkt_list_add(pktlist, &pkt);
Jingning Han's avatar
Jingning Han committed
136 137 138 139 140 141 142 143 144
}
#endif

static void zero_stats(FIRSTPASS_STATS *section) {
  section->frame = 0.0;
  section->weight = 0.0;
  section->intra_error = 0.0;
  section->coded_error = 0.0;
  section->sr_coded_error = 0.0;
145 146
  section->pcnt_inter = 0.0;
  section->pcnt_motion = 0.0;
Jingning Han's avatar
Jingning Han committed
147 148 149 150 151 152
  section->pcnt_second_ref = 0.0;
  section->pcnt_neutral = 0.0;
  section->intra_skip_pct = 0.0;
  section->inactive_zone_rows = 0.0;
  section->inactive_zone_cols = 0.0;
  section->MVr = 0.0;
153 154 155 156 157 158
  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;
Jingning Han's avatar
Jingning Han committed
159
  section->new_mv_count = 0.0;
160 161
  section->count = 0.0;
  section->duration = 1.0;
Jingning Han's avatar
Jingning Han committed
162 163 164 165 166 167 168 169 170
}

static void accumulate_stats(FIRSTPASS_STATS *section,
                             const FIRSTPASS_STATS *frame) {
  section->frame += frame->frame;
  section->weight += frame->weight;
  section->intra_error += frame->intra_error;
  section->coded_error += frame->coded_error;
  section->sr_coded_error += frame->sr_coded_error;
171
  section->pcnt_inter += frame->pcnt_inter;
Jingning Han's avatar
Jingning Han committed
172 173 174 175 176 177 178
  section->pcnt_motion += frame->pcnt_motion;
  section->pcnt_second_ref += frame->pcnt_second_ref;
  section->pcnt_neutral += frame->pcnt_neutral;
  section->intra_skip_pct += frame->intra_skip_pct;
  section->inactive_zone_rows += frame->inactive_zone_rows;
  section->inactive_zone_cols += frame->inactive_zone_cols;
  section->MVr += frame->MVr;
179 180 181 182 183 184
  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;
Jingning Han's avatar
Jingning Han committed
185
  section->new_mv_count += frame->new_mv_count;
186 187
  section->count += frame->count;
  section->duration += frame->duration;
Jingning Han's avatar
Jingning Han committed
188 189 190 191 192 193 194 195 196
}

static void subtract_stats(FIRSTPASS_STATS *section,
                           const FIRSTPASS_STATS *frame) {
  section->frame -= frame->frame;
  section->weight -= frame->weight;
  section->intra_error -= frame->intra_error;
  section->coded_error -= frame->coded_error;
  section->sr_coded_error -= frame->sr_coded_error;
197
  section->pcnt_inter -= frame->pcnt_inter;
Jingning Han's avatar
Jingning Han committed
198 199 200 201 202 203 204
  section->pcnt_motion -= frame->pcnt_motion;
  section->pcnt_second_ref -= frame->pcnt_second_ref;
  section->pcnt_neutral -= frame->pcnt_neutral;
  section->intra_skip_pct -= frame->intra_skip_pct;
  section->inactive_zone_rows -= frame->inactive_zone_rows;
  section->inactive_zone_cols -= frame->inactive_zone_cols;
  section->MVr -= frame->MVr;
205 206 207 208 209 210
  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;
Jingning Han's avatar
Jingning Han committed
211
  section->new_mv_count -= frame->new_mv_count;
212 213
  section->count -= frame->count;
  section->duration -= frame->duration;
Jingning Han's avatar
Jingning Han committed
214 215
}

paulwilkins's avatar
paulwilkins committed
216 217
// Calculate the linear size relative to a baseline of 1080P
#define BASE_SIZE 2073600.0  // 1920x1080
Yaowu Xu's avatar
Yaowu Xu committed
218
static double get_linear_size_factor(const AV1_COMP *cpi) {
paulwilkins's avatar
paulwilkins committed
219 220 221 222
  const double this_area = cpi->initial_width * cpi->initial_height;
  return pow(this_area / BASE_SIZE, 0.5);
}

Jingning Han's avatar
Jingning Han committed
223 224 225 226
// Calculate an active area of the image that discounts formatting
// bars and partially discounts other 0 energy areas.
#define MIN_ACTIVE_AREA 0.5
#define MAX_ACTIVE_AREA 1.0
Yaowu Xu's avatar
Yaowu Xu committed
227
static double calculate_active_area(const AV1_COMP *cpi,
228
                                    const FIRSTPASS_STATS *this_frame) {
Jingning Han's avatar
Jingning Han committed
229 230
  double active_pct;

231 232 233 234
  active_pct =
      1.0 -
      ((this_frame->intra_skip_pct / 2) +
       ((this_frame->inactive_zone_rows * 2) / (double)cpi->common.mb_rows));
Jingning Han's avatar
Jingning Han committed
235 236 237 238 239 240
  return fclamp(active_pct, MIN_ACTIVE_AREA, MAX_ACTIVE_AREA);
}

// Calculate a modified Error used in distributing bits between easier and
// harder frames.
#define ACT_AREA_CORRECTION 0.5
Yaowu Xu's avatar
Yaowu Xu committed
241
static double calculate_modified_err(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
242
                                     const TWO_PASS *twopass,
Yaowu Xu's avatar
Yaowu Xu committed
243
                                     const AV1EncoderConfig *oxcf,
Jingning Han's avatar
Jingning Han committed
244 245 246 247 248
                                     const FIRSTPASS_STATS *this_frame) {
  const FIRSTPASS_STATS *const stats = &twopass->total_stats;
  const double av_weight = stats->weight / stats->count;
  const double av_err = (stats->coded_error * av_weight) / stats->count;
  double modified_error =
249 250 251
      av_err * pow(this_frame->coded_error * this_frame->weight /
                       DOUBLE_DIVIDE_CHECK(av_err),
                   oxcf->two_pass_vbrbias / 100.0);
Jingning Han's avatar
Jingning Han committed
252 253 254 255 256 257 258

  // Correction for active area. Frames with a reduced active area
  // (eg due to formatting bars) have a higher error per mb for the
  // remaining active MBs. The correction here assumes that coding
  // 0.5N blocks of complexity 2X is a little easier than coding N
  // blocks of complexity X.
  modified_error *=
259
      pow(calculate_active_area(cpi, this_frame), ACT_AREA_CORRECTION);
Jingning Han's avatar
Jingning Han committed
260

261 262
  return fclamp(modified_error, twopass->modified_error_min,
                twopass->modified_error_max);
Jingning Han's avatar
Jingning Han committed
263 264 265 266
}

// This function returns the maximum target rate per frame.
static int frame_max_bits(const RATE_CONTROL *rc,
Yaowu Xu's avatar
Yaowu Xu committed
267
                          const AV1EncoderConfig *oxcf) {
Jingning Han's avatar
Jingning Han committed
268
  int64_t max_bits = ((int64_t)rc->avg_frame_bandwidth *
269 270
                      (int64_t)oxcf->two_pass_vbrmax_section) /
                     100;
Jingning Han's avatar
Jingning Han committed
271 272 273 274 275 276 277 278
  if (max_bits < 0)
    max_bits = 0;
  else if (max_bits > rc->max_frame_bandwidth)
    max_bits = rc->max_frame_bandwidth;

  return (int)max_bits;
}

Yaowu Xu's avatar
Yaowu Xu committed
279
void av1_init_first_pass(AV1_COMP *cpi) {
Jingning Han's avatar
Jingning Han committed
280 281 282
  zero_stats(&cpi->twopass.total_stats);
}

Yaowu Xu's avatar
Yaowu Xu committed
283
void av1_end_first_pass(AV1_COMP *cpi) {
Yunqing Wang's avatar
Yunqing Wang committed
284
  output_stats(&cpi->twopass.total_stats, cpi->output_pkt_list);
Jingning Han's avatar
Jingning Han committed
285 286
}

Yaowu Xu's avatar
Yaowu Xu committed
287
static aom_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
Jingning Han's avatar
Jingning Han committed
288
  switch (bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
289 290 291 292
    case BLOCK_8X8: return aom_mse8x8;
    case BLOCK_16X8: return aom_mse16x8;
    case BLOCK_8X16: return aom_mse8x16;
    default: return aom_mse16x16;
Jingning Han's avatar
Jingning Han committed
293 294 295 296 297 298 299
  }
}

static unsigned int get_prediction_error(BLOCK_SIZE bsize,
                                         const struct buf_2d *src,
                                         const struct buf_2d *ref) {
  unsigned int sse;
Yaowu Xu's avatar
Yaowu Xu committed
300
  const aom_variance_fn_t fn = get_block_variance_fn(bsize);
Jingning Han's avatar
Jingning Han committed
301 302 303 304
  fn(src->buf, src->stride, ref->buf, ref->stride, &sse);
  return sse;
}

Yaowu Xu's avatar
Yaowu Xu committed
305 306
#if CONFIG_AOM_HIGHBITDEPTH
static aom_variance_fn_t highbd_get_block_variance_fn(BLOCK_SIZE bsize,
Jingning Han's avatar
Jingning Han committed
307 308 309 310
                                                      int bd) {
  switch (bd) {
    default:
      switch (bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
311 312 313 314
        case BLOCK_8X8: return aom_highbd_8_mse8x8;
        case BLOCK_16X8: return aom_highbd_8_mse16x8;
        case BLOCK_8X16: return aom_highbd_8_mse8x16;
        default: return aom_highbd_8_mse16x16;
Jingning Han's avatar
Jingning Han committed
315 316 317 318
      }
      break;
    case 10:
      switch (bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
319 320 321 322
        case BLOCK_8X8: return aom_highbd_10_mse8x8;
        case BLOCK_16X8: return aom_highbd_10_mse16x8;
        case BLOCK_8X16: return aom_highbd_10_mse8x16;
        default: return aom_highbd_10_mse16x16;
Jingning Han's avatar
Jingning Han committed
323 324 325 326
      }
      break;
    case 12:
      switch (bsize) {
Yaowu Xu's avatar
Yaowu Xu committed
327 328 329 330
        case BLOCK_8X8: return aom_highbd_12_mse8x8;
        case BLOCK_16X8: return aom_highbd_12_mse16x8;
        case BLOCK_8X16: return aom_highbd_12_mse8x16;
        default: return aom_highbd_12_mse16x16;
Jingning Han's avatar
Jingning Han committed
331 332 333 334 335 336 337 338 339 340
      }
      break;
  }
}

static unsigned int highbd_get_prediction_error(BLOCK_SIZE bsize,
                                                const struct buf_2d *src,
                                                const struct buf_2d *ref,
                                                int bd) {
  unsigned int sse;
Yaowu Xu's avatar
Yaowu Xu committed
341
  const aom_variance_fn_t fn = highbd_get_block_variance_fn(bsize, bd);
Jingning Han's avatar
Jingning Han committed
342 343 344
  fn(src->buf, src->stride, ref->buf, ref->stride, &sse);
  return sse;
}
Yaowu Xu's avatar
Yaowu Xu committed
345
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
346 347 348

// Refine the motion search range according to the frame dimension
// for first pass test.
Yaowu Xu's avatar
Yaowu Xu committed
349
static int get_search_range(const AV1_COMP *cpi) {
Jingning Han's avatar
Jingning Han committed
350
  int sr = 0;
Yaowu Xu's avatar
Yaowu Xu committed
351
  const int dim = AOMMIN(cpi->initial_width, cpi->initial_height);
Jingning Han's avatar
Jingning Han committed
352

353
  while ((dim << sr) < MAX_FULL_PEL_VAL) ++sr;
Jingning Han's avatar
Jingning Han committed
354 355 356
  return sr;
}

Yaowu Xu's avatar
Yaowu Xu committed
357
static void first_pass_motion_search(AV1_COMP *cpi, MACROBLOCK *x,
Jingning Han's avatar
Jingning Han committed
358 359 360
                                     const MV *ref_mv, MV *best_mv,
                                     int *best_motion_err) {
  MACROBLOCKD *const xd = &x->e_mbd;
361 362
  MV tmp_mv = { 0, 0 };
  MV ref_mv_full = { ref_mv->row >> 3, ref_mv->col >> 3 };
Jingning Han's avatar
Jingning Han committed
363 364
  int num00, tmp_err, n;
  const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
Yaowu Xu's avatar
Yaowu Xu committed
365
  aom_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
Jingning Han's avatar
Jingning Han committed
366 367 368 369 370 371 372 373 374 375
  const int new_mv_mode_penalty = NEW_MV_MODE_PENALTY;

  int step_param = 3;
  int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
  const int sr = get_search_range(cpi);
  step_param += sr;
  further_steps -= sr;

  // Override the default variance function to use MSE.
  v_fn_ptr.vf = get_block_variance_fn(bsize);
Yaowu Xu's avatar
Yaowu Xu committed
376
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
377 378 379
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    v_fn_ptr.vf = highbd_get_block_variance_fn(bsize, xd->bd);
  }
Yaowu Xu's avatar
Yaowu Xu committed
380
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
381 382 383

  // Center the initial step/diamond search on best mv.
  tmp_err = cpi->diamond_search_sad(x, &cpi->ss_cfg, &ref_mv_full, &tmp_mv,
384 385
                                    step_param, x->sadperbit16, &num00,
                                    &v_fn_ptr, ref_mv);
Jingning Han's avatar
Jingning Han committed
386
  if (tmp_err < INT_MAX)
Yaowu Xu's avatar
Yaowu Xu committed
387
    tmp_err = av1_get_mvpred_var(x, &tmp_mv, ref_mv, &v_fn_ptr, 1);
388
  if (tmp_err < INT_MAX - new_mv_mode_penalty) tmp_err += new_mv_mode_penalty;
Jingning Han's avatar
Jingning Han committed
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405

  if (tmp_err < *best_motion_err) {
    *best_motion_err = tmp_err;
    *best_mv = tmp_mv;
  }

  // Carry out 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, &cpi->ss_cfg, &ref_mv_full, &tmp_mv,
406 407
                                        step_param + n, x->sadperbit16, &num00,
                                        &v_fn_ptr, ref_mv);
Jingning Han's avatar
Jingning Han committed
408
      if (tmp_err < INT_MAX)
Yaowu Xu's avatar
Yaowu Xu committed
409
        tmp_err = av1_get_mvpred_var(x, &tmp_mv, ref_mv, &v_fn_ptr, 1);
Jingning Han's avatar
Jingning Han committed
410 411 412 413 414 415 416 417 418 419 420
      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 = tmp_mv;
      }
    }
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
421
static BLOCK_SIZE get_bsize(const AV1_COMMON *cm, int mb_row, int mb_col) {
Jingning Han's avatar
Jingning Han committed
422
  if (2 * mb_col + 1 < cm->mi_cols) {
423
    return 2 * mb_row + 1 < cm->mi_rows ? BLOCK_16X16 : BLOCK_16X8;
Jingning Han's avatar
Jingning Han committed
424
  } else {
425
    return 2 * mb_row + 1 < cm->mi_rows ? BLOCK_8X16 : BLOCK_8X8;
Jingning Han's avatar
Jingning Han committed
426 427 428
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
429
static int find_fp_qindex(aom_bit_depth_t bit_depth) {
Jingning Han's avatar
Jingning Han committed
430 431 432
  int i;

  for (i = 0; i < QINDEX_RANGE; ++i)
Yaowu Xu's avatar
Yaowu Xu committed
433
    if (av1_convert_qindex_to_q(i, bit_depth) >= FIRST_PASS_Q) break;
Jingning Han's avatar
Jingning Han committed
434

435
  if (i == QINDEX_RANGE) i--;
Jingning Han's avatar
Jingning Han committed
436 437 438 439

  return i;
}

Yaowu Xu's avatar
Yaowu Xu committed
440 441
static void set_first_pass_params(AV1_COMP *cpi) {
  AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
442
  if (!cpi->refresh_alt_ref_frame &&
443
      (cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY))) {
Jingning Han's avatar
Jingning Han committed
444 445 446 447 448 449 450 451 452 453
    cm->frame_type = KEY_FRAME;
  } else {
    cm->frame_type = INTER_FRAME;
  }
  // Do not use periodic key frames.
  cpi->rc.frames_to_key = INT_MAX;
}

#define UL_INTRA_THRESH 50
#define INVALID_ROW -1
Yaowu Xu's avatar
Yaowu Xu committed
454
void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) {
Jingning Han's avatar
Jingning Han committed
455 456
  int mb_row, mb_col;
  MACROBLOCK *const x = &cpi->td.mb;
Yaowu Xu's avatar
Yaowu Xu committed
457
  AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
458 459 460 461
  MACROBLOCKD *const xd = &x->e_mbd;
  TileInfo tile;
  struct macroblock_plane *const p = x->plane;
  struct macroblockd_plane *const pd = xd->plane;
Geza Lore's avatar
Geza Lore committed
462 463
  const PICK_MODE_CONTEXT *ctx =
      &cpi->td.pc_root[MAX_MIB_SIZE_LOG2 - MIN_MIB_SIZE_LOG2]->none;
Jingning Han's avatar
Jingning Han committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
  int i;

  int recon_yoffset, recon_uvoffset;
  int64_t intra_error = 0;
  int64_t coded_error = 0;
  int64_t sr_coded_error = 0;

  int sum_mvr = 0, sum_mvc = 0;
  int sum_mvr_abs = 0, sum_mvc_abs = 0;
  int64_t sum_mvrs = 0, sum_mvcs = 0;
  int mvcount = 0;
  int intercount = 0;
  int second_ref_count = 0;
  const int intrapenalty = INTRA_MODE_PENALTY;
  double neutral_count;
  int intra_skip_count = 0;
  int image_data_start_row = INVALID_ROW;
  int new_mv_count = 0;
  int sum_in_vectors = 0;
483
  MV lastmv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
484
  TWO_PASS *twopass = &cpi->twopass;
485
  const MV zero_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
486 487 488 489 490 491 492 493 494
  int recon_y_stride, recon_uv_stride, uv_mb_height;

  YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
  YV12_BUFFER_CONFIG *gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
  YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
  const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
  double intra_factor;
  double brightness_factor;
  BufferPool *const pool = cm->buffer_pool;
495
  const int qindex = find_fp_qindex(cm->bit_depth);
496 497 498
#if CONFIG_PVQ
  PVQ_QUEUE pvq_q;
#endif
Jingning Han's avatar
Jingning Han committed
499 500 501

  // First pass code requires valid last and new frame buffers.
  assert(new_yv12 != NULL);
Yunqing Wang's avatar
Yunqing Wang committed
502
  assert(frame_is_intra_only(cm) || (lst_yv12 != NULL));
Jingning Han's avatar
Jingning Han committed
503 504 505

#if CONFIG_FP_MB_STATS
  if (cpi->use_fp_mb_stats) {
506
    av1_zero_array(cpi->twopass.frame_mb_stats_buf, cpi->initial_mbs);
Jingning Han's avatar
Jingning Han committed
507 508 509
  }
#endif

Yaowu Xu's avatar
Yaowu Xu committed
510
  aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
511 512 513 514 515 516

  intra_factor = 0.0;
  brightness_factor = 0.0;
  neutral_count = 0.0;

  set_first_pass_params(cpi);
517
  av1_set_quantizer(cm, qindex);
Jingning Han's avatar
Jingning Han committed
518

Yaowu Xu's avatar
Yaowu Xu committed
519
  av1_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
Jingning Han's avatar
Jingning Han committed
520

Yaowu Xu's avatar
Yaowu Xu committed
521 522
  av1_setup_src_planes(x, cpi->Source, 0, 0);
  av1_setup_dst_planes(xd->plane, new_yv12, 0, 0);
Jingning Han's avatar
Jingning Han committed
523 524

  if (!frame_is_intra_only(cm)) {
Yaowu Xu's avatar
Yaowu Xu committed
525
    av1_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
Jingning Han's avatar
Jingning Han committed
526 527 528 529 530
  }

  xd->mi = cm->mi_grid_visible;
  xd->mi[0] = cm->mi;

Yaowu Xu's avatar
Yaowu Xu committed
531
  av1_frame_init_quantizer(cpi);
Jingning Han's avatar
Jingning Han committed
532

533 534 535 536 537 538
#if CONFIG_PVQ
  // For pass 1 of 2-pass encoding, init here for PVQ for now.
  {
    od_adapt_ctx *adapt;

    pvq_q.buf_len = 5000;
539 540
    CHECK_MEM_ERROR(cm, pvq_q.buf,
                    aom_malloc(pvq_q.buf_len * sizeof(PVQ_INFO)));
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
    pvq_q.curr_pos = 0;
    x->pvq_coded = 0;

    x->pvq_q = &pvq_q;

    // TODO(yushin): Since this init step is also called in 2nd pass,
    // or 1-pass encoding, consider factoring out it as a function.
    // TODO(yushin)
    // If activity masking is enabled, change below to OD_HVS_QM
    x->daala_enc.qm = OD_FLAT_QM;  // Hard coded. Enc/dec required to sync.
    x->daala_enc.pvq_norm_lambda = OD_PVQ_LAMBDA;
    x->daala_enc.pvq_norm_lambda_dc = OD_PVQ_LAMBDA;

    od_init_qm(x->daala_enc.state.qm, x->daala_enc.state.qm_inv,
               x->daala_enc.qm == OD_HVS_QM ? OD_QM8_Q4_HVS : OD_QM8_Q4_FLAT);
    od_ec_enc_init(&x->daala_enc.ec, 65025);

    adapt = &x->daala_enc.state.adapt;
    od_ec_enc_reset(&x->daala_enc.ec);
    od_adapt_ctx_reset(adapt, 0);
  }
#endif

Jingning Han's avatar
Jingning Han committed
564
  for (i = 0; i < MAX_MB_PLANE; ++i) {
565 566 567
    p[i].coeff = ctx->coeff[i];
    p[i].qcoeff = ctx->qcoeff[i];
    pd[i].dqcoeff = ctx->dqcoeff[i];
568 569 570
#if CONFIG_PVQ
    pd[i].pvq_ref_coeff = ctx->pvq_ref_coeff[i];
#endif
571
    p[i].eobs = ctx->eobs[i];
Jingning Han's avatar
Jingning Han committed
572 573
  }

Yaowu Xu's avatar
Yaowu Xu committed
574
  av1_init_mv_probs(cm);
Angie Chiang's avatar
Angie Chiang committed
575 576 577
#if CONFIG_ADAPT_SCAN
  av1_init_scan_order(cm);
#endif
Angie Chiang's avatar
Angie Chiang committed
578
  av1_convolve_init();
Yaowu Xu's avatar
Yaowu Xu committed
579
  av1_initialize_rd_consts(cpi);
Jingning Han's avatar
Jingning Han committed
580 581

  // Tiling is ignored in the first pass.
Yaowu Xu's avatar
Yaowu Xu committed
582
  av1_tile_init(&tile, cm, 0, 0);
Jingning Han's avatar
Jingning Han committed
583 584 585 586 587 588

  recon_y_stride = new_yv12->y_stride;
  recon_uv_stride = new_yv12->uv_stride;
  uv_mb_height = 16 >> (new_yv12->y_height > new_yv12->uv_height);

  for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
589
    MV best_ref_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
590 591 592 593 594 595 596 597 598

    // Reset above block coeffs.
    xd->up_available = (mb_row != 0);
    recon_yoffset = (mb_row * recon_y_stride * 16);
    recon_uvoffset = (mb_row * recon_uv_stride * uv_mb_height);

    // Set up limit values for motion vectors to prevent them extending
    // outside the UMV borders.
    x->mv_row_min = -((mb_row * 16) + BORDER_MV_PIXELS_B16);
599
    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + BORDER_MV_PIXELS_B16;
Jingning Han's avatar
Jingning Han committed
600 601 602 603 604 605 606 607 608 609 610 611

    for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
      int this_error;
      const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
      const BLOCK_SIZE bsize = get_bsize(cm, mb_row, mb_col);
      double log_intra;
      int level_sample;

#if CONFIG_FP_MB_STATS
      const int mb_index = mb_row * cm->mb_cols + mb_col;
#endif

Yaowu Xu's avatar
Yaowu Xu committed
612
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
613 614 615 616 617 618 619

      xd->plane[0].dst.buf = new_yv12->y_buffer + recon_yoffset;
      xd->plane[1].dst.buf = new_yv12->u_buffer + recon_uvoffset;
      xd->plane[2].dst.buf = new_yv12->v_buffer + recon_uvoffset;
      xd->left_available = (mb_col != 0);
      xd->mi[0]->mbmi.sb_type = bsize;
      xd->mi[0]->mbmi.ref_frame[0] = INTRA_FRAME;
620
      set_mi_row_col(xd, &tile, mb_row << 1, num_8x8_blocks_high_lookup[bsize],
Jingning Han's avatar
Jingning Han committed
621 622
                     mb_col << 1, num_8x8_blocks_wide_lookup[bsize],
                     cm->mi_rows, cm->mi_cols);
623 624 625
      set_plane_n4(xd, num_8x8_blocks_wide_lookup[bsize],
                   num_8x8_blocks_high_lookup[bsize],
                   mi_width_log2_lookup[bsize], mi_height_log2_lookup[bsize]);
Jingning Han's avatar
Jingning Han committed
626 627

      // Do intra 16x16 prediction.
628
      xd->mi[0]->mbmi.segment_id = 0;
629 630 631
#if CONFIG_SUPERTX
      xd->mi[0]->mbmi.segment_id_supertx = 0;
#endif  // CONFIG_SUPERTX
632
      xd->lossless[xd->mi[0]->mbmi.segment_id] = (qindex == 0);
Jingning Han's avatar
Jingning Han committed
633
      xd->mi[0]->mbmi.mode = DC_PRED;
634 635
      xd->mi[0]->mbmi.tx_size =
          use_dc_pred ? (bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4;
Angie Chiang's avatar
Angie Chiang committed
636
      av1_encode_intra_block_plane(cm, x, bsize, 0, 0);
Yaowu Xu's avatar
Yaowu Xu committed
637
      this_error = aom_get_mb_ss(x->plane[0].src_diff);
Jingning Han's avatar
Jingning Han committed
638 639 640 641 642 643 644 645 646 647 648 649

      // Keep a record of blocks that have almost no intra error residual
      // (i.e. are in effect completely flat and untextured in the intra
      // domain). In natural videos this is uncommon, but it is much more
      // common in animations, graphics and screen content, so may be used
      // as a signal to detect these types of content.
      if (this_error < UL_INTRA_THRESH) {
        ++intra_skip_count;
      } else if ((mb_col > 0) && (image_data_start_row == INVALID_ROW)) {
        image_data_start_row = mb_row;
      }

Yaowu Xu's avatar
Yaowu Xu committed
650
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
651 652
      if (cm->use_highbitdepth) {
        switch (cm->bit_depth) {
Yaowu Xu's avatar
Yaowu Xu committed
653 654 655
          case AOM_BITS_8: break;
          case AOM_BITS_10: this_error >>= 4; break;
          case AOM_BITS_12: this_error >>= 8; break;
Jingning Han's avatar
Jingning Han committed
656
          default:
657
            assert(0 &&
Yaowu Xu's avatar
Yaowu Xu committed
658 659
                   "cm->bit_depth should be AOM_BITS_8, "
                   "AOM_BITS_10 or AOM_BITS_12");
Jingning Han's avatar
Jingning Han committed
660 661 662
            return;
        }
      }
Yaowu Xu's avatar
Yaowu Xu committed
663
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
664

Yaowu Xu's avatar
Yaowu Xu committed
665
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
666 667 668 669 670 671
      log_intra = log(this_error + 1.0);
      if (log_intra < 10.0)
        intra_factor += 1.0 + ((10.0 - log_intra) * 0.05);
      else
        intra_factor += 1.0;

Yaowu Xu's avatar
Yaowu Xu committed
672
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
      if (cm->use_highbitdepth)
        level_sample = CONVERT_TO_SHORTPTR(x->plane[0].src.buf)[0];
      else
        level_sample = x->plane[0].src.buf[0];
#else
      level_sample = x->plane[0].src.buf[0];
#endif
      if ((level_sample < DARK_THRESH) && (log_intra < 9.0))
        brightness_factor += 1.0 + (0.01 * (DARK_THRESH - level_sample));
      else
        brightness_factor += 1.0;

      // Intrapenalty below deals with situations where the intra and inter
      // error scores are very low (e.g. a plain black frame).
      // We do not have special cases in first pass for 0,0 and nearest etc so
      // all inter modes carry an overhead cost estimate for the mv.
      // When the error score is very low this causes us to pick all or lots of
      // INTRA modes and throw lots of key frames.
      // This penalty adds a cost matching that of a 0,0 mv to the intra case.
      this_error += intrapenalty;

      // Accumulate the intra error.
      intra_error += (int64_t)this_error;

#if CONFIG_FP_MB_STATS
      if (cpi->use_fp_mb_stats) {
        // initialization
        cpi->twopass.frame_mb_stats_buf[mb_index] = 0;
      }
#endif

      // Set up limit values for motion vectors to prevent them extending
      // outside the UMV borders.
      x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
      x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;

      // Other than for the first frame do a motion search.
Yunqing Wang's avatar
Yunqing Wang committed
710
      if (cm->current_video_frame > 0) {
Jingning Han's avatar
Jingning Han committed
711 712
        int tmp_err, motion_error, raw_motion_error;
        // Assume 0,0 motion with no mv overhead.
713
        MV mv = { 0, 0 }, tmp_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
714 715 716
        struct buf_2d unscaled_last_source_buf_2d;

        xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
Yaowu Xu's avatar
Yaowu Xu committed
717
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
718 719 720 721
        if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
          motion_error = highbd_get_prediction_error(
              bsize, &x->plane[0].src, &xd->plane[0].pre[0], xd->bd);
        } else {
722 723
          motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                              &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
724 725
        }
#else
726 727
        motion_error =
            get_prediction_error(bsize, &x->plane[0].src, &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
728
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
729 730 731 732 733 734 735 736

        // Compute the motion error of the 0,0 motion using the last source
        // frame as the reference. Skip the further motion search on
        // reconstructed frame if this error is small.
        unscaled_last_source_buf_2d.buf =
            cpi->unscaled_last_source->y_buffer + recon_yoffset;
        unscaled_last_source_buf_2d.stride =
            cpi->unscaled_last_source->y_stride;
Yaowu Xu's avatar
Yaowu Xu committed
737
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
738 739 740 741
        if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
          raw_motion_error = highbd_get_prediction_error(
              bsize, &x->plane[0].src, &unscaled_last_source_buf_2d, xd->bd);
        } else {
742 743
          raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                  &unscaled_last_source_buf_2d);
Jingning Han's avatar
Jingning Han committed
744 745
        }
#else
746 747
        raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                &unscaled_last_source_buf_2d);
Yaowu Xu's avatar
Yaowu Xu committed
748
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
749 750

        // TODO(pengchong): Replace the hard-coded threshold
Yunqing Wang's avatar
Yunqing Wang committed
751
        if (raw_motion_error > 25) {
Jingning Han's avatar
Jingning Han committed
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
          // Test last reference frame using the previous best mv as the
          // starting point (best reference) for the search.
          first_pass_motion_search(cpi, x, &best_ref_mv, &mv, &motion_error);

          // If the current best reference mv is not centered on 0,0 then do a
          // 0,0 based search as well.
          if (!is_zero_mv(&best_ref_mv)) {
            tmp_err = INT_MAX;
            first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv, &tmp_err);

            if (tmp_err < motion_error) {
              motion_error = tmp_err;
              mv = tmp_mv;
            }
          }

          // Search in an older reference frame.
Yunqing Wang's avatar
Yunqing Wang committed
769
          if ((cm->current_video_frame > 1) && gld_yv12 != NULL) {
Jingning Han's avatar
Jingning Han committed
770 771 772 773
            // Assume 0,0 motion with no mv overhead.
            int gf_motion_error;

            xd->plane[0].pre[0].buf = gld_yv12->y_buffer + recon_yoffset;
Yaowu Xu's avatar
Yaowu Xu committed
774
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
775 776 777 778
            if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
              gf_motion_error = highbd_get_prediction_error(
                  bsize, &x->plane[0].src, &xd->plane[0].pre[0], xd->bd);
            } else {
779 780
              gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                     &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
781 782
            }
#else
783 784
            gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                   &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
785
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831

            first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv,
                                     &gf_motion_error);

            if (gf_motion_error < motion_error && gf_motion_error < this_error)
              ++second_ref_count;

            // Reset to last frame as reference buffer.
            xd->plane[0].pre[0].buf = first_ref_buf->y_buffer + recon_yoffset;
            xd->plane[1].pre[0].buf = first_ref_buf->u_buffer + recon_uvoffset;
            xd->plane[2].pre[0].buf = first_ref_buf->v_buffer + recon_uvoffset;

            // In accumulating a score for the older reference frame take the
            // best of the motion predicted score and the intra coded error
            // (just as will be done for) accumulation of "coded_error" for
            // the last frame.
            if (gf_motion_error < this_error)
              sr_coded_error += gf_motion_error;
            else
              sr_coded_error += this_error;
          } else {
            sr_coded_error += motion_error;
          }
        } else {
          sr_coded_error += motion_error;
        }

        // Start by assuming that intra mode is best.
        best_ref_mv.row = 0;
        best_ref_mv.col = 0;

#if CONFIG_FP_MB_STATS
        if (cpi->use_fp_mb_stats) {
          // intra predication statistics
          cpi->twopass.frame_mb_stats_buf[mb_index] = 0;
          cpi->twopass.frame_mb_stats_buf[mb_index] |= FPMB_DCINTRA_MASK;
          cpi->twopass.frame_mb_stats_buf[mb_index] |= FPMB_MOTION_ZERO_MASK;
          if (this_error > FPMB_ERROR_LARGE_TH) {
            cpi->twopass.frame_mb_stats_buf[mb_index] |= FPMB_ERROR_LARGE_MASK;
          } else if (this_error < FPMB_ERROR_SMALL_TH) {
            cpi->twopass.frame_mb_stats_buf[mb_index] |= FPMB_ERROR_SMALL_MASK;
          }
        }
#endif

        if (motion_error <= this_error) {
Yaowu Xu's avatar
Yaowu Xu committed
832
          aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
833 834 835 836 837 838 839

          // Keep a count of cases where the inter and intra were very close
          // and very low. This helps with scene cut detection for example in
          // cropped clips with black bars at the sides or top and bottom.
          if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
              (this_error < (2 * intrapenalty))) {
            neutral_count += 1.0;
840 841
            // Also track cases where the intra is not much worse than the inter
            // and use this in limiting the GF/arf group length.
Jingning Han's avatar
Jingning Han committed
842 843
          } else if ((this_error > NCOUNT_INTRA_THRESH) &&
                     (this_error < (NCOUNT_INTRA_FACTOR * motion_error))) {
844 845
            neutral_count +=
                (double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error);
Jingning Han's avatar
Jingning Han committed
846 847 848 849 850 851 852 853 854 855
          }

          mv.row *= 8;
          mv.col *= 8;
          this_error = motion_error;
          xd->mi[0]->mbmi.mode = NEWMV;
          xd->mi[0]->mbmi.mv[0].as_mv = mv;
          xd->mi[0]->mbmi.tx_size = TX_4X4;
          xd->mi[0]->mbmi.ref_frame[0] = LAST_FRAME;
          xd->mi[0]->mbmi.ref_frame[1] = NONE;
Yaowu Xu's avatar
Yaowu Xu committed
856
          av1_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
Angie Chiang's avatar
Angie Chiang committed
857
          av1_encode_sby_pass1(cm, x, bsize);
Jingning Han's avatar
Jingning Han committed
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
          sum_mvr += mv.row;
          sum_mvr_abs += abs(mv.row);
          sum_mvc += mv.col;
          sum_mvc_abs += abs(mv.col);
          sum_mvrs += mv.row * mv.row;
          sum_mvcs += mv.col * mv.col;
          ++intercount;

          best_ref_mv = mv;

#if CONFIG_FP_MB_STATS
          if (cpi->use_fp_mb_stats) {
            // inter predication statistics
            cpi->twopass.frame_mb_stats_buf[mb_index] = 0;
            cpi->twopass.frame_mb_stats_buf[mb_index] &= ~FPMB_DCINTRA_MASK;
            cpi->twopass.frame_mb_stats_buf[mb_index] |= FPMB_MOTION_ZERO_MASK;
            if (this_error > FPMB_ERROR_LARGE_TH) {
              cpi->twopass.frame_mb_stats_buf[mb_index] |=
                  FPMB_ERROR_LARGE_MASK;
            } else if (this_error < FPMB_ERROR_SMALL_TH) {
              cpi->twopass.frame_mb_stats_buf[mb_index] |=
                  FPMB_ERROR_SMALL_MASK;
            }
          }
#endif

          if (!is_zero_mv(&mv)) {
            ++mvcount;

#if CONFIG_FP_MB_STATS
            if (cpi->use_fp_mb_stats) {
              cpi->twopass.frame_mb_stats_buf[mb_index] &=
                  ~FPMB_MOTION_ZERO_MASK;
              // check estimated motion direction
892
              if (mv.col > 0 && mv.col >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
893 894 895
                // right direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_RIGHT_MASK;
896
              } else if (mv.row < 0 && abs(mv.row) >= abs(mv.col)) {
Jingning Han's avatar
Jingning Han committed
897 898 899
                // up direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_UP_MASK;
900
              } else if (mv.col < 0 && abs(mv.col) >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
901 902 903 904 905 906 907 908 909 910 911 912
                // left direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_LEFT_MASK;
              } else {
                // down direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_DOWN_MASK;
              }
            }
#endif

            // Non-zero vector, was it different from the last non zero vector?
913
            if (!is_equal_mv(&mv, &lastmv)) ++new_mv_count;
Jingning Han's avatar
Jingning Han committed
914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
            lastmv = mv;

            // Does the row vector point inwards or outwards?
            if (mb_row < cm->mb_rows / 2) {
              if (mv.row > 0)
                --sum_in_vectors;
              else if (mv.row < 0)
                ++sum_in_vectors;
            } else if (mb_row > cm->mb_rows / 2) {
              if (mv.row > 0)
                ++sum_in_vectors;
              else if (mv.row < 0)
                --sum_in_vectors;
            }

            // Does the col vector point inwards or outwards?
            if (mb_col < cm->mb_cols / 2) {
              if (mv.col > 0)
                --sum_in_vectors;
              else if (mv.col < 0)
                ++sum_in_vectors;
            } else if (mb_col > cm->mb_cols / 2) {
              if (mv.col > 0)
                ++sum_in_vectors;
              else if (mv.col < 0)
                --sum_in_vectors;
            }
          }
        }
      } else {
        sr_coded_error += (int64_t)this_error;
      }
      coded_error += (int64_t)this_error;

      // Adjust to the next column of MBs.
      x->plane[0].src.buf += 16;
      x->plane[1].src.buf += uv_mb_height;
      x->plane[2].src.buf += uv_mb_height;

      recon_yoffset += 16;
      recon_uvoffset += uv_mb_height;
    }

    // Adjust to the next row of MBs.
    x->plane[0].src.buf += 16 * x->plane[0].src.stride - 16 * cm->mb_cols;
959 960 961 962
    x->plane[1].src.buf +=
        uv_mb_height * x->plane[1].src.stride - uv_mb_height * cm->mb_cols;
    x->plane[2].src.buf +=
        uv_mb_height * x->plane[1].src.stride - uv_mb_height * cm->mb_cols;
Jingning Han's avatar
Jingning Han committed
963

Yaowu Xu's avatar
Yaowu Xu committed
964
    aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
965 966
  }

967 968 969 970 971 972 973 974 975 976
#if CONFIG_PVQ
  od_ec_enc_clear(&x->daala_enc.ec);

  x->pvq_q->last_pos = x->pvq_q->curr_pos;
  x->pvq_q->curr_pos = 0;
  x->pvq_q = NULL;

  aom_free(pvq_q.buf);
#endif

Jingning Han's avatar
Jingning Han committed
977 978 979 980 981 982 983 984 985
  // Clamp the image start to rows/2. This number of rows is discarded top
  // and bottom as dead data so rows / 2 means the frame is blank.
  if ((image_data_start_row > cm->mb_rows / 2) ||
      (image_data_start_row == INVALID_ROW)) {
    image_data_start_row = cm->mb_rows / 2;
  }
  // Exclude any image dead zone
  if (image_data_start_row > 0) {
    intra_skip_count =
Yaowu Xu's avatar
Yaowu Xu committed
986
        AOMMAX(0, intra_skip_count - (image_data_start_row * cm->mb_cols * 2));
Jingning Han's avatar
Jingning Han committed
987 988 989 990 991 992 993 994 995 996
  }

  {
    FIRSTPASS_STATS fps;
    // The minimum error here insures some bit allocation to frames even
    // in static regions. The allocation per MB declines for larger formats
    // where the typical "real" energy per MB also falls.
    // Initial estimate here uses sqrt(mbs) to define the min_err, where the
    // number of mbs is proportional to the image area.
    const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE)
997 998
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Jingning Han's avatar
Jingning Han committed
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    const double min_err = 200 * sqrt(num_mbs);

    intra_factor = intra_factor / (double)num_mbs;
    brightness_factor = brightness_factor / (double)num_mbs;
    fps.weight = intra_factor * brightness_factor;

    fps.frame = cm->current_video_frame;
    fps.coded_error = (double)(coded_error >> 8) + min_err;
    fps.sr_coded_error = (double)(sr_coded_error >> 8) + min_err;
    fps.intra_error = (double)(intra_error >> 8) + min_err;
    fps.count = 1.0;
    fps.pcnt_inter = (double)intercount / num_mbs;
    fps.pcnt_second_ref = (double)second_ref_count / num_mbs;
    fps.pcnt_neutral = (double)neutral_count / num_mbs;
    fps.intra_skip_pct = (double)intra_skip_count / num_mbs;
    fps.inactive_zone_rows = (double)image_data_start_row;
    fps.inactive_zone_cols = (double)0;  // TODO(paulwilkins): fix

    if (mvcount > 0) {
      fps.MVr = (double)sum_mvr / mvcount;
      fps.mvr_abs = (double)sum_mvr_abs / mvcount;
      fps.MVc = (double)sum_mvc / mvcount;
      fps.mvc_abs = (double)sum_mvc_abs / mvcount;
1022 1023 1024 1025
      fps.MVrv =
          ((double)sum_mvrs - ((double)sum_mvr * sum_mvr / mvcount)) / mvcount;
      fps.MVcv =
          ((double)sum_mvcs - ((double)sum_mvc * sum_mvc / mvcount)) / mvcount;
Jingning Han's avatar
Jingning Han committed
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
      fps.mv_in_out_count = (double)sum_in_vectors / (mvcount * 2);
      fps.new_mv_count = new_mv_count;
      fps.pcnt_motion = (double)mvcount / num_mbs;
    } else {
      fps.MVr = 0.0;
      fps.mvr_abs = 0.0;
      fps.MVc = 0.0;
      fps.mvc_abs = 0.0;
      fps.MVrv = 0.0;
      fps.MVcv = 0.0;
      fps.mv_in_out_count = 0.0;
      fps.new_mv_count = 0.0;
      fps.pcnt_motion = 0.0;
    }

    // TODO(paulwilkins):  Handle the case when duration is set to 0, or
    // something less than the full time between subsequent values of
    // cpi->source_time_stamp.
    fps.duration = (double)(source->ts_end - source->ts_start);

    // Don't want to do output stats with a stack variable!
    twopass->this_frame_stats = fps;
    output_stats(&twopass->this_frame_stats, cpi->output_pkt_list);
    accumulate_stats(&twopass->total_stats, &fps);

#if CONFIG_FP_MB_STATS
    if (cpi->use_fp_mb_stats) {
1053 1054
      output_fpmb_stats(twopass->frame_mb_stats_buf, cpi->initial_mbs,
                        cpi->output_pkt_list);
Jingning Han's avatar
Jingning Han committed
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
    }
#endif
  }

  // Copy the previous Last Frame back into gf and and arf buffers if
  // the prediction is good enough... but also don't allow it to lag too far.
  if ((twopass->sr_update_lag > 3) ||
      ((cm->current_video_frame > 0) &&
       (twopass->this_frame_stats.pcnt_inter > 0.20) &&
       ((twopass->this_frame_stats.intra_error /
         DOUBLE_DIVIDE_CHECK(twopass->this_frame_stats.coded_error)) > 2.0))) {
    if (gld_yv12 != NULL) {
1067 1068 1069 1070
#if CONFIG_EXT_REFS
      ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
                 cm->ref_frame_map[cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]]);
#else
Jingning Han's avatar
Jingning Han committed
1071 1072
      ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
                 cm->ref_frame_map[cpi->lst_fb_idx]);
1073
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1074 1075 1076 1077 1078 1079
    }
    twopass->sr_update_lag = 1;
  } else {
    ++twopass->sr_update_lag;
  }

Yaowu Xu's avatar
Yaowu Xu committed
1080
  aom_extend_frame_borders(new_yv12);
Jingning Han's avatar
Jingning Han committed
1081

1082
// The frame we just compressed now becomes the last frame.
1083 1084 1085 1086 1087
#if CONFIG_EXT_REFS
  ref_cnt_fb(pool->frame_bufs,
             &cm->ref_frame_map[cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]],
             cm->new_fb_idx);
#else
Yunqing Wang's avatar
Yunqing Wang committed
1088 1089
  ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
             cm->new_fb_idx);
1090
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1091 1092 1093

  // Special case for the first frame. Copy into the GF buffer as a second
  // reference.
Yunqing Wang's avatar
Yunqing Wang committed
1094
  if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
1095 1096 1097 1098
#if CONFIG_EXT_REFS
    ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
               cm->ref_frame_map[cpi->lst_fb_idxes[LAST_FRAME - LAST_FRAME]]);
#else
Jingning Han's avatar
Jingning Han committed
1099 1100
    ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
               cm->ref_frame_map[cpi->lst_fb_idx]);
1101
#endif  // CONFIG_EXT_REFS