vp9_firstpass.c 85.6 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5
6
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS.  All contributing project authors may
8
 *  be found in the AUTHORS file in the root of the source tree.
John Koleszar's avatar
John Koleszar committed
9
10
 */

11
12
13
#include <math.h>
#include <limits.h>
#include <stdio.h>
14
#include "vp9/common/vp9_systemdependent.h"
15
#include "vp9/encoder/vp9_block.h"
16
17
18
19
20
#include "vp9/encoder/vp9_encodeframe.h"
#include "vp9/encoder/vp9_encodemb.h"
#include "vp9/encoder/vp9_extend.h"
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/encoder/vp9_mcomp.h"
21
22
#include "vp9/encoder/vp9_onyx_int.h"
#include "vp9/encoder/vp9_variance.h"
Johann's avatar
Johann committed
23
#include "vpx_scale/vpx_scale.h"
John Koleszar's avatar
John Koleszar committed
24
#include "vpx_mem/vpx_mem.h"
25
#include "vpx_scale/yv12config.h"
26
#include "vp9/encoder/vp9_quantize.h"
27
28
#include "vp9/encoder/vp9_rdopt.h"
#include "vp9/encoder/vp9_ratectrl.h"
29
30
#include "vp9/common/vp9_quant_common.h"
#include "vp9/common/vp9_entropymv.h"
31
#include "vp9/encoder/vp9_encodemv.h"
32
#include "vp9/encoder/vp9_vaq.h"
33
#include "./vpx_scale_rtcd.h"
34
35
// TODO(jkoleszar): for setup_dst_planes
#include "vp9/common/vp9_reconinter.h"
John Koleszar's avatar
John Koleszar committed
36

37
#define OUTPUT_FPF 0
John Koleszar's avatar
John Koleszar committed
38

39
40
#define IIFACTOR   12.5
#define IIKFACTOR1 12.5
41
#define IIKFACTOR2 15.0
42
#define RMAX       512.0
43
#define GF_RMAX    96.0
Paul Wilkins's avatar
Paul Wilkins committed
44
#define ERR_DIVISOR   150.0
45
#define MIN_DECAY_FACTOR 0.1
John Koleszar's avatar
John Koleszar committed
46

47
48
#define KF_MB_INTRA_MIN 150
#define GF_MB_INTRA_MIN 100
Paul Wilkins's avatar
CQ Mode    
Paul Wilkins committed
49

50
#define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001)
John Koleszar's avatar
John Koleszar committed
51

52
53
54
55
56
57
static void swap_yv12(YV12_BUFFER_CONFIG *a, YV12_BUFFER_CONFIG *b) {
  YV12_BUFFER_CONFIG temp = *a;
  *a = *b;
  *b = temp;
}

John Koleszar's avatar
John Koleszar committed
58
59
60
static int select_cq_level(int qindex) {
  int ret_val = QINDEX_RANGE - 1;
  int i;
Paul Wilkins's avatar
Paul Wilkins committed
61

62
  double target_q = (vp9_convert_qindex_to_q(qindex) * 0.5847) + 1.0;
Paul Wilkins's avatar
Paul Wilkins committed
63

John Koleszar's avatar
John Koleszar committed
64
  for (i = 0; i < QINDEX_RANGE; i++) {
65
    if (target_q <= vp9_convert_qindex_to_q(i)) {
John Koleszar's avatar
John Koleszar committed
66
67
      ret_val = i;
      break;
Paul Wilkins's avatar
Paul Wilkins committed
68
    }
John Koleszar's avatar
John Koleszar committed
69
  }
Paul Wilkins's avatar
Paul Wilkins committed
70

John Koleszar's avatar
John Koleszar committed
71
  return ret_val;
Paul Wilkins's avatar
Paul Wilkins committed
72
}
Paul Wilkins's avatar
CQ Mode    
Paul Wilkins committed
73

74
75
76
77
78
79
80
81
82
83
84
85
86
static int gfboost_qadjust(int qindex) {
  const double q = vp9_convert_qindex_to_q(qindex);
  return (int)((0.00000828 * q * q * q) +
               (-0.0055 * q * q) +
               (1.32 * q) + 79.3);
}

static int kfboost_qadjust(int qindex) {
  const double q = vp9_convert_qindex_to_q(qindex);
  return (int)((0.00000973 * q * q * q) +
               (-0.00613 * q * q) +
               (1.316 * q) + 121.2);
}
John Koleszar's avatar
John Koleszar committed
87

88
89
// Resets the first pass file to the given position using a relative seek from
// the current position.
90
91
92
static void reset_fpf_position(struct twopass_rc *p,
                               FIRSTPASS_STATS *position) {
  p->stats_in = position;
John Koleszar's avatar
John Koleszar committed
93
94
}

95
96
97
static int lookup_next_frame_stats(const struct twopass_rc *p,
                                   FIRSTPASS_STATS *next_frame) {
  if (p->stats_in >= p->stats_in_end)
John Koleszar's avatar
John Koleszar committed
98
    return EOF;
John Koleszar's avatar
John Koleszar committed
99

100
  *next_frame = *p->stats_in;
John Koleszar's avatar
John Koleszar committed
101
  return 1;
John Koleszar's avatar
John Koleszar committed
102
103
}

104

105
// Read frame stats at an offset from the current position
106
107
108
static int read_frame_stats(const struct twopass_rc *p,
                            FIRSTPASS_STATS *frame_stats, int offset) {
  const FIRSTPASS_STATS *fps_ptr = p->stats_in;
John Koleszar's avatar
John Koleszar committed
109
110
111

  // Check legality of offset
  if (offset >= 0) {
112
    if (&fps_ptr[offset] >= p->stats_in_end)
John Koleszar's avatar
John Koleszar committed
113
114
      return EOF;
  } else if (offset < 0) {
115
    if (&fps_ptr[offset] < p->stats_in_start)
John Koleszar's avatar
John Koleszar committed
116
117
118
119
120
      return EOF;
  }

  *frame_stats = fps_ptr[offset];
  return 1;
121
122
}

