vp9_loopfilter.c 22.2 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
static void lf_init_lut(loop_filter_info_n *lfi) {
  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;
Yaowu Xu's avatar
Yaowu Xu committed
29
  lfi->mode_lf_lut[I4X4_PRED]  = 0;
30
#if !CONFIG_SB8X8
John Koleszar's avatar
John Koleszar committed
31
  lfi->mode_lf_lut[I8X8_PRED] = 0;
32
#endif
John Koleszar's avatar
John Koleszar committed
33 34 35 36 37
  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
38 39
}

40
void vp9_loop_filter_update_sharpness(loop_filter_info_n *lfi,
John Koleszar's avatar
John Koleszar committed
41 42 43 44 45 46 47
                                      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
48

John Koleszar's avatar
John Koleszar committed
49 50 51
    /* 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
52

John Koleszar's avatar
John Koleszar committed
53 54 55
    if (sharpness_lvl > 0) {
      if (block_inside_limit > (9 - sharpness_lvl))
        block_inside_limit = (9 - sharpness_lvl);
John Koleszar's avatar
John Koleszar committed
56
    }
John Koleszar's avatar
John Koleszar committed
57 58 59 60 61 62 63 64 65 66

    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
67
}
John Koleszar's avatar
John Koleszar committed
68

69
void vp9_loop_filter_init(VP9_COMMON *cm) {
John Koleszar's avatar
John Koleszar committed
70 71
  loop_filter_info_n *lfi = &cm->lf_info;
  int i;
Attila Nagy's avatar
Attila Nagy committed
72

73
  // init limits for given sharpness
74
  vp9_loop_filter_update_sharpness(lfi, cm->sharpness_level);
John Koleszar's avatar
John Koleszar committed
75
  cm->last_sharpness_level = cm->sharpness_level;
Attila Nagy's avatar
Attila Nagy committed
76

77
  // init LUT for lvl  and hev thr picking
John Koleszar's avatar
John Koleszar committed
78
  lf_init_lut(lfi);
Attila Nagy's avatar
Attila Nagy committed
79

80 81
  // init hev threshold const vectors
  for (i = 0; i < 4; i++)
John Koleszar's avatar
John Koleszar committed
82
    vpx_memset(lfi->hev_thr[i], i, SIMD_WIDTH);
John Koleszar's avatar
John Koleszar committed
83 84
}

85
void vp9_loop_filter_frame_init(VP9_COMMON *cm,
86
                                MACROBLOCKD *xd,
John Koleszar's avatar
John Koleszar committed
87
                                int default_filt_lvl) {
88 89 90 91 92 93 94
  int seg,    // segment number
      ref,    // index in ref_lf_deltas
      mode;   // index in mode_lf_deltas
  // n_shift is the a multiplier for lf_deltas
  // the multiplier is 1 for when filter_lvl is between 0 and 31;
  // 2 when filter_lvl is between 32 and 63
  int n_shift = default_filt_lvl >> 5;
John Koleszar's avatar
John Koleszar committed
95

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

John Koleszar's avatar
John Koleszar committed
98
  /* update limits if sharpness has changed */
99 100 101
  // 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
102
  if (cm->last_sharpness_level != cm->sharpness_level) {
103
    vp9_loop_filter_update_sharpness(lfi, cm->sharpness_level);
John Koleszar's avatar
John Koleszar committed
104 105 106 107 108 109 110 111 112
    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
113
    if (vp9_segfeature_active(xd, seg, SEG_LVL_ALT_LF)) {
John Koleszar's avatar
John Koleszar committed
114 115
      /* Abs value */
      if (xd->mb_segment_abs_delta == SEGMENT_ABSDATA) {
116
        lvl_seg = vp9_get_segdata(xd, seg, SEG_LVL_ALT_LF);
John Koleszar's avatar
John Koleszar committed
117
      } else { /* Delta Value */
118
        lvl_seg += vp9_get_segdata(xd, seg, SEG_LVL_ALT_LF);
Dmitry Kovalev's avatar
Dmitry Kovalev committed
119
        lvl_seg = clamp(lvl_seg, 0, 63);
John Koleszar's avatar
John Koleszar committed
120 121
      }
    }
John Koleszar's avatar
John Koleszar committed
122

John Koleszar's avatar
John Koleszar committed
123 124 125 126 127 128 129
    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
130

John Koleszar's avatar
John Koleszar committed
131
    lvl_ref = lvl_seg;
John Koleszar's avatar
John Koleszar committed
132

John Koleszar's avatar
John Koleszar committed
133 134
    /* INTRA_FRAME */
    ref = INTRA_FRAME;
John Koleszar's avatar
John Koleszar committed
135

John Koleszar's avatar
John Koleszar committed
136
    /* Apply delta for reference frame */
137
    lvl_ref += xd->ref_lf_deltas[ref] << n_shift;
Attila Nagy's avatar
Attila Nagy committed
138

John Koleszar's avatar
John Koleszar committed
139
    /* Apply delta for Intra modes */
Yaowu Xu's avatar
Yaowu Xu committed
140 141
    mode = 0; /* I4X4_PRED */
    /* Only the split mode I4X4_PRED has a further special case */
142 143
    lvl_mode = lvl_ref + (xd->mode_lf_deltas[mode] << n_shift);
    lfi->lvl[seg][ref][mode] = clamp(lvl_mode, 0, 63);
Attila Nagy's avatar
Attila Nagy committed
144

John Koleszar's avatar
John Koleszar committed
145
    mode = 1; /* all the rest of Intra modes */
146 147
    lvl_mode = lvl_ref;
    lfi->lvl[seg][ref][mode] = clamp(lvl_mode, 0, 63);
John Koleszar's avatar
John Koleszar committed
148

John Koleszar's avatar
John Koleszar committed
149 150 151
    /* LAST, GOLDEN, ALT */
    for (ref = 1; ref < MAX_REF_FRAMES; ref++) {
      int lvl_ref = lvl_seg;
John Koleszar's avatar
John Koleszar committed
152

John Koleszar's avatar
John Koleszar committed
153
      /* Apply delta for reference frame */
154
      lvl_ref += xd->ref_lf_deltas[ref] << n_shift;
John Koleszar's avatar
John Koleszar committed
155

John Koleszar's avatar
John Koleszar committed
156 157
      /* Apply delta for Inter modes */
      for (mode = 1; mode < 4; mode++) {
158 159
        lvl_mode = lvl_ref + (xd->mode_lf_deltas[mode] << n_shift);
        lfi->lvl[seg][ref][mode] = clamp(lvl_mode, 0, 63);
John Koleszar's avatar
John Koleszar committed
160
      }
John Koleszar's avatar
John Koleszar committed
161
    }
John Koleszar's avatar
John Koleszar committed
162
  }
John Koleszar's avatar
John Koleszar committed
163 164
}

