vp9_loopfilter.c 14.5 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
John Koleszar's avatar
John Koleszar committed
3
 *
4
 *  Use of this source code is governed by a BSD-style license
5 6
 *  that can be found in the LICENSE file in the root of the source
 *  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.
John Koleszar's avatar
John Koleszar committed
9 10
 */

Attila Nagy's avatar
Attila Nagy committed
11
#include "vpx_config.h"
12 13
#include "vp9/common/vp9_loopfilter.h"
#include "vp9/common/vp9_onyxc_int.h"
Attila Nagy's avatar
Attila Nagy committed
14
#include "vpx_mem/vpx_mem.h"
John Koleszar's avatar
John Koleszar committed
15

16
#include "vp9/common/vp9_seg_common.h"
17

John Koleszar's avatar
John Koleszar committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
static void lf_init_lut(loop_filter_info_n *lfi) {
  int filt_lvl;

  for (filt_lvl = 0; filt_lvl <= MAX_LOOP_FILTER; filt_lvl++) {
    if (filt_lvl >= 40) {
      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 2;
      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 3;
    } else if (filt_lvl >= 20) {
      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 2;
    } else if (filt_lvl >= 15) {
      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 1;
    } else {
      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 0;
      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 0;
Attila Nagy's avatar
Attila Nagy committed
34
    }
John Koleszar's avatar
John Koleszar committed
35
  }
Attila Nagy's avatar
Attila Nagy committed
36

John Koleszar's avatar
John Koleszar committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
  lfi->mode_lf_lut[DC_PRED] = 1;
  lfi->mode_lf_lut[D45_PRED] = 1;
  lfi->mode_lf_lut[D135_PRED] = 1;
  lfi->mode_lf_lut[D117_PRED] = 1;
  lfi->mode_lf_lut[D153_PRED] = 1;
  lfi->mode_lf_lut[D27_PRED] = 1;
  lfi->mode_lf_lut[D63_PRED] = 1;
  lfi->mode_lf_lut[V_PRED] = 1;
  lfi->mode_lf_lut[H_PRED] = 1;
  lfi->mode_lf_lut[TM_PRED] = 1;
  lfi->mode_lf_lut[B_PRED]  = 0;
  lfi->mode_lf_lut[I8X8_PRED] = 0;
  lfi->mode_lf_lut[ZEROMV]  = 1;
  lfi->mode_lf_lut[NEARESTMV] = 2;
  lfi->mode_lf_lut[NEARMV] = 2;
  lfi->mode_lf_lut[NEWMV] = 2;
  lfi->mode_lf_lut[SPLITMV] = 3;
Attila Nagy's avatar
Attila Nagy committed
54 55
}

56
void vp9_loop_filter_update_sharpness(loop_filter_info_n *lfi,
John Koleszar's avatar
John Koleszar committed
57 58 59 60 61 62 63
                                      int sharpness_lvl) {
  int i;

  /* For each possible value for the loop filter fill out limits */
  for (i = 0; i <= MAX_LOOP_FILTER; i++) {
    int filt_lvl = i;
    int block_inside_limit = 0;
John Koleszar's avatar
John Koleszar committed
64

John Koleszar's avatar
John Koleszar committed
65 66 67
    /* Set loop filter paramaeters that control sharpness. */
    block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
    block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
John Koleszar's avatar
John Koleszar committed
68

John Koleszar's avatar
John Koleszar committed
69 70 71
    if (sharpness_lvl > 0) {
      if (block_inside_limit > (9 - sharpness_lvl))
        block_inside_limit = (9 - sharpness_lvl);
John Koleszar's avatar
John Koleszar committed
72
    }
John Koleszar's avatar
John Koleszar committed
73 74 75 76 77 78 79 80 81 82

    if (block_inside_limit < 1)
      block_inside_limit = 1;

    vpx_memset(lfi->lim[i], block_inside_limit, SIMD_WIDTH);
    vpx_memset(lfi->blim[i], (2 * filt_lvl + block_inside_limit),
               SIMD_WIDTH);
    vpx_memset(lfi->mblim[i], (2 * (filt_lvl + 2) + block_inside_limit),
               SIMD_WIDTH);
  }
Attila Nagy's avatar
Attila Nagy committed
83
}
John Koleszar's avatar
John Koleszar committed
84

