vp9_temporal_filter.c 17.8 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
#include "vpx_mem/vpx_mem.h"
#include "vpx_ports/vpx_timer.h"

#define ALT_REF_MC_ENABLED 1    // dis/enable MC in AltRef filtering
32
#define ALT_REF_SUBPEL_ENABLED 1  // dis/enable subpel in MC AltRef filtering
Johann's avatar
Johann committed
33

34
35
36
37
38
39
40
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,
Yunqing Wang's avatar
Yunqing Wang committed
41
42
                                            uint8_t *pred,
                                            struct scale_factors *scale) {
43
  const int which_mv = 0;
44
  MV mv = { mv_row, mv_col };
John Koleszar's avatar
John Koleszar committed
45

46
47
  vp9_build_inter_predictor(y_mb_ptr, stride,
                            &pred[0], 16,
48
                            &mv,
Yunqing Wang's avatar
Yunqing Wang committed
49
                            scale,
50
                            16, 16,
51
                            which_mv,
52
                            &xd->subpix, MV_PRECISION_Q3);
John Koleszar's avatar
John Koleszar committed
53
54

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

56
57
58
  vp9_build_inter_predictor(u_mb_ptr, stride,
                            &pred[256], 8,
                            &mv,
Yunqing Wang's avatar
Yunqing Wang committed
59
                            scale,
60
61
62
                            8, 8,
                            which_mv,
                            &xd->subpix, MV_PRECISION_Q4);
63

64
65
66
  vp9_build_inter_predictor(v_mb_ptr, stride,
                            &pred[320], 8,
                            &mv,
Yunqing Wang's avatar
Yunqing Wang committed
67
                            scale,
68
69
70
                            8, 8,
                            which_mv,
                            &xd->subpix, MV_PRECISION_Q4);
Johann's avatar
Johann committed
71
}
72
73
74
75
76
77
78
79
80

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
81
82
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
  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
109
    }
John Koleszar's avatar
John Koleszar committed
110
111
112

    byte += stride - block_size;
  }
Johann's avatar
Johann committed
113
114
115
116
}

#if ALT_REF_MC_ENABLED

117
static int temporal_filter_find_matching_mb_c(VP9_COMP *cpi,
118
119
120
                                              uint8_t *arf_frame_buf,
                                              uint8_t *frame_ptr_buf,
                                              int stride,
121
                                              int error_thresh) {
John Koleszar's avatar
John Koleszar committed
122
  MACROBLOCK *x = &cpi->mb;
123
  MACROBLOCKD* const xd = &x->e_mbd;
John Koleszar's avatar
John Koleszar committed
124
125
126
127
128
129
  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
130
  int_mv *ref_mv;
John Koleszar's avatar
John Koleszar committed
131
132

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

  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
141
142
143
144
  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
145
146

  // Further step/diamond searches as necessary
147
  if (cpi->speed < 8)
148
    step_param = cpi->sf.reduce_first_step_size + ((cpi->speed > 5) ? 1 : 0);
149
  else
150
151
    step_param = cpi->sf.reduce_first_step_size + 2;
  step_param = MIN(step_param, (cpi->sf.max_step_search_steps - 2));
John Koleszar's avatar
John Koleszar committed
152
153
154

  /*cpi->sf.search_method == HEX*/
  // Ignore mv costing by sending NULL pointer instead of cost arrays
155
  ref_mv = &x->e_mbd.mi_8x8[0]->bmi[0].as_mv[0];
156
  bestsme = vp9_hex_search(x, &best_ref_mv1_full.as_mv,
157
158
                           step_param, sadpb, 1,
                           &cpi->fn_ptr[BLOCK_16X16],
159
                           0, &best_ref_mv1.as_mv, &ref_mv->as_mv);
Johann's avatar
Johann committed
160
161

#if ALT_REF_SUBPEL_ENABLED
John Koleszar's avatar
John Koleszar committed
162
163
164
165
166
167
  // 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
168
169
    bestsme = cpi->find_fractional_mv_step(x, &ref_mv->as_mv,
                                           &best_ref_mv1.as_mv,
170
                                           cpi->common.allow_high_precision_mv,
John Koleszar's avatar
John Koleszar committed
171
172
                                           x->errorperbit,
                                           &cpi->fn_ptr[BLOCK_16X16],
173
                                           0, cpi->sf.subpel_iters_per_step,
174
                                           NULL, NULL,
175
                                           &distortion, &sse);
John Koleszar's avatar
John Koleszar committed
176
  }