123
124
static int input_stats(struct twopass_rc *p, FIRSTPASS_STATS *fps) {
  if (p->stats_in >= p->stats_in_end)
John Koleszar's avatar
John Koleszar committed
125
    return EOF;
126

127
128
  *fps = *p->stats_in;
  ++p->stats_in;
John Koleszar's avatar
John Koleszar committed
129
  return 1;
130
131
}

132
static void output_stats(const VP9_COMP            *cpi,
133
                         struct vpx_codec_pkt_list *pktlist,
John Koleszar's avatar
John Koleszar committed
134
135
136
137
138
139
                         FIRSTPASS_STATS            *stats) {
  struct vpx_codec_cx_pkt pkt;
  pkt.kind = VPX_CODEC_STATS_PKT;
  pkt.data.twopass_stats.buf = stats;
  pkt.data.twopass_stats.sz = sizeof(FIRSTPASS_STATS);
  vpx_codec_pkt_list_add(pktlist, &pkt);
140
141
142
143

// TEMP debug code
#if OUTPUT_FPF

John Koleszar's avatar
John Koleszar committed
144
145
146
147
  {
    FILE *fpfile;
    fpfile = fopen("firstpass.stt", "a");

148
    fprintf(fpfile, "%12.0f %12.0f %12.0f %12.0f %12.0f %12.4f %12.4f"
John Koleszar's avatar
John Koleszar committed
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
            "%12.4f %12.4f %12.4f %12.4f %12.4f %12.4f %12.4f"
            "%12.0f %12.0f %12.4f %12.0f %12.0f %12.4f\n",
            stats->frame,
            stats->intra_error,
            stats->coded_error,
            stats->sr_coded_error,
            stats->ssim_weighted_pred_err,
            stats->pcnt_inter,
            stats->pcnt_motion,
            stats->pcnt_second_ref,
            stats->pcnt_neutral,
            stats->MVr,
            stats->mvr_abs,
            stats->MVc,
            stats->mvc_abs,
            stats->MVrv,
            stats->MVcv,
            stats->mv_in_out_count,
            stats->new_mv_count,
            stats->count,
            stats->duration);
    fclose(fpfile);
  }
172
173
174
#endif
}

John Koleszar's avatar
John Koleszar committed
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
static void zero_stats(FIRSTPASS_STATS *section) {
  section->frame      = 0.0;
  section->intra_error = 0.0;
  section->coded_error = 0.0;
  section->sr_coded_error = 0.0;
  section->ssim_weighted_pred_err = 0.0;
  section->pcnt_inter  = 0.0;
  section->pcnt_motion  = 0.0;
  section->pcnt_second_ref = 0.0;
  section->pcnt_neutral = 0.0;
  section->MVr        = 0.0;
  section->mvr_abs     = 0.0;
  section->MVc        = 0.0;
  section->mvc_abs     = 0.0;
  section->MVrv       = 0.0;
  section->MVcv       = 0.0;
  section->mv_in_out_count  = 0.0;
  section->new_mv_count = 0.0;
  section->count      = 0.0;
  section->duration   = 1.0;
195
196
}

John Koleszar's avatar
John Koleszar committed
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
static void accumulate_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) {
  section->frame += frame->frame;
  section->intra_error += frame->intra_error;
  section->coded_error += frame->coded_error;
  section->sr_coded_error += frame->sr_coded_error;
  section->ssim_weighted_pred_err += frame->ssim_weighted_pred_err;
  section->pcnt_inter  += frame->pcnt_inter;
  section->pcnt_motion += frame->pcnt_motion;
  section->pcnt_second_ref += frame->pcnt_second_ref;
  section->pcnt_neutral += frame->pcnt_neutral;
  section->MVr        += frame->MVr;
  section->mvr_abs     += frame->mvr_abs;
  section->MVc        += frame->MVc;
  section->mvc_abs     += frame->mvc_abs;
  section->MVrv       += frame->MVrv;
  section->MVcv       += frame->MVcv;
  section->mv_in_out_count  += frame->mv_in_out_count;
  section->new_mv_count += frame->new_mv_count;
  section->count      += frame->count;
  section->duration   += frame->duration;
217
218
}

John Koleszar's avatar
John Koleszar committed
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
static void subtract_stats(FIRSTPASS_STATS *section, FIRSTPASS_STATS *frame) {
  section->frame -= frame->frame;
  section->intra_error -= frame->intra_error;
  section->coded_error -= frame->coded_error;
  section->sr_coded_error -= frame->sr_coded_error;
  section->ssim_weighted_pred_err -= frame->ssim_weighted_pred_err;
  section->pcnt_inter  -= frame->pcnt_inter;
  section->pcnt_motion -= frame->pcnt_motion;
  section->pcnt_second_ref -= frame->pcnt_second_ref;
  section->pcnt_neutral -= frame->pcnt_neutral;
  section->MVr        -= frame->MVr;
  section->mvr_abs     -= frame->mvr_abs;
  section->MVc        -= frame->MVc;
  section->mvc_abs     -= frame->mvc_abs;
  section->MVrv       -= frame->MVrv;
  section->MVcv       -= frame->MVcv;
  section->mv_in_out_count  -= frame->mv_in_out_count;
  section->new_mv_count -= frame->new_mv_count;
  section->count      -= frame->count;
  section->duration   -= frame->duration;
239
240
}

