firstpass.c 107 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);
Jingning Han's avatar
Jingning Han committed
496
497
498

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

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

Yaowu Xu's avatar
Yaowu Xu committed
507
  aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
508
509
510
511
512
513

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

  set_first_pass_params(cpi);
514
  av1_set_quantizer(cm, qindex);
Jingning Han's avatar
Jingning Han committed
515

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

Yaowu Xu's avatar
Yaowu Xu committed
518
519
  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
520
521

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

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

Yaowu Xu's avatar
Yaowu Xu committed
528
  av1_frame_init_quantizer(cpi);
Jingning Han's avatar
Jingning Han committed
529
530

  for (i = 0; i < MAX_MB_PLANE; ++i) {
531
532
533
534
    p[i].coeff = ctx->coeff[i][1];
    p[i].qcoeff = ctx->qcoeff[i][1];
    pd[i].dqcoeff = ctx->dqcoeff[i][1];
    p[i].eobs = ctx->eobs[i][1];
Jingning Han's avatar
Jingning Han committed
535
536
  }

Yaowu Xu's avatar
Yaowu Xu committed
537
538
  av1_init_mv_probs(cm);
  av1_initialize_rd_consts(cpi);
Jingning Han's avatar
Jingning Han committed
539
540

  // Tiling is ignored in the first pass.
Yaowu Xu's avatar
Yaowu Xu committed
541
  av1_tile_init(&tile, cm, 0, 0);
