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

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

14
#include "vp9/common/vp9_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/encoder/vp9_extend.h"
19
#include "vp9/encoder/vp9_firstpass.h"
20
#include "vp9/encoder/vp9_mcomp.h"
Dmitry Kovalev's avatar
Dmitry Kovalev committed
21
#include "vp9/encoder/vp9_encoder.h"
22
#include "vp9/encoder/vp9_quantize.h"
23 24
#include "vp9/encoder/vp9_ratectrl.h"
#include "vp9/encoder/vp9_segmentation.h"
James Zern's avatar
James Zern committed
25
#include "vp9/encoder/vp9_temporal_filter.h"
26
#include "vpx_dsp/vpx_dsp_common.h"
Johann's avatar
Johann committed
27
#include "vpx_mem/vpx_mem.h"
28
#include "vpx_ports/mem.h"
Johann's avatar
Johann committed
29
#include "vpx_ports/vpx_timer.h"
30
#include "vpx_scale/vpx_scale.h"
Johann's avatar
Johann committed
31

32 33
static int fixed_divide[512];

34 35 36 37 38
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,
39 40
                                            int uv_block_width,
                                            int uv_block_height,
41 42
                                            int mv_row,
                                            int mv_col,
Yunqing Wang's avatar
Yunqing Wang committed
43
                                            uint8_t *pred,
44 45
                                            struct scale_factors *scale,
                                            int x, int y) {
46
  const int which_mv = 0;
47 48
  const MV mv = { mv_row, mv_col };
  const InterpKernel *const kernel =
James Zern's avatar
James Zern committed
49
    vp9_filter_kernels[xd->mi[0]->mbmi.interp_filter];
50

Alex Converse's avatar
Alex Converse committed
51 52
  enum mv_precision mv_precision_uv;
  int uv_stride;
53
  if (uv_block_width == 8) {
Alex Converse's avatar
Alex Converse committed
54 55 56 57 58 59
    uv_stride = (stride + 1) >> 1;
    mv_precision_uv = MV_PRECISION_Q4;
  } else {
    uv_stride = stride;
    mv_precision_uv = MV_PRECISION_Q3;
  }
John Koleszar's avatar
John Koleszar committed
60

61 62
#if CONFIG_VP9_HIGHBITDEPTH
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
63 64 65 66 67 68 69
    vp9_highbd_build_inter_predictor(y_mb_ptr, stride,
                                     &pred[0], 16,
                                     &mv,
                                     scale,
                                     16, 16,
                                     which_mv,
                                     kernel, MV_PRECISION_Q3, x, y, xd->bd);
70

71 72 73 74 75 76 77
    vp9_highbd_build_inter_predictor(u_mb_ptr, uv_stride,
                                     &pred[256], uv_block_width,
                                     &mv,
                                     scale,
                                     uv_block_width, uv_block_height,
                                     which_mv,
                                     kernel, mv_precision_uv, x, y, xd->bd);
78

79 80 81 82 83 84 85
    vp9_highbd_build_inter_predictor(v_mb_ptr, uv_stride,
                                     &pred[512], uv_block_width,
                                     &mv,
                                     scale,
                                     uv_block_width, uv_block_height,
                                     which_mv,
                                     kernel, mv_precision_uv, x, y, xd->bd);
86 87 88
    return;
  }
#endif  // CONFIG_VP9_HIGHBITDEPTH
89 90
  vp9_build_inter_predictor(y_mb_ptr, stride,
                            &pred[0], 16,
91
                            &mv,
Yunqing Wang's avatar
Yunqing Wang committed
92
                            scale,
93
                            16, 16,
94
                            which_mv,
95
                            kernel, MV_PRECISION_Q3, x, y);
Johann's avatar
Johann committed
96

Alex Converse's avatar
Alex Converse committed
97
  vp9_build_inter_predictor(u_mb_ptr, uv_stride,
98
                            &pred[256], uv_block_width,
99
                            &mv,
Yunqing Wang's avatar
Yunqing Wang committed
100
                            scale,
101
                            uv_block_width, uv_block_height,
102
                            which_mv,
103
                            kernel, mv_precision_uv, x, y);
104

Alex Converse's avatar
Alex Converse committed
105
  vp9_build_inter_predictor(v_mb_ptr, uv_stride,
106
                            &pred[512], uv_block_width,
107
                            &mv,
Yunqing Wang's avatar
Yunqing Wang committed
108
                            scale,
109
                            uv_block_width, uv_block_height,
110
                            which_mv,
111
                            kernel, mv_precision_uv, x, y);
