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

Dmitry Kovalev's avatar
Dmitry Kovalev committed
11 12
#include <math.h>
#include <limits.h>
Johann's avatar
Johann committed
13

14
#include "vp9/common/vp9_onyxc_int.h"
15
#include "vp9/common/vp9_reconinter.h"
16
#include "vp9/encoder/vp9_onyx_int.h"
17
#include "vp9/common/vp9_systemdependent.h"
18
#include "vp9/encoder/vp9_quantize.h"
19
#include "vp9/common/vp9_alloccommon.h"
20 21 22
#include "vp9/encoder/vp9_mcomp.h"
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/encoder/vp9_psnr.h"
Johann's avatar
Johann committed
23
#include "vpx_scale/vpx_scale.h"
24
#include "vp9/common/vp9_extend.h"
25
#include "vp9/encoder/vp9_ratectrl.h"
26
#include "vp9/common/vp9_quant_common.h"
27
#include "vp9/encoder/vp9_segmentation.h"
Johann's avatar
Johann committed
28 29 30 31 32 33
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/vpx_timer.h"

#define ALT_REF_MC_ENABLED 1    // dis/enable MC in AltRef filtering
#define ALT_REF_SUBPEL_ENABLED 1 // dis/enable subpel in MC AltRef filtering

34 35 36 37 38 39 40 41
static void temporal_filter_predictors_mb_c(MACROBLOCKD *xd,
                                            uint8_t *y_mb_ptr,
                                            uint8_t *u_mb_ptr,
                                            uint8_t *v_mb_ptr,
                                            int stride,
                                            int mv_row,
                                            int mv_col,
                                            uint8_t *pred) {
42
  const int which_mv = 0;
43
  int_mv mv;
John Koleszar's avatar
John Koleszar committed
44

45 46
  mv.as_mv.row = mv_row;
  mv.as_mv.col = mv_col;
John Koleszar's avatar
John Koleszar committed
47

48 49
  vp9_build_inter_predictor(y_mb_ptr, stride,
                            &pred[0], 16,
50
                            &mv,
51
                            &xd->scale_factor[which_mv],
52
                            16, 16,
53
                            which_mv,
54
                            &xd->subpix);
John Koleszar's avatar
John Koleszar committed
55 56

  stride = (stride + 1) >> 1;
Johann's avatar
Johann committed
57

58 59
  vp9_build_inter_predictor_q4(u_mb_ptr, stride,
                               &pred[256], 8,
60
                               &mv,
61
                               &xd->scale_factor_uv[which_mv],
62
                               8, 8,
63
                               which_mv,
64
                               &xd->subpix);
65

66 67
  vp9_build_inter_predictor_q4(v_mb_ptr, stride,
                               &pred[320], 8,
68
                               &mv,
69
                               &xd->scale_factor_uv[which_mv],
70
                               8, 8,
71
                               which_mv,
72
                               &xd->subpix);
Johann's avatar
Johann committed
73
}
74 75 76 77 78 79 80 81 82

void vp9_temporal_filter_apply_c(uint8_t *frame1,
                                 unsigned int stride,
                                 uint8_t *frame2,
                                 unsigned int block_size,
                                 int strength,
                                 int filter_weight,
                                 unsigned int *accumulator,
                                 uint16_t *count) {
John Koleszar's avatar
John Koleszar committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
  unsigned int i, j, k;
  int modifier;
  int byte = 0;

  for (i = 0, k = 0; i < block_size; i++) {
    for (j = 0; j < block_size; j++, k++) {

      int src_byte = frame1[byte];
      int pixel_value = *frame2++;

      modifier   = src_byte - pixel_value;
      // This is an integer approximation of:
      // float coeff = (3.0 * modifer * modifier) / pow(2, strength);
      // modifier =  (int)roundf(coeff > 16 ? 0 : 16-coeff);
      modifier  *= modifier;
      modifier  *= 3;
      modifier  += 1 << (strength - 1);
      modifier >>= strength;

      if (modifier > 16)
        modifier = 16;

      modifier = 16 - modifier;
      modifier *= filter_weight;

      count[k] += modifier;
      accumulator[k] += modifier * pixel_value;

      byte++;
Johann's avatar
Johann committed
112
    }
John Koleszar's avatar
John Koleszar committed
113 114 115

    byte += stride - block_size;
  }
Johann's avatar
Johann committed
116 117 118 119
}

