vp9_temporal_filter.c 14.6 KB
Newer Older
Johann's avatar
Johann committed
1
2
3
4
5
6
7
8
9
10
11
/*
 *  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.
 */


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

#include <math.h>
#include <limits.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

35
#if VP9_TEMPORAL_ALT_REF
Johann's avatar
Johann committed
36

37

38
static void temporal_filter_predictors_mb_c
Johann's avatar
Johann committed
39
(
Paul Wilkins's avatar
Paul Wilkins committed
40
  MACROBLOCKD *xd,
John Koleszar's avatar
John Koleszar committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  unsigned char *y_mb_ptr,
  unsigned char *u_mb_ptr,
  unsigned char *v_mb_ptr,
  int stride,
  int mv_row,
  int mv_col,
  unsigned char *pred
) {
  int offset;
  unsigned char *yptr, *uptr, *vptr;
  int omv_row, omv_col;

  // Y
  yptr = y_mb_ptr + (mv_row >> 3) * stride + (mv_col >> 3);

  if ((mv_row | mv_col) & 7) {
Paul Wilkins's avatar
Paul Wilkins committed
57
    xd->subpixel_predict16x16(yptr, stride,
John Koleszar's avatar
John Koleszar committed
58
59
                             (mv_col & 7) << 1, (mv_row & 7) << 1, &pred[0], 16);
  } else {
60
    vp9_copy_mem16x16(yptr, stride, &pred[0], 16);
John Koleszar's avatar
John Koleszar committed
61
62
63
64
65
66
67
68
69
70
71
  }

  // U & V
  omv_row = mv_row;
  omv_col = mv_col;
  mv_row >>= 1;
  mv_col >>= 1;
  stride = (stride + 1) >> 1;
  offset = (mv_row >> 3) * stride + (mv_col >> 3);
  uptr = u_mb_ptr + offset;
  vptr = v_mb_ptr + offset;
Johann's avatar
Johann committed
72

John Koleszar's avatar
John Koleszar committed
73
  if ((omv_row | omv_col) & 15) {
Paul Wilkins's avatar
Paul Wilkins committed
74
    xd->subpixel_predict8x8(uptr, stride,
John Koleszar's avatar
John Koleszar committed
75
                           (omv_col & 15), (omv_row & 15), &pred[256], 8);
Paul Wilkins's avatar
Paul Wilkins committed
76
    xd->subpixel_predict8x8(vptr, stride,
John Koleszar's avatar
John Koleszar committed
77
78
79
                           (omv_col & 15), (omv_row & 15), &pred[320], 8);
  }
  else {
80
81
    vp9_copy_mem8x8(uptr, stride, &pred[256], 8);
    vp9_copy_mem8x8(vptr, stride, &pred[320], 8);
John Koleszar's avatar
John Koleszar committed
82
  }
Johann's avatar
Johann committed
83
}
84
void vp9_temporal_filter_apply_c
Johann's avatar
Johann committed
85
(
John Koleszar's avatar
John Koleszar committed
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
112
113
114
115
116
117
118
119
120
121
122
123
  unsigned char *frame1,
  unsigned int stride,
  unsigned char *frame2,
  unsigned int block_size,
  int strength,
  int filter_weight,
  unsigned int *accumulator,
  unsigned short *count
) {
  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
124
    }
John Koleszar's avatar
John Koleszar committed
125
126
127

    byte += stride - block_size;
  }
Johann's avatar
Johann committed
128
129
130
131
}

#if ALT_REF_MC_ENABLED

