vp9_temporal_filter.c 15.2 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
39
40
41
42
43
44
45
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) {
John Koleszar's avatar
John Koleszar committed
46
  int offset;
47
  uint8_t *yptr, *uptr, *vptr;
John Koleszar's avatar
John Koleszar committed
48
49
50
51
52
  int omv_row, omv_col;

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

53
54
55
56
57
  xd->subpix.predict[!!(mv_col & 7)][!!(mv_row & 7)][0](
      yptr, stride, &pred[0], 16,
      xd->subpix.filter_x[(mv_col & 7) << 1], xd->subpix.x_step_q4,
      xd->subpix.filter_y[(mv_row & 7) << 1], xd->subpix.y_step_q4,
      16, 16);
John Koleszar's avatar
John Koleszar committed
58
59
60
61
62
63
64
65
66
67

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

69
70
71
72
73
74
75
76
77
78
79
  xd->subpix.predict[!!(omv_col & 15)][!!(omv_row & 15)][0](
      uptr, stride, &pred[256], 8,
      xd->subpix.filter_x[(omv_col & 15)], xd->subpix.x_step_q4,
      xd->subpix.filter_y[(omv_row & 15)], xd->subpix.y_step_q4,
      8, 8);

  xd->subpix.predict[!!(omv_col & 15)][!!(omv_row & 15)][0](
      vptr, stride, &pred[320], 8,
      xd->subpix.filter_x[(omv_col & 15)], xd->subpix.x_step_q4,
      xd->subpix.filter_y[(omv_row & 15)], xd->subpix.y_step_q4,
      8, 8);
Johann's avatar
Johann committed
80
}
81
82
83
84
85
86
87
88
89

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
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
  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
119
    }
John Koleszar's avatar
John Koleszar committed
120
121
122

    byte += stride - block_size;
  }
Johann's avatar
Johann committed
123
124
125
126
}

#if ALT_REF_MC_ENABLED

127
128
129
130
131
static int temporal_filter_find_matching_mb_c(VP9_COMP *cpi,
                                              YV12_BUFFER_CONFIG *arf_frame,
                                              YV12_BUFFER_CONFIG *frame_ptr,
                                              int mb_offset,
                                              int error_thresh) {
John Koleszar's avatar
John Koleszar committed
132
133
134
135
136
137
138
139
140
141
142
  MACROBLOCK *x = &cpi->mb;
  int step_param;
  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
143
  uint8_t **base_src = b->base_src;
John Koleszar's avatar
John Koleszar committed
144
145
  int src = b->src;
  int src_stride = b->src_stride;
146
  uint8_t **base_pre = d->base_pre;
John Koleszar's avatar
John Koleszar committed
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
  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);
  } else {
    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
174
  bestsme = vp9_hex_search(x, b, d, &best_ref_mv1_full, &d->bmi.as_mv[0],
John Koleszar's avatar
John Koleszar committed
175
                           step_param, sadpb, &cpi->fn_ptr[BLOCK_16X16],
176
                           NULL, NULL, NULL, NULL,
177
                           &best_ref_mv1);
Johann's avatar
Johann committed
178
179

#if ALT_REF_SUBPEL_ENABLED
John Koleszar's avatar
John Koleszar committed
180
181
182
183
184
185
  // 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
186
    bestsme = cpi->find_fractional_mv_step(x, b, d, &d->bmi.as_mv[0],
John Koleszar's avatar
John Koleszar committed
187
188
189
                                           &best_ref_mv1,
                                           x->errorperbit,
                                           &cpi->fn_ptr[BLOCK_16X16],
190
                                           NULL, NULL,
191
                                           &distortion, &sse);
John Koleszar's avatar
John Koleszar committed
192
  }
Johann's avatar
Johann committed
193
194
#endif

John Koleszar's avatar
John Koleszar committed
195
196
197
198
199
200
201
  // 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
202

John Koleszar's avatar
John Koleszar committed
203
  return bestsme;
Johann's avatar
Johann committed
204
205
206
}
#endif

207
208
209
210
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
211
212
213
214
215
216
217
218
219
  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);
220
  DECLARE_ALIGNED_ARRAY(16, uint16_t, count, 16 * 16 + 8 * 8 + 8 * 8);
John Koleszar's avatar
John Koleszar committed
221
222
  MACROBLOCKD *mbd = &cpi->mb.e_mbd;
  YV12_BUFFER_CONFIG *f = cpi->frames[alt_ref_index];
223
224
  uint8_t *dst1, *dst2;
  DECLARE_ALIGNED_ARRAY(16, uint8_t,  predictor, 16 * 16 + 8 * 8 + 8 * 8);