#if ALT_REF_MC_ENABLED

120
static int temporal_filter_find_matching_mb_c(VP9_COMP *cpi,
121 122 123
                                              uint8_t *arf_frame_buf,
                                              uint8_t *frame_ptr_buf,
                                              int stride,
124
                                              int error_thresh) {
John Koleszar's avatar
John Koleszar committed
125
  MACROBLOCK *x = &cpi->mb;
126
  MACROBLOCKD* const xd = &x->e_mbd;
John Koleszar's avatar
John Koleszar committed
127 128 129 130 131 132
  int step_param;
  int sadpb = x->sadperbit16;
  int bestsme = INT_MAX;

  int_mv best_ref_mv1;
  int_mv best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
Scott LaVarnway's avatar
Scott LaVarnway committed
133
  int_mv *ref_mv;
John Koleszar's avatar
John Koleszar committed
134 135

  // Save input state
John Koleszar's avatar
John Koleszar committed
136
  struct buf_2d src = x->plane[0].src;
137
  struct buf_2d pre = xd->plane[0].pre[0];
John Koleszar's avatar
John Koleszar committed
138 139 140 141 142 143

  best_ref_mv1.as_int = 0;
  best_ref_mv1_full.as_mv.col = best_ref_mv1.as_mv.col >> 3;
  best_ref_mv1_full.as_mv.row = best_ref_mv1.as_mv.row >> 3;

  // Setup frame pointers
144 145 146 147
  x->plane[0].src.buf = arf_frame_buf;
  x->plane[0].src.stride = stride;
  xd->plane[0].pre[0].buf = frame_ptr_buf;
  xd->plane[0].pre[0].stride = stride;
John Koleszar's avatar
John Koleszar committed
148 149

  // Further step/diamond searches as necessary
150 151 152
  if (cpi->speed < 8)
    step_param = cpi->sf.first_step + ((cpi->speed > 5) ? 1 : 0);
  else
John Koleszar's avatar
John Koleszar committed
153 154 155 156 157
    step_param = cpi->sf.first_step + 2;

  /*cpi->sf.search_method == HEX*/
  // TODO Check that the 16x16 vf & sdf are selected here
  // Ignore mv costing by sending NULL pointer instead of cost arrays
Scott LaVarnway's avatar
Scott LaVarnway committed
158
  ref_mv = &x->e_mbd.mode_info_context->bmi[0].as_mv[0];
John Koleszar's avatar
John Koleszar committed
159
  bestsme = vp9_hex_search(x, &best_ref_mv1_full, ref_mv,
John Koleszar's avatar
John Koleszar committed
160
                           step_param, sadpb, &cpi->fn_ptr[BLOCK_16X16],
161
                           NULL, NULL, NULL, NULL,
162
                           &best_ref_mv1);
Johann's avatar
Johann committed
163 164

#if ALT_REF_SUBPEL_ENABLED
John Koleszar's avatar
John Koleszar committed
165 166 167 168 169 170
  // Try sub-pixel MC?
  // if (bestsme > error_thresh && bestsme < INT_MAX)
  {
    int distortion;
    unsigned int sse;
    // Ignore mv costing by sending NULL pointer instead of cost array
John Koleszar's avatar
John Koleszar committed
171
    bestsme = cpi->find_fractional_mv_step(x, ref_mv,
John Koleszar's avatar
John Koleszar committed
172 173 174
                                           &best_ref_mv1,
                                           x->errorperbit,
                                           &cpi->fn_ptr[BLOCK_16X16],
175
                                           NULL, NULL,
176
                                           &distortion, &sse);
John Koleszar's avatar
John Koleszar committed
177
  }
Johann's avatar
Johann committed
178 179
#endif

180
  // Restore input state
John Koleszar's avatar
John Koleszar committed
181
  x->plane[0].src = src;
182
  xd->plane[0].pre[0] = pre;
Johann's avatar
Johann committed
183

John Koleszar's avatar
John Koleszar committed
184
  return bestsme;
Johann's avatar
Johann committed
185 186 187
}
#endif

