firstpass.c 109 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
#include "av1/encoder/av1_quantize.h"
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/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) {
422
423
424
425
426
427
  if (mi_size_wide[BLOCK_16X16] * mb_col + mi_size_wide[BLOCK_8X8] <
      cm->mi_cols) {
    return mi_size_wide[BLOCK_16X16] * mb_row + mi_size_wide[BLOCK_8X8] <
                   cm->mi_rows
               ? BLOCK_16X16
               : BLOCK_16X8;
Jingning Han's avatar
Jingning Han committed
428
  } else {
429
430
431
432
    return mi_size_wide[BLOCK_16X16] * mb_row + mi_size_wide[BLOCK_8X8] <
                   cm->mi_rows
               ? BLOCK_8X16
               : BLOCK_8X8;
Jingning Han's avatar
Jingning Han committed
433
434
435
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
436
static int find_fp_qindex(aom_bit_depth_t bit_depth) {
Jingning Han's avatar
Jingning Han committed
437
438
439
  int i;

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

442
  if (i == QINDEX_RANGE) i--;
Jingning Han's avatar
Jingning Han committed
443
444
445
446

  return i;
}

Yaowu Xu's avatar
Yaowu Xu committed
447
448
static void set_first_pass_params(AV1_COMP *cpi) {
  AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
449
  if (!cpi->refresh_alt_ref_frame &&
450
      (cm->current_video_frame == 0 || (cpi->frame_flags & FRAMEFLAGS_KEY))) {
Jingning Han's avatar
Jingning Han committed
451
452
453
454
455
456
457
458
459
460
    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
461
void av1_first_pass(AV1_COMP *cpi, const struct lookahead_entry *source) {
Jingning Han's avatar
Jingning Han committed
462
463
  int mb_row, mb_col;
  MACROBLOCK *const x = &cpi->td.mb;
Yaowu Xu's avatar
Yaowu Xu committed
464
  AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
465
466
467
468
  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
469
470
  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
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
  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;
490
  MV lastmv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
491
  TWO_PASS *twopass = &cpi->twopass;
492
  const MV zero_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
493
494
495
496
497
498
499
500
501
  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;
502
  const int qindex = find_fp_qindex(cm->bit_depth);
503
  const int mb_scale = mi_size_wide[BLOCK_16X16];
504
505
506
#if CONFIG_PVQ
  PVQ_QUEUE pvq_q;
#endif
Jingning Han's avatar
Jingning Han committed
507
508
509

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

#if CONFIG_FP_MB_STATS
  if (cpi->use_fp_mb_stats) {
514
    av1_zero_array(cpi->twopass.frame_mb_stats_buf, cpi->initial_mbs);
Jingning Han's avatar
Jingning Han committed
515
516
517
  }
#endif

Yaowu Xu's avatar
Yaowu Xu committed
518
  aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
519
520
521
522
523
524

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

  set_first_pass_params(cpi);
525
  av1_set_quantizer(cm, qindex);
Jingning Han's avatar
Jingning Han committed
526

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

Yaowu Xu's avatar
Yaowu Xu committed
529
530
  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
531
532

  if (!frame_is_intra_only(cm)) {
Yaowu Xu's avatar
Yaowu Xu committed
533
    av1_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
Jingning Han's avatar
Jingning Han committed
534
535
536
537
538
  }

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

Yaowu Xu's avatar
Yaowu Xu committed
539
  av1_frame_init_quantizer(cpi);
Jingning Han's avatar
Jingning Han committed
540

541
542
543
544
545
546
#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;
547
548
    CHECK_MEM_ERROR(cm, pvq_q.buf,
                    aom_malloc(pvq_q.buf_len * sizeof(PVQ_INFO)));
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);
564
565
566
567
568
#if CONFIG_DAALA_EC
    od_ec_enc_init(&x->daala_enc.w.ec, 65025);
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
569
570

    adapt = &x->daala_enc.state.adapt;
571
572
573
574
575
#if CONFIG_DAALA_EC
    od_ec_enc_reset(&x->daala_enc.w.ec);
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
576
577
578
579
    od_adapt_ctx_reset(adapt, 0);
  }
#endif

Jingning Han's avatar
Jingning Han committed
580
  for (i = 0; i < MAX_MB_PLANE; ++i) {
581
582
583
    p[i].coeff = ctx->coeff[i];
    p[i].qcoeff = ctx->qcoeff[i];
    pd[i].dqcoeff = ctx->dqcoeff[i];
584
585
586
#if CONFIG_PVQ
    pd[i].pvq_ref_coeff = ctx->pvq_ref_coeff[i];
#endif
587
    p[i].eobs = ctx->eobs[i];
Jingning Han's avatar
Jingning Han committed
588
589
  }

Yaowu Xu's avatar
Yaowu Xu committed
590
  av1_init_mv_probs(cm);
Angie Chiang's avatar
Angie Chiang committed
591
592
593
#if CONFIG_ADAPT_SCAN
  av1_init_scan_order(cm);
#endif
Angie Chiang's avatar
Angie Chiang committed
594
  av1_convolve_init();
Yaowu Xu's avatar
Yaowu Xu committed
595
  av1_initialize_rd_consts(cpi);
Jingning Han's avatar
Jingning Han committed
596
597

  // Tiling is ignored in the first pass.
Yaowu Xu's avatar
Yaowu Xu committed
598
  av1_tile_init(&tile, cm, 0, 0);
Jingning Han's avatar
Jingning Han committed
599
600
601
602
603
604

  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) {
605
    MV best_ref_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
606
607
608
609
610
611
612
613
614

    // 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);
615
    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + BORDER_MV_PIXELS_B16;
Jingning Han's avatar
Jingning Han committed
616
617
618
619
620
621
622
623
624
625
626
627

    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
628
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
629
630
631
632
633
634
635

      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;
636
637
638
639
640
#if CONFIG_DEPENDENT_HORZTILES
      set_mi_row_col(xd, &tile, mb_row * mb_scale, mi_size_high[bsize],
                     mb_col * mb_scale, mi_size_wide[bsize], cm->mi_rows,
                     cm->mi_cols, cm->dependent_horz_tiles);
#else
641
642
643
      set_mi_row_col(xd, &tile, mb_row * mb_scale, mi_size_high[bsize],
                     mb_col * mb_scale, mi_size_wide[bsize], cm->mi_rows,
                     cm->mi_cols);
644
645
#endif

Jingning Han's avatar
Jingning Han committed
646
      set_plane_n4(xd, mi_size_wide[bsize], mi_size_high[bsize]);
Jingning Han's avatar
Jingning Han committed
647
648

      // Do intra 16x16 prediction.
649
      xd->mi[0]->mbmi.segment_id = 0;
650
651
652
#if CONFIG_SUPERTX
      xd->mi[0]->mbmi.segment_id_supertx = 0;
#endif  // CONFIG_SUPERTX
653
      xd->lossless[xd->mi[0]->mbmi.segment_id] = (qindex == 0);
Jingning Han's avatar
Jingning Han committed
654
      xd->mi[0]->mbmi.mode = DC_PRED;
655
656
      xd->mi[0]->mbmi.tx_size =
          use_dc_pred ? (bsize >= BLOCK_16X16 ? TX_16X16 : TX_8X8) : TX_4X4;
657
      av1_encode_intra_block_plane(cm, x, bsize, 0, 0, mb_row * 2, mb_col * 2);
Yaowu Xu's avatar
Yaowu Xu committed
658
      this_error = aom_get_mb_ss(x->plane[0].src_diff);
Jingning Han's avatar
Jingning Han committed
659
660
661
662
663
664
665
666
667
668
669
670

      // 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
671
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
672
673
      if (cm->use_highbitdepth) {
        switch (cm->bit_depth) {
Yaowu Xu's avatar
Yaowu Xu committed
674
675
676
          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
677
          default:
678
            assert(0 &&
Yaowu Xu's avatar
Yaowu Xu committed
679
680
                   "cm->bit_depth should be AOM_BITS_8, "
                   "AOM_BITS_10 or AOM_BITS_12");
Jingning Han's avatar
Jingning Han committed
681
682
683
            return;
        }
      }
Yaowu Xu's avatar
Yaowu Xu committed
684
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
685

Yaowu Xu's avatar
Yaowu Xu committed
686
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
687
688
689
690
691
692
      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
693
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
      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;

730
      if (!frame_is_intra_only(cm)) {  // Do a motion search
Jingning Han's avatar
Jingning Han committed
731
732
        int tmp_err, motion_error, raw_motion_error;
        // Assume 0,0 motion with no mv overhead.
733
        MV mv = { 0, 0 }, tmp_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
734
735
736
        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
737
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
738
739
740
741
        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 {
742
743
          motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                              &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
744
745
        }
#else
746
747
        motion_error =
            get_prediction_error(bsize, &x->plane[0].src, &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
748
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
749
750
751
752
753
754
755
756

        // 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
757
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
758
759
760
761
        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 {
762
763
          raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                  &unscaled_last_source_buf_2d);
Jingning Han's avatar
Jingning Han committed
764
765
        }
#else
766
767
        raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                &unscaled_last_source_buf_2d);
Yaowu Xu's avatar
Yaowu Xu committed
768
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
769
770

        // TODO(pengchong): Replace the hard-coded threshold
Yunqing Wang's avatar
Yunqing Wang committed
771
        if (raw_motion_error > 25) {
Jingning Han's avatar
Jingning Han committed
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
          // 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
789
          if ((cm->current_video_frame > 1) && gld_yv12 != NULL) {
Jingning Han's avatar
Jingning Han committed
790
791
792
793
            // 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
794
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
795
796
797
798
            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 {
799
800
              gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                     &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
801
802
            }
#else
803
804
            gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                   &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
805
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
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
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

            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
852
          aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
853
854
855
856
857
858
859

          // 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;
860
861
            // 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
862
863
          } else if ((this_error > NCOUNT_INTRA_THRESH) &&
                     (this_error < (NCOUNT_INTRA_FACTOR * motion_error))) {
864
865
            neutral_count +=
                (double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error);
Jingning Han's avatar
Jingning Han committed
866
867
868
869
870
871
872
873
874
          }

          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;
Emil Keyder's avatar
Emil Keyder committed
875
          xd->mi[0]->mbmi.ref_frame[1] = NONE_FRAME;
876
877
          av1_build_inter_predictors_sby(xd, mb_row * mb_scale,
                                         mb_col * mb_scale, NULL, bsize);
Angie Chiang's avatar
Angie Chiang committed
878
          av1_encode_sby_pass1(cm, x, bsize);
Jingning Han's avatar
Jingning Han committed
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
          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
913
              if (mv.col > 0 && mv.col >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
914
915
916
                // right direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_RIGHT_MASK;
917
              } else if (mv.row < 0 && abs(mv.row) >= abs(mv.col)) {
Jingning Han's avatar
Jingning Han committed
918
919
920
                // up direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_UP_MASK;
921
              } else if (mv.col < 0 && abs(mv.col) >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
922
923
924
925
926
927
928
929
930
931
932
933
                // 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?
934
            if (!is_equal_mv(&mv, &lastmv)) ++new_mv_count;
Jingning Han's avatar
Jingning Han committed
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
            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;
980
981
982
983
    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
984

Yaowu Xu's avatar
Yaowu Xu committed
985
    aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
986
987
  }

988
#if CONFIG_PVQ
989
990
991
992
993
#if CONFIG_DAALA_EC
  od_ec_enc_clear(&x->daala_enc.w.ec);
#else
#error "CONFIG_PVQ currently requires CONFIG_DAALA_EC."
#endif
994
995
996
997
998
999
1000
1001

  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
1002
1003
1004
1005
1006
1007
1008
1009
1010
  // 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
1011
        AOMMAX(0, intra_skip_count - (image_data_start_row * cm->mb_cols * 2));
Jingning Han's avatar
Jingning Han committed
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  }

  {
    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)
1022
1023
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Jingning Han's avatar
Jingning Han committed
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
    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;
1047
1048
1049
1050
      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
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
      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) {
1078
1079
      output_fpmb_stats(twopass->frame_mb_stats_buf, cpi->initial_mbs,
                        cpi->output_pkt_list);
Jingning Han's avatar
Jingning Han committed
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
    }
#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) {
1092
1093
1094
1095
#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
1096
1097
      ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
                 cm->ref_frame_map[cpi->lst_fb_idx]);
1098
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1099
1100
1101
1102
1103
1104
    }
    twopass->sr_update_lag = 1;
  } else {
    ++twopass->sr_update_lag;
  }