John Koleszar's avatar
John Koleszar committed
225
226

  // Save input state
227
228
229
  uint8_t *y_buffer = mbd->pre.y_buffer;
  uint8_t *u_buffer = mbd->pre.u_buffer;
  uint8_t *v_buffer = mbd->pre.v_buffer;
John Koleszar's avatar
John Koleszar committed
230
231

  for (mb_row = 0; mb_row < mb_rows; mb_row++) {
Johann's avatar
Johann committed
232
#if ALT_REF_MC_ENABLED
John Koleszar's avatar
John Koleszar committed
233
    // Source frames are extended to 16 pixels.  This is different than
John Koleszar's avatar
John Koleszar committed
234
    //  L/A/G reference frames that have a border of 32 (VP9BORDERINPIXELS)
John Koleszar's avatar
John Koleszar committed
235
236
    // 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
237
238
239
240
241
    //  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
242
    // To keep the mv in play for both Y and UV planes the max that it
John Koleszar's avatar
John Koleszar committed
243
244
    //  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
245
    cpi->mb.mv_row_max = ((cpi->common.mb_rows - 1 - mb_row) * 16)
John Koleszar's avatar
John Koleszar committed
246
                         + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
247
248
#endif

John Koleszar's avatar
John Koleszar committed
249
250
251
    for (mb_col = 0; mb_col < mb_cols; mb_col++) {
      int i, j, k;
      int stride;
Johann's avatar
Johann committed
252

John Koleszar's avatar
John Koleszar committed
253
      vpx_memset(accumulator, 0, 384 * sizeof(unsigned int));
254
      vpx_memset(count, 0, 384 * sizeof(uint16_t));
Johann's avatar
Johann committed
255
256

#if ALT_REF_MC_ENABLED
John Koleszar's avatar
John Koleszar committed
257
      cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2 * VP9_INTERP_EXTEND));
John Koleszar's avatar
John Koleszar committed
258
      cpi->mb.mv_col_max = ((cpi->common.mb_cols - 1 - mb_col) * 16)
John Koleszar's avatar
John Koleszar committed
259
                           + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
260
261
#endif

John Koleszar's avatar
John Koleszar committed
262
263
264
265
      for (frame = 0; frame < frame_count; frame++) {
        if (cpi->frames[frame] == NULL)
          continue;

266
267
        mbd->block[0].bmi.as_mv[0].as_mv.row = 0;
        mbd->block[0].bmi.as_mv[0].as_mv.col = 0;
John Koleszar's avatar
John Koleszar committed
268
269
270
271
272

        if (frame == alt_ref_index) {
          filter_weight = 2;
        } else {
          int err = 0;
Johann's avatar
Johann committed
273
274
275
276
#if ALT_REF_MC_ENABLED
#define THRESH_LOW   10000
#define THRESH_HIGH  20000

John Koleszar's avatar
John Koleszar committed
277
          // Find best match in this frame by MC
278
          err = temporal_filter_find_matching_mb_c
John Koleszar's avatar
John Koleszar committed
279
280
281
282
283
                (cpi,
                 cpi->frames[alt_ref_index],
                 cpi->frames[frame],
                 mb_y_offset,
                 THRESH_LOW);
Johann's avatar
Johann committed
284
#endif
John Koleszar's avatar
John Koleszar committed
285
286
287
288
289
290
291
292
293
          // 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
294
          temporal_filter_predictors_mb_c
John Koleszar's avatar
John Koleszar committed
295
296
297
298
299
          (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,
300
301
           mbd->block[0].bmi.as_mv[0].as_mv.row,
           mbd->block[0].bmi.as_mv[0].as_mv.col,
John Koleszar's avatar
John Koleszar committed
302
303
304
           predictor);

          // Apply the filter (YUV)
Jim Bankoski's avatar
Jim Bankoski committed
305
306
307
308
309
310
311
312
313
314
315
          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
316
317
318
319
320
321
322
323
324
325
326
327
328
        }
      }

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

329
          dst1[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349

          // 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;
350
          dst1[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
351
352
353
354
355

          // V
          pval = accumulator[m] + (count[m] >> 1);
          pval *= cpi->fixed_divide[count[m]];
          pval >>= 19;
356
          dst2[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
357
358
359

          // move to next pixel
          byte++;
Johann's avatar
Johann committed
360
361
        }

John Koleszar's avatar
John Koleszar committed
362
363
364
365
366
        byte += stride - 8;
      }

      mb_y_offset += 16;
      mb_uv_offset += 8;
Johann's avatar
Johann committed
367
368
    }

