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

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

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

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

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

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

#define GROUP_ADAPTIVE_MAXQ 1

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

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

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

#if ARF_STATS_OUTPUT
unsigned int arf_count = 0;
#endif

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

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

  return &p->stats_in[offset];
}

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

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

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

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

112
113
    fprintf(fpfile,
            "%12.0lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf %12.4lf"
Jingning Han's avatar
Jingning Han committed
114
115
            "%12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf %12.4lf"
            "%12.4lf %12.4lf %12.0lf %12.0lf %12.0lf %12.4lf\n",
116
117
118
119
120
121
122
            stats->frame, stats->weight, stats->intra_error, stats->coded_error,
            stats->sr_coded_error, stats->pcnt_inter, stats->pcnt_motion,
            stats->pcnt_second_ref, stats->pcnt_neutral, stats->intra_skip_pct,
            stats->inactive_zone_rows, stats->inactive_zone_cols, stats->MVr,
            stats->mvr_abs, stats->MVc, stats->mvc_abs, stats->MVrv,
            stats->MVcv, stats->mv_in_out_count, stats->new_mv_count,
            stats->count, stats->duration);
Jingning Han's avatar
Jingning Han committed
123
124
125
126
127
128
    fclose(fpfile);
  }
#endif
}

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

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

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

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

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

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

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

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

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

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

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

  return (int)max_bits;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

  // Carry out further step/diamond searches as necessary.
  n = num00;
  num00 = 0;

  while (n < further_steps) {
    ++n;

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

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

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

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

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

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

  return i;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    x->pvq_q = &pvq_q;

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

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

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

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

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

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

  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) {
588
    MV best_ref_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
589
590
591
592
593
594
595
596
597

    // 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);
598
    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16) + BORDER_MV_PIXELS_B16;
Jingning Han's avatar
Jingning Han committed
599
600
601
602
603
604
605
606
607
608
609
610

    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
611
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
612
613
614
615
616
617
618

      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;
619
      set_mi_row_col(xd, &tile, mb_row << 1, num_8x8_blocks_high_lookup[bsize],
Jingning Han's avatar
Jingning Han committed
620
621
                     mb_col << 1, num_8x8_blocks_wide_lookup[bsize],
                     cm->mi_rows, cm->mi_cols);
622
623
624
      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
625
626

      // Do intra 16x16 prediction.
627
      xd->mi[0]->mbmi.segment_id = 0;
628
629
630
#if CONFIG_SUPERTX
      xd->mi[0]->mbmi.segment_id_supertx = 0;
#endif  // CONFIG_SUPERTX
631
      xd->lossless[xd->mi[0]->mbmi.segment_id] = (qindex == 0);
Jingning Han's avatar
Jingning Han committed
632
      xd->mi[0]->mbmi.mode = DC_PRED;
633
634
      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
635
      av1_encode_intra_block_plane(cm, x, bsize, 0, 0);
Yaowu Xu's avatar
Yaowu Xu committed
636
      this_error = aom_get_mb_ss(x->plane[0].src_diff);
Jingning Han's avatar
Jingning Han committed
637
638
639
640
641
642
643
644
645
646
647
648

      // 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
649
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
650
651
      if (cm->use_highbitdepth) {
        switch (cm->bit_depth) {
Yaowu Xu's avatar
Yaowu Xu committed
652
653
654
          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
655
          default:
656
            assert(0 &&
Yaowu Xu's avatar
Yaowu Xu committed
657
658
                   "cm->bit_depth should be AOM_BITS_8, "
                   "AOM_BITS_10 or AOM_BITS_12");
Jingning Han's avatar
Jingning Han committed
659
660
661
            return;
        }
      }
Yaowu Xu's avatar
Yaowu Xu committed
662
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
663

Yaowu Xu's avatar
Yaowu Xu committed
664
      aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
665
666
667
668
669
670
      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
671
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
      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
709
      if (cm->current_video_frame > 0) {
Jingning Han's avatar
Jingning Han committed
710
711
        int tmp_err, motion_error, raw_motion_error;
        // Assume 0,0 motion with no mv overhead.
712
        MV mv = { 0, 0 }, tmp_mv = { 0, 0 };
Jingning Han's avatar
Jingning Han committed
713
714
715
        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
716
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
717
718
719
720
        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 {
721
722
          motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                              &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
723
724
        }
#else
725
726
        motion_error =
            get_prediction_error(bsize, &x->plane[0].src, &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
727
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
728
729
730
731
732
733
734
735

        // 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
736
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
737
738
739
740
        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 {
741
742
          raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                  &unscaled_last_source_buf_2d);
Jingning Han's avatar
Jingning Han committed
743
744
        }
#else
745
746
        raw_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                &unscaled_last_source_buf_2d);