Johann's avatar
Johann committed
112
}
113

114
void vp9_temporal_filter_init(void) {
115 116 117 118 119 120 121
  int i;

  fixed_divide[0] = 0;
  for (i = 1; i < 512; ++i)
    fixed_divide[i] = 0x80000 / i;
}

122 123 124
void vp9_temporal_filter_apply_c(uint8_t *frame1,
                                 unsigned int stride,
                                 uint8_t *frame2,
125 126
                                 unsigned int block_width,
                                 unsigned int block_height,
127 128 129 130
                                 int strength,
                                 int filter_weight,
                                 unsigned int *accumulator,
                                 uint16_t *count) {
John Koleszar's avatar
John Koleszar committed
131 132 133
  unsigned int i, j, k;
  int modifier;
  int byte = 0;
134
  const int rounding = strength > 0 ? 1 << (strength - 1) : 0;
John Koleszar's avatar
John Koleszar committed
135

136 137
  for (i = 0, k = 0; i < block_height; i++) {
    for (j = 0; j < block_width; j++, k++) {
John Koleszar's avatar
John Koleszar committed
138 139 140 141 142 143 144 145 146
      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;
147
      modifier  += rounding;
John Koleszar's avatar
John Koleszar committed
148 149 150 151 152 153 154 155 156 157 158 159
      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
160
    }
John Koleszar's avatar
John Koleszar committed
161

162
    byte += stride - block_width;
John Koleszar's avatar
John Koleszar committed
163
  }
Johann's avatar
Johann committed
164 165
}

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
#if CONFIG_VP9_HIGHBITDEPTH
void vp9_highbd_temporal_filter_apply_c(uint8_t *frame1_8,
                                        unsigned int stride,
                                        uint8_t *frame2_8,
                                        unsigned int block_width,
                                        unsigned int block_height,
                                        int strength,
                                        int filter_weight,
                                        unsigned int *accumulator,
                                        uint16_t *count) {
  uint16_t *frame1 = CONVERT_TO_SHORTPTR(frame1_8);
  uint16_t *frame2 = CONVERT_TO_SHORTPTR(frame2_8);
  unsigned int i, j, k;
  int modifier;
  int byte = 0;
  const int rounding = strength > 0 ? 1 << (strength - 1) : 0;

  for (i = 0, k = 0; i < block_height; i++) {
    for (j = 0; j < block_width; 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 += rounding;
      modifier >>= strength;

      if (modifier > 16)
        modifier = 16;

      modifier = 16 - modifier;
      modifier *= filter_weight;

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

      byte++;
    }

    byte += stride - block_width;
  }
}
#endif  // CONFIG_VP9_HIGHBITDEPTH