85
void vp9_loop_filter_init(VP9_COMMON *cm) {
John Koleszar's avatar
John Koleszar committed
86 87
  loop_filter_info_n *lfi = &cm->lf_info;
  int i;
Attila Nagy's avatar
Attila Nagy committed
88

89
  // init limits for given sharpness
90
  vp9_loop_filter_update_sharpness(lfi, cm->sharpness_level);
John Koleszar's avatar
John Koleszar committed
91
  cm->last_sharpness_level = cm->sharpness_level;
Attila Nagy's avatar
Attila Nagy committed
92

93
  // init LUT for lvl  and hev thr picking
John Koleszar's avatar
John Koleszar committed
94
  lf_init_lut(lfi);
Attila Nagy's avatar
Attila Nagy committed
95

96 97
  // init hev threshold const vectors
  for (i = 0; i < 4; i++)
John Koleszar's avatar
John Koleszar committed
98
    vpx_memset(lfi->hev_thr[i], i, SIMD_WIDTH);
John Koleszar's avatar
John Koleszar committed
99 100
}

101
void vp9_loop_filter_frame_init(VP9_COMMON *cm,
102
                                MACROBLOCKD *xd,
John Koleszar's avatar
John Koleszar committed
103 104 105 106
                                int default_filt_lvl) {
  int seg,  /* segment number */
      ref,  /* index in ref_lf_deltas */
      mode; /* index in mode_lf_deltas */
John Koleszar's avatar
John Koleszar committed
107

John Koleszar's avatar
John Koleszar committed
108
  loop_filter_info_n *lfi = &cm->lf_info;
John Koleszar's avatar
John Koleszar committed
109

John Koleszar's avatar
John Koleszar committed
110
  /* update limits if sharpness has changed */
111 112 113
  // printf("vp9_loop_filter_frame_init %d\n", default_filt_lvl);
  // printf("sharpness level: %d [%d]\n",
  //        cm->sharpness_level, cm->last_sharpness_level);
John Koleszar's avatar
John Koleszar committed
114
  if (cm->last_sharpness_level != cm->sharpness_level) {
115
    vp9_loop_filter_update_sharpness(lfi, cm->sharpness_level);
John Koleszar's avatar
John Koleszar committed
116 117 118 119 120 121 122 123 124
    cm->last_sharpness_level = cm->sharpness_level;
  }

  for (seg = 0; seg < MAX_MB_SEGMENTS; seg++) {
    int lvl_seg = default_filt_lvl;
    int lvl_ref, lvl_mode;


    // Set the baseline filter values for each segment
125
    if (vp9_segfeature_active(xd, seg, SEG_LVL_ALT_LF)) {
John Koleszar's avatar
John Koleszar committed
126 127
      /* Abs value */
      if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA) {
128
        lvl_seg = vp9_get_segdata(xd, seg, SEG_LVL_ALT_LF);
John Koleszar's avatar
John Koleszar committed
129
      } else { /* Delta Value */
130
        lvl_seg += vp9_get_segdata(xd, seg, SEG_LVL_ALT_LF);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
131
        lvl_seg = clamp(lvl_seg, 0, 63);
John Koleszar's avatar
John Koleszar committed
132 133
      }
    }
John Koleszar's avatar
John Koleszar committed
134

John Koleszar's avatar
John Koleszar committed
135 136 137 138 139 140 141
    if (!xd->mode_ref_lf_delta_enabled) {
      /* we could get rid of this if we assume that deltas are set to
       * zero when not in use; encoder always uses deltas
       */
      vpx_memset(lfi->lvl[seg][0], lvl_seg, 4 * 4);
      continue;
    }
John Koleszar's avatar
John Koleszar committed
142

John Koleszar's avatar
John Koleszar committed
143
    lvl_ref = lvl_seg;
John Koleszar's avatar
John Koleszar committed
144

John Koleszar's avatar
John Koleszar committed
145 146
    /* INTRA_FRAME */
    ref = INTRA_FRAME;
John Koleszar's avatar
John Koleszar committed
147

John Koleszar's avatar
John Koleszar committed
148 149
    /* Apply delta for reference frame */
    lvl_ref += xd->ref_lf_deltas[ref];
Attila Nagy's avatar
Attila Nagy committed
150

John Koleszar's avatar
John Koleszar committed
151 152 153
    /* Apply delta for Intra modes */
    mode = 0; /* B_PRED */
    /* Only the split mode BPRED has a further special case */
Dmitry Kovalev's avatar
Dmitry Kovalev committed
154
    lvl_mode = clamp(lvl_ref +  xd->mode_lf_deltas[mode], 0, 63);
Attila Nagy's avatar
Attila Nagy committed
155

John Koleszar's avatar
John Koleszar committed
156
    lfi->lvl[seg][ref][mode] = lvl_mode;
Attila Nagy's avatar
Attila Nagy committed
157

John Koleszar's avatar
John Koleszar committed
158
    mode = 1; /* all the rest of Intra modes */
Dmitry Kovalev's avatar
Dmitry Kovalev committed
159
    lvl_mode = clamp(lvl_ref, 0, 63);
John Koleszar's avatar
John Koleszar committed
160
    lfi->lvl[seg][ref][mode] = lvl_mode;
John Koleszar's avatar
John Koleszar committed
161

John Koleszar's avatar
John Koleszar committed
162 163 164
    /* LAST, GOLDEN, ALT */
    for (ref = 1; ref < MAX_REF_FRAMES; ref++) {
      int lvl_ref = lvl_seg;
John Koleszar's avatar
John Koleszar committed
165

John Koleszar's avatar
John Koleszar committed
166 167
      /* Apply delta for reference frame */
      lvl_ref += xd->ref_lf_deltas[ref];
John Koleszar's avatar
John Koleszar committed
168

John Koleszar's avatar
John Koleszar committed
169 170
      /* Apply delta for Inter modes */
      for (mode = 1; mode < 4; mode++) {
Dmitry Kovalev's avatar
Dmitry Kovalev committed
171
        lvl_mode = clamp(lvl_ref + xd->mode_lf_deltas[mode], 0, 63);
John Koleszar's avatar
John Koleszar committed
172 173
        lfi->lvl[seg][ref][mode] = lvl_mode;
      }
John Koleszar's avatar
John Koleszar committed
174
    }
John Koleszar's avatar
John Koleszar committed
175
  }