John Koleszar's avatar
John Koleszar committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
static void avg_stats(FIRSTPASS_STATS *section) {
  if (section->count < 1.0)
    return;

  section->intra_error /= section->count;
  section->coded_error /= section->count;
  section->sr_coded_error /= section->count;
  section->ssim_weighted_pred_err /= section->count;
  section->pcnt_inter  /= section->count;
  section->pcnt_second_ref /= section->count;
  section->pcnt_neutral /= section->count;
  section->pcnt_motion /= section->count;
  section->MVr        /= section->count;
  section->mvr_abs     /= section->count;
  section->MVc        /= section->count;
  section->mvc_abs     /= section->count;
  section->MVrv       /= section->count;
  section->MVcv       /= section->count;
  section->mv_in_out_count   /= section->count;
  section->duration   /= section->count;
261
262
}

263
264
265
266
// Calculate a modified Error used in distributing bits between easier and
// harder frames.
static double calculate_modified_err(VP9_COMP *cpi,
                                     FIRSTPASS_STATS *this_frame) {
267
268
  struct twopass_rc *const twopass = &cpi->twopass;
  const FIRSTPASS_STATS *const stats = &twopass->total_stats;
269
  const double av_err = stats->ssim_weighted_pred_err / stats->count;
270
271
272
  double modified_error = av_err * pow(this_frame->ssim_weighted_pred_err /
                                           DOUBLE_DIVIDE_CHECK(av_err),
                                       cpi->oxcf.two_pass_vbrbias / 100.0);
273

274
275
  return fclamp(modified_error,
                twopass->modified_error_min, twopass->modified_error_max);
John Koleszar's avatar
John Koleszar committed
276
277
}

278
static const double weight_table[256] = {
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.020000,
  0.020000, 0.020000, 0.020000, 0.020000, 0.020000, 0.031250, 0.062500,
  0.093750, 0.125000, 0.156250, 0.187500, 0.218750, 0.250000, 0.281250,
  0.312500, 0.343750, 0.375000, 0.406250, 0.437500, 0.468750, 0.500000,
  0.531250, 0.562500, 0.593750, 0.625000, 0.656250, 0.687500, 0.718750,
  0.750000, 0.781250, 0.812500, 0.843750, 0.875000, 0.906250, 0.937500,
  0.968750, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
  1.000000, 1.000000, 1.000000, 1.000000
316
317
};

318
static double simple_weight(const YV12_BUFFER_CONFIG *buf) {
John Koleszar's avatar
John Koleszar committed
319
  int i, j;
320
321
322
323
324
325
326
327
328
329
330
  double sum = 0.0;
  const int w = buf->y_crop_width;
  const int h = buf->y_crop_height;
  const uint8_t *row = buf->y_buffer;

  for (i = 0; i < h; ++i) {
    const uint8_t *pixel = row;
    for (j = 0; j < w; ++j)
      sum += weight_table[*pixel++];
    row += buf->y_stride;
  }
John Koleszar's avatar
John Koleszar committed
331

332
  return MAX(0.1, sum / (w * h));
John Koleszar's avatar
John Koleszar committed
333
334
}

335
// This function returns the maximum target rate per frame.
336
static int frame_max_bits(VP9_COMP *cpi) {
337
  int64_t max_bits =
Paul Wilkins's avatar
Paul Wilkins committed
338
339
    ((int64_t)cpi->rc.av_per_frame_bandwidth *
     (int64_t)cpi->oxcf.two_pass_vbrmax_section) / 100;
340

Yaowu Xu's avatar
Yaowu Xu committed
341
  if (max_bits < 0)
Paul Wilkins's avatar
Paul Wilkins committed
342
343
344
345
    max_bits = 0;
  else if (max_bits > cpi->rc.max_frame_bandwidth)
    max_bits = cpi->rc.max_frame_bandwidth;

Yaowu Xu's avatar
Yaowu Xu committed
346
  return (int)max_bits;
John Koleszar's avatar
John Koleszar committed
347
348
}

349
void vp9_init_first_pass(VP9_COMP *cpi) {
350
  zero_stats(&cpi->twopass.total_stats);
John Koleszar's avatar
John Koleszar committed
351
352
}

353
void vp9_end_first_pass(VP9_COMP *cpi) {
354
  output_stats(cpi, cpi->output_pkt_list, &cpi->twopass.total_stats);
355
}
John Koleszar's avatar
John Koleszar committed
356

357
358
359
360
361
362
363
364
365
366
367
368
369
static vp9_variance_fn_t get_block_variance_fn(BLOCK_SIZE bsize) {
  switch (bsize) {
    case BLOCK_8X8:
      return vp9_mse8x8;
    case BLOCK_16X8:
      return vp9_mse16x8;
    case BLOCK_8X16:
      return vp9_mse8x16;
    default:
      return vp9_mse16x16;
  }
}

370
371
static unsigned int zz_motion_search(const VP9_COMP *cpi, const MACROBLOCK *x) {
  const MACROBLOCKD *const xd = &x->e_mbd;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
372
373
  const uint8_t *const src = x->plane[0].src.buf;
  const int src_stride = x->plane[0].src.stride;
374
  const uint8_t *const ref = xd->plane[0].pre[0].buf;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
375
  const int ref_stride = xd->plane[0].pre[0].stride;
John Koleszar's avatar
John Koleszar committed
376

Dmitry Kovalev's avatar
Dmitry Kovalev committed
377
  unsigned int sse;
378
379
  vp9_variance_fn_t fn = get_block_variance_fn(xd->mi_8x8[0]->mbmi.sb_type);
  fn(src, src_stride, ref, ref_stride, &sse);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
380
  return sse;
381
382
}

383
static void first_pass_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
384
                                     const MV *ref_mv, MV *best_mv,