Yaowu Xu's avatar
Yaowu Xu committed
165 166 167 168
// 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.
169 170 171
static int mb_lf_skip(const MB_MODE_INFO *const mbmi) {
  const int skip_coef = mbmi->mb_skip_coeff;
  const int tx_size = mbmi->txfm_size;
172 173 174 175
#if CONFIG_SB8X8
  return mbmi->sb_type >= BLOCK_SIZE_MB16X16 &&
#else
  const MB_PREDICTION_MODE mode = mbmi->mode;
Yaowu Xu's avatar
Yaowu Xu committed
176
  return mode != I4X4_PRED && mode != I8X8_PRED && mode != SPLITMV &&
177
#endif
Yaowu Xu's avatar
Yaowu Xu committed
178
         (tx_size >= TX_16X16 || skip_coef);
179
}
Yaowu Xu's avatar
Yaowu Xu committed
180 181 182 183 184

// 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
185 186
static int sb_mb_lf_skip(const MODE_INFO *const mip0,
                         const MODE_INFO *const mip1) {
Yaowu Xu's avatar
Yaowu Xu committed
187
  const MB_MODE_INFO *mbmi0 = &mip0->mbmi;
Yaowu Xu's avatar
Yaowu Xu committed
188
  const MB_MODE_INFO *mbmi1 = &mip1->mbmi;
Yaowu Xu's avatar
Yaowu Xu committed
189
  return mb_lf_skip(mbmi0) && mb_lf_skip(mbmi1) &&
Yaowu Xu's avatar
Yaowu Xu committed
190 191
         mbmi0->ref_frame != INTRA_FRAME &&
         mbmi1->ref_frame != INTRA_FRAME;
192
}
193