214
static int temporal_filter_find_matching_mb_c(VP9_COMP *cpi,
215 216
                                              uint8_t *arf_frame_buf,
                                              uint8_t *frame_ptr_buf,
217
                                              int stride) {
218
  MACROBLOCK *const x = &cpi->td.mb;
219
  MACROBLOCKD *const xd = &x->e_mbd;
220 221
  MV_SPEED_FEATURES *const mv_sf = &cpi->sf.mv;
  const SEARCH_METHODS old_search_method = mv_sf->search_method;
John Koleszar's avatar
John Koleszar committed
222 223 224
  int step_param;
  int sadpb = x->sadperbit16;
  int bestsme = INT_MAX;
225 226
  int distortion;
  unsigned int sse;
227
  int cost_list[5];
John Koleszar's avatar
John Koleszar committed
228

Dmitry Kovalev's avatar
Dmitry Kovalev committed
229 230
  MV best_ref_mv1 = {0, 0};
  MV best_ref_mv1_full; /* full-pixel value of best_ref_mv1 */
231
  MV *ref_mv = &x->e_mbd.mi[0]->bmi[0].as_mv[0].as_mv;
John Koleszar's avatar
John Koleszar committed
232 233

  // Save input state
John Koleszar's avatar
John Koleszar committed
234
  struct buf_2d src = x->plane[0].src;
235
  struct buf_2d pre = xd->plane[0].pre[0];
John Koleszar's avatar
John Koleszar committed
236

Dmitry Kovalev's avatar
Dmitry Kovalev committed
237 238
  best_ref_mv1_full.col = best_ref_mv1.col >> 3;
  best_ref_mv1_full.row = best_ref_mv1.row >> 3;
John Koleszar's avatar
John Koleszar committed
239 240

  // Setup frame pointers
241 242 243 244
  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
245

246
  step_param = mv_sf->reduce_first_step_size;
247
  step_param = VPXMIN(step_param, MAX_MVSEARCH_STEPS - 2);
John Koleszar's avatar
John Koleszar committed
248

249 250 251 252 253
  mv_sf->search_method = HEX;
  vp9_full_pixel_search(cpi, x, BLOCK_16X16, &best_ref_mv1_full, step_param,
                        sadpb, cond_cost_list(cpi, cost_list), &best_ref_mv1,
                        ref_mv, 0, 0);
  mv_sf->search_method = old_search_method;
Johann's avatar
Johann committed
254

255 256 257 258 259 260
  // Ignore mv costing by sending NULL pointer instead of cost array
  bestsme = cpi->find_fractional_mv_step(x, ref_mv,
                                         &best_ref_mv1,
                                         cpi->common.allow_high_precision_mv,
                                         x->errorperbit,
                                         &cpi->fn_ptr[BLOCK_16X16],
261
                                         0, mv_sf->subpel_iters_per_step,
262
                                         cond_cost_list(cpi, cost_list),
263
                                         NULL, NULL,
264
                                         &distortion, &sse, NULL, 0, 0);
Johann's avatar
Johann committed
265

266
  // Restore input state
John Koleszar's avatar
John Koleszar committed
267
  x->plane[0].src = src;
268
  xd->plane[0].pre[0] = pre;
Johann's avatar
Johann committed
269

John Koleszar's avatar
John Koleszar committed
270
  return bestsme;
Johann's avatar
Johann committed
271 272
}

273
static void temporal_filter_iterate_c(VP9_COMP *cpi,
274
                                      YV12_BUFFER_CONFIG **frames,
275 276
                                      int frame_count,
                                      int alt_ref_index,
Yunqing Wang's avatar
Yunqing Wang committed
277 278
                                      int strength,
                                      struct scale_factors *scale) {
John Koleszar's avatar
John Koleszar committed
279 280 281 282
  int byte;
  int frame;
  int mb_col, mb_row;
  unsigned int filter_weight;
283 284
  int mb_cols = (frames[alt_ref_index]->y_crop_width + 15) >> 4;
  int mb_rows = (frames[alt_ref_index]->y_crop_height + 15) >> 4;
John Koleszar's avatar
John Koleszar committed
285 286
  int mb_y_offset = 0;
  int mb_uv_offset = 0;
287 288
  DECLARE_ALIGNED(16, unsigned int, accumulator[16 * 16 * 3]);
  DECLARE_ALIGNED(16, uint16_t, count[16 * 16 * 3]);
289
  MACROBLOCKD *mbd = &cpi->td.mb.e_mbd;
290
  YV12_BUFFER_CONFIG *f = frames[alt_ref_index];
291
  uint8_t *dst1, *dst2;
292
#if CONFIG_VP9_HIGHBITDEPTH
293 294
  DECLARE_ALIGNED(16, uint16_t,  predictor16[16 * 16 * 3]);
  DECLARE_ALIGNED(16, uint8_t,  predictor8[16 * 16 * 3]);
295 296
  uint8_t *predictor;
#else
297
  DECLARE_ALIGNED(16, uint8_t,  predictor[16 * 16 * 3]);
298
#endif
Alex Converse's avatar
Alex Converse committed
299
  const int mb_uv_height = 16 >> mbd->plane[1].subsampling_y;
300
  const int mb_uv_width  = 16 >> mbd->plane[1].subsampling_x;
John Koleszar's avatar
John Koleszar committed
301 302

  // Save input state
303 304
  uint8_t* input_buffer[MAX_MB_PLANE];
  int i;
305 306 307 308 309 310 311
#if CONFIG_VP9_HIGHBITDEPTH
  if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    predictor = CONVERT_TO_BYTEPTR(predictor16);
  } else {
    predictor = predictor8;
  }