385
                                     int *best_motion_err) {
John Koleszar's avatar
John Koleszar committed
386
  MACROBLOCKD *const xd = &x->e_mbd;
387
  MV tmp_mv = {0, 0};
388
389
  MV ref_mv_full = {ref_mv->row >> 3, ref_mv->col >> 3};
  int num00, tmp_err, n, sr = 0;
John Koleszar's avatar
John Koleszar committed
390
391
  int step_param = 3;
  int further_steps = (MAX_MVSEARCH_STEPS - 1) - step_param;
392
393
  const BLOCK_SIZE bsize = xd->mi_8x8[0]->mbmi.sb_type;
  vp9_variance_fn_ptr_t v_fn_ptr = cpi->fn_ptr[bsize];
John Koleszar's avatar
John Koleszar committed
394
  int new_mv_mode_penalty = 256;
395
  const int quart_frm = MIN(cpi->common.width, cpi->common.height);
396
397
398
399
400
401

  // refine the motion search range accroding to the frame dimension
  // for first pass test
  while ((quart_frm << sr) < MAX_FULL_PEL_VAL)
    sr++;

402
  step_param += sr;
403
404
  further_steps -= sr;

John Koleszar's avatar
John Koleszar committed
405
  // override the default variance function to use MSE
406
  v_fn_ptr.vf = get_block_variance_fn(bsize);
John Koleszar's avatar
John Koleszar committed
407
408

  // Initial step/diamond search centred on best mv
409
  tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv,
410
                                    step_param,
John Koleszar's avatar
John Koleszar committed
411
                                    x->sadperbit16, &num00, &v_fn_ptr,
412
                                    x->nmvjointcost,
413
                                    x->mvcost, ref_mv);
John Koleszar's avatar
John Koleszar committed
414
415
416
417
418
  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;
419
420
    best_mv->row = tmp_mv.row;
    best_mv->col = tmp_mv.col;
John Koleszar's avatar
John Koleszar committed
421
422
423
424
425
426
427
428
429
  }

  // Further step/diamond searches as necessary
  n = num00;
  num00 = 0;

  while (n < further_steps) {
    n++;

430
    if (num00) {
John Koleszar's avatar
John Koleszar committed
431
      num00--;
432
    } else {
433
      tmp_err = cpi->diamond_search_sad(x, &ref_mv_full, &tmp_mv,
John Koleszar's avatar
John Koleszar committed
434
435
                                        step_param + n, x->sadperbit16,
                                        &num00, &v_fn_ptr,
436
                                        x->nmvjointcost,
437
                                        x->mvcost, ref_mv);
John Koleszar's avatar
John Koleszar committed
438
      if (tmp_err < INT_MAX - new_mv_mode_penalty)
John Koleszar's avatar
John Koleszar committed
439
440
        tmp_err += new_mv_mode_penalty;

John Koleszar's avatar
John Koleszar committed
441
      if (tmp_err < *best_motion_err) {
John Koleszar's avatar
John Koleszar committed
442
        *best_motion_err = tmp_err;
443
444
        best_mv->row = tmp_mv.row;
        best_mv->col = tmp_mv.col;
John Koleszar's avatar
John Koleszar committed
445
      }
John Koleszar's avatar
John Koleszar committed
446
    }
John Koleszar's avatar
John Koleszar committed
447
  }
John Koleszar's avatar
John Koleszar committed
448
449
}

450
451
452
453
454
455
456
457
458
459
static BLOCK_SIZE get_bsize(const VP9_COMMON *cm, int mb_row, int mb_col) {
  if (2 * mb_col + 1 < cm->mi_cols) {
    return 2 * mb_row + 1 < cm->mi_rows ? BLOCK_16X16
                                        : BLOCK_16X8;
  } else {
    return 2 * mb_row + 1 < cm->mi_rows ? BLOCK_8X16
                                        : BLOCK_8X8;
  }
}

460
void vp9_first_pass(VP9_COMP *cpi) {
John Koleszar's avatar
John Koleszar committed
461
  int mb_row, mb_col;
John Koleszar's avatar
John Koleszar committed
462
  MACROBLOCK *const x = &cpi->mb;
463
  VP9_COMMON *const cm = &cpi->common;
John Koleszar's avatar
John Koleszar committed
464
  MACROBLOCKD *const xd = &x->e_mbd;
James Zern's avatar
James Zern committed
465
  TileInfo tile;
466
467
468
469
  struct macroblock_plane *const p = x->plane;
  struct macroblockd_plane *const pd = xd->plane;
  PICK_MODE_CONTEXT *ctx = &x->sb64_context;
  int i;
John Koleszar's avatar
John Koleszar committed
470
471

  int recon_yoffset, recon_uvoffset;
472
473
  YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
  YV12_BUFFER_CONFIG *const gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
474
  YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
475
476
  const int recon_y_stride = lst_yv12->y_stride;
  const int recon_uv_stride = lst_yv12->uv_stride;
Alex Converse's avatar
Alex Converse committed
477
  const int uv_mb_height = 16 >> (lst_yv12->y_height > lst_yv12->uv_height);
John Koleszar's avatar
John Koleszar committed
478
479
480
481
482
483
  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;
484
  int64_t sum_mvrs = 0, sum_mvcs = 0;
John Koleszar's avatar
John Koleszar committed
485
486
487
488
489
490
491
492
  int mvcount = 0;
  int intercount = 0;
  int second_ref_count = 0;
  int intrapenalty = 256;
  int neutral_count = 0;
  int new_mv_count = 0;
  int sum_in_vectors = 0;
  uint32_t lastmv_as_int = 0;
493
  struct twopass_rc *const twopass = &cpi->twopass;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
494
  const MV zero_mv = {0, 0};
John Koleszar's avatar
John Koleszar committed
495

496
  vp9_clear_system_state();  // __asm emms;
John Koleszar's avatar
John Koleszar committed
497

John Koleszar's avatar
John Koleszar committed
498
  vp9_setup_src_planes(x, cpi->Source, 0, 0);
499
  setup_pre_planes(xd, 0, lst_yv12, 0, 0, NULL);
500
  setup_dst_planes(xd, new_yv12, 0, 0);
John Koleszar's avatar
John Koleszar committed
501

502
  xd->mi_8x8 = cm->mi_grid_visible;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
503
  xd->mi_8x8[0] = cm->mi;  // required for vp9_frame_init_quantizer
John Koleszar's avatar
John Koleszar committed
504

505
  setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
John Koleszar's avatar
John Koleszar committed
506

507
  vp9_frame_init_quantizer(cpi);
John Koleszar's avatar
John Koleszar committed
508

509
510
  for (i = 0; i < MAX_MB_PLANE; ++i) {
    p[i].coeff = ctx->coeff_pbuf[i][1];
511
    p[i].qcoeff = ctx->qcoeff_pbuf[i][1];
512
    pd[i].dqcoeff = ctx->dqcoeff_pbuf[i][1];
513
    p[i].eobs = ctx->eobs_pbuf[i][1];
514
  }
515
  x->skip_recode = 0;
516

Dmitry Kovalev's avatar
Dmitry Kovalev committed
517
518
  vp9_init_mv_probs(cm);
  vp9_initialize_rd_consts(cpi);
John Koleszar's avatar
John Koleszar committed
519

James Zern's avatar
James Zern committed
520
521
522
  // tiling is ignored in the first pass
  vp9_tile_init(&tile, cm, 0, 0);

John Koleszar's avatar
John Koleszar committed
523
524
525
526
527
528
529
530
531
  // for each macroblock row in image
  for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
    int_mv best_ref_mv;

    best_ref_mv.as_int = 0;

    // reset above block coeffs
    xd->up_available = (mb_row != 0);
    recon_yoffset = (mb_row * recon_y_stride * 16);
Alex Converse's avatar
Alex Converse committed
532
    recon_uvoffset = (mb_row * recon_uv_stride * uv_mb_height);
John Koleszar's avatar
John Koleszar committed
533

534
535
536
    // 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);
John Koleszar's avatar
John Koleszar committed
537
    x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16)