Yaowu Xu's avatar
Yaowu Xu committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
static void lpf_mb(VP9_COMMON *cm, const MODE_INFO *mi,
                   int do_left_mb_v, int do_above_mb_h,
                   int do_left_mbuv_v, int do_above_mbuv_h,
                   uint8_t *y_ptr, uint8_t *u_ptr, uint8_t *v_ptr,
                   int y_stride, int uv_stride, int dering) {
  loop_filter_info_n *lfi_n = &cm->lf_info;
  struct loop_filter_info lfi;
  int mode = mi->mbmi.mode;
  int mode_index = lfi_n->mode_lf_lut[mode];
  int seg = mi->mbmi.segment_id;
  int ref_frame = mi->mbmi.ref_frame;
  int filter_level = lfi_n->lvl[seg][ref_frame][mode_index];

  if (filter_level) {
    const int skip_lf = mb_lf_skip(&mi->mbmi);
    const int tx_size = mi->mbmi.txfm_size;
    if (cm->filter_type == NORMAL_LOOPFILTER) {
211
      const int hev_index = filter_level >> 4;
Yaowu Xu's avatar
Yaowu Xu committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
      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];

      if (do_above_mb_h) {
        if (tx_size >= TX_16X16)
          vp9_lpf_mbh_w(y_ptr,
                        do_above_mbuv_h ? u_ptr : NULL,
                        do_above_mbuv_h ? v_ptr : NULL,
                        y_stride, uv_stride, &lfi);
        else
          vp9_loop_filter_mbh(y_ptr, u_ptr, v_ptr, y_stride, uv_stride, &lfi);
      }

      if (!skip_lf) {
        if (tx_size >= TX_8X8) {
229 230 231 232 233 234 235
          if (tx_size == TX_8X8 &&
#if CONFIG_SB8X8
              (mi->mbmi.sb_type < BLOCK_SIZE_MB16X16)
#else
              (mode == I8X8_PRED || mode == SPLITMV)
#endif
              )
Yaowu Xu's avatar
Yaowu Xu committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
            vp9_loop_filter_bh8x8(y_ptr, u_ptr, v_ptr,
                                  y_stride, uv_stride, &lfi);
          else
            vp9_loop_filter_bh8x8(y_ptr, NULL, NULL,
                                  y_stride, uv_stride, &lfi);
        } else {
          vp9_loop_filter_bh(y_ptr, u_ptr, v_ptr,
                             y_stride, uv_stride, &lfi);
        }
      }

      if (do_left_mb_v) {
        if (tx_size >= TX_16X16)
          vp9_lpf_mbv_w(y_ptr,
                        do_left_mbuv_v ? u_ptr : NULL,
                        do_left_mbuv_v ? v_ptr : NULL,
                        y_stride, uv_stride, &lfi);
        else
          vp9_loop_filter_mbv(y_ptr, u_ptr, v_ptr, y_stride, uv_stride, &lfi);
      }

      if (!skip_lf) {
        if (tx_size >= TX_8X8) {
259 260 261 262 263 264 265
          if (tx_size == TX_8X8 &&
#if CONFIG_SB8X8
              (mi->mbmi.sb_type < BLOCK_SIZE_MB16X16)
#else
              (mode == I8X8_PRED || mode == SPLITMV)
#endif
              )
Yaowu Xu's avatar
Yaowu Xu committed
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
            vp9_loop_filter_bv8x8(y_ptr, u_ptr, v_ptr,
                                  y_stride, uv_stride, &lfi);
          else
            vp9_loop_filter_bv8x8(y_ptr, NULL, NULL,
                                  y_stride, uv_stride, &lfi);
        } else {
          vp9_loop_filter_bv(y_ptr, u_ptr, v_ptr,
                             y_stride, uv_stride, &lfi);
        }
      }
      if (dering) {
#if CONFIG_LOOP_DERING
        vp9_post_proc_down_and_across(y_ptr, y_ptr,
          y_stride, y_stride,
          16, 16, dering);
        if (u_ptr && v_ptr) {
          vp9_post_proc_down_and_across(u_ptr, u_ptr,
            uv_stride, uv_stride,
            8, 8, dering);
          vp9_post_proc_down_and_across(v_ptr, v_ptr,
            uv_stride, uv_stride,
            8, 8, dering);
        }
#endif
      }
    } else {
      // TODO(yaowu): simple loop filter
    }
  }
}