#endif
312 313 314

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

  for (mb_row = 0; mb_row < mb_rows; mb_row++) {
317
    // Source frames are extended to 16 pixels. This is different than
318
    //  L/A/G reference frames that have a border of 32 (VP9ENCBORDERINPIXELS)
John Koleszar's avatar
John Koleszar committed
319 320
    // 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
321 322 323 324 325
    //  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
326
    // To keep the mv in play for both Y and UV planes the max that it
John Koleszar's avatar
John Koleszar committed
327
    //  can be on a border is therefore 16 - (2*VP9_INTERP_EXTEND+1).
328 329
    cpi->td.mb.mv_row_min = -((mb_row * 16) + (17 - 2 * VP9_INTERP_EXTEND));
    cpi->td.mb.mv_row_max = ((mb_rows - 1 - mb_row) * 16)
John Koleszar's avatar
John Koleszar committed
330
                         + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
331

John Koleszar's avatar
John Koleszar committed
332 333 334
    for (mb_col = 0; mb_col < mb_cols; mb_col++) {
      int i, j, k;
      int stride;
Johann's avatar
Johann committed
335

James Zern's avatar
James Zern committed
336 337
      memset(accumulator, 0, 16 * 16 * 3 * sizeof(accumulator[0]));
      memset(count, 0, 16 * 16 * 3 * sizeof(count[0]));
Johann's avatar
Johann committed
338

339 340
      cpi->td.mb.mv_col_min = -((mb_col * 16) + (17 - 2 * VP9_INTERP_EXTEND));
      cpi->td.mb.mv_col_max = ((mb_cols - 1 - mb_col) * 16)
John Koleszar's avatar
John Koleszar committed
341
                           + (17 - 2 * VP9_INTERP_EXTEND);
Johann's avatar
Johann committed
342

John Koleszar's avatar
John Koleszar committed
343
      for (frame = 0; frame < frame_count; frame++) {
344 345 346
        const int thresh_low  = 10000;
        const int thresh_high = 20000;

347
        if (frames[frame] == NULL)
John Koleszar's avatar
John Koleszar committed
348 349
          continue;

350 351
        mbd->mi[0]->bmi[0].as_mv[0].as_mv.row = 0;
        mbd->mi[0]->bmi[0].as_mv[0].as_mv.col = 0;
John Koleszar's avatar
John Koleszar committed
352 353 354 355 356

        if (frame == alt_ref_index) {
          filter_weight = 2;
        } else {
          // Find best match in this frame by MC
357
          int err = temporal_filter_find_matching_mb_c(cpi,
358 359 360
              frames[alt_ref_index]->y_buffer + mb_y_offset,
              frames[frame]->y_buffer + mb_y_offset,
              frames[frame]->y_stride);
361

John Koleszar's avatar
John Koleszar committed
362 363 364
          // 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.
365 366
          filter_weight = err < thresh_low
                          ? 2 : err < thresh_high ? 1 : 0;
John Koleszar's avatar
John Koleszar committed
367 368 369 370
        }

        if (filter_weight != 0) {
          // Construct the predictors
371
          temporal_filter_predictors_mb_c(mbd,
372 373 374 375
              frames[frame]->y_buffer + mb_y_offset,
              frames[frame]->u_buffer + mb_uv_offset,
              frames[frame]->v_buffer + mb_uv_offset,
              frames[frame]->y_stride,
376
              mb_uv_width, mb_uv_height,
377 378
              mbd->mi[0]->bmi[0].as_mv[0].as_mv.row,
              mbd->mi[0]->bmi[0].as_mv[0].as_mv.col,
379 380
              predictor, scale,
              mb_col * 16, mb_row * 16);
John Koleszar's avatar
John Koleszar committed
381

382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
#if CONFIG_VP9_HIGHBITDEPTH
          if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
            int adj_strength = strength + 2 * (mbd->bd - 8);
            // Apply the filter (YUV)
            vp9_highbd_temporal_filter_apply(f->y_buffer + mb_y_offset,
                                             f->y_stride,
                                             predictor, 16, 16, adj_strength,
                                             filter_weight,
                                             accumulator, count);
            vp9_highbd_temporal_filter_apply(f->u_buffer + mb_uv_offset,
                                             f->uv_stride, predictor + 256,
                                             mb_uv_width, mb_uv_height,
                                             adj_strength,
                                             filter_weight, accumulator + 256,
                                             count + 256);
            vp9_highbd_temporal_filter_apply(f->v_buffer + mb_uv_offset,
                                             f->uv_stride, predictor + 512,
                                             mb_uv_width, mb_uv_height,
                                             adj_strength, filter_weight,
                                             accumulator + 512, count + 512);
          } else {
            // Apply the filter (YUV)
            vp9_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
                                      predictor, 16, 16,
                                      strength, filter_weight,
                                      accumulator, count);
            vp9_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
                                      predictor + 256,
                                      mb_uv_width, mb_uv_height, strength,
                                      filter_weight, accumulator + 256,
                                      count + 256);
            vp9_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
                                      predictor + 512,
                                      mb_uv_width, mb_uv_height, strength,
                                      filter_weight, accumulator + 512,
                                      count + 512);
          }