John Koleszar's avatar
John Koleszar committed
176 177
}

Yaowu Xu's avatar
Yaowu Xu committed
178 179 180 181
// Determine if we should skip inner-MB loop filtering within a MB
// The current condition is that the loop filtering is skipped only
// the MB uses a prediction size of 16x16 and either 16x16 transform
// is used or there is no residue at all.
182 183 184 185 186
static int mb_lf_skip(const MB_MODE_INFO *const mbmi) {
  const MB_PREDICTION_MODE mode = mbmi->mode;
  const int skip_coef = mbmi->mb_skip_coeff;
  const int tx_size = mbmi->txfm_size;
  return mode != B_PRED && mode != I8X8_PRED && mode != SPLITMV &&
Yaowu Xu's avatar
Yaowu Xu committed
187
         (tx_size >= TX_16X16 || skip_coef);
188
}
Yaowu Xu's avatar
Yaowu Xu committed
189 190 191 192 193

// Determine if we should skip MB loop filtering on a MB edge within
// a superblock, the current condition is that MB loop filtering is
// skipped only when both MBs do not use inner MB loop filtering, and
// same motion vector with same reference frame
194 195
static int sb_mb_lf_skip(const MODE_INFO *const mip0,
                         const MODE_INFO *const mip1) {
Yaowu Xu's avatar
Yaowu Xu committed
196 197 198 199 200 201 202
  const MB_MODE_INFO *mbmi0 = &mip0->mbmi;
  const MB_MODE_INFO *mbmi1 = &mip0->mbmi;
  return mb_lf_skip(mbmi0) && mb_lf_skip(mbmi1) &&
         (mbmi0->ref_frame == mbmi1->ref_frame) &&
         (mbmi0->mv[mbmi0->ref_frame].as_int ==
          mbmi1->mv[mbmi1->ref_frame].as_int) &&
         mbmi0->ref_frame != INTRA_FRAME;
203
}
204