static void lpf_sb32(VP9_COMMON *cm, const MODE_INFO *mode_info_context,
                     int mb_row, int mb_col,
                     uint8_t *y_ptr, uint8_t *u_ptr, uint8_t *v_ptr,
                     int y_stride, int uv_stride,
                     int y_only, int dering) {
302 303 304 305 306 307 308 309 310 311 312 313 314
  BLOCK_SIZE_TYPE sb_type = mode_info_context->mbmi.sb_type;
  const int wbl = b_width_log2(sb_type), hbl = b_height_log2(sb_type);
  TX_SIZE tx_size = mode_info_context->mbmi.txfm_size;
  int do_left_v, do_above_h;
  int do_left_v_mbuv, do_above_h_mbuv;
  int mis = cm->mode_info_stride;
  const MODE_INFO *mi;

  // process 1st MB top-left
  mi = mode_info_context;
  do_left_v = (mb_col > 0);
  do_above_h = (mb_row > 0);
  do_left_v_mbuv = !(sb_type >= BLOCK_SIZE_SB64X64 &&
Yaowu Xu's avatar
Yaowu Xu committed
315
      tx_size >= TX_32X32 && (mb_col & 2));
316
  do_above_h_mbuv = !(sb_type >= BLOCK_SIZE_SB64X64 &&
Yaowu Xu's avatar
Yaowu Xu committed
317
      tx_size >= TX_32X32 && (mb_row & 2));
318
  lpf_mb(cm, mi, do_left_v, do_above_h,
Yaowu Xu's avatar
Yaowu Xu committed
319 320 321 322 323
      do_left_v_mbuv, do_above_h_mbuv,
      y_ptr,
      y_only? 0 : u_ptr,
      y_only? 0 : v_ptr,
      y_stride, uv_stride, dering);
324
  // process 2nd MB top-right
325
  mi = mode_info_context + (1 << CONFIG_SB8X8);
326
  do_left_v = !(wbl >= 3 /* 32x16 or >=32x32 */ && (tx_size >= TX_32X32 ||
Yaowu Xu's avatar
Yaowu Xu committed
327
      sb_mb_lf_skip(mode_info_context, mi)));
328
  do_above_h = (mb_row > 0);
329 330
  do_left_v_mbuv = !(wbl >= 3 /* 32x16 or >=32x32 */ && (tx_size >= TX_16X16 ||
      sb_mb_lf_skip(mode_info_context, mi)));
331
  do_above_h_mbuv = !(sb_type >= BLOCK_SIZE_SB64X64 &&
Yaowu Xu's avatar
Yaowu Xu committed
332
      tx_size >= TX_32X32 && (mb_row & 2));
333
  lpf_mb(cm, mi, do_left_v, do_above_h,
Yaowu Xu's avatar
Yaowu Xu committed
334 335 336 337 338 339
      do_left_v_mbuv, do_above_h_mbuv,
      y_ptr + 16,
      y_only ? 0 : (u_ptr + 8),
      y_only ? 0 : (v_ptr + 8),
      y_stride, uv_stride, dering);

340
  // process 3rd MB bottom-left
341
  mi = mode_info_context + (mis << CONFIG_SB8X8);
342 343
  do_left_v = (mb_col > 0);
  do_above_h = !(hbl >= 3 /* 16x32 or >=32x32 */ && (tx_size >= TX_32X32 ||
Yaowu Xu's avatar
Yaowu Xu committed
344
      sb_mb_lf_skip(mode_info_context, mi)));
345
  do_left_v_mbuv = !(sb_type >= BLOCK_SIZE_SB64X64 &&
Yaowu Xu's avatar
Yaowu Xu committed
346
      tx_size >= TX_32X32 && (mb_col & 2));
347 348
  do_above_h_mbuv = !(hbl >= 3 /* 16x32 or >=32x32 */ && (tx_size >= TX_16X16 ||
      sb_mb_lf_skip(mode_info_context, mi)));
349
  lpf_mb(cm, mi, do_left_v, do_above_h,
Yaowu Xu's avatar
Yaowu Xu committed
350 351 352 353 354 355
      do_left_v_mbuv, do_above_h_mbuv,
      y_ptr + 16 * y_stride,
      y_only ? 0 : (u_ptr + 8 * uv_stride),
      y_only ? 0 : (v_ptr + 8 * uv_stride),
      y_stride, uv_stride, dering);

356
  // process 4th MB bottom right
357
  mi = mode_info_context + ((mis + 1) << CONFIG_SB8X8);
358
  do_left_v = !(wbl >= 3 /* 32x16 or >=32x32 */ && (tx_size >= TX_32X32 ||
359
      sb_mb_lf_skip(mi - (1 << CONFIG_SB8X8), mi)));
360
  do_above_h = !(hbl >= 3 /* 16x32 or >=32x32 */ && (tx_size >= TX_32X32 ||
361
      sb_mb_lf_skip(mode_info_context + (1 << CONFIG_SB8X8), mi)));
362
  do_left_v_mbuv = (wbl >= 3 /* 32x16 or >=32x32 */ && (tx_size >= TX_16X16 ||
363
      sb_mb_lf_skip(mi - (1 << CONFIG_SB8X8), mi)));
364
  do_above_h_mbuv = !(hbl >= 3 /* 16x32 or >=32x32 */ && (tx_size >= TX_16X16 ||
365
      sb_mb_lf_skip(mode_info_context + (1 << CONFIG_SB8X8), mi)));
366
  lpf_mb(cm, mi, do_left_v, do_above_h,
Yaowu Xu's avatar
Yaowu Xu committed
367 368 369 370 371 372 373 374 375 376 377 378
      do_left_v_mbuv, do_above_h_mbuv,
      y_ptr + 16 * y_stride + 16,
      y_only ? 0 : (u_ptr + 8 * uv_stride + 8),
      y_only ? 0 : (v_ptr + 8 * uv_stride + 8),
      y_stride, uv_stride, dering);
}