#else
John Koleszar's avatar
John Koleszar committed
420
          // Apply the filter (YUV)
Jim Bankoski's avatar
Jim Bankoski committed
421
          vp9_temporal_filter_apply(f->y_buffer + mb_y_offset, f->y_stride,
422 423
                                    predictor, 16, 16,
                                    strength, filter_weight,
Jim Bankoski's avatar
Jim Bankoski committed
424 425
                                    accumulator, count);
          vp9_temporal_filter_apply(f->u_buffer + mb_uv_offset, f->uv_stride,
426 427
                                    predictor + 256,
                                    mb_uv_width, mb_uv_height, strength,
Alex Converse's avatar
Alex Converse committed
428 429
                                    filter_weight, accumulator + 256,
                                    count + 256);
Jim Bankoski's avatar
Jim Bankoski committed
430
          vp9_temporal_filter_apply(f->v_buffer + mb_uv_offset, f->uv_stride,
431 432
                                    predictor + 512,
                                    mb_uv_width, mb_uv_height, strength,
Alex Converse's avatar
Alex Converse committed
433 434
                                    filter_weight, accumulator + 512,
                                    count + 512);
435
#endif  // CONFIG_VP9_HIGHBITDEPTH
John Koleszar's avatar
John Koleszar committed
436 437 438
        }
      }

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 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 528 529 530 531 532 533 534 535 536
#if CONFIG_VP9_HIGHBITDEPTH
      if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
        uint16_t *dst1_16;
        uint16_t *dst2_16;
        // Normalize filter output to produce AltRef frame
        dst1 = cpi->alt_ref_buffer.y_buffer;
        dst1_16 = CONVERT_TO_SHORTPTR(dst1);
        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 *= fixed_divide[count[k]];
            pval >>= 19;

            dst1_16[byte] = (uint16_t)pval;

            // move to next pixel
            byte++;
          }

          byte += stride - 16;
        }

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

            // U
            unsigned int pval = accumulator[k] + (count[k] >> 1);
            pval *= fixed_divide[count[k]];
            pval >>= 19;
            dst1_16[byte] = (uint16_t)pval;

            // V
            pval = accumulator[m] + (count[m] >> 1);
            pval *= fixed_divide[count[m]];
            pval >>= 19;
            dst2_16[byte] = (uint16_t)pval;

            // move to next pixel
            byte++;
          }

          byte += stride - mb_uv_width;
        }
      } else {
        // 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 *= fixed_divide[count[k]];
            pval >>= 19;

            dst1[byte] = (uint8_t)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 < mb_uv_height; i++) {
          for (j = 0; j < mb_uv_width; j++, k++) {
            int m = k + 256;

            // U
            unsigned int pval = accumulator[k] + (count[k] >> 1);
            pval *= fixed_divide[count[k]];
            pval >>= 19;
            dst1[byte] = (uint8_t)pval;

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

            // move to next pixel
            byte++;
          }
          byte += stride - mb_uv_width;
        }
      }
#else
John Koleszar's avatar
John Koleszar committed
537 538 539 540 541 542 543
      // 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);
544
          pval *= fixed_divide[count[k]];
John Koleszar's avatar
John Koleszar committed
545 546
          pval >>= 19;