188 189 190 191
static void temporal_filter_iterate_c(VP9_COMP *cpi,
                                      int frame_count,
                                      int alt_ref_index,
                                      int strength) {
John Koleszar's avatar
John Koleszar committed
192 193 194 195 196 197 198 199 200
  int byte;
  int frame;
  int mb_col, mb_row;
  unsigned int filter_weight;
  int mb_cols = cpi->common.mb_cols;
  int mb_rows = cpi->common.mb_rows;
  int mb_y_offset = 0;
  int mb_uv_offset = 0;
  DECLARE_ALIGNED_ARRAY(16, unsigned int, accumulator, 16 * 16 + 8 * 8 + 8 * 8);
201
  DECLARE_ALIGNED_ARRAY(16, uint16_t, count, 16 * 16 + 8 * 8 + 8 * 8);
John Koleszar's avatar
John Koleszar committed
202 203
  MACROBLOCKD *mbd = &cpi->mb.e_mbd;
  YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
204 205
  uint8_t *dst1, *dst2;
  DECLARE_ALIGNED_ARRAY(16, uint8_t,  predictor, 16 * 16 + 8 * 8 + 8 * 8);
John Koleszar's avatar
John Koleszar committed
206 207

  // Save input state
208 209 210 211 212
  uint8_t* input_buffer[MAX_MB_PLANE];
  int i;

  for (i = 0; i < MAX_MB_PLANE; i++)
    input_buffer[i] = mbd->plane[i].pre[0].buf;
John Koleszar's avatar
John Koleszar committed
213 214

  for (mb_row = 0; mb_row < mb_rows; mb_row++) {
Johann's avatar
Johann committed
215
#if ALT_REF_MC_ENABLED
John Koleszar's avatar
John Koleszar committed
216
    // Source frames are extended to 16 pixels.  This is different than
John Koleszar's avatar
John Koleszar committed
217
    //  L/A/G reference frames that have a border of 32 (VP9BORDERINPIXELS)
John Koleszar's avatar
John Koleszar committed
218 219
    // A 6/8 tap filter is used for motion search.  This requires 2 pixels
    //  before and 3 pixels after.  So the largest Y mv on a border would
John Koleszar's avatar
John Koleszar committed
220 221 222 223 224
    //  then be 16 - VP9_INTERP_EXTEND. The UV blocks are half the size of the
    //  Y and therefore only extended by 8.  The largest mv that a UV block
    //  can support is 8 - VP9_INTERP_EXTEND.  A UV mv is half of a Y mv.
    //  (16 - VP9_INTERP_EXTEND) >> 1 which is greater than
    //  8 - VP9_INTERP_EXTEND.
John Koleszar's avatar
John Koleszar committed
225
    // To keep the mv in play for both Y and UV planes the max that it
John Koleszar's avatar
John Koleszar committed
226 227
    //  can be on a border is therefore 16 - (2*VP9_INTERP_EXTEND+1).
    cpi->mb.mv_row_min = -((mb_row * 16) + (17 - 2 * VP9_INTERP_EXTEND));
John Koleszar's avatar
John Koleszar committed
228
    cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16)
John Koleszar's avatar
John Koleszar committed
229
                         + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
230 231
#endif

John Koleszar's avatar
John Koleszar committed
232 233 234
    for (mb_col = 0; mb_col < mb_cols; mb_col++) {
      int i, j, k;
      int stride;
Johann's avatar
Johann committed
235

John Koleszar's avatar
John Koleszar committed
236
      vpx_memset(accumulator, 0, 384 * sizeof(unsigned int));
237
      vpx_memset(count, 0, 384 * sizeof(uint16_t));
Johann's avatar
Johann committed
238 239

#if ALT_REF_MC_ENABLED
John Koleszar's avatar
John Koleszar committed
240
      cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2 * VP9_INTERP_EXTEND));
John Koleszar's avatar
John Koleszar committed
241
      cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16)
John Koleszar's avatar
John Koleszar committed
242
                           + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
243 244
#endif