static void lpf_sb64(VP9_COMMON *cm, const MODE_INFO *mode_info_context,
                     int mb_row, int mb_col,
                     uint8_t *y_ptr, uint8_t *u_ptr, uint8_t *v_ptr,
                     int y_stride, int uv_stride,
                     int y_only, int dering) {
379
  lpf_sb32(cm, mode_info_context, mb_row, mb_col,
Yaowu Xu's avatar
Yaowu Xu committed
380 381
      y_ptr, u_ptr, v_ptr,
      y_stride, uv_stride, y_only, dering);
382
  lpf_sb32(cm, mode_info_context + (2 << CONFIG_SB8X8), mb_row, mb_col + 2,
Yaowu Xu's avatar
Yaowu Xu committed
383 384
      y_ptr + 32, u_ptr + 16, v_ptr + 16,
      y_stride, uv_stride, y_only, dering);
385
  lpf_sb32(cm, mode_info_context + cm->mode_info_stride * (2 << CONFIG_SB8X8),
Yaowu Xu's avatar
Yaowu Xu committed
386 387 388 389 390
      mb_row + 2, mb_col,
      y_ptr + 32 * y_stride,
      u_ptr + 16 * uv_stride,
      v_ptr + 16 * uv_stride,
      y_stride, uv_stride, y_only, dering);
391 392
  lpf_sb32(cm, mode_info_context + cm->mode_info_stride *
      (2 << CONFIG_SB8X8) + (2 << CONFIG_SB8X8),
Yaowu Xu's avatar
Yaowu Xu committed
393 394 395 396 397 398
      mb_row + 2, mb_col + 2,
      y_ptr + 32 * y_stride + 32,
      u_ptr + 16 * uv_stride + 16,
      v_ptr + 16 * uv_stride + 16,
      y_stride, uv_stride, y_only, dering);
}
399