538
                    + BORDER_MV_PIXELS_B16;
John Koleszar's avatar
John Koleszar committed
539
540
541
542

    // for each macroblock col in image
    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
      int this_error;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
543
      const int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
544
      double error_weight = 1.0;
545
      const BLOCK_SIZE bsize = get_bsize(cm, mb_row, mb_col);
546
547

      vp9_clear_system_state();  // __asm emms;
John Koleszar's avatar
John Koleszar committed
548

549
550
551
      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;
John Koleszar's avatar
John Koleszar committed
552
      xd->left_available = (mb_col != 0);
553
      xd->mi_8x8[0]->mbmi.sb_type = bsize;
554
      xd->mi_8x8[0]->mbmi.ref_frame[0] = INTRA_FRAME;
James Zern's avatar
James Zern committed
555
      set_mi_row_col(xd, &tile,
556
557
                     mb_row << 1, num_8x8_blocks_high_lookup[bsize],
                     mb_col << 1, num_8x8_blocks_wide_lookup[bsize],
James Zern's avatar
James Zern committed
558
                     cm->mi_rows, cm->mi_cols);
Jingning Han's avatar
Jingning Han committed
559

560
      if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
561
        const int energy = vp9_block_energy(cpi, x, bsize);
562
563
564
        error_weight = vp9_vaq_inv_q_ratio(energy);
      }

John Koleszar's avatar
John Koleszar committed
565
      // do intra 16x16 prediction
566
      this_error = vp9_encode_intra(x, use_dc_pred);
567
      if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
568
569
570
        vp9_clear_system_state();  // __asm emms;
        this_error *= error_weight;
      }
John Koleszar's avatar
John Koleszar committed
571

572
573
574
575
576
577
      // intrapenalty below deals with situations where the intra and inter
      // error scores are very low (eg 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.
John Koleszar's avatar
John Koleszar committed
578
579
580
581
582
583
      // This penalty adds a cost matching that of a 0,0 mv to the intra case.
      this_error += intrapenalty;

      // Cumulative intra error total
      intra_error += (int64_t)this_error;

584
585
      // Set up limit values for motion vectors to prevent them extending
      // outside the UMV borders.
586
      x->mv_col_min = -((mb_col * 16) + BORDER_MV_PIXELS_B16);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
587
      x->mv_col_max = ((cm->mb_cols - 1 - mb_col) * 16) + BORDER_MV_PIXELS_B16;
John Koleszar's avatar
John Koleszar committed
588
589
590

      // Other than for the first frame do a motion search
      if (cm->current_video_frame > 0) {
591
        int tmp_err, motion_error;
John Koleszar's avatar
John Koleszar committed
592
        int_mv mv, tmp_mv;
593
594
595

        xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
        motion_error = zz_motion_search(cpi, x);
John Koleszar's avatar
John Koleszar committed
596
597
598
599
600
        // Simple 0,0 motion with no mv overhead
        mv.as_int = tmp_mv.as_int = 0;

        // Test last reference frame using the previous best mv as the
        // starting point (best reference) for the search
601
        first_pass_motion_search(cpi, x, &best_ref_mv.as_mv, &mv.as_mv,
602
                                 &motion_error);
603
        if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
604
605
606
          vp9_clear_system_state();  // __asm emms;
          motion_error *= error_weight;
        }
John Koleszar's avatar
John Koleszar committed
607

608
609
        // If the current best reference mv is not centered on 0,0 then do a 0,0
        // based search as well.
John Koleszar's avatar
John Koleszar committed
610
611
        if (best_ref_mv.as_int) {
          tmp_err = INT_MAX;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
612
          first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv,
613
                                   &tmp_err);
614
          if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
615
616
617
            vp9_clear_system_state();  // __asm emms;
            tmp_err *= error_weight;
          }