547
          dst1[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
548 549 550 551 552 553 554 555 556 557 558

          // 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;
Alex Converse's avatar
Alex Converse committed
559
      for (i = 0, k = 256; i < mb_uv_height; i++) {
560
        for (j = 0; j < mb_uv_width; j++, k++) {
Alex Converse's avatar
Alex Converse committed
561
          int m = k + 256;
John Koleszar's avatar
John Koleszar committed
562 563 564

          // U
          unsigned int pval = accumulator[k] + (count[k] >> 1);
565
          pval *= fixed_divide[count[k]];
John Koleszar's avatar
John Koleszar committed
566
          pval >>= 19;
567
          dst1[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
568 569 570

          // V
          pval = accumulator[m] + (count[m] >> 1);
571
          pval *= fixed_divide[count[m]];
John Koleszar's avatar
John Koleszar committed
572
          pval >>= 19;
573
          dst2[byte] = (uint8_t)pval;
John Koleszar's avatar
John Koleszar committed
574 575 576

          // move to next pixel
          byte++;
Johann's avatar
Johann committed
577
        }
578
        byte += stride - mb_uv_width;
John Koleszar's avatar
John Koleszar committed
579
      }
580
#endif  // CONFIG_VP9_HIGHBITDEPTH
John Koleszar's avatar
John Koleszar committed
581
      mb_y_offset += 16;
582
      mb_uv_offset += mb_uv_width;
Johann's avatar
Johann committed
583
    }
John Koleszar's avatar
John Koleszar committed
584
    mb_y_offset += 16 * (f->y_stride - mb_cols);
585
    mb_uv_offset += mb_uv_height * f->uv_stride - mb_uv_width * mb_cols;
John Koleszar's avatar
John Koleszar committed
586 587 588
  }

  // Restore input state
589 590
  for (i = 0; i < MAX_MB_PLANE; i++)
    mbd->plane[i].pre[0].buf = input_buffer[i];
Johann's avatar
Johann committed
591 592
}

593 594
// Apply buffer limits and context specific adjustments to arnr filter.
static void adjust_arnr_filter(VP9_COMP *cpi,
595 596 597
                               int distance, int group_boost,
                               int *arnr_frames, int *arnr_strength) {
  const VP9EncoderConfig *const oxcf = &cpi->oxcf;
598
  const int frames_after_arf =
599
      vp9_lookahead_depth(cpi->lookahead) - distance - 1;
600 601
  int frames_fwd = (cpi->oxcf.arnr_max_frames - 1) >> 1;
  int frames_bwd;
602
  int q, frames, strength;
John Koleszar's avatar
John Koleszar committed
603

604 605 606 607 608
  // Define the forward and backwards filter limits for this arnr group.
  if (frames_fwd > frames_after_arf)
    frames_fwd = frames_after_arf;
  if (frames_fwd > distance)
    frames_fwd = distance;
609

610
  frames_bwd = frames_fwd;
611

612 613 614
  // For even length filter there is one more frame backward
  // than forward: e.g. len=6 ==> bbbAff, len=7 ==> bbbAfff.
  if (frames_bwd < distance)
615
    frames_bwd += (oxcf->arnr_max_frames + 1) & 0x1;
616

617
  // Set the baseline active filter size.
618
  frames = frames_bwd + 1 + frames_fwd;
619

620
  // Adjust the strength based on active max q.
621
  if (cpi->common.current_video_frame > 1)
622
    q = ((int)vp9_convert_qindex_to_q(
623
        cpi->rc.avg_frame_qindex[INTER_FRAME], cpi->common.bit_depth));
624
  else
625
    q = ((int)vp9_convert_qindex_to_q(
626
        cpi->rc.avg_frame_qindex[KEY_FRAME], cpi->common.bit_depth));
627
  if (q > 16) {
628
    strength = oxcf->arnr_strength;
629
  } else {
630 631 632
    strength = oxcf->arnr_strength - ((16 - q) / 2);
    if (strength < 0)
      strength = 0;
633 634 635
  }

  // Adjust number of frames in filter and strength based on gf boost level.
636 637 638
  if (frames > group_boost / 150) {
    frames = group_boost / 150;
    frames += !(frames & 1);
639
  }
640 641 642

  if (strength > group_boost / 300) {
    strength = group_boost / 300;
643
  }
644 645

  // Adjustments for second level arf in multi arf case.
646
  if (cpi->oxcf.pass == 2 && cpi->multi_arf_allowed) {
647 648
    const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
    if (gf_group->rf_level[gf_group->index] != GF_ARF_STD) {
649
      strength >>= 1;
650 651
    }
  }
652 653 654

  *arnr_frames = frames;
  *arnr_strength = strength;
655 656 657 658 659
}

void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
  VP9_COMMON *const cm = &cpi->common;
  RATE_CONTROL *const rc = &cpi->rc;
660
  MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