400 401 402
void vp9_loop_filter_frame(VP9_COMMON *cm,
                           MACROBLOCKD *xd,
                           int frame_filter_level,
403 404
                           int y_only,
                           int dering) {
John Koleszar's avatar
John Koleszar committed
405
  YV12_BUFFER_CONFIG *post = cm->frame_to_show;
406
  int mb_row, mb_col;
Yaowu Xu's avatar
Yaowu Xu committed
407 408 409 410 411 412
  const int sb64_rows = cm->mb_rows / 4;
  const int sb64_cols = cm->mb_cols / 4;
  const int extra_sb32_row = (cm->mb_rows & 2) != 0;
  const int extra_sb32_col = (cm->mb_cols & 2) != 0;
  const int extra_mb_col = cm->mb_cols & 1;
  const int extra_mb_row = cm->mb_rows & 1;
413 414 415 416 417 418
  // 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
419
  const MODE_INFO *mode_info_context = cm->mi;
Yaowu Xu's avatar
Yaowu Xu committed
420
  const MODE_INFO *mi;
421
  const int mis = cm->mode_info_stride;
Yaowu Xu's avatar
Yaowu Xu committed
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
  const int y_stride = post->y_stride;
  const int uv_stride = post->uv_stride;
  // These two flags signal if MB left edge and above edge
  // should be filtered using MB edge filter. Currently, MB
  // edge filtering is not applied on MB edge internal to a
  // 32x32 superblock if:
  // 1) SB32 is using 32x32 prediction and 32x32 transform
  // 2) SB32 is using 32x32 prediction and 16x16 transform
  //    but all coefficients are zero.
  // MB edges are on 32x32 superblock boundary are always
  // filtered except on image frame boundary.
  int do_left_v, do_above_h;
  // These two flags signal if MB UV left edge and above edge
  // should be filtered using MB edge filter. Currently, MB
  // edge filtering is not applied for MB edges internal to
  // a 32x32 superblock if:
  // 1) SB32 is using 32x32 prediction and 32x32 transform
  // 2) SB32 is using 32x32 prediction and 16x16 transform
  //    but all coefficients are zero.
  // 3) SB32 UV edges internal to a SB64 and 32x32 transform
  //    is used, i.e. UV is doing 32x32 transform hence no
  //    transform boundary exists inside the SB64 for UV
  int do_left_v_mbuv, do_above_h_mbuv;
John Koleszar's avatar
John Koleszar committed
445

446
  // Initialize the loop filter for this frame.
447
  vp9_loop_filter_frame_init(cm, xd, frame_filter_level);
John Koleszar's avatar
John Koleszar committed
448

Yaowu Xu's avatar
Yaowu Xu committed
449 450 451 452 453 454 455 456 457 458 459 460 461
  // vp9_filter each 64x64 SB
  // For each SB64: the 4 SB32 are filtered in raster scan order
  // For each SB32: the 4 MBs are filtered in raster scan order
  // For each MB:   the left and above MB edges as well as the
  //                internal block edges are processed together
  for (mb_row = 0; mb_row < sb64_rows * 4; mb_row += 4) {
    for (mb_col = 0; mb_col < sb64_cols * 4; mb_col += 4) {
      lpf_sb64(cm, mode_info_context, mb_row, mb_col,
               y_ptr, u_ptr, v_ptr,
               y_stride, uv_stride, y_only, dering);
      y_ptr += 64;
      u_ptr = y_only? 0 : u_ptr + 32;
      v_ptr = y_only? 0 : v_ptr + 32;
462
      mode_info_context += 4 << CONFIG_SB8X8;       // step to next SB64
Yaowu Xu's avatar
Yaowu Xu committed
463 464 465 466 467 468
    }
    if (extra_sb32_col) {
      // process 2 SB32s in the extra SB32 col
      lpf_sb32(cm, mode_info_context, mb_row, mb_col,
               y_ptr, u_ptr, v_ptr,
               y_stride, uv_stride, y_only, dering);
469
      lpf_sb32(cm, mode_info_context + mis * (2 << CONFIG_SB8X8),
Yaowu Xu's avatar
Yaowu Xu committed
470 471 472 473 474 475 476 477
               mb_row + 2, mb_col,
               y_ptr + 32 * y_stride,
               u_ptr + 16 * uv_stride,
               v_ptr + 16 * uv_stride,
               y_stride, uv_stride, y_only, dering);
      y_ptr += 32;
      u_ptr = y_only? 0 : u_ptr + 16;
      v_ptr = y_only? 0 : v_ptr + 16;
478
      mode_info_context += 2 << CONFIG_SB8X8;       // step to next SB32
Yaowu Xu's avatar
Yaowu Xu committed
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
      mb_col += 2;
    }
    if (extra_mb_col) {
      // process 4 MB in the extra MB col
      // process 1st MB
      mi = mode_info_context;
      do_left_v = (mb_col > 0);
      do_above_h = (mb_row > 0);
      do_left_v_mbuv =  1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr,
             y_only? 0 : u_ptr,
             y_only? 0 : v_ptr,
             y_stride, uv_stride, dering);
      // process 2nd MB
496
      mi = mode_info_context + (mis << CONFIG_SB8X8);
Yaowu Xu's avatar
Yaowu Xu committed
497 498 499 500 501 502 503 504 505 506 507
      do_left_v = (mb_col > 0);
      do_above_h = 1;
      do_left_v_mbuv =  1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr + 16 * y_stride,
             y_only ? 0 : (u_ptr + 8 * uv_stride),
             y_only ? 0 : (v_ptr + 8 * uv_stride),
             y_stride, uv_stride, dering);
      // process 3nd MB
508
      mi = mode_info_context + (mis << CONFIG_SB8X8) * 2;
Yaowu Xu's avatar
Yaowu Xu committed
509 510 511 512 513 514 515 516 517 518 519
      do_left_v = (mb_col > 0);
      do_above_h = 1;
      do_left_v_mbuv =  1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr + 32 * y_stride,
             y_only ? 0 : (u_ptr + 16 * uv_stride),
             y_only ? 0 : (v_ptr + 16 * uv_stride),
             y_stride, uv_stride, dering);
      // process 4th MB