John Koleszar's avatar
John Koleszar committed
245 246 247 248
      for (frame = 0; frame < frame_count; frame++) {
        if (cpi->frames[frame] == NULL)
          continue;

Scott LaVarnway's avatar
Scott LaVarnway committed
249 250
        mbd->mode_info_context->bmi[0].as_mv[0].as_mv.row = 0;
        mbd->mode_info_context->bmi[0].as_mv[0].as_mv.col = 0;
John Koleszar's avatar
John Koleszar committed
251 252 253 254 255

        if (frame == alt_ref_index) {
          filter_weight = 2;
        } else {
          int err = 0;
Johann's avatar
Johann committed
256 257 258 259
#if ALT_REF_MC_ENABLED
#define THRESH_LOW   10000
#define THRESH_HIGH  20000

John Koleszar's avatar
John Koleszar committed
260
          // Find best match in this frame by MC
261
          err = temporal_filter_find_matching_mb_c
John Koleszar's avatar
John Koleszar committed
262
                (cpi,
263 264 265
                 cpi->frames[alt_ref_index]->y_buffer + mb_y_offset,
                 cpi->frames[frame]->y_buffer + mb_y_offset,
                 cpi->frames[frame]->y_stride,
John Koleszar's avatar
John Koleszar committed
266
                 THRESH_LOW);
Johann's avatar
Johann committed
267
#endif
John Koleszar's avatar
John Koleszar committed
268 269 270 271 272 273 274 275 276
          // Assign higher weight to matching MB if it's error
          // score is lower. If not applying MC default behavior
          // is to weight all MBs equal.
          filter_weight = err < THRESH_LOW
                          ? 2 : err < THRESH_HIGH ? 1 : 0;
        }

        if (filter_weight != 0) {
          // Construct the predictors
277
          temporal_filter_predictors_mb_c
John Koleszar's avatar
John Koleszar committed
278 279 280 281 282
          (mbd,
           cpi->frames[frame]->y_buffer + mb_y_offset,
           cpi->frames[frame]->u_buffer + mb_uv_offset,
           cpi->frames[frame]->v_buffer + mb_uv_offset,
           cpi->frames[frame]->y_stride,
Scott LaVarnway's avatar
Scott LaVarnway committed
283 284
           mbd->mode_info_context->bmi[0].as_mv[0].as_mv.row,
           mbd->mode_info_context->bmi[0].as_mv[0].as_mv.col,
John Koleszar's avatar
John Koleszar committed
285 286 287
           predictor);

          // Apply the filter (YUV)
Jim Bankoski's avatar
Jim Bankoski committed
288 289 290 291 292 293 294 295 296 297 298
          vp9_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
                                    predictor, 16, strength, filter_weight,
                                    accumulator, count);

          vp9_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
                                    predictor + 256, 8, strength, filter_weight,
                                    accumulator + 256, count + 256);

          vp9_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
                                    predictor + 320, 8, strength, filter_weight,
                                    accumulator + 320, count + 320);
John Koleszar's avatar
John Koleszar committed
299 300 301 302 303 304 305 306 307 308 309 310 311
        }
      }

      // Normalize filter output to produce AltRef frame
      dst1 = cpi->alt_ref_buffer.y_buffer;
      stride = cpi->alt_ref_buffer.y_stride;
      byte = mb_y_offset;
      for (i = 0, k = 0; i < 16; i++) {
        for (j = 0; j < 16; j++, k++) {
          unsigned int pval = accumulator[k] + (count[k] >> 1);
          pval *= cpi->fixed_divide[count[k]];
          pval >>= 19;

312
          dst1[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332

          // move to next pixel
          byte++;
        }

        byte += stride - 16;
      }

      dst1 = cpi->alt_ref_buffer.u_buffer;
      dst2 = cpi->alt_ref_buffer.v_buffer;
      stride = cpi->alt_ref_buffer.uv_stride;
      byte = mb_uv_offset;
      for (i = 0, k = 256; i < 8; i++) {
        for (j = 0; j < 8; j++, k++) {
          int m = k + 64;

          // U
          unsigned int pval = accumulator[k] + (count[k] >> 1);
          pval *= cpi->fixed_divide[count[k]];
          pval >>= 19;
333
          dst1[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
334 335 336 337 338

          // V
          pval = accumulator[m] + (count[m] >> 1);
          pval *= cpi->fixed_divide[count[m]];
          pval >>= 19;
339
          dst2[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
340 341 342

          // move to next pixel
          byte++;
Johann's avatar
Johann committed
343 344
        }

John Koleszar's avatar
John Koleszar committed
345 346 347 348 349
        byte += stride - 8;
      }

      mb_y_offset += 16;
      mb_uv_offset += 8;
Johann's avatar
Johann committed
350 351
    }

John Koleszar's avatar
John Koleszar committed
352 353 354 355 356
    mb_y_offset += 16 * (f->y_stride - mb_cols);
    mb_uv_offset += 8 * (f->uv_stride - mb_cols);
  }

  // Restore input state
357 358
  for (i = 0; i < MAX_MB_PLANE; i++)
    mbd->plane[i].pre[0].buf = input_buffer[i];
Johann's avatar
Johann committed
359 360
}