John Koleszar's avatar
John Koleszar committed
618
619
620
621
622
623

          if (tmp_err < motion_error) {
            motion_error = tmp_err;
            mv.as_int = tmp_mv.as_int;
          }
        }
John Koleszar's avatar
John Koleszar committed
624

John Koleszar's avatar
John Koleszar committed
625
626
627
        // Experimental search in an older reference frame
        if (cm->current_video_frame > 1) {
          // Simple 0,0 motion with no mv overhead
628
629
630
631
          int gf_motion_error;

          xd->plane[0].pre[0].buf = gld_yv12->y_buffer + recon_yoffset;
          gf_motion_error = zz_motion_search(cpi, x);
John Koleszar's avatar
John Koleszar committed
632

Dmitry Kovalev's avatar
Dmitry Kovalev committed
633
          first_pass_motion_search(cpi, x, &zero_mv, &tmp_mv.as_mv,
634
                                   &gf_motion_error);
635
          if (cpi->oxcf.aq_mode == VARIANCE_AQ) {
636
637
638
            vp9_clear_system_state();  // __asm emms;
            gf_motion_error *= error_weight;
          }
John Koleszar's avatar
John Koleszar committed
639

Dmitry Kovalev's avatar
Dmitry Kovalev committed
640
          if (gf_motion_error < motion_error && gf_motion_error < this_error)
John Koleszar's avatar
John Koleszar committed
641
642
643
            second_ref_count++;

          // Reset to last frame as reference buffer
644
645
646
          xd->plane[0].pre[0].buf = lst_yv12->y_buffer + recon_yoffset;
          xd->plane[1].pre[0].buf = lst_yv12->u_buffer + recon_uvoffset;
          xd->plane[2].pre[0].buf = lst_yv12->v_buffer + recon_uvoffset;
John Koleszar's avatar
John Koleszar committed
647
648
649
650
651
652
653
654
655

          // 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;
656
        } else {
John Koleszar's avatar
John Koleszar committed
657
          sr_coded_error += motion_error;
658
        }
John Koleszar's avatar
John Koleszar committed
659
        /* Intra assumed best */
660
        best_ref_mv.as_int = 0;
John Koleszar's avatar
John Koleszar committed
661

John Koleszar's avatar
John Koleszar committed
662
663
664
665
666
        if (motion_error <= this_error) {
          // 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.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
667
668
          if (((this_error - intrapenalty) * 9 <= motion_error * 10) &&
              this_error < 2 * intrapenalty)
John Koleszar's avatar
John Koleszar committed
669
670
            neutral_count++;

Yaowu Xu's avatar
Yaowu Xu committed
671
672
          mv.as_mv.row *= 8;
          mv.as_mv.col *= 8;
John Koleszar's avatar
John Koleszar committed
673
          this_error = motion_error;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
674
          vp9_set_mbmode_and_mvs(xd, NEWMV, &mv.as_mv);
675
676
677
          xd->mi_8x8[0]->mbmi.tx_size = TX_4X4;
          xd->mi_8x8[0]->mbmi.ref_frame[0] = LAST_FRAME;
          xd->mi_8x8[0]->mbmi.ref_frame[1] = NONE;
678
679
          vp9_build_inter_predictors_sby(xd, mb_row << 1, mb_col << 1, bsize);
          vp9_encode_sby(x, bsize);
John Koleszar's avatar
John Koleszar committed
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
          sum_mvr += mv.as_mv.row;
          sum_mvr_abs += abs(mv.as_mv.row);
          sum_mvc += mv.as_mv.col;
          sum_mvc_abs += abs(mv.as_mv.col);
          sum_mvrs += mv.as_mv.row * mv.as_mv.row;
          sum_mvcs += mv.as_mv.col * mv.as_mv.col;
          intercount++;

          best_ref_mv.as_int = mv.as_int;

          // Was the vector non-zero
          if (mv.as_int) {
            mvcount++;

            // Was it different from the last non zero vector
            if (mv.as_int != lastmv_as_int)
              new_mv_count++;
            lastmv_as_int = mv.as_int;

            // Does the Row vector point inwards or outwards
            if (mb_row < cm->mb_rows / 2) {
              if (mv.as_mv.row > 0)
                sum_in_vectors--;
              else if (mv.as_mv.row < 0)
                sum_in_vectors++;
            } else if (mb_row > cm->mb_rows / 2) {
              if (mv.as_mv.row > 0)
                sum_in_vectors++;
              else if (mv.as_mv.row < 0)
                sum_in_vectors--;
John Koleszar's avatar
John Koleszar committed
710
711
            }

John Koleszar's avatar
John Koleszar committed
712
713
714
715
716
717
718
719
720
721
722
723
724
            // Does the Row vector point inwards or outwards
            if (mb_col < cm->mb_cols / 2) {
              if (mv.as_mv.col > 0)
                sum_in_vectors--;
              else if (mv.as_mv.col < 0)
                sum_in_vectors++;
            } else if (mb_col > cm->mb_cols / 2) {
              if (mv.as_mv.col > 0)
                sum_in_vectors++;
              else if (mv.as_mv.col < 0)
                sum_in_vectors--;
            }
          }
John Koleszar's avatar
John Koleszar committed
725
        }
726
      } else {
John Koleszar's avatar
John Koleszar committed
727
        sr_coded_error += (int64_t)this_error;
728
      }
John Koleszar's avatar
John Koleszar committed
729
      coded_error += (int64_t)this_error;
John Koleszar's avatar
John Koleszar committed
730

John Koleszar's avatar
John Koleszar committed
731
      // adjust to the next column of macroblocks
John Koleszar's avatar
John Koleszar committed
732
      x->plane[0].src.buf += 16;
Alex Converse's avatar
Alex Converse committed
733
734
      x->plane[1].src.buf += uv_mb_height;
      x->plane[2].src.buf += uv_mb_height;
