]> granicus.if.org Git - libvpx/blob - vp9/encoder/vp9_temporal_filter.c
Merge "Refactor encode_rd_sb_row function"
[libvpx] / vp9 / encoder / vp9_temporal_filter.c
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include <math.h>
12 #include <limits.h>
13
14 #include "vp9/common/vp9_alloccommon.h"
15 #include "vp9/common/vp9_onyxc_int.h"
16 #include "vp9/common/vp9_quant_common.h"
17 #include "vp9/common/vp9_reconinter.h"
18 #include "vp9/common/vp9_systemdependent.h"
19 #include "vp9/encoder/vp9_extend.h"
20 #include "vp9/encoder/vp9_firstpass.h"
21 #include "vp9/encoder/vp9_mcomp.h"
22 #include "vp9/encoder/vp9_encoder.h"
23 #include "vp9/encoder/vp9_quantize.h"
24 #include "vp9/encoder/vp9_ratectrl.h"
25 #include "vp9/encoder/vp9_segmentation.h"
26 #include "vpx_mem/vpx_mem.h"
27 #include "vpx_ports/vpx_timer.h"
28 #include "vpx_scale/vpx_scale.h"
29
30 static int fixed_divide[512];
31
32 static void temporal_filter_predictors_mb_c(MACROBLOCKD *xd,
33                                             uint8_t *y_mb_ptr,
34                                             uint8_t *u_mb_ptr,
35                                             uint8_t *v_mb_ptr,
36                                             int stride,
37                                             int uv_block_width,
38                                             int uv_block_height,
39                                             int mv_row,
40                                             int mv_col,
41                                             uint8_t *pred,
42                                             struct scale_factors *scale,
43                                             int x, int y) {
44   const int which_mv = 0;
45   const MV mv = { mv_row, mv_col };
46   const InterpKernel *const kernel =
47     vp9_get_interp_kernel(xd->mi[0].src_mi->mbmi.interp_filter);
48
49   enum mv_precision mv_precision_uv;
50   int uv_stride;
51   if (uv_block_width == 8) {
52     uv_stride = (stride + 1) >> 1;
53     mv_precision_uv = MV_PRECISION_Q4;
54   } else {
55     uv_stride = stride;
56     mv_precision_uv = MV_PRECISION_Q3;
57   }
58
59 #if CONFIG_VP9_HIGHBITDEPTH
60   if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
61     vp9_high_build_inter_predictor(y_mb_ptr, stride,
62                                    &pred[0], 16,
63                                    &mv,
64                                    scale,
65                                    16, 16,
66                                    which_mv,
67                                    kernel, MV_PRECISION_Q3, x, y, xd->bd);
68
69     vp9_high_build_inter_predictor(u_mb_ptr, uv_stride,
70                                    &pred[256], uv_block_width,
71                                    &mv,
72                                    scale,
73                                    uv_block_width, uv_block_height,
74                                    which_mv,
75                                    kernel, mv_precision_uv, x, y, xd->bd);
76
77     vp9_high_build_inter_predictor(v_mb_ptr, uv_stride,
78                                    &pred[512], uv_block_width,
79                                    &mv,
80                                    scale,
81                                    uv_block_width, uv_block_height,
82                                    which_mv,
83                                    kernel, mv_precision_uv, x, y, xd->bd);
84     return;
85   }
86 #endif  // CONFIG_VP9_HIGHBITDEPTH
87   vp9_build_inter_predictor(y_mb_ptr, stride,
88                             &pred[0], 16,
89                             &mv,
90                             scale,
91                             16, 16,
92                             which_mv,
93                             kernel, MV_PRECISION_Q3, x, y);
94
95   vp9_build_inter_predictor(u_mb_ptr, uv_stride,
96                             &pred[256], uv_block_width,
97                             &mv,
98                             scale,
99                             uv_block_width, uv_block_height,
100                             which_mv,
101                             kernel, mv_precision_uv, x, y);
102
103   vp9_build_inter_predictor(v_mb_ptr, uv_stride,
104                             &pred[512], uv_block_width,
105                             &mv,
106                             scale,
107                             uv_block_width, uv_block_height,
108                             which_mv,
109                             kernel, mv_precision_uv, x, y);
110 }
111
112 void vp9_temporal_filter_init() {
113   int i;
114
115   fixed_divide[0] = 0;
116   for (i = 1; i < 512; ++i)
117     fixed_divide[i] = 0x80000 / i;
118 }
119
120 void vp9_temporal_filter_apply_c(uint8_t *frame1,
121                                  unsigned int stride,
122                                  uint8_t *frame2,
123                                  unsigned int block_width,
124                                  unsigned int block_height,
125                                  int strength,
126                                  int filter_weight,
127                                  unsigned int *accumulator,
128                                  uint16_t *count) {
129   unsigned int i, j, k;
130   int modifier;
131   int byte = 0;
132   const int rounding = strength > 0 ? 1 << (strength - 1) : 0;
133
134   for (i = 0, k = 0; i < block_height; i++) {
135     for (j = 0; j < block_width; j++, k++) {
136       int src_byte = frame1[byte];
137       int pixel_value = *frame2++;
138
139       modifier   = src_byte - pixel_value;
140       // This is an integer approximation of:
141       // float coeff = (3.0 * modifer * modifier) / pow(2, strength);
142       // modifier =  (int)roundf(coeff > 16 ? 0 : 16-coeff);
143       modifier  *= modifier;
144       modifier  *= 3;
145       modifier  += rounding;
146       modifier >>= strength;
147
148       if (modifier > 16)
149         modifier = 16;
150
151       modifier = 16 - modifier;
152       modifier *= filter_weight;
153
154       count[k] += modifier;
155       accumulator[k] += modifier * pixel_value;
156
157       byte++;
158     }
159
160     byte += stride - block_width;
161   }
162 }
163
164 #if CONFIG_VP9_HIGHBITDEPTH
165 void vp9_highbd_temporal_filter_apply_c(uint8_t *frame1_8,
166                                         unsigned int stride,
167                                         uint8_t *frame2_8,
168                                         unsigned int block_width,
169                                         unsigned int block_height,
170                                         int strength,
171                                         int filter_weight,
172                                         unsigned int *accumulator,
173                                         uint16_t *count) {
174   uint16_t *frame1 = CONVERT_TO_SHORTPTR(frame1_8);
175   uint16_t *frame2 = CONVERT_TO_SHORTPTR(frame2_8);
176   unsigned int i, j, k;
177   int modifier;
178   int byte = 0;
179   const int rounding = strength > 0 ? 1 << (strength - 1) : 0;
180
181   for (i = 0, k = 0; i < block_height; i++) {
182     for (j = 0; j < block_width; j++, k++) {
183       int src_byte = frame1[byte];
184       int pixel_value = *frame2++;
185
186       modifier   = src_byte - pixel_value;
187       // This is an integer approximation of:
188       // float coeff = (3.0 * modifer * modifier) / pow(2, strength);
189       // modifier =  (int)roundf(coeff > 16 ? 0 : 16-coeff);
190       modifier *= modifier;
191       modifier *= 3;
192       modifier += rounding;
193       modifier >>= strength;
194
195       if (modifier > 16)
196         modifier = 16;
197
198       modifier = 16 - modifier;
199       modifier *= filter_weight;
200
201       count[k] += modifier;
202       accumulator[k] += modifier * pixel_value;
203
204       byte++;
205     }
206
207     byte += stride - block_width;
208   }
209 }
210 #endif  // CONFIG_VP9_HIGHBITDEPTH
211
212 static int temporal_filter_find_matching_mb_c(VP9_COMP *cpi,
213                                               uint8_t *arf_frame_buf,
214                                               uint8_t *frame_ptr_buf,
215                                               int stride) {
216   MACROBLOCK *const x = &cpi->mb;
217   MACROBLOCKD *const xd = &x->e_mbd;
218   const MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
219   int step_param;
220   int sadpb = x->sadperbit16;
221   int bestsme = INT_MAX;
222   int distortion;
223   unsigned int sse;
224   int sad_list[5];
225
226   MV best_ref_mv1 = {0, 0};
227   MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
228   MV *ref_mv = &x->e_mbd.mi[0].src_mi->bmi[0].as_mv[0].as_mv;
229
230   // Save input state
231   struct buf_2d src = x->plane[0].src;
232   struct buf_2d pre = xd->plane[0].pre[0];
233
234   best_ref_mv1_full.col = best_ref_mv1.col >> 3;
235   best_ref_mv1_full.row = best_ref_mv1.row >> 3;
236
237   // Setup frame pointers
238   x->plane[0].src.buf = arf_frame_buf;
239   x->plane[0].src.stride = stride;
240   xd->plane[0].pre[0].buf = frame_ptr_buf;
241   xd->plane[0].pre[0].stride = stride;
242
243   step_param = mv_sf->reduce_first_step_size;
244   step_param = MIN(step_param, MAX_MVSEARCH_STEPS - 2);
245
246   // Ignore mv costing by sending NULL pointer instead of cost arrays
247   vp9_hex_search(x, &best_ref_mv1_full, step_param, sadpb, 1,
248                  cond_sad_list(cpi, sad_list),
249                  &cpi->fn_ptr[BLOCK_16X16], 0, &best_ref_mv1, ref_mv);
250
251   // Ignore mv costing by sending NULL pointer instead of cost array
252   bestsme = cpi->find_fractional_mv_step(x, ref_mv,
253                                          &best_ref_mv1,
254                                          cpi->common.allow_high_precision_mv,
255                                          x->errorperbit,
256                                          &cpi->fn_ptr[BLOCK_16X16],
257                                          0, mv_sf->subpel_iters_per_step,
258                                          cond_sad_list(cpi, sad_list),
259                                          NULL, NULL,
260                                          &distortion, &sse, NULL, 0, 0);
261
262   // Restore input state
263   x->plane[0].src = src;
264   xd->plane[0].pre[0] = pre;
265
266   return bestsme;
267 }
268
269 static void temporal_filter_iterate_c(VP9_COMP *cpi,
270                                       YV12_BUFFER_CONFIG **frames,
271                                       int frame_count,
272                                       int alt_ref_index,
273                                       int strength,
274                                       struct scale_factors *scale) {
275   int byte;
276   int frame;
277   int mb_col, mb_row;
278   unsigned int filter_weight;
279   int mb_cols = (frames[alt_ref_index]->y_crop_width + 15) >> 4;
280   int mb_rows = (frames[alt_ref_index]->y_crop_height + 15) >> 4;
281   int mb_y_offset = 0;
282   int mb_uv_offset = 0;
283   DECLARE_ALIGNED_ARRAY(16, unsigned int, accumulator, 16 * 16 * 3);
284   DECLARE_ALIGNED_ARRAY(16, uint16_t, count, 16 * 16 * 3);
285   MACROBLOCKD *mbd = &cpi->mb.e_mbd;
286   YV12_BUFFER_CONFIG *f = frames[alt_ref_index];
287   uint8_t *dst1, *dst2;
288 #if CONFIG_VP9_HIGHBITDEPTH
289   DECLARE_ALIGNED_ARRAY(16, uint16_t,  predictor16, 16 * 16 * 3);
290   DECLARE_ALIGNED_ARRAY(16, uint8_t,  predictor8, 16 * 16 * 3);
291   uint8_t *predictor;
292 #else
293   DECLARE_ALIGNED_ARRAY(16, uint8_t,  predictor, 16 * 16 * 3);
294 #endif
295   const int mb_uv_height = 16 >> mbd->plane[1].subsampling_y;
296   const int mb_uv_width  = 16 >> mbd->plane[1].subsampling_x;
297
298   // Save input state
299   uint8_t* input_buffer[MAX_MB_PLANE];
300   int i;
301 #if CONFIG_VP9_HIGHBITDEPTH
302   if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
303     predictor = CONVERT_TO_BYTEPTR(predictor16);
304   } else {
305     predictor = predictor8;
306   }
307 #endif
308
309   for (i = 0; i < MAX_MB_PLANE; i++)
310     input_buffer[i] = mbd->plane[i].pre[0].buf;
311
312   for (mb_row = 0; mb_row < mb_rows; mb_row++) {
313     // Source frames are extended to 16 pixels. This is different than
314     //  L/A/G reference frames that have a border of 32 (VP9ENCBORDERINPIXELS)
315     // A 6/8 tap filter is used for motion search.  This requires 2 pixels
316     //  before and 3 pixels after.  So the largest Y mv on a border would
317     //  then be 16 - VP9_INTERP_EXTEND. The UV blocks are half the size of the
318     //  Y and therefore only extended by 8.  The largest mv that a UV block
319     //  can support is 8 - VP9_INTERP_EXTEND.  A UV mv is half of a Y mv.
320     //  (16 - VP9_INTERP_EXTEND) >> 1 which is greater than
321     //  8 - VP9_INTERP_EXTEND.
322     // To keep the mv in play for both Y and UV planes the max that it
323     //  can be on a border is therefore 16 - (2*VP9_INTERP_EXTEND+1).
324     cpi->mb.mv_row_min = -((mb_row * 16) + (17 - 2 * VP9_INTERP_EXTEND));
325     cpi->mb.mv_row_max = ((mb_rows - 1 - mb_row) * 16)
326                          + (17 - 2 * VP9_INTERP_EXTEND);
327
328     for (mb_col = 0; mb_col < mb_cols; mb_col++) {
329       int i, j, k;
330       int stride;
331
332       vpx_memset(accumulator, 0, 16 * 16 * 3 * sizeof(accumulator[0]));
333       vpx_memset(count, 0, 16 * 16 * 3 * sizeof(count[0]));
334
335       cpi->mb.mv_col_min = -((mb_col * 16) + (17 - 2 * VP9_INTERP_EXTEND));
336       cpi->mb.mv_col_max = ((mb_cols - 1 - mb_col) * 16)
337                            + (17 - 2 * VP9_INTERP_EXTEND);
338
339       for (frame = 0; frame < frame_count; frame++) {
340         const int thresh_low  = 10000;
341         const int thresh_high = 20000;
342
343         if (frames[frame] == NULL)
344           continue;
345
346         mbd->mi[0].src_mi->bmi[0].as_mv[0].as_mv.row = 0;
347         mbd->mi[0].src_mi->bmi[0].as_mv[0].as_mv.col = 0;
348
349         if (frame == alt_ref_index) {
350           filter_weight = 2;
351         } else {
352           // Find best match in this frame by MC
353           int err = temporal_filter_find_matching_mb_c(cpi,
354               frames[alt_ref_index]->y_buffer + mb_y_offset,
355               frames[frame]->y_buffer + mb_y_offset,
356               frames[frame]->y_stride);
357
358           // Assign higher weight to matching MB if it's error
359           // score is lower. If not applying MC default behavior
360           // is to weight all MBs equal.
361           filter_weight = err < thresh_low
362                           ? 2 : err < thresh_high ? 1 : 0;
363         }
364
365         if (filter_weight != 0) {
366           // Construct the predictors
367           temporal_filter_predictors_mb_c(mbd,
368               frames[frame]->y_buffer + mb_y_offset,
369               frames[frame]->u_buffer + mb_uv_offset,
370               frames[frame]->v_buffer + mb_uv_offset,
371               frames[frame]->y_stride,
372               mb_uv_width, mb_uv_height,
373               mbd->mi[0].src_mi->bmi[0].as_mv[0].as_mv.row,
374               mbd->mi[0].src_mi->bmi[0].as_mv[0].as_mv.col,
375               predictor, scale,
376               mb_col * 16, mb_row * 16);
377
378 #if CONFIG_VP9_HIGHBITDEPTH
379           if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
380             int adj_strength = strength + 2 * (mbd->bd - 8);
381             // Apply the filter (YUV)
382             vp9_highbd_temporal_filter_apply(f->y_buffer + mb_y_offset,
383                                              f->y_stride,
384                                              predictor, 16, 16, adj_strength,
385                                              filter_weight,
386                                              accumulator, count);
387             vp9_highbd_temporal_filter_apply(f->u_buffer + mb_uv_offset,
388                                              f->uv_stride, predictor + 256,
389                                              mb_uv_width, mb_uv_height,
390                                              adj_strength,
391                                              filter_weight, accumulator + 256,
392                                              count + 256);
393             vp9_highbd_temporal_filter_apply(f->v_buffer + mb_uv_offset,
394                                              f->uv_stride, predictor + 512,
395                                              mb_uv_width, mb_uv_height,
396                                              adj_strength, filter_weight,
397                                              accumulator + 512, count + 512);
398           } else {
399             // Apply the filter (YUV)
400             vp9_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
401                                       predictor, 16, 16,
402                                       strength, filter_weight,
403                                       accumulator, count);
404             vp9_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
405                                       predictor + 256,
406                                       mb_uv_width, mb_uv_height, strength,
407                                       filter_weight, accumulator + 256,
408                                       count + 256);
409             vp9_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
410                                       predictor + 512,
411                                       mb_uv_width, mb_uv_height, strength,
412                                       filter_weight, accumulator + 512,
413                                       count + 512);
414           }
415 #else
416           // Apply the filter (YUV)
417           vp9_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
418                                     predictor, 16, 16,
419                                     strength, filter_weight,
420                                     accumulator, count);
421           vp9_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
422                                     predictor + 256,
423                                     mb_uv_width, mb_uv_height, strength,
424                                     filter_weight, accumulator + 256,
425                                     count + 256);
426           vp9_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
427                                     predictor + 512,
428                                     mb_uv_width, mb_uv_height, strength,
429                                     filter_weight, accumulator + 512,
430                                     count + 512);
431 #endif  // CONFIG_VP9_HIGHBITDEPTH
432         }
433       }
434
435 #if CONFIG_VP9_HIGHBITDEPTH
436       if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
437         uint16_t *dst1_16;
438         uint16_t *dst2_16;
439         // Normalize filter output to produce AltRef frame
440         dst1 = cpi->alt_ref_buffer.y_buffer;
441         dst1_16 = CONVERT_TO_SHORTPTR(dst1);
442         stride = cpi->alt_ref_buffer.y_stride;
443         byte = mb_y_offset;
444         for (i = 0, k = 0; i < 16; i++) {
445           for (j = 0; j < 16; j++, k++) {
446             unsigned int pval = accumulator[k] + (count[k] >> 1);
447             pval *= fixed_divide[count[k]];
448             pval >>= 19;
449
450             dst1_16[byte] = (uint16_t)pval;
451
452             // move to next pixel
453             byte++;
454           }
455
456           byte += stride - 16;
457         }
458
459         dst1 = cpi->alt_ref_buffer.u_buffer;
460         dst2 = cpi->alt_ref_buffer.v_buffer;
461         dst1_16 = CONVERT_TO_SHORTPTR(dst1);
462         dst2_16 = CONVERT_TO_SHORTPTR(dst2);
463         stride = cpi->alt_ref_buffer.uv_stride;
464         byte = mb_uv_offset;
465         for (i = 0, k = 256; i < mb_uv_height; i++) {
466           for (j = 0; j < mb_uv_width; j++, k++) {
467             int m = k + 256;
468
469             // U
470             unsigned int pval = accumulator[k] + (count[k] >> 1);
471             pval *= fixed_divide[count[k]];
472             pval >>= 19;
473             dst1_16[byte] = (uint16_t)pval;
474
475             // V
476             pval = accumulator[m] + (count[m] >> 1);
477             pval *= fixed_divide[count[m]];
478             pval >>= 19;
479             dst2_16[byte] = (uint16_t)pval;
480
481             // move to next pixel
482             byte++;
483           }
484
485           byte += stride - mb_uv_width;
486         }
487       } else {
488         // Normalize filter output to produce AltRef frame
489         dst1 = cpi->alt_ref_buffer.y_buffer;
490         stride = cpi->alt_ref_buffer.y_stride;
491         byte = mb_y_offset;
492         for (i = 0, k = 0; i < 16; i++) {
493           for (j = 0; j < 16; j++, k++) {
494             unsigned int pval = accumulator[k] + (count[k] >> 1);
495             pval *= fixed_divide[count[k]];
496             pval >>= 19;
497
498             dst1[byte] = (uint8_t)pval;
499
500             // move to next pixel
501             byte++;
502           }
503           byte += stride - 16;
504         }
505
506         dst1 = cpi->alt_ref_buffer.u_buffer;
507         dst2 = cpi->alt_ref_buffer.v_buffer;
508         stride = cpi->alt_ref_buffer.uv_stride;
509         byte = mb_uv_offset;
510         for (i = 0, k = 256; i < mb_uv_height; i++) {
511           for (j = 0; j < mb_uv_width; j++, k++) {
512             int m = k + 256;
513
514             // U
515             unsigned int pval = accumulator[k] + (count[k] >> 1);
516             pval *= fixed_divide[count[k]];
517             pval >>= 19;
518             dst1[byte] = (uint8_t)pval;
519
520             // V
521             pval = accumulator[m] + (count[m] >> 1);
522             pval *= fixed_divide[count[m]];
523             pval >>= 19;
524             dst2[byte] = (uint8_t)pval;
525
526             // move to next pixel
527             byte++;
528           }
529           byte += stride - mb_uv_width;
530         }
531       }
532 #else
533       // Normalize filter output to produce AltRef frame
534       dst1 = cpi->alt_ref_buffer.y_buffer;
535       stride = cpi->alt_ref_buffer.y_stride;
536       byte = mb_y_offset;
537       for (i = 0, k = 0; i < 16; i++) {
538         for (j = 0; j < 16; j++, k++) {
539           unsigned int pval = accumulator[k] + (count[k] >> 1);
540           pval *= fixed_divide[count[k]];
541           pval >>= 19;
542
543           dst1[byte] = (uint8_t)pval;
544
545           // move to next pixel
546           byte++;
547         }
548         byte += stride - 16;
549       }
550
551       dst1 = cpi->alt_ref_buffer.u_buffer;
552       dst2 = cpi->alt_ref_buffer.v_buffer;
553       stride = cpi->alt_ref_buffer.uv_stride;
554       byte = mb_uv_offset;
555       for (i = 0, k = 256; i < mb_uv_height; i++) {
556         for (j = 0; j < mb_uv_width; j++, k++) {
557           int m = k + 256;
558
559           // U
560           unsigned int pval = accumulator[k] + (count[k] >> 1);
561           pval *= fixed_divide[count[k]];
562           pval >>= 19;
563           dst1[byte] = (uint8_t)pval;
564
565           // V
566           pval = accumulator[m] + (count[m] >> 1);
567           pval *= fixed_divide[count[m]];
568           pval >>= 19;
569           dst2[byte] = (uint8_t)pval;
570
571           // move to next pixel
572           byte++;
573         }
574         byte += stride - mb_uv_width;
575       }
576 #endif  // CONFIG_VP9_HIGHBITDEPTH
577       mb_y_offset += 16;
578       mb_uv_offset += mb_uv_width;
579     }
580     mb_y_offset += 16 * (f->y_stride - mb_cols);
581     mb_uv_offset += mb_uv_height * f->uv_stride - mb_uv_width * mb_cols;
582   }
583
584   // Restore input state
585   for (i = 0; i < MAX_MB_PLANE; i++)
586     mbd->plane[i].pre[0].buf = input_buffer[i];
587 }
588
589 // Apply buffer limits and context specific adjustments to arnr filter.
590 static void adjust_arnr_filter(VP9_COMP *cpi,
591                                int distance, int group_boost,
592                                int *arnr_frames, int *arnr_strength) {
593   const VP9EncoderConfig *const oxcf = &cpi->oxcf;
594   const int frames_after_arf =
595       vp9_lookahead_depth(cpi->lookahead) - distance - 1;
596   int frames_fwd = (cpi->oxcf.arnr_max_frames - 1) >> 1;
597   int frames_bwd;
598   int q, frames, strength;
599
600   // Define the forward and backwards filter limits for this arnr group.
601   if (frames_fwd > frames_after_arf)
602     frames_fwd = frames_after_arf;
603   if (frames_fwd > distance)
604     frames_fwd = distance;
605
606   frames_bwd = frames_fwd;
607
608   // For even length filter there is one more frame backward
609   // than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
610   if (frames_bwd < distance)
611     frames_bwd += (oxcf->arnr_max_frames + 1) & 0x1;
612
613   // Set the baseline active filter size.
614   frames = frames_bwd + 1 + frames_fwd;
615
616   // Adjust the strength based on active max q.
617   if (cpi->common.current_video_frame > 1)
618     q = ((int)vp9_convert_qindex_to_q(
619         cpi->rc.avg_frame_qindex[INTER_FRAME], cpi->common.bit_depth));
620   else
621     q = ((int)vp9_convert_qindex_to_q(
622         cpi->rc.avg_frame_qindex[KEY_FRAME], cpi->common.bit_depth));
623   if (q > 16) {
624     strength = oxcf->arnr_strength;
625   } else {
626     strength = oxcf->arnr_strength - ((16 - q) / 2);
627     if (strength < 0)
628       strength = 0;
629   }
630
631   // Adjust number of frames in filter and strength based on gf boost level.
632   if (frames > group_boost / 150) {
633     frames = group_boost / 150;
634     frames += !(frames & 1);
635   }
636
637   if (strength > group_boost / 300) {
638     strength = group_boost / 300;
639   }
640
641   // Adjustments for second level arf in multi arf case.
642   if (cpi->oxcf.pass == 2 && cpi->multi_arf_allowed) {
643     const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
644     if (gf_group->rf_level[gf_group->index] != GF_ARF_STD) {
645       strength >>= 1;
646     }
647   }
648
649   *arnr_frames = frames;
650   *arnr_strength = strength;
651 }
652
653 void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
654   VP9_COMMON *const cm = &cpi->common;
655   RATE_CONTROL *const rc = &cpi->rc;
656   int frame;
657   int frames_to_blur;
658   int start_frame;
659   int strength;
660   int frames_to_blur_backward;
661   int frames_to_blur_forward;
662   struct scale_factors sf;
663   YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = {NULL};
664
665   // Apply context specific adjustments to the arnr filter parameters.
666   adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength);
667   frames_to_blur_backward = (frames_to_blur / 2);
668   frames_to_blur_forward = ((frames_to_blur - 1) / 2);
669   start_frame = distance + frames_to_blur_forward;
670
671   // Setup frame pointers, NULL indicates frame not included in filter.
672   for (frame = 0; frame < frames_to_blur; ++frame) {
673     const int which_buffer = start_frame - frame;
674     struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
675                                                      which_buffer);
676     frames[frames_to_blur - 1 - frame] = &buf->img;
677   }
678
679   // Setup scaling factors. Scaling on each of the arnr frames is not supported
680   if (is_two_pass_svc(cpi)) {
681     // In spatial svc the scaling factors might be less then 1/2. So we will use
682     // non-normative scaling.
683     int frame_used = 0;
684 #if CONFIG_VP9_HIGHBITDEPTH
685     vp9_setup_scale_factors_for_frame(&sf,
686                                       get_frame_new_buffer(cm)->y_crop_width,
687                                       get_frame_new_buffer(cm)->y_crop_height,
688                                       get_frame_new_buffer(cm)->y_crop_width,
689                                       get_frame_new_buffer(cm)->y_crop_height,
690                                       cm->use_highbitdepth);
691 #else
692     vp9_setup_scale_factors_for_frame(&sf,
693                                       get_frame_new_buffer(cm)->y_crop_width,
694                                       get_frame_new_buffer(cm)->y_crop_height,
695                                       get_frame_new_buffer(cm)->y_crop_width,
696                                       get_frame_new_buffer(cm)->y_crop_height);
697 #endif  // CONFIG_VP9_HIGHBITDEPTH
698
699     for (frame = 0; frame < frames_to_blur; ++frame) {
700       if (cm->mi_cols * MI_SIZE != frames[frame]->y_width ||
701           cm->mi_rows * MI_SIZE != frames[frame]->y_height) {
702         if (vp9_realloc_frame_buffer(&cpi->svc.scaled_frames[frame_used],
703                                      cm->width, cm->height,
704                                      cm->subsampling_x, cm->subsampling_y,
705 #if CONFIG_VP9_HIGHBITDEPTH
706                                      cm->use_highbitdepth,
707 #endif
708                                      VP9_ENC_BORDER_IN_PIXELS, NULL, NULL,
709                                      NULL))
710           vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
711                              "Failed to reallocate alt_ref_buffer");
712
713         frames[frame] = vp9_scale_if_required(cm, frames[frame],
714                             &cpi->svc.scaled_frames[frame_used]);
715         ++frame_used;
716       }
717     }
718   } else {
719     // ARF is produced at the native frame size and resized when coded.
720 #if CONFIG_VP9_HIGHBITDEPTH
721     vp9_setup_scale_factors_for_frame(&sf,
722                                       frames[0]->y_crop_width,
723                                       frames[0]->y_crop_height,
724                                       frames[0]->y_crop_width,
725                                       frames[0]->y_crop_height,
726                                       cm->use_highbitdepth);
727 #else
728     vp9_setup_scale_factors_for_frame(&sf,
729                                       frames[0]->y_crop_width,
730                                       frames[0]->y_crop_height,
731                                       frames[0]->y_crop_width,
732                                       frames[0]->y_crop_height);
733 #endif  // CONFIG_VP9_HIGHBITDEPTH
734   }
735
736   temporal_filter_iterate_c(cpi, frames, frames_to_blur,
737                             frames_to_blur_backward, strength, &sf);
738 }