Dmitry Kovalev's avatar
Dmitry Kovalev committed
361
void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
362 363
  VP9_COMMON *const cm = &cpi->common;

John Koleszar's avatar
John Koleszar committed
364
  int frame = 0;
Johann's avatar
Johann committed
365

John Koleszar's avatar
John Koleszar committed
366 367 368 369
  int frames_to_blur_backward = 0;
  int frames_to_blur_forward = 0;
  int frames_to_blur = 0;
  int start_frame = 0;
Johann's avatar
Johann committed
370

371
  int strength = cpi->active_arnr_strength;
John Koleszar's avatar
John Koleszar committed
372 373
  int blur_type = cpi->oxcf.arnr_type;
  int max_frames = cpi->active_arnr_frames;
Johann's avatar
Johann committed
374

375 376 377
  const int num_frames_backward = distance;
  const int num_frames_forward = vp9_lookahead_depth(cpi->lookahead)
                               - (num_frames_backward + 1);
Johann's avatar
Johann committed
378

John Koleszar's avatar
John Koleszar committed
379
  switch (blur_type) {
Johann's avatar
Johann committed
380
    case 1:
John Koleszar's avatar
John Koleszar committed
381 382
      // Backward Blur
      frames_to_blur_backward = num_frames_backward;
Johann's avatar
Johann committed
383

John Koleszar's avatar
John Koleszar committed
384 385
      if (frames_to_blur_backward >= max_frames)
        frames_to_blur_backward = max_frames - 1;
Johann's avatar
Johann committed
386

John Koleszar's avatar
John Koleszar committed
387 388
      frames_to_blur = frames_to_blur_backward + 1;
      break;
Johann's avatar
Johann committed
389 390

    case 2:
John Koleszar's avatar
John Koleszar committed
391
      // Forward Blur
Johann's avatar
Johann committed
392

John Koleszar's avatar
John Koleszar committed
393
      frames_to_blur_forward = num_frames_forward;
Johann's avatar
Johann committed
394

John Koleszar's avatar
John Koleszar committed
395 396
      if (frames_to_blur_forward >= max_frames)
        frames_to_blur_forward = max_frames - 1;
Johann's avatar
Johann committed
397

John Koleszar's avatar
John Koleszar committed
398 399
      frames_to_blur = frames_to_blur_forward + 1;
      break;
Johann's avatar
Johann committed
400 401 402

    case 3:
    default:
John Koleszar's avatar
John Koleszar committed
403 404 405
      // Center Blur
      frames_to_blur_forward = num_frames_forward;
      frames_to_blur_backward = num_frames_backward;
Johann's avatar
Johann committed
406

John Koleszar's avatar
John Koleszar committed
407 408
      if (frames_to_blur_forward > frames_to_blur_backward)
        frames_to_blur_forward = frames_to_blur_backward;
Johann's avatar
Johann committed
409

John Koleszar's avatar
John Koleszar committed
410 411
      if (frames_to_blur_backward > frames_to_blur_forward)
        frames_to_blur_backward = frames_to_blur_forward;
Johann's avatar
Johann committed
412

John Koleszar's avatar
John Koleszar committed
413 414 415
      // When max_frames is even we have 1 more frame backward than forward
      if (frames_to_blur_forward > (max_frames - 1) / 2)
        frames_to_blur_forward = ((max_frames - 1) / 2);
Johann's avatar
Johann committed
416

John Koleszar's avatar
John Koleszar committed
417 418
      if (frames_to_blur_backward > (max_frames / 2))
        frames_to_blur_backward = (max_frames / 2);
Johann's avatar
Johann committed
419

John Koleszar's avatar
John Koleszar committed
420 421 422
      frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
      break;
  }
Johann's avatar
Johann committed
423

John Koleszar's avatar
John Koleszar committed
424
  start_frame = distance + frames_to_blur_forward;
Johann's avatar
Johann committed
425 426