John Koleszar's avatar
John Koleszar committed
735

John Koleszar's avatar
John Koleszar committed
736
      recon_yoffset += 16;
Alex Converse's avatar
Alex Converse committed
737
      recon_uvoffset += uv_mb_height;
John Koleszar's avatar
John Koleszar committed
738
739
    }

John Koleszar's avatar
John Koleszar committed
740
    // adjust to the next row of mbs
John Koleszar's avatar
John Koleszar committed
741
    x->plane[0].src.buf += 16 * x->plane[0].src.stride - 16 * cm->mb_cols;
Alex Converse's avatar
Alex Converse committed
742
743
744
745
    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;
John Koleszar's avatar
John Koleszar committed
746

747
    vp9_clear_system_state();  // __asm emms;
John Koleszar's avatar
John Koleszar committed
748
749
  }

750
  vp9_clear_system_state();  // __asm emms;
John Koleszar's avatar
John Koleszar committed
751
752
753
  {
    FIRSTPASS_STATS fps;

754
755
756
757
    fps.frame = cm->current_video_frame;
    fps.intra_error = intra_error >> 8;
    fps.coded_error = coded_error >> 8;
    fps.sr_coded_error = sr_coded_error >> 8;
758
    fps.ssim_weighted_pred_err = fps.coded_error * simple_weight(cpi->Source);
759
760
761
762
    fps.count = 1.0;
    fps.pcnt_inter = (double)intercount / cm->MBs;
    fps.pcnt_second_ref = (double)second_ref_count / cm->MBs;
    fps.pcnt_neutral = (double)neutral_count / cm->MBs;
John Koleszar's avatar
John Koleszar committed
763
764

    if (mvcount > 0) {
765
766
767
768
      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;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
769
770
      fps.MVrv = ((double)sum_mvrs - (fps.MVr * fps.MVr / mvcount)) / mvcount;
      fps.MVcv = ((double)sum_mvcs - (fps.MVc * fps.MVc / mvcount)) / mvcount;
771
      fps.mv_in_out_count = (double)sum_in_vectors / (mvcount * 2);
John Koleszar's avatar
John Koleszar committed
772
      fps.new_mv_count = new_mv_count;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
773
      fps.pcnt_motion = (double)mvcount / cm->MBs;
774
775
776
777
778
779
780
781
782
783
    } 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;
Paul Wilkins's avatar
Paul Wilkins committed
784
    }
John Koleszar's avatar
John Koleszar committed
785

786
787
788
    // 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.
789
    fps.duration = (double)(cpi->source->ts_end - cpi->source->ts_start);
John Koleszar's avatar
John Koleszar committed
790
791

    // don't want to do output stats with a stack variable!
792
793
794
    twopass->this_frame_stats = fps;
    output_stats(cpi, cpi->output_pkt_list, &twopass->this_frame_stats);
    accumulate_stats(&twopass->total_stats, &fps);
John Koleszar's avatar
John Koleszar committed
795
796
797
798
  }

  // Copy the previous Last Frame back into gf and and arf buffers if
  // the prediction is good enough... but also dont allow it to lag too far
799
  if ((twopass->sr_update_lag > 3) ||
John Koleszar's avatar
John Koleszar committed
800
      ((cm->current_video_frame > 0) &&
801
802
803
       (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))) {
John Koleszar's avatar
John Koleszar committed
804
    vp8_yv12_copy_frame(lst_yv12, gld_yv12);
805
    twopass->sr_update_lag = 1;
806
  } else {
807
    twopass->sr_update_lag++;
808
  }
John Koleszar's avatar
John Koleszar committed
809
  // swap frame pointers so last frame refers to the frame we just compressed
810
811
  swap_yv12(lst_yv12, new_yv12);

John Koleszar's avatar
John Koleszar committed
812
  vp9_extend_frame_borders(lst_yv12, cm->subsampling_x, cm->subsampling_y);
John Koleszar's avatar
John Koleszar committed
813

814
815
  // Special case for the first frame. Copy into the GF buffer as a second
  // reference.
816
  if (cm->current_video_frame == 0)
John Koleszar's avatar
John Koleszar committed
817
    vp8_yv12_copy_frame(lst_yv12, gld_yv12);
John Koleszar's avatar
John Koleszar committed
818

John Koleszar's avatar
John Koleszar committed
819
820
821
822
  // use this to see what the first pass reconstruction looks like
  if (0) {
    char filename[512];
    FILE *recon_file;
823
824
    snprintf(filename, sizeof(filename), "enc%04d.yuv",
             (int)cm->current_video_frame);
John Koleszar's avatar
John Koleszar committed
825

John Koleszar's avatar
John Koleszar committed
826
827
828
829
830
    if (cm->current_video_frame == 0)
      recon_file = fopen(filename, "wb");
    else
      recon_file = fopen(filename, "ab");

Frank Galligan's avatar
Frank Galligan committed
831
    (void)fwrite(lst_yv12->buffer_alloc, lst_yv12->frame_size, 1, recon_file);
John Koleszar's avatar
John Koleszar committed
832
833
    fclose(recon_file);
  }
John Koleszar's avatar
John Koleszar committed
834

John Koleszar's avatar
John Koleszar committed
835
  cm->current_video_frame++;
John Koleszar's avatar
John Koleszar committed
836
837
}

838
839
840
841
842
843
// Estimate a cost per mb attributable to overheads such as the coding of
// modes and motion vectors.
// Currently simplistic in its assumptions for testing.
//


844
static double bitcost(double prob) {
John Koleszar's avatar
John Koleszar committed
845
  return -(log(prob) / log(2.0));
846
}
847