Yaowu Xu's avatar
Yaowu Xu committed
747
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
748
749

        // TODO(pengchong): Replace the hard-coded threshold
Yunqing Wang's avatar
Yunqing Wang committed
750
        if (raw_motion_error > 25) {
Jingning Han's avatar
Jingning Han committed
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
          // 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
768
          if ((cm->current_video_frame > 1) && gld_yv12 != NULL) {
Jingning Han's avatar
Jingning Han committed
769
770
771
772
            // 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
773
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
774
775
776
777
            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 {
778
779
              gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                     &xd->plane[0].pre[0]);
Jingning Han's avatar
Jingning Han committed
780
781
            }
#else
782
783
            gf_motion_error = get_prediction_error(bsize, &x->plane[0].src,
                                                   &xd->plane[0].pre[0]);
Yaowu Xu's avatar
Yaowu Xu committed
784
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830

            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
831
          aom_clear_system_state();
Jingning Han's avatar
Jingning Han committed
832
833
834
835
836
837
838

          // 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;
839
840
            // 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
841
842
          } else if ((this_error > NCOUNT_INTRA_THRESH) &&
                     (this_error < (NCOUNT_INTRA_FACTOR * motion_error))) {
843
844
            neutral_count +=
                (double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error);
Jingning Han's avatar
Jingning Han committed
845
846
847
848
849
850
851
852
853
854
          }

          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
855
          av1_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
Angie Chiang's avatar
Angie Chiang committed
856
          av1_encode_sby_pass1(cm, x, bsize);
Jingning Han's avatar
Jingning Han committed
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
          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
891
              if (mv.col > 0 && mv.col >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
892
893
894
                // right direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_RIGHT_MASK;
895
              } else if (mv.row < 0 && abs(mv.row) >= abs(mv.col)) {
Jingning Han's avatar
Jingning Han committed
896
897
898
                // up direction
                cpi->twopass.frame_mb_stats_buf[mb_index] |=
                    FPMB_MOTION_UP_MASK;
899
              } else if (mv.col < 0 && abs(mv.col) >= abs(mv.row)) {
Jingning Han's avatar
Jingning Han committed
900
901
902
903
904
905
906
907
908
909
910
911
                // 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?
912
            if (!is_equal_mv(&mv, &lastmv)) ++new_mv_count;
Jingning Han's avatar
Jingning Han committed
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
            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;
958
959
960
961
    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
962

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

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

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

  aom_free(pvq_q.buf);
#endif

Jingning Han's avatar
Jingning Han committed
976
977
978
979
980
981
982
983
984
  // 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
985
        AOMMAX(0, intra_skip_count - (image_data_start_row * cm->mb_cols * 2));
Jingning Han's avatar
Jingning Han committed
986
987
988
989
990
991
992
993
994
995
  }

  {
    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)
996
997
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Jingning Han's avatar
Jingning Han committed
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
    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;
1021
1022
1023
1024
      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
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
      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) {
1052
1053
      output_fpmb_stats(twopass->frame_mb_stats_buf, cpi->initial_mbs,
                        cpi->output_pkt_list);
Jingning Han's avatar
Jingning Han committed
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
    }
#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) {
1066
1067
1068
1069
#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
1070
1071
      ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
                 cm->ref_frame_map[cpi->lst_fb_idx]);
1072
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1073
1074
1075
1076
1077
1078
    }
    twopass->sr_update_lag = 1;
  } else {
    ++twopass->sr_update_lag;
  }

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

1081
// The frame we just compressed now becomes the last frame.
1082
1083
1084
1085
1086
#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
1087
1088
  ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->lst_fb_idx],
             cm->new_fb_idx);
1089
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1090
1091
1092

  // Special case for the first frame. Copy into the GF buffer as a second
  // reference.
Yunqing Wang's avatar
Yunqing Wang committed
1093
  if (cm->current_video_frame == 0 && cpi->gld_fb_idx != INVALID_IDX) {
1094
1095
1096
1097
#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
1098
1099
    ref_cnt_fb(pool->frame_bufs, &cm->ref_frame_map[cpi->gld_fb_idx],
               cm->ref_frame_map[cpi->lst_fb_idx]);
1100
#endif  // CONFIG_EXT_REFS
Jingning Han's avatar
Jingning Han committed
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
  }

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