#ifdef DEBUGFWG
John Koleszar's avatar
John Koleszar committed
427 428 429 430 431 432 433 434 435 436 437
  // DEBUG FWG
  printf("max:%d FBCK:%d FFWD:%d ftb:%d ftbbck:%d ftbfwd:%d sei:%d lasei:%d start:%d"
, max_frames
, num_frames_backward
, num_frames_forward
, frames_to_blur
, frames_to_blur_backward
, frames_to_blur_forward
, cpi->source_encode_index
, cpi->last_alt_ref_sei
, start_frame);
Johann's avatar
Johann committed
438 439
#endif

440 441
  // Setup scaling factors. Scaling on each of the arnr frames is not supported
  vp9_setup_scale_factors_for_frame(&cpi->mb.e_mbd.scale_factor[0],
442 443 444
      cm->yv12_fb[cm->new_fb_idx].y_crop_width,
      cm->yv12_fb[cm->new_fb_idx].y_crop_height,
      cm->width, cm->height);
445 446
  cpi->mb.e_mbd.scale_factor_uv[0] = cpi->mb.e_mbd.scale_factor[0];

John Koleszar's avatar
John Koleszar committed
447 448 449
  // Setup frame pointers, NULL indicates frame not included in filter
  vpx_memset(cpi->frames, 0, max_frames * sizeof(YV12_BUFFER_CONFIG *));
  for (frame = 0; frame < frames_to_blur; frame++) {
450
    int which_buffer = start_frame - frame;
451
    struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
John Koleszar's avatar
John Koleszar committed
452 453 454 455
                                                     which_buffer);
    cpi->frames[frames_to_blur - 1 - frame] = &buf->img;
  }

456 457
  temporal_filter_iterate_c(cpi, frames_to_blur, frames_to_blur_backward,
                            strength);
Johann's avatar
Johann committed
458
}
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474

void configure_arnr_filter(VP9_COMP *cpi, const unsigned int this_frame,
                           const int group_boost) {
  int half_gf_int;
  int frames_after_arf;
  int frames_bwd = cpi->oxcf.arnr_max_frames - 1;
  int frames_fwd = cpi->oxcf.arnr_max_frames - 1;
  int q;

  // Define the arnr filter width for this group of frames:
  // We only filter frames that lie within a distance of half
  // the GF interval from the ARF frame. We also have to trap
  // cases where the filter extends beyond the end of clip.
  // Note: this_frame->frame has been updated in the loop
  // so it now points at the ARF frame.
  half_gf_int = cpi->baseline_gf_interval >> 1;
475
  frames_after_arf = (int)(cpi->twopass.total_stats.count - this_frame - 1);
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529

  switch (cpi->oxcf.arnr_type) {
    case 1:  // Backward filter
      frames_fwd = 0;
      if (frames_bwd > half_gf_int)
        frames_bwd = half_gf_int;
      break;

    case 2:  // Forward filter
      if (frames_fwd > half_gf_int)
        frames_fwd = half_gf_int;
      if (frames_fwd > frames_after_arf)
        frames_fwd = frames_after_arf;
      frames_bwd = 0;
      break;

    case 3:  // Centered filter
    default:
      frames_fwd >>= 1;
      if (frames_fwd > frames_after_arf)
        frames_fwd = frames_after_arf;
      if (frames_fwd > half_gf_int)
        frames_fwd = half_gf_int;

      frames_bwd = frames_fwd;

      // For even length filter there is one more frame backward
      // than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
      if (frames_bwd < half_gf_int)
        frames_bwd += (cpi->oxcf.arnr_max_frames + 1) & 0x1;
      break;
  }

  cpi->active_arnr_frames = frames_bwd + 1 + frames_fwd;

  // Adjust the strength based on active max q
  q = ((int)vp9_convert_qindex_to_q(cpi->active_worst_quality) >> 1);
  if (q > 8) {
    cpi->active_arnr_strength = cpi->oxcf.arnr_strength;
  } else {
    cpi->active_arnr_strength = cpi->oxcf.arnr_strength - (8 - q);
    if (cpi->active_arnr_strength < 0)
      cpi->active_arnr_strength = 0;
  }

  // Adjust number of frames in filter and strength based on gf boost level.
  if (cpi->active_arnr_frames > (group_boost / 150)) {
    cpi->active_arnr_frames = (group_boost / 150);
    cpi->active_arnr_frames += !(cpi->active_arnr_frames & 1);
  }
  if (cpi->active_arnr_strength > (group_boost / 300)) {
    cpi->active_arnr_strength = (group_boost / 300);
  }
}