Jingning Han's avatar
Jingning Han committed
542
543
544
545
546
547

  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) {
548
    MV best_ref_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
549
550
551
552
553
554
555
556
557

    // 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);
558
    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + BORDER_MV_PIXELS_B16;
Jingning Han's avatar
Jingning Han committed
559
560
561
562
563
564
565
566
567
568
569
570

    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
571
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
572
573
574
575
576
577
578

      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;
579
      set_mi_row_col(xd, &tile, mb_row << 1, num_8x8_blocks_high_lookup[bsize],
Jingning Han's avatar
Jingning Han committed
580
581
                     mb_col << 1, num_8x8_blocks_wide_lookup[bsize],
                     cm->mi_rows, cm->mi_cols);
582
583
584
      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
585
586

      // Do intra 16x16 prediction.
587
      xd->mi[0]->mbmi.segment_id = 0;
588
589
590
#if CONFIG_SUPERTX
      xd->mi[0]->mbmi.segment_id_supertx = 0;
#endif  // CONFIG_SUPERTX
591
592
      xd->qindex[xd->mi[0]->mbmi.segment_id] = qindex;
      xd->lossless[xd->mi[0]->mbmi.segment_id] = (qindex == 0);
Jingning Han's avatar
Jingning Han committed
593
      xd->mi[0]->mbmi.mode = DC_PRED;
594
595
      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
596
      av1_encode_intra_block_plane(cm, x, bsize, 0, 0);
Yaowu Xu's avatar
Yaowu Xu committed
597
      this_error = aom_get_mb_ss(x->plane[0].src_diff);
Jingning Han's avatar
Jingning Han committed
598
599
600
601
602
603
604
605
606
607
608
609

      // 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
610
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
611
612
      if (cm->use_highbitdepth) {
        switch (cm->bit_depth) {
Yaowu Xu's avatar
Yaowu Xu committed
613
614
615
          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
616
          default:
617
            assert(0 &&
Yaowu Xu's avatar
Yaowu Xu committed
618
619
                   "cm->bit_depth should be AOM_BITS_8, "
                   "AOM_BITS_10 or AOM_BITS_12");
Jingning Han's avatar
Jingning Han committed
620
621
622
            return;
        }
      }
Yaowu Xu's avatar
Yaowu Xu committed
623
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
624

Yaowu Xu's avatar
Yaowu Xu committed
625
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
626
627
628
629
630
631
      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
632
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
      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
670
      if (cm->current_video_frame > 0) {
Jingning Han's avatar
Jingning Han committed
671
672
        int tmp_err, motion_error, raw_motion_error;
        // Assume 0,0 motion with no mv overhead.
673
        MV mv = { 0, 0 }, tmp_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
674
675
676
        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
677
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
678
679
680
681
        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 {
682
683
          motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                              &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
684
685
        }
#else
686
687
        motion_error =
            get_prediction_error(bsize, &x->plane[0].src, &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
688
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
689
690
691
692
693
694
695
696

        // 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
697
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
698
699
700
701
        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 {
702
703
          raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                  &unscaled_last_source_buf_2d);
Jingning Han's avatar
Jingning Han committed
704
705
        }
#else
706
707
        raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                &unscaled_last_source_buf_2d);
Yaowu Xu's avatar
Yaowu Xu committed
708
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
709
710

        // TODO(pengchong): Replace the hard-coded threshold
Yunqing Wang's avatar
Yunqing Wang committed
711
        if (raw_motion_error > 25) {
Jingning Han's avatar
Jingning Han committed
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
          // 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
729
          if ((cm->current_video_frame > 1) && gld_yv12 != NULL) {
Jingning Han's avatar
Jingning Han committed
730
731
732
733
            // 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
734
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
735
736
737
738
            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 {
739
740
              gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                     &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
741
742
            }
#else
743
744
            gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                   &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
745
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791

            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
792
          aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
793
794
795
796
797
798
799

          // 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;
800
801
            // 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
802
803
          } else if ((this_error > NCOUNT_INTRA_THRESH) &&
                     (this_error < (NCOUNT_INTRA_FACTOR * motion_error))) {
804
805
            neutral_count +=
                (double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error);
Jingning Han's avatar
Jingning Han committed
806
807
808
809
810
811
812
813
814
815
          }

          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
816
          av1_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
Angie Chiang's avatar
Angie Chiang committed
817
          av1_encode_sby_pass1(cm, x, bsize);
Jingning Han's avatar
Jingning Han committed
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
          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
852
              if (mv.col > 0 && mv.col >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
853
854
855
                // right direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_RIGHT_MASK;
856
              } else if (mv.row < 0 && abs(mv.row) >= abs(mv.col)) {
Jingning Han's avatar
Jingning Han committed
857
858
859
                // up direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_UP_MASK;
860
              } else if (mv.col < 0 && abs(mv.col) >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
861
862
863
864
865
866
867
868
869
870
871
872
                // 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?
873
            if (!is_equal_mv(&mv, &lastmv)) ++new_mv_count;
Jingning Han's avatar
Jingning Han committed
874
875
876
877
878
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
913
914
915
916
917
918
            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;
919
920
921
922
    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
923

Yaowu Xu's avatar
Yaowu Xu committed
924
    aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
925
926
927
928
929
930
931
932
933
934
935
  }

  // 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
936
        AOMMAX(0, intra_skip_count - (image_data_start_row * cm->mb_cols * 2));
Jingning Han's avatar
Jingning Han committed
937
938
939
940
941
942
943
944
945
946
  }

  {
    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)
947
948
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Jingning Han's avatar
Jingning Han committed
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
    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;
972
973
974
975
      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
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
      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) {
1003
1004
      output_fpmb_stats(twopass->frame_mb_stats_buf, cpi->initial_mbs,
                        cpi->output_pkt_list);
Jingning Han's avatar
Jingning Han committed
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
    }
#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) {
1017
1018
1019
1020
#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
1021
1022
      ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
                 cm->ref_frame_map[cpi->lst_fb_idx]);
1023
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1024
1025
1026
1027
1028
1029
    }
    twopass->sr_update_lag = 1;
  } else {
    ++twopass->sr_update_lag;
  }

Yaowu Xu's avatar
Yaowu Xu committed
1030
  aom_extend_frame_borders(new_yv12);
Jingning Han's avatar
Jingning Han committed
1031

1032
// The frame we just compressed now becomes the last frame.
1033
1034
1035
1036
1037
#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
1038
1039
  ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
             cm->new_fb_idx);
1040
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1041
1042
1043

  // Special case for the first frame. Copy into the GF buffer as a second
  // reference.