Johann's avatar
Johann committed
177
178
#endif

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

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

187
188
189
static void temporal_filter_iterate_c(VP9_COMP *cpi,
                                      int frame_count,
                                      int alt_ref_index,
Yunqing Wang's avatar
Yunqing Wang committed
190
191
                                      int strength,
                                      struct scale_factors *scale) {
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;

249
250
        mbd->mi_8x8[0]->bmi[0].as_mv[0].as_mv.row = 0;
        mbd->mi_8x8[0]->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,
283
284
           mbd->mi_8x8[0]->bmi[0].as_mv[0].as_mv.row,
           mbd->mi_8x8[0]->bmi[0].as_mv[0].as_mv.col,
Yunqing Wang's avatar
Yunqing Wang committed
285
           predictor, scale);
John Koleszar's avatar
John Koleszar committed
286
287

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

Yunqing Wang's avatar
Yunqing Wang committed
379
380
381
  struct scale_factors scale;
  struct scale_factors_common scale_comm;

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

John Koleszar's avatar
John Koleszar committed
387
388
      if (frames_to_blur_backward >= max_frames)
        frames_to_blur_backward = max_frames - 1;
Johann's avatar
Johann committed
389

John Koleszar's avatar
John Koleszar committed
390
391
      frames_to_blur = frames_to_blur_backward + 1;
      break;
Johann's avatar
Johann committed
392
393

    case 2:
John Koleszar's avatar
John Koleszar committed
394
      // Forward Blur
Johann's avatar
Johann committed
395

John Koleszar's avatar
John Koleszar committed
396
      frames_to_blur_forward = num_frames_forward;
Johann's avatar
Johann committed
397

John Koleszar's avatar
John Koleszar committed
398
399
      if (frames_to_blur_forward >= max_frames)
        frames_to_blur_forward = max_frames - 1;
Johann's avatar
Johann committed
400

John Koleszar's avatar
John Koleszar committed
401
402
      frames_to_blur = frames_to_blur_forward + 1;
      break;
Johann's avatar
Johann committed
403
404
405

    case 3:
    default:
John Koleszar's avatar
John Koleszar committed
406
407
408
      // Center Blur
      frames_to_blur_forward = num_frames_forward;
      frames_to_blur_backward = num_frames_backward;
Johann's avatar
Johann committed
409

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

John Koleszar's avatar
John Koleszar committed
413
414
      if (frames_to_blur_backward > frames_to_blur_forward)
        frames_to_blur_backward = frames_to_blur_forward;
Johann's avatar
Johann committed
415

John Koleszar's avatar
John Koleszar committed
416
417
418
      // 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
419

John Koleszar's avatar
John Koleszar committed
420
421
      if (frames_to_blur_backward > (max_frames / 2))
        frames_to_blur_backward = (max_frames / 2);
Johann's avatar
Johann committed
422

John Koleszar's avatar
John Koleszar committed
423
424
425
      frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
      break;
  }
Johann's avatar
Johann committed
426

John Koleszar's avatar
John Koleszar committed
427
  start_frame = distance + frames_to_blur_forward;
Johann's avatar
Johann committed
428
429

#ifdef DEBUGFWG
John Koleszar's avatar
John Koleszar committed
430
  // DEBUG FWG
431
432
433
434
435
436
  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
437
438
#endif

439
  // Setup scaling factors. Scaling on each of the arnr frames is not supported
Yunqing Wang's avatar
Yunqing Wang committed
440
  vp9_setup_scale_factors_for_frame(&scale, &scale_comm,
441
442
      get_frame_new_buffer(cm)->y_crop_width,
      get_frame_new_buffer(cm)->y_crop_height,
443
      cm->width, cm->height);
444

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

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

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;
473
  frames_after_arf = (int)(cpi->twopass.total_stats.count - this_frame - 1);
474
475
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

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