520
      mi = mode_info_context + (mis << CONFIG_SB8X8) * 3;
Yaowu Xu's avatar
Yaowu Xu committed
521 522 523 524 525 526 527 528 529 530
      do_left_v = (mb_col > 0);
      do_above_h = 1;
      do_left_v_mbuv =  1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr + 48 * y_stride,
             y_only ? 0 : (u_ptr + 24 * uv_stride),
             y_only ? 0 : (v_ptr + 24 * uv_stride),
             y_stride, uv_stride, dering);
John Koleszar's avatar
John Koleszar committed
531
      y_ptr += 16;
Yaowu Xu's avatar
Yaowu Xu committed
532 533
      u_ptr = y_only? 0 : u_ptr + 8;
      v_ptr = y_only? 0 : v_ptr + 8;
534
      mode_info_context += 1 << CONFIG_SB8X8;       // step to next MB
John Koleszar's avatar
John Koleszar committed
535
    }
Yaowu Xu's avatar
Yaowu Xu committed
536 537
    // move pointers to the begining of next sb64 row
    y_ptr += y_stride  * 64 - post->y_width;
538
    if (!y_only) {
Yaowu Xu's avatar
Yaowu Xu committed
539 540 541 542
      u_ptr += uv_stride *  32 - post->uv_width;
      v_ptr += uv_stride *  32 - post->uv_width;
    }
    /* skip to next SB64 row */