Yunqing Wang's avatar
Yunqing Wang committed
1044
  if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
1045
1046
1047
1048
#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
1049
1050
    ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
               cm->ref_frame_map[cpi->lst_fb_idx]);
1051
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
  }

  // 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;
}

1073
1074
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
1075
                                     aom_bit_depth_t bit_depth) {
Jingning Han's avatar
Jingning Han committed
1076
1077
1078
1079
  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
1080
      AOMMIN(av1_convert_qindex_to_q(q, bit_depth) * 0.01 + pt_low, pt_high);
Jingning Han's avatar
Jingning Han committed
1081
1082

  // Calculate correction factor.
1083
  if (power_term < 1.0) assert(error_term >= 0.0);
Jingning Han's avatar
Jingning Han committed
1084
1085
1086
1087

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

1088
#define ERR_DIVISOR 100.0
Yaowu Xu's avatar
Yaowu Xu committed
1089
static int get_twopass_worst_quality(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1090
1091
1092
1093
1094
                                     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
1095
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
Jingning Han's avatar
Jingning Han committed
1096
1097
1098
1099
1100
1101
1102

  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)
1103
1104
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Yaowu Xu's avatar
Yaowu Xu committed
1105
    const int active_mbs = AOMMAX(1, num_mbs - (int)(num_mbs * inactive_zone));
Jingning Han's avatar
Jingning Han committed
1106
1107
    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
1108
    double ediv_size_correction;
1109
1110
    const int target_norm_bits_per_mb =
        ((uint64_t)section_target_bandwidth << BPER_MB_NORMBITS) / active_mbs;
Jingning Han's avatar
Jingning Han committed
1111
1112
    int q;

paulwilkins's avatar
paulwilkins committed
1113
1114
1115
1116
1117
1118
    // 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
1119
        AOMMAX(0.2, AOMMIN(5.0, get_linear_size_factor(cpi)));
paulwilkins's avatar
paulwilkins committed
1120
1121
1122
1123
    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
1124
1125
1126
    // 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) {
1127
1128
1129
      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
1130
      const int bits_per_mb = av1_rc_bits_per_mb(
1131
1132
1133
          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
1134
1135
1136
    }

    // Restriction on active max q for constrained quality mode.
Yaowu Xu's avatar
Yaowu Xu committed
1137
    if (cpi->oxcf.rc_mode == AOM_CQ) q = AOMMAX(q, oxcf->cq_level);
Jingning Han's avatar
Jingning Han committed
1138
1139
1140
1141
    return q;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1142
static void setup_rf_level_maxq(AV1_COMP *cpi) {
Jingning Han's avatar
Jingning Han committed
1143
1144
1145
  int i;
  RATE_CONTROL *const rc = &cpi->rc;
  for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) {
Yaowu Xu's avatar
Yaowu Xu committed
1146
1147
    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
1148
1149
1150
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1151
1152
void av1_init_subsampling(AV1_COMP *cpi) {
  const AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
  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
1167
1168
void av1_calculate_coded_size(AV1_COMP *cpi, int *scaled_frame_width,
                              int *scaled_frame_height) {
Jingning Han's avatar
Jingning Han committed
1169
1170
1171
1172
1173
  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
1174
1175
void av1_init_second_pass(AV1_COMP *cpi) {
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
Yunqing Wang's avatar
Yunqing Wang committed
1176
  TWO_PASS *const twopass = &cpi->twopass;
Jingning Han's avatar
Jingning Han committed
1177
1178
1179
1180
1181
1182
  double frame_rate;
  FIRSTPASS_STATS *stats;

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

1183
  if (!twopass->stats_in_end) return;
Jingning Han's avatar
Jingning Han committed
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195

  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
1196
  av1_new_framerate(cpi, frame_rate);
1197
1198
  twopass->bits_left =
      (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
Jingning Han's avatar
Jingning Han committed
1199
1200
1201
1202
1203
1204
1205

  // 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.
  {
1206
1207
    const double avg_error =
        stats->coded_error / DOUBLE_DIVIDE_CHECK(stats->count);
Jingning Han's avatar
Jingning Han committed
1208
1209
    const FIRSTPASS_STATS *s = twopass->stats_in;
    double modified_error_total = 0.0;
1210
1211
1212
1213
    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
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
    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
1232
    av1_init_subsampling(cpi);
Jingning Han's avatar
Jingning Han committed
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
  }
}

#define SR_DIFF_PART 0.0015
#define MOTION_AMP_PART 0.003
#define INTRA_PART 0.005
#define DEFAULT_DECAY_LIMIT 0.75
#define LOW_SR_DIFF_TRHESH 0.1
#define SR_DIFF_MAX 128.0

Yaowu Xu's avatar
Yaowu Xu committed
1243
static double get_sr_decay_rate(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1244
                                const FIRSTPASS_STATS *frame) {
1245
1246
1247
  const int num_mbs = (cpi->oxcf.resize_mode != RESIZE_NONE) ? cpi->initial_mbs
                                                             : cpi->common.MBs;
  double sr_diff = (frame->sr_coded_error - frame->coded_error) / num_mbs;
Jingning Han's avatar
Jingning Han committed
1248
1249
1250
1251
  double sr_decay = 1.0;
  double modified_pct_inter;
  double modified_pcnt_intra;
  const double motion_amplitude_factor =
1252
      frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2);
Jingning Han's avatar
Jingning Han committed
1253
1254
1255
1256
1257
1258
1259
1260
1261

  modified_pct_inter = frame->pcnt_inter;
  if ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) <
      (double)NCOUNT_FRAME_II_THRESH) {
    modified_pct_inter = frame->pcnt_inter - frame->pcnt_neutral;
  }
  modified_pcnt_intra = 100 * (1.0 - modified_pct_inter);

  if ((sr_diff > LOW_SR_DIFF_TRHESH)) {
Yaowu Xu's avatar
Yaowu Xu committed
1262
    sr_diff = AOMMIN(sr_diff, SR_DIFF_MAX);
Jingning Han's avatar
Jingning Han committed
1263
1264
1265
1266
    sr_decay = 1.0 - (SR_DIFF_PART * sr_diff) -
               (MOTION_AMP_PART * motion_amplitude_factor) -
               (INTRA_PART * modified_pcnt_intra);
  }
Yaowu Xu's avatar
Yaowu Xu committed
1267
  return AOMMAX(sr_decay, AOMMIN(DEFAULT_DECAY_LIMIT, modified_pct_inter));
Jingning Han's avatar
Jingning Han committed
1268
1269
1270
1271
}

// This function gives an estimate of how badly we believe the prediction
// quality is decaying from frame to frame.
Yaowu Xu's avatar
Yaowu Xu committed
1272
static double get_zero_motion_factor(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1273
                                     const FIRSTPASS_STATS *frame) {
1274
  const double zero_motion_pct = frame->pcnt_inter - frame->pcnt_motion;
Jingning Han's avatar
Jingning Han committed
1275
  double sr_decay = get_sr_decay_rate(cpi, frame);
Yaowu Xu's avatar
Yaowu Xu committed
1276
  return AOMMIN(sr_decay, zero_motion_pct);
Jingning Han's avatar
Jingning Han committed
1277
1278
1279
1280
}

#define ZM_POWER_FACTOR 0.75

Yaowu Xu's avatar
Yaowu Xu committed
1281
static double get_prediction_decay_rate(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1282
1283
1284
                                        const FIRSTPASS_STATS *next_frame) {
  const double sr_decay_rate = get_sr_decay_rate(cpi, next_frame);
  const double zero_motion_factor =
1285
1286
      (0.95 * pow((next_frame->pcnt_inter - next_frame->pcnt_motion),
                  ZM_POWER_FACTOR));
Jingning Han's avatar
Jingning Han committed
1287

Yaowu Xu's avatar
Yaowu Xu committed
1288
  return AOMMAX(zero_motion_factor,
1289
                (sr_decay_rate + ((1.0 - sr_decay_rate) * zero_motion_factor)));