1122
1123
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
1124
                                     aom_bit_depth_t bit_depth) {
Jingning Han's avatar
Jingning Han committed
1125
1126
1127
1128
  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
1129
      AOMMIN(av1_convert_qindex_to_q(q, bit_depth) * 0.01 + pt_low, pt_high);
Jingning Han's avatar
Jingning Han committed
1130
1131

  // Calculate correction factor.
1132
  if (power_term < 1.0) assert(error_term >= 0.0);
Jingning Han's avatar
Jingning Han committed
1133
1134
1135
1136

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

1137
#define ERR_DIVISOR 100.0
Yaowu Xu's avatar
Yaowu Xu committed
1138
static int get_twopass_worst_quality(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1139
1140
1141
1142
1143
                                     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
1144
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
Jingning Han's avatar
Jingning Han committed
1145
1146
1147
1148
1149
1150
1151

  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)
1152
1153
                            ? cpi->initial_mbs
                            : cpi->common.MBs;
Yaowu Xu's avatar
Yaowu Xu committed
1154
    const int active_mbs = AOMMAX(1, num_mbs - (int)(num_mbs * inactive_zone));
Jingning Han's avatar
Jingning Han committed
1155
1156
    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
1157
    double ediv_size_correction;
1158
1159
    const int target_norm_bits_per_mb =
        ((uint64_t)section_target_bandwidth << BPER_MB_NORMBITS) / active_mbs;
Jingning Han's avatar
Jingning Han committed
1160
1161
    int q;

paulwilkins's avatar
paulwilkins committed
1162
1163
1164
1165
1166
1167
    // 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
1168
        AOMMAX(0.2, AOMMIN(5.0, get_linear_size_factor(cpi)));
paulwilkins's avatar
paulwilkins committed
1169
1170
1171
1172
    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
1173
1174
1175
    // 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) {
1176
1177
1178
      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
1179
      const int bits_per_mb = av1_rc_bits_per_mb(
1180
1181
1182
          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
1183
1184
1185
    }

    // Restriction on active max q for constrained quality mode.
Yaowu Xu's avatar
Yaowu Xu committed
1186
    if (cpi->oxcf.rc_mode == AOM_CQ) q = AOMMAX(q, oxcf->cq_level);
Jingning Han's avatar
Jingning Han committed
1187
1188
1189
1190
    return q;
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1191
static void setup_rf_level_maxq(AV1_COMP *cpi) {
Jingning Han's avatar
Jingning Han committed
1192
1193
1194
  int i;
  RATE_CONTROL *const rc = &cpi->rc;
  for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) {
Yaowu Xu's avatar
Yaowu Xu committed
1195
1196
    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
1197
1198
1199
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
1200
1201
void av1_init_subsampling(AV1_COMP *cpi) {
  const AV1_COMMON *const cm = &cpi->common;
Jingning Han's avatar
Jingning Han committed
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
  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
1216
1217
void av1_calculate_coded_size(AV1_COMP *cpi, int *scaled_frame_width,
                              int *scaled_frame_height) {
Jingning Han's avatar
Jingning Han committed
1218
1219
1220
1221
1222
  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
1223
1224
void av1_init_second_pass(AV1_COMP *cpi) {
  const AV1EncoderConfig *const oxcf = &cpi->oxcf;
Yunqing Wang's avatar
Yunqing Wang committed
1225
  TWO_PASS *const twopass = &cpi->twopass;
Jingning Han's avatar
Jingning Han committed
1226
1227
1228
1229
1230
1231
  double frame_rate;
  FIRSTPASS_STATS *stats;

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

1232
  if (!twopass->stats_in_end) return;
Jingning Han's avatar
Jingning Han committed
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244

  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
1245
  av1_new_framerate(cpi, frame_rate);
1246
1247
  twopass->bits_left =
      (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
Jingning Han's avatar
Jingning Han committed
1248
1249
1250
1251
1252
1253
1254

  // 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.
  {
1255
1256
    const double avg_error =
        stats->coded_error / DOUBLE_DIVIDE_CHECK(stats->count);
Jingning Han's avatar
Jingning Han committed
1257
1258
    const FIRSTPASS_STATS *s = twopass->stats_in;
    double modified_error_total = 0.0;
1259
1260
1261
1262
    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
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
    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
1281
    av1_init_subsampling(cpi);
Jingning Han's avatar
Jingning Han committed
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
  }
}

#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
1292
static double get_sr_decay_rate(const AV1_COMP *cpi,
Jingning Han's avatar
Jingning Han committed
1293
                                const FIRSTPASS_STATS *frame) {
1294
1295
1296
  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
1297
1298
1299
1300
  double sr_decay = 1.0;
  double modified_pct_inter;
  double modified_pcnt_intra;
  const double motion_amplitude_factor =
1301
      frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2);
Jingning Han's avatar
Jingning Han committed
1302
1303
1304
1305
1306
1307
1308
1309
1310

  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
1311
    sr_diff = AOMMIN(sr_diff, SR_DIFF_MAX);