Yaowu Xu's avatar
Yaowu Xu committed
1105
  aom_extend_frame_borders(new_yv12);
Jingning Han's avatar
Jingning Han committed
1106

1107
// The frame we just compressed now becomes the last frame.
1108
1109
1110
1111
1112
#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
1113
1114
  ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
             cm->new_fb_idx);
1115
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1116
1117
1118

  // Special case for the first frame. Copy into the GF buffer as a second
  // reference.
Yunqing Wang's avatar
Yunqing Wang committed
1119
  if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
1120
1121
1122
1123
#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
1124
1125
    ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
               cm->ref_frame_map[cpi->lst_fb_idx]);
1126
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
  }

  // Use this to see what the first pass reconstruction looks like.
  if (0) {
    char filename[512];
    FILE *recon_file;
    snprintf(filename, sizeof(filename), "enc%04d.yuv",
             (int)cm->current_video_frame);

    if (cm->current_video_frame == 0)
      recon_file = fopen(filename, "wb");
    else
      recon_file = fopen(filename, "ab");

    (void)fwrite(lst_yv12->buffer_alloc, lst_yv12->frame_size, 1, recon_file);
    fclose(recon_file);
  }

  ++cm->current_video_frame;
}

1148
1149
static double calc_correction_factor(double err_per_mb, double err_divisor,
                                     double pt_low, double pt_high, int q,
Yaowu Xu's avatar
Yaowu Xu committed
1150
                                     aom_bit_depth_t bit_depth) {
Jingning Han's avatar
Jingning Han committed
1151
1152
1153
1154
  const double error_term = err_per_mb / err_divisor;

  // Adjustment based on actual quantizer to power term.
  const double power_term =
Yaowu Xu's avatar
Yaowu Xu committed
1155
      AOMMIN(av1_convert_qindex_to_q(q, bit_depth) * 0.01 + pt_low, pt_high);
Jingning Han's avatar
Jingning Han committed
1156
1157

  // Calculate correction factor.
1158
  if (power_term < 1.0) assert(error_term >= 0.0);
Jingning Han's avatar
Jingning Han committed
1159
1160
1161
1162

  return fclamp(pow(error_term, power_term), 0.05, 5.0);
}