132
static int temporal_filter_find_matching_mb_c
Johann's avatar
Johann committed
133
(
134
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  YV12_BUFFER_CONFIG *arf_frame,
  YV12_BUFFER_CONFIG *frame_ptr,
  int mb_offset,
  int error_thresh
) {
  MACROBLOCK *x = &cpi->mb;
  int step_param;
  int further_steps;
  int sadpb = x->sadperbit16;
  int bestsme = INT_MAX;

  BLOCK *b = &x->block[0];
  BLOCKD *d = &x->e_mbd.block[0];
  int_mv best_ref_mv1;
  int_mv best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */

  // Save input state
  unsigned char **base_src = b->base_src;
  int src = b->src;
  int src_stride = b->src_stride;
  unsigned char **base_pre = d->base_pre;
  int pre = d->pre;
  int pre_stride = d->pre_stride;

  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
  b->base_src = &arf_frame->y_buffer;
  b->src_stride = arf_frame->y_stride;
  b->src = mb_offset;

  d->base_pre = &frame_ptr->y_buffer;
  d->pre_stride = frame_ptr->y_stride;
  d->pre = mb_offset;

  // Further step/diamond searches as necessary
  if (cpi->Speed < 8) {
    step_param = cpi->sf.first_step +
                 ((cpi->Speed > 5) ? 1 : 0);
    further_steps =
      (cpi->sf.max_step_search_steps - 1) - step_param;
  } else {
    step_param = cpi->sf.first_step + 2;
    further_steps = 0;
  }

  /*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
186
  bestsme = vp9_hex_search(x, b, d, &best_ref_mv1_full, &d->bmi.as_mv.first,
John Koleszar's avatar
John Koleszar committed
187
                           step_param, sadpb, &cpi->fn_ptr[BLOCK_16X16],
188
                           NULL, NULL, NULL, NULL,
189
                           &best_ref_mv1);
Johann's avatar
Johann committed
190
191

#if ALT_REF_SUBPEL_ENABLED
John Koleszar's avatar
John Koleszar committed
192
193
194
195
196
197
198
199
200
201
  // 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
    bestsme = cpi->find_fractional_mv_step(x, b, d, &d->bmi.as_mv.first,
                                           &best_ref_mv1,
                                           x->errorperbit,
                                           &cpi->fn_ptr[BLOCK_16X16],
202
                                           NULL, NULL,
203
                                           &distortion, &sse);
John Koleszar's avatar
John Koleszar committed
204
  }
Johann's avatar
Johann committed
205
206
#endif

John Koleszar's avatar
John Koleszar committed
207
208
209
210
211
212
213
  // Save input state
  b->base_src = base_src;
  b->src = src;
  b->src_stride = src_stride;
  d->base_pre = base_pre;
  d->pre = pre;
  d->pre_stride = pre_stride;
Johann's avatar
Johann committed
214

John Koleszar's avatar
John Koleszar committed
215
  return bestsme;
Johann's avatar
Johann committed
216
217
218
}
#endif

219
static void temporal_filter_iterate_c
Johann's avatar
Johann committed
220
(
221
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  int frame_count,
  int alt_ref_index,
  int strength
) {
  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);
  DECLARE_ALIGNED_ARRAY(16, unsigned short, count, 16 * 16 + 8 * 8 + 8 * 8);
  MACROBLOCKD *mbd = &cpi->mb.e_mbd;
  YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
  unsigned char *dst1, *dst2;
  DECLARE_ALIGNED_ARRAY(16, unsigned char,  predictor, 16 * 16 + 8 * 8 + 8 * 8);

  // Save input state
  unsigned char *y_buffer = mbd->pre.y_buffer;
  unsigned char *u_buffer = mbd->pre.u_buffer;
  unsigned char *v_buffer = mbd->pre.v_buffer;

  for (mb_row = 0; mb_row < mb_rows; mb_row++) {
Johann's avatar
Johann committed
247
#if ALT_REF_MC_ENABLED
John Koleszar's avatar
John Koleszar committed
248
    // Source frames are extended to 16 pixels.  This is different than
John Koleszar's avatar
John Koleszar committed
249
    //  L/A/G reference frames that have a border of 32 (VP9BORDERINPIXELS)
John Koleszar's avatar
John Koleszar committed
250
251
    // 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
252
253
254
255
256
    //  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
257
    // To keep the mv in play for both Y and UV planes the max that it
John Koleszar's avatar
John Koleszar committed
258
259
    //  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
260
    cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16)
John Koleszar's avatar
John Koleszar committed
261
                         + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
262
263
#endif

John Koleszar's avatar
John Koleszar committed
264
265
266
    for (mb_col = 0; mb_col < mb_cols; mb_col++) {
      int i, j, k;
      int stride;
Johann's avatar
Johann committed
267

John Koleszar's avatar
John Koleszar committed
268
269
      vpx_memset(accumulator, 0, 384 * sizeof(unsigned int));
      vpx_memset(count, 0, 384 * sizeof(unsigned short));
Johann's avatar
Johann committed
270
271

#if ALT_REF_MC_ENABLED
John Koleszar's avatar
John Koleszar committed
272
      cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2 * VP9_INTERP_EXTEND));
John Koleszar's avatar
John Koleszar committed
273
      cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16)
John Koleszar's avatar
John Koleszar committed
274
                           + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
275
276
#endif

John Koleszar's avatar
John Koleszar committed
277
278
279
280
281
282
283
284
285
286
287
      for (frame = 0; frame < frame_count; frame++) {
        if (cpi->frames[frame] == NULL)
          continue;

        mbd->block[0].bmi.as_mv.first.as_mv.row = 0;
        mbd->block[0].bmi.as_mv.first.as_mv.col = 0;

        if (frame == alt_ref_index) {
          filter_weight = 2;
        } else {
          int err = 0;
Johann's avatar
Johann committed
288
289
290
291
#if ALT_REF_MC_ENABLED
#define THRESH_LOW   10000
#define THRESH_HIGH  20000

John Koleszar's avatar
John Koleszar committed
292
          // Find best match in this frame by MC
293
          err = temporal_filter_find_matching_mb_c
John Koleszar's avatar
John Koleszar committed
294
295
296
297
298
                (cpi,
                 cpi->frames[alt_ref_index],
                 cpi->frames[frame],
                 mb_y_offset,
                 THRESH_LOW);
Johann's avatar
Johann committed
299
#endif
John Koleszar's avatar
John Koleszar committed
300
301
302
303
304
305
306
307
308
          // 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
309
          temporal_filter_predictors_mb_c
John Koleszar's avatar
John Koleszar committed
310
311
312
313
314
315
316
317
318
319
          (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,
           mbd->block[0].bmi.as_mv.first.as_mv.row,
           mbd->block[0].bmi.as_mv.first.as_mv.col,
           predictor);

          // Apply the filter (YUV)
Jim Bankoski's avatar
Jim Bankoski committed
320
321
322
323
324
325
326
327
328
329
330
          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
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
        }
      }

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

          dst1[byte] = (unsigned char)pval;

          // 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;
          dst1[byte] = (unsigned char)pval;

          // V
          pval = accumulator[m] + (count[m] >> 1);
          pval *= cpi->fixed_divide[count[m]];
          pval >>= 19;
          dst2[byte] = (unsigned char)pval;

          // move to next pixel
          byte++;
Johann's avatar
Johann committed
375
376
        }

John Koleszar's avatar
John Koleszar committed
377
378
379
380
381
        byte += stride - 8;
      }

      mb_y_offset += 16;
      mb_uv_offset += 8;
Johann's avatar
Johann committed
382
383
    }

John Koleszar's avatar
John Koleszar committed
384
385
386
387
388
389
390
391
    mb_y_offset += 16 * (f->y_stride - mb_cols);
    mb_uv_offset += 8 * (f->uv_stride - mb_cols);
  }

  // Restore input state
  mbd->pre.y_buffer = y_buffer;
  mbd->pre.u_buffer = u_buffer;
  mbd->pre.v_buffer = v_buffer;
Johann's avatar
Johann committed
392
393
}

394
void vp9_temporal_filter_prepare
Johann's avatar
Johann committed
395
(
396
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
397
398
399
  int distance
) {
  int frame = 0;
Johann's avatar
Johann committed
400

John Koleszar's avatar
John Koleszar committed
401
402
403
404
405
406
  int num_frames_backward = 0;
  int num_frames_forward = 0;
  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
407

John Koleszar's avatar
John Koleszar committed
408
  int strength = cpi->oxcf.arnr_strength;
Johann's avatar
Johann committed
409

John Koleszar's avatar
John Koleszar committed
410
  int blur_type = cpi->oxcf.arnr_type;
Johann's avatar
Johann committed
411

John Koleszar's avatar
John Koleszar committed
412
  int max_frames = cpi->active_arnr_frames;
Johann's avatar
Johann committed
413

John Koleszar's avatar
John Koleszar committed
414
  num_frames_backward = distance;
415
  num_frames_forward = vp9_lookahead_depth(cpi->lookahead)
John Koleszar's avatar
John Koleszar committed
416
                       - (num_frames_backward + 1);
Johann's avatar
Johann committed
417

John Koleszar's avatar
John Koleszar committed
418
  switch (blur_type) {
Johann's avatar
Johann committed
419
    case 1:
John Koleszar's avatar
John Koleszar committed
420
421
      /////////////////////////////////////////
      // Backward Blur
Johann's avatar
Johann committed
422

John Koleszar's avatar
John Koleszar committed
423
      frames_to_blur_backward = num_frames_backward;
Johann's avatar
Johann committed
424

John Koleszar's avatar
John Koleszar committed
425
426
      if (frames_to_blur_backward >= max_frames)
        frames_to_blur_backward = max_frames - 1;
Johann's avatar
Johann committed
427

John Koleszar's avatar
John Koleszar committed
428
429
      frames_to_blur = frames_to_blur_backward + 1;
      break;
Johann's avatar
Johann committed
430
431

    case 2:
John Koleszar's avatar
John Koleszar committed
432
433
      /////////////////////////////////////////
      // Forward Blur
Johann's avatar
Johann committed
434

John Koleszar's avatar
John Koleszar committed
435
      frames_to_blur_forward = num_frames_forward;
Johann's avatar
Johann committed
436

John Koleszar's avatar
John Koleszar committed
437
438
      if (frames_to_blur_forward >= max_frames)
        frames_to_blur_forward = max_frames - 1;
Johann's avatar
Johann committed
439

John Koleszar's avatar
John Koleszar committed
440
441
      frames_to_blur = frames_to_blur_forward + 1;
      break;
Johann's avatar
Johann committed
442
443
444

    case 3:
    default:
John Koleszar's avatar
John Koleszar committed
445
446
447
448
      /////////////////////////////////////////
      // Center Blur
      frames_to_blur_forward = num_frames_forward;
      frames_to_blur_backward = num_frames_backward;
Johann's avatar
Johann committed
449

John Koleszar's avatar
John Koleszar committed
450
451
      if (frames_to_blur_forward > frames_to_blur_backward)
        frames_to_blur_forward = frames_to_blur_backward;
Johann's avatar
Johann committed
452

John Koleszar's avatar
John Koleszar committed
453
454
      if (frames_to_blur_backward > frames_to_blur_forward)
        frames_to_blur_backward = frames_to_blur_forward;
Johann's avatar
Johann committed
455

John Koleszar's avatar
John Koleszar committed
456
457
458
      // 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
459

John Koleszar's avatar
John Koleszar committed
460
461
      if (frames_to_blur_backward > (max_frames / 2))
        frames_to_blur_backward = (max_frames / 2);
Johann's avatar
Johann committed
462

John Koleszar's avatar
John Koleszar committed
463
464
465
      frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
      break;
  }
Johann's avatar
Johann committed
466

John Koleszar's avatar
John Koleszar committed
467
  start_frame = distance + frames_to_blur_forward;
Johann's avatar
Johann committed
468
469

#ifdef DEBUGFWG
John Koleszar's avatar
John Koleszar committed
470
471
472
473
474
475
476
477
478
479
480
  // 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
481
482
#endif

John Koleszar's avatar
John Koleszar committed
483
484
485
486
  // 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++) {
    int which_buffer =  start_frame - frame;
487
    struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
John Koleszar's avatar
John Koleszar committed
488
489
490
491
                                                     which_buffer);
    cpi->frames[frames_to_blur - 1 - frame] = &buf->img;
  }

492
  temporal_filter_iterate_c(
John Koleszar's avatar
John Koleszar committed
493
494
495
496
    cpi,
    frames_to_blur,
    frames_to_blur_backward,
    strength);
Johann's avatar
Johann committed
497
498
}
#endif