205 206 207
void vp9_loop_filter_frame(VP9_COMMON *cm,
                           MACROBLOCKD *xd,
                           int frame_filter_level,
208 209
                           int y_only,
                           int dering) {
John Koleszar's avatar
John Koleszar committed
210 211
  YV12_BUFFER_CONFIG *post = cm->frame_to_show;
  loop_filter_info_n *lfi_n = &cm->lf_info;
212
  struct loop_filter_info lfi;
213 214
  const FRAME_TYPE frame_type = cm->frame_type;
  int mb_row, mb_col;
John Koleszar's avatar
John Koleszar committed
215

216 217 218 219 220 221
  // Set up the buffer pointers
  uint8_t *y_ptr = post->y_buffer;
  uint8_t *u_ptr = y_only ? 0 : post->u_buffer;
  uint8_t *v_ptr = y_only ? 0 : post->v_buffer;

  // Point at base of Mb MODE_INFO list
John Koleszar's avatar
John Koleszar committed
222
  const MODE_INFO *mode_info_context = cm->mi;
223
  const int mis = cm->mode_info_stride;
John Koleszar's avatar
John Koleszar committed
224

225
  // Initialize the loop filter for this frame.
226
  vp9_loop_filter_frame_init(cm, xd, frame_filter_level);
John Koleszar's avatar
John Koleszar committed
227

228
  // vp9_filter each macro block
John Koleszar's avatar
John Koleszar committed
229 230
  for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
231 232
      const MB_PREDICTION_MODE mode = mode_info_context->mbmi.mode;
      const int mode_index = lfi_n->mode_lf_lut[mode];
John Koleszar's avatar
John Koleszar committed
233 234
      const int seg = mode_info_context->mbmi.segment_id;
      const int ref_frame = mode_info_context->mbmi.ref_frame;
235
      const int filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
John Koleszar's avatar
John Koleszar committed
236
      if (filter_level) {
237 238
        const int skip_lf = mb_lf_skip(&mode_info_context->mbmi);
        const int tx_size = mode_info_context->mbmi.txfm_size;
John Koleszar's avatar
John Koleszar committed
239 240 241 242 243 244 245
        if (cm->filter_type == NORMAL_LOOPFILTER) {
          const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
          lfi.mblim = lfi_n->mblim[filter_level];
          lfi.blim = lfi_n->blim[filter_level];
          lfi.lim = lfi_n->lim[filter_level];
          lfi.hev_thr = lfi_n->hev_thr[hev_index];

Yaowu Xu's avatar
Yaowu Xu committed
246 247 248 249
          if (mb_col > 0 &&
              !((mb_col & 1) && mode_info_context->mbmi.sb_type &&
                (sb_mb_lf_skip(mode_info_context - 1, mode_info_context) ||
                 tx_size >= TX_32X32))
250 251
              ) {
            if (tx_size >= TX_16X16)
252
              vp9_lpf_mbv_w(y_ptr, u_ptr, v_ptr, post->y_stride,
253
                            post->uv_stride, &lfi);
254
            else
255
              vp9_loop_filter_mbv(y_ptr, u_ptr, v_ptr, post->y_stride,
256
                                  post->uv_stride, &lfi);
257
          }
258
          if (!skip_lf) {
259 260
            if (tx_size >= TX_8X8) {
              if (tx_size == TX_8X8 && (mode == I8X8_PRED || mode == SPLITMV))
261
                vp9_loop_filter_bv8x8(y_ptr, u_ptr, v_ptr, post->y_stride,
262 263
                                      post->uv_stride, &lfi);
              else
264
                vp9_loop_filter_bv8x8(y_ptr, NULL, NULL, post->y_stride,
265 266
                                      post->uv_stride, &lfi);
            } else {
267
              vp9_loop_filter_bv(y_ptr, u_ptr, v_ptr, post->y_stride,
268
                                 post->uv_stride, &lfi);
269
            }
John Koleszar's avatar
John Koleszar committed
270 271
          }
          /* don't apply across umv border */
Yaowu Xu's avatar
Yaowu Xu committed
272 273 274 275
          if (mb_row > 0 &&
              !((mb_row & 1) && mode_info_context->mbmi.sb_type &&
                (sb_mb_lf_skip(mode_info_context - mis, mode_info_context) ||
                tx_size >= TX_32X32))
276 277
              ) {
            if (tx_size >= TX_16X16)
278
              vp9_lpf_mbh_w(y_ptr, u_ptr, v_ptr, post->y_stride,
279
                            post->uv_stride, &lfi);
280
            else
281
              vp9_loop_filter_mbh(y_ptr, u_ptr, v_ptr, post->y_stride,
282
                                  post->uv_stride, &lfi);
283
          }
284
          if (!skip_lf) {
285 286
            if (tx_size >= TX_8X8) {
              if (tx_size == TX_8X8 && (mode == I8X8_PRED || mode == SPLITMV))
287
                vp9_loop_filter_bh8x8(y_ptr, u_ptr, v_ptr, post->y_stride,
288 289
                                      post->uv_stride, &lfi);
              else
290
                vp9_loop_filter_bh8x8(y_ptr, NULL, NULL, post->y_stride,
291 292
                                      post->uv_stride, &lfi);
            } else {
293
              vp9_loop_filter_bh(y_ptr, u_ptr, v_ptr, post->y_stride,
294
                                 post->uv_stride, &lfi);
295
            }
John Koleszar's avatar
John Koleszar committed
296
          }
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
#if CONFIG_LOOP_DERING
          if (dering) {
            if (mb_row && mb_row < cm->mb_rows - 1 &&
                mb_col && mb_col < cm->mb_cols - 1) {
              vp9_post_proc_down_and_across(y_ptr, y_ptr,
                                            post->y_stride, post->y_stride,
                                            16, 16, dering);
              if (!y_only) {
                vp9_post_proc_down_and_across(u_ptr, u_ptr,
                                              post->uv_stride, post->uv_stride,
                                              8, 8, dering);
                vp9_post_proc_down_and_across(v_ptr, v_ptr,
                                              post->uv_stride, post->uv_stride,
                                              8, 8, dering);
              }
            } else {
              // Adjust the filter so that no out-of-frame data is used.
              uint8_t *dr_y = y_ptr, *dr_u = u_ptr, *dr_v = v_ptr;
              int w_adjust = 0;
              int h_adjust = 0;

              if (mb_col == 0) {
                dr_y += 2;
                dr_u += 2;
                dr_v += 2;
                w_adjust += 2;
              }
              if (mb_col == cm->mb_cols - 1)
                w_adjust += 2;
              if (mb_row == 0) {
                dr_y += 2 * post->y_stride;
                dr_u += 2 * post->uv_stride;
                dr_v += 2 * post->uv_stride;
                h_adjust += 2;
              }
              if (mb_row == cm->mb_rows - 1)
                h_adjust += 2;
              vp9_post_proc_down_and_across_c(dr_y, dr_y,
                                              post->y_stride, post->y_stride,
                                              16 - w_adjust, 16 - h_adjust,
                                              dering);
              if (!y_only) {
                vp9_post_proc_down_and_across_c(dr_u, dr_u,
                                                post->uv_stride,
                                                post->uv_stride,
                                                8 - w_adjust, 8 - h_adjust,
                                                dering);
                vp9_post_proc_down_and_across_c(dr_v, dr_v,
                                                post->uv_stride,
                                                post->uv_stride,
                                                8 - w_adjust, 8 - h_adjust,
                                                dering);
              }
            }
          }
#endif
John Koleszar's avatar
John Koleszar committed
353
        } else {
Daniel Kang's avatar
Daniel Kang committed
354
          // FIXME: Not 8x8 aware
355 356 357
          if (mb_col > 0 &&
              !(skip_lf && mb_lf_skip(&mode_info_context[-1].mbmi)) &&
              !((mb_col & 1) && mode_info_context->mbmi.sb_type))
358
            vp9_loop_filter_simple_mbv(y_ptr, post->y_stride,
359
                                       lfi_n->mblim[filter_level]);
John Koleszar's avatar
John Koleszar committed
360
          if (!skip_lf)
361
            vp9_loop_filter_simple_bv(y_ptr, post->y_stride,
362
                                      lfi_n->blim[filter_level]);
John Koleszar's avatar
John Koleszar committed
363 364

          /* don't apply across umv border */
365
          if (mb_row > 0 &&
366 367
              !(skip_lf && mb_lf_skip(&mode_info_context[-mis].mbmi)) &&
              !((mb_row & 1) && mode_info_context->mbmi.sb_type))
368
            vp9_loop_filter_simple_mbh(y_ptr, post->y_stride,
369
                                       lfi_n->mblim[filter_level]);
John Koleszar's avatar
John Koleszar committed
370
          if (!skip_lf)
371
            vp9_loop_filter_simple_bh(y_ptr, post->y_stride,
372
                                      lfi_n->blim[filter_level]);
John Koleszar's avatar
John Koleszar committed
373
        }
John Koleszar's avatar
John Koleszar committed
374 375
      }
      y_ptr += 16;
376 377 378 379
      if (!y_only) {
        u_ptr += 8;
        v_ptr += 8;
      }
380
      mode_info_context++;  // step to next MB
John Koleszar's avatar
John Koleszar committed
381
    }
John Koleszar's avatar
John Koleszar committed
382
    y_ptr += post->y_stride  * 16 - post->y_width;
383 384 385 386
    if (!y_only) {
      u_ptr += post->uv_stride *  8 - post->uv_width;
      v_ptr += post->uv_stride *  8 - post->uv_width;
    }
387
    mode_info_context++;  // Skip border mb
John Koleszar's avatar
John Koleszar committed
388
  }
John Koleszar's avatar
John Koleszar committed
389 390
}

391