848
static int64_t estimate_modemvcost(VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
849
                                     FIRSTPASS_STATS *fpstats) {
850
#if 0
John Koleszar's avatar
John Koleszar committed
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
  int mv_cost;
  int mode_cost;

  double av_pct_inter = fpstats->pcnt_inter / fpstats->count;
  double av_pct_motion = fpstats->pcnt_motion / fpstats->count;
  double av_intra = (1.0 - av_pct_inter);

  double zz_cost;
  double motion_cost;
  double intra_cost;

  zz_cost = bitcost(av_pct_inter - av_pct_motion);
  motion_cost = bitcost(av_pct_motion);
  intra_cost = bitcost(av_intra);

  // Estimate of extra bits per mv overhead for mbs
867
  // << 9 is the normalization to the (bits * 512) used in vp9_rc_bits_per_mb
John Koleszar's avatar
John Koleszar committed
868
869
870
  mv_cost = ((int)(fpstats->new_mv_count / fpstats->count) * 8) << 9;

  // Crude estimate of overhead cost from modes
871
  // << 9 is the normalization to (bits * 512) used in vp9_rc_bits_per_mb
John Koleszar's avatar
John Koleszar committed
872
873
874
875
876
877
  mode_cost =
    (int)((((av_pct_inter - av_pct_motion) * zz_cost) +
           (av_pct_motion * motion_cost) +
           (av_intra * intra_cost)) * cpi->common.MBs) << 9;

  // return mv_cost + mode_cost;
878
  // TODO(paulwilkins): Fix overhead costs for extended Q range.
879
#endif
John Koleszar's avatar
John Koleszar committed
880
  return 0;
881
882
}

John Koleszar's avatar
John Koleszar committed
883
884
885
886
static double calc_correction_factor(double err_per_mb,
                                     double err_divisor,
                                     double pt_low,
                                     double pt_high,
887
888
                                     int q) {
  const double error_term = err_per_mb / err_divisor;
889

John Koleszar's avatar
John Koleszar committed
890
  // Adjustment based on actual quantizer to power term.
Paul Wilkins's avatar
Paul Wilkins committed
891
  const double power_term = MIN(vp9_convert_qindex_to_q(q) * 0.0125 + pt_low,
892
                                pt_high);
893

John Koleszar's avatar
John Koleszar committed
894
  // Calculate correction factor
John Koleszar's avatar
John Koleszar committed
895
896
  if (power_term < 1.0)
    assert(error_term >= 0.0);
897

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

Dmitry Kovalev's avatar
Dmitry Kovalev committed
901
static int estimate_max_q(VP9_COMP *cpi, FIRSTPASS_STATS *fpstats,
902
                          int section_target_bandwitdh) {
903
  int q;
904
  const int num_mbs = cpi->common.MBs;
John Koleszar's avatar
John Koleszar committed
905
  int target_norm_bits_per_mb;
Dmitry Kovalev's avatar
Dmitry Kovalev committed
906
  RATE_CONTROL *const rc = &cpi->rc;
John Koleszar's avatar
John Koleszar committed
907

Dmitry Kovalev's avatar
Dmitry Kovalev committed
908
909
  const double section_err = fpstats->coded_error / fpstats->count;
  const double err_per_mb = section_err / num_mbs;
John Koleszar's avatar
John Koleszar committed
910
911

  if (section_target_bandwitdh <= 0)
Dmitry Kovalev's avatar
Dmitry Kovalev committed
912
    return rc->worst_quality;          // Highest value allowed
John Koleszar's avatar
John Koleszar committed
913

914
915
916
  target_norm_bits_per_mb = section_target_bandwitdh < (1 << 20)
                              ? (512 * section_target_bandwitdh) / num_mbs
                              : 512 * (section_target_bandwitdh / num_mbs);
John Koleszar's avatar
John Koleszar committed
917
918
919

  // Try and pick a max Q that will be high enough to encode the
  // content at the given rate.
Dmitry Kovalev's avatar
Dmitry Kovalev committed
920
921
922
923
924
  for (q = rc->best_quality; q < rc->worst_quality; q++) {
    const double err_correction_factor = calc_correction_factor(err_per_mb,
                                             ERR_DIVISOR, 0.5, 0.90, q);
    const int bits_per_mb_at_this_q = vp9_rc_bits_per_mb(INTER_FRAME, q,
                                                         err_correction_factor);
John Koleszar's avatar
John Koleszar committed
925
926
927
928
929
    if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
      break;
  }

  // Restriction on active max q for constrained quality mode.
930
931
  if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
    q = MAX(q, cpi->cq_target_quality);
John Koleszar's avatar
John Koleszar committed
932

933
  return q;
John Koleszar's avatar
John Koleszar committed
934
}
935
936
937

// For cq mode estimate a cq level that matches the observed
// complexity and data rate.
938
static int estimate_cq(VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
939
                       FIRSTPASS_STATS *fpstats,
940
                       int section_target_bandwitdh) {
941
  int q;
John Koleszar's avatar
John Koleszar committed
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
  int num_mbs = cpi->common.MBs;
  int target_norm_bits_per_mb;

  double section_err = (fpstats->coded_error / fpstats->count);
  double err_per_mb = section_err / num_mbs;
  double err_correction_factor;
  double clip_iiratio;
  double clip_iifactor;

  target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20))
                            ? (512 * section_target_bandwitdh) / num_mbs
                            : 512 * (section_target_bandwitdh / num_mbs);


  // II ratio correction factor for clip as a whole
957
958
  clip_iiratio = cpi->twopass.total_stats.intra_error /
                 DOUBLE_DIVIDE_CHECK(cpi->twopass.total_stats.coded_error);
John Koleszar's avatar
John Koleszar committed
959
960
961
962
963
  clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025);
  if (clip_iifactor < 0.80)
    clip_iifactor = 0.80;

  // Try and pick a Q that can encode the content at the given rate.
964
  for (q = 0; q < MAXQ; q++) {