1163
#define ERR_DIVISOR 100.0
Yaowu Xu's avatar
Yaowu Xu committed
1164
static int get_twopass_worst_quality(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1165
1166
1167
1168
1169
                                     const double section_err,
                                     double inactive_zone,
                                     int section_target_bandwidth,
                                     double group_weight_factor) {
  const RATE_CONTROL *const rc = &cpi->rc;
Yaowu Xu's avatar
Yaowu Xu committed
1170
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
Jingning Han's avatar
Jingning Han committed
1171
1172
1173
1174
1175
1176
1177

  inactive_zone = fclamp(inactive_zone, 0.0, 1.0);

  if (section_target_bandwidth <= 0) {
    return rc->worst_quality;  // Highest value allowed
  } else {
    const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE)
1178
1179
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Yaowu Xu's avatar
Yaowu Xu committed
1180
    const int active_mbs = AOMMAX(1, num_mbs - (int)(num_mbs * inactive_zone));
Jingning Han's avatar
Jingning Han committed
1181
1182
    const double av_err_per_mb = section_err / active_mbs;
    const double speed_term = 1.0 + 0.04 * oxcf->speed;
paulwilkins's avatar
paulwilkins committed
1183
    double ediv_size_correction;
1184
1185
    const int target_norm_bits_per_mb =
        ((uint64_t)section_target_bandwidth << BPER_MB_NORMBITS) / active_mbs;
Jingning Han's avatar
Jingning Han committed
1186
1187
    int q;

paulwilkins's avatar
paulwilkins committed
1188
1189
1190
1191
1192
1193
    // Larger image formats are expected to be a little harder to code
    // relatively given the same prediction error score. This in part at
    // least relates to the increased size and hence coding overheads of
    // motion vectors. Some account of this is made through adjustment of
    // the error divisor.
    ediv_size_correction =
Yaowu Xu's avatar
Yaowu Xu committed
1194
        AOMMAX(0.2, AOMMIN(5.0, get_linear_size_factor(cpi)));
paulwilkins's avatar
paulwilkins committed
1195
1196
1197
1198
    if (ediv_size_correction < 1.0)
      ediv_size_correction = -(1.0 / ediv_size_correction);
    ediv_size_correction *= 4.0;

Jingning Han's avatar
Jingning Han committed
1199
1200
1201
    // Try and pick a max Q that will be high enough to encode the
    // content at the given rate.
    for (q = rc->best_quality; q < rc->worst_quality; ++q) {
1202
1203
1204
      const double factor = calc_correction_factor(
          av_err_per_mb, ERR_DIVISOR - ediv_size_correction, FACTOR_PT_LOW,
          FACTOR_PT_HIGH, q, cpi->common.bit_depth);
Yaowu Xu's avatar
Yaowu Xu committed
1205
      const int bits_per_mb = av1_rc_bits_per_mb(
1206
1207
1208
          INTER_FRAME, q, factor * speed_term * group_weight_factor,
          cpi->common.bit_depth);
      if (bits_per_mb <= target_norm_bits_per_mb) break;
Jingning Han's avatar
Jingning Han committed
1209
1210
1211
    }

    // Restriction on active max q for constrained quality mode.
Yaowu Xu's avatar
Yaowu Xu committed
1212
    if (cpi->oxcf.rc_mode == AOM_CQ) q = AOMMAX(q, oxcf->cq_level);
Jingning Han's avatar
Jingning Han committed
1213
1214
1215
1216
    return q;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1217
static void setup_rf_level_maxq(AV1_COMP *cpi) {
Jingning Han's avatar
Jingning Han committed
1218
1219
1220
  int i;
  RATE_CONTROL *const rc = &cpi->rc;
  for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) {
Yaowu Xu's avatar
Yaowu Xu committed
1221
1222
    int qdelta = av1_frame_type_qdelta(cpi, i, rc->worst_quality);
    rc->rf_level_maxq[i] = AOMMAX(rc->worst_quality + qdelta, rc->best_quality);
Jingning Han's avatar
Jingning Han committed
1223
1224
1225
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1226
1227
void av1_init_subsampling(AV1_COMP *cpi) {
  const AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
  RATE_CONTROL *const rc = &cpi->rc;
  const int w = cm->width;
  const int h = cm->height;
  int i;

  for (i = 0; i < FRAME_SCALE_STEPS; ++i) {
    // Note: Frames with odd-sized dimensions may result from this scaling.
    rc->frame_width[i] = (w * 16) / frame_scale_factor[i];
    rc->frame_height[i] = (h * 16) / frame_scale_factor[i];
  }

  setup_rf_level_maxq(cpi);
}

Yaowu Xu's avatar
Yaowu Xu committed
1242
1243
void av1_calculate_coded_size(AV1_COMP *cpi, int *scaled_frame_width,
                              int *scaled_frame_height) {
Jingning Han's avatar
Jingning Han committed
1244
1245
1246
1247
1248
  RATE_CONTROL *const rc = &cpi->rc;
  *scaled_frame_width = rc->frame_width[rc->frame_size_selector];
  *scaled_frame_height = rc->frame_height[rc->frame_size_selector];
}

Yaowu Xu's avatar
Yaowu Xu committed
1249
1250
void av1_init_second_pass(AV1_COMP *cpi) {
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
Yunqing Wang's avatar
Yunqing Wang committed
1251
  TWO_PASS *const twopass = &cpi->twopass;
Jingning Han's avatar
Jingning Han committed
1252
1253
1254
1255
1256
1257
  double frame_rate;
  FIRSTPASS_STATS *stats;

  zero_stats(&twopass->total_stats);
  zero_stats(&twopass->total_left_stats);

1258
  if (!twopass->stats_in_end) return;
Jingning Han's avatar
Jingning Han committed
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270

  stats = &twopass->total_stats;

  *stats = *twopass->stats_in_end;
  twopass->total_left_stats = *stats;

  frame_rate = 10000000.0 * stats->count / stats->duration;
  // Each frame can have a different duration, as the frame rate in the source
  // isn't guaranteed to be constant. The frame rate prior to the first frame
  // encoded in the second pass is a guess. However, the sum duration is not.
  // It is calculated based on the actual durations of all frames from the
  // first pass.
Yaowu Xu's avatar
Yaowu Xu committed
1271
  av1_new_framerate(cpi, frame_rate);
1272
1273
  twopass->bits_left =
      (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
Jingning Han's avatar
Jingning Han committed
1274
1275
1276
1277
1278
1279
1280

  // This variable monitors how far behind the second ref update is lagging.
  twopass->sr_update_lag = 1;

  // Scan the first pass file and calculate a modified total error based upon
  // the bias/power function used to allocate bits.
  {
1281
1282
    const double avg_error =
        stats->coded_error / DOUBLE_DIVIDE_CHECK(stats->count);
Jingning Han's avatar
Jingning Han committed
1283
1284
    const FIRSTPASS_STATS *s = twopass->stats_in;
    double modified_error_total = 0.0;
1285
1286
1287
1288
    twopass->modified_error_min =
        (avg_error * oxcf->two_pass_vbrmin_section) / 100;
    twopass->modified_error_max =
        (avg_error * oxcf->two_pass_vbrmax_section) / 100;
Jingning Han's avatar
Jingning Han committed
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
    while (s < twopass->stats_in_end) {
      modified_error_total += calculate_modified_err(cpi, twopass, oxcf, s);
      ++s;
    }
    twopass->modified_error_left = modified_error_total;
  }

  // Reset the vbr bits off target counters
  cpi->rc.vbr_bits_off_target = 0;
  cpi->rc.vbr_bits_off_target_fast = 0;

  cpi->rc.rate_error_estimate = 0;

  // Static sequence monitor variables.
  twopass->kf_zeromotion_pct = 100;
  twopass->last_kfgroup_zeromotion_pct = 100;

  if (oxcf->resize_mode != RESIZE_NONE) {
Yaowu Xu's avatar
Yaowu Xu committed
1307
    av1_init_subsampling(cpi);