661 662 663 664 665 666 667
  int frame;
  int frames_to_blur;
  int start_frame;
  int strength;
  int frames_to_blur_backward;
  int frames_to_blur_forward;
  struct scale_factors sf;
668
  YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS] = {NULL};
669 670

  // Apply context specific adjustments to the arnr filter parameters.
671
  adjust_arnr_filter(cpi, distance, rc->gfu_boost, &frames_to_blur, &strength);
672 673 674 675 676 677 678 679 680
  frames_to_blur_backward = (frames_to_blur / 2);
  frames_to_blur_forward = ((frames_to_blur - 1) / 2);
  start_frame = distance + frames_to_blur_forward;

  // Setup frame pointers, NULL indicates frame not included in filter.
  for (frame = 0; frame < frames_to_blur; ++frame) {
    const int which_buffer = start_frame - frame;
    struct lookahead_entry *buf = vp9_lookahead_peek(cpi->lookahead,
                                                     which_buffer);
681
    frames[frames_to_blur - 1 - frame] = &buf->img;
682 683
  }

684 685 686
  if (frames_to_blur > 0) {
    // Setup scaling factors. Scaling on each of the arnr frames is not
    // supported.
687
    if (cpi->use_svc) {
688 689 690
      // In spatial svc the scaling factors might be less then 1/2.
      // So we will use non-normative scaling.
      int frame_used = 0;
691
#if CONFIG_VP9_HIGHBITDEPTH
692 693 694 695 696 697 698
      vp9_setup_scale_factors_for_frame(
          &sf,
          get_frame_new_buffer(cm)->y_crop_width,
          get_frame_new_buffer(cm)->y_crop_height,
          get_frame_new_buffer(cm)->y_crop_width,
          get_frame_new_buffer(cm)->y_crop_height,
          cm->use_highbitdepth);
699
#else
700 701 702 703 704 705
      vp9_setup_scale_factors_for_frame(
          &sf,
          get_frame_new_buffer(cm)->y_crop_width,
          get_frame_new_buffer(cm)->y_crop_height,
          get_frame_new_buffer(cm)->y_crop_width,
          get_frame_new_buffer(cm)->y_crop_height);
706 707
#endif  // CONFIG_VP9_HIGHBITDEPTH

708 709 710
      for (frame = 0; frame < frames_to_blur; ++frame) {
        if (cm->mi_cols * MI_SIZE != frames[frame]->y_width ||
            cm->mi_rows * MI_SIZE != frames[frame]->y_height) {
711
          if (vpx_realloc_frame_buffer(&cpi->svc.scaled_frames[frame_used],
712 713
                                       cm->width, cm->height,
                                       cm->subsampling_x, cm->subsampling_y,
714
#if CONFIG_VP9_HIGHBITDEPTH
715
                                       cm->use_highbitdepth,
716
#endif
717 718 719
                                       VP9_ENC_BORDER_IN_PIXELS,
                                       cm->byte_alignment,
                                       NULL, NULL, NULL)) {
720 721 722 723 724 725 726
            vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
                               "Failed to reallocate alt_ref_buffer");
          }
          frames[frame] = vp9_scale_if_required(
              cm, frames[frame], &cpi->svc.scaled_frames[frame_used]);
          ++frame_used;
        }
727
      }
728
      cm->mi = cm->mip + cm->mi_stride + 1;
729 730
      xd->mi = cm->mi_grid_visible;
      xd->mi[0] = cm->mi;
731 732
    } else {
      // ARF is produced at the native frame size and resized when coded.
733
#if CONFIG_VP9_HIGHBITDEPTH
734 735 736 737 738 739
      vp9_setup_scale_factors_for_frame(&sf,
                                        frames[0]->y_crop_width,
                                        frames[0]->y_crop_height,
                                        frames[0]->y_crop_width,
                                        frames[0]->y_crop_height,
                                        cm->use_highbitdepth);
740
#else
741 742 743 744 745
      vp9_setup_scale_factors_for_frame(&sf,
                                        frames[0]->y_crop_width,
                                        frames[0]->y_crop_height,
                                        frames[0]->y_crop_width,
                                        frames[0]->y_crop_height);
746
#endif  // CONFIG_VP9_HIGHBITDEPTH
747
    }
748 749
  }

750 751
  temporal_filter_iterate_c(cpi, frames, frames_to_blur,
                            frames_to_blur_backward, strength, &sf);
752
}