John Koleszar's avatar
John Koleszar committed
369
370
371
372
373
374
375
376
    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
377
378
}

379
void vp9_temporal_filter_prepare
Johann's avatar
Johann committed
380
(
381
  VP9_COMP *cpi,
John Koleszar's avatar
John Koleszar committed
382
383
384
  int distance
) {
  int frame = 0;
Johann's avatar
Johann committed
385

John Koleszar's avatar
John Koleszar committed
386
387
388
389
390
391
  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
392

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

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

John Koleszar's avatar
John Koleszar committed
397
  int max_frames = cpi->active_arnr_frames;
Johann's avatar
Johann committed
398

John Koleszar's avatar
John Koleszar committed
399
  num_frames_backward = distance;
400
  num_frames_forward = vp9_lookahead_depth(cpi->lookahead)
John Koleszar's avatar
John Koleszar committed
401
                       - (num_frames_backward + 1);
Johann's avatar
Johann committed
402

John Koleszar's avatar
John Koleszar committed
403
  switch (blur_type) {
Johann's avatar
Johann committed
404
    case 1:
John Koleszar's avatar
John Koleszar committed
405
406
      /////////////////////////////////////////
      // Backward Blur
Johann's avatar
Johann committed
407

John Koleszar's avatar
John Koleszar committed
408
      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_backward >= max_frames)
        frames_to_blur_backward = max_frames - 1;
Johann's avatar
Johann committed
412

John Koleszar's avatar
John Koleszar committed
413
414
      frames_to_blur = frames_to_blur_backward + 1;
      break;
Johann's avatar
Johann committed
415
416

    case 2:
John Koleszar's avatar
John Koleszar committed
417
418
      /////////////////////////////////////////
      // Forward Blur
Johann's avatar
Johann committed
419

John Koleszar's avatar
John Koleszar committed
420
      frames_to_blur_forward = num_frames_forward;
Johann's avatar
Johann committed
421

John Koleszar's avatar
John Koleszar committed
422
423
      if (frames_to_blur_forward >= max_frames)
        frames_to_blur_forward = max_frames - 1;
Johann's avatar
Johann committed
424

John Koleszar's avatar
John Koleszar committed
425
426
      frames_to_blur = frames_to_blur_forward + 1;
      break;
Johann's avatar
Johann committed
427
428
429

    case 3:
    default:
John Koleszar's avatar
John Koleszar committed
430
431
432
433
      /////////////////////////////////////////
      // Center Blur
      frames_to_blur_forward = num_frames_forward;
      frames_to_blur_backward = num_frames_backward;
Johann's avatar
Johann committed
434

John Koleszar's avatar
John Koleszar committed
435
436
      if (frames_to_blur_forward > frames_to_blur_backward)
        frames_to_blur_forward = frames_to_blur_backward;
Johann's avatar
Johann committed
437

John Koleszar's avatar
John Koleszar committed
438
439
      if (frames_to_blur_backward > frames_to_blur_forward)
        frames_to_blur_backward = frames_to_blur_forward;
Johann's avatar
Johann committed
440

John Koleszar's avatar
John Koleszar committed
441
442
443
      // 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
444

John Koleszar's avatar
John Koleszar committed
445
446
      if (frames_to_blur_backward > (max_frames / 2))
        frames_to_blur_backward = (max_frames / 2);
Johann's avatar
Johann committed
447

John Koleszar's avatar
John Koleszar committed
448
449
450
      frames_to_blur = frames_to_blur_backward + frames_to_blur_forward + 1;
      break;
  }
Johann's avatar
Johann committed
451

John Koleszar's avatar
John Koleszar committed
452
  start_frame = distance + frames_to_blur_forward;
Johann's avatar
Johann committed
453
454

#ifdef DEBUGFWG
John Koleszar's avatar
John Koleszar committed
455
456
457
458
459
460
461
462
463
464
465
  // 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
466
467
#endif

John Koleszar's avatar
John Koleszar committed
468
469
470
471
  // 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;
472
    struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
John Koleszar's avatar
John Koleszar committed
473
474
475
476
                                                     which_buffer);
    cpi->frames[frames_to_blur - 1 - frame] = &buf->img;
  }

477
  temporal_filter_iterate_c(
John Koleszar's avatar
John Koleszar committed
478
479
480
481
    cpi,
    frames_to_blur,
    frames_to_blur_backward,
    strength);
Johann's avatar
Johann committed
482
483
}
#endif