543
    mode_info_context += mis * (4 << CONFIG_SB8X8) - cm->mi_cols;
Yaowu Xu's avatar
Yaowu Xu committed
544 545 546 547 548 549 550 551 552 553
  }
  if (extra_sb32_row) {
    const int sb32_cols = sb64_cols * 2 + extra_sb32_col;
    for (mb_col = 0; mb_col < sb32_cols * 2; mb_col += 2) {
      lpf_sb32(cm, mode_info_context, mb_row, mb_col,
               y_ptr, u_ptr, v_ptr,
               y_stride, uv_stride, y_only, dering);
      y_ptr += 32;
      u_ptr = y_only? 0 : u_ptr + 16;
      v_ptr = y_only? 0 : v_ptr + 16;
554
      mode_info_context += 2 << CONFIG_SB8X8;       // step to next SB32
Yaowu Xu's avatar
Yaowu Xu committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
    }
    if (extra_mb_col) {
      // process 1st MB
      mi = mode_info_context;
      do_left_v = (mb_col > 0);
      do_above_h = (mb_row > 0);
      do_left_v_mbuv =  1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr,
             y_only? NULL : u_ptr,
             y_only? NULL : v_ptr,
             y_stride, uv_stride, dering);
      // process 2nd MB
570
      mi = mode_info_context + (mis << CONFIG_SB8X8);
Yaowu Xu's avatar
Yaowu Xu committed
571 572 573 574 575 576 577 578 579 580 581 582 583
      do_left_v = (mb_col > 0);
      do_above_h = 1;
      do_left_v_mbuv =  1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr + 16 * y_stride,
             y_only ? NULL : (u_ptr + 8 * uv_stride),
             y_only ? NULL : (v_ptr + 8 * uv_stride),
             y_stride, uv_stride, dering);
      y_ptr += 16;
      u_ptr = y_only? 0 : u_ptr + 8;
      v_ptr = y_only? 0 : v_ptr + 8;
584
      mode_info_context += 1 << CONFIG_SB8X8;       /* step to next MB */
Yaowu Xu's avatar
Yaowu Xu committed
585 586 587 588 589 590
    }
    // move pointers to the beginning of next sb64 row
    y_ptr += y_stride * 32 - post->y_width;
    u_ptr += y_only? 0 : uv_stride *  16 - post->uv_width;
    v_ptr += y_only? 0 : uv_stride *  16 - post->uv_width;
    // skip to next MB row if exist
591
    mode_info_context += mis * (2 << CONFIG_SB8X8) - cm->mi_cols;
Yaowu Xu's avatar
Yaowu Xu committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
    mb_row += 2;
  }
  if (extra_mb_row) {
    for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
      const MODE_INFO *mi = mode_info_context;
      do_left_v =  (mb_col > 0);
      do_above_h = (mb_row > 0);
      do_left_v_mbuv = 1;
      do_above_h_mbuv = 1;
      lpf_mb(cm, mi, do_left_v, do_above_h,
             do_left_v_mbuv, do_above_h_mbuv,
             y_ptr,
             y_only? 0 : u_ptr,
             y_only? 0 : v_ptr,
             y_stride, uv_stride, dering);
      y_ptr += 16;
      u_ptr = y_only? 0 : u_ptr + 8;
      v_ptr = y_only? 0 : v_ptr + 8;
610
      mode_info_context += 1 << CONFIG_SB8X8;     // step to next MB
611
    }
John Koleszar's avatar
John Koleszar committed
612
  }
John Koleszar's avatar
John Koleszar committed
613
}