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 "vpx_config.h"
12#include "vp8_rtcd.h"
13#include "loopfilter.h"
14#include "onyxc_int.h"
15#include "vpx_mem/vpx_mem.h"
16
17static void lf_init_lut(loop_filter_info_n *lfi) {
18  int filt_lvl;
19
20  for (filt_lvl = 0; filt_lvl <= MAX_LOOP_FILTER; ++filt_lvl) {
21    if (filt_lvl >= 40) {
22      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 2;
23      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 3;
24    } else if (filt_lvl >= 20) {
25      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
26      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 2;
27    } else if (filt_lvl >= 15) {
28      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 1;
29      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 1;
30    } else {
31      lfi->hev_thr_lut[KEY_FRAME][filt_lvl] = 0;
32      lfi->hev_thr_lut[INTER_FRAME][filt_lvl] = 0;
33    }
34  }
35
36  lfi->mode_lf_lut[DC_PRED] = 1;
37  lfi->mode_lf_lut[V_PRED] = 1;
38  lfi->mode_lf_lut[H_PRED] = 1;
39  lfi->mode_lf_lut[TM_PRED] = 1;
40  lfi->mode_lf_lut[B_PRED] = 0;
41
42  lfi->mode_lf_lut[ZEROMV] = 1;
43  lfi->mode_lf_lut[NEARESTMV] = 2;
44  lfi->mode_lf_lut[NEARMV] = 2;
45  lfi->mode_lf_lut[NEWMV] = 2;
46  lfi->mode_lf_lut[SPLITMV] = 3;
47}
48
49void vp8_loop_filter_update_sharpness(loop_filter_info_n *lfi,
50                                      int sharpness_lvl) {
51  int i;
52
53  /* For each possible value for the loop filter fill out limits */
54  for (i = 0; i <= MAX_LOOP_FILTER; ++i) {
55    int filt_lvl = i;
56    int block_inside_limit = 0;
57
58    /* Set loop filter paramaeters that control sharpness. */
59    block_inside_limit = filt_lvl >> (sharpness_lvl > 0);
60    block_inside_limit = block_inside_limit >> (sharpness_lvl > 4);
61
62    if (sharpness_lvl > 0) {
63      if (block_inside_limit > (9 - sharpness_lvl)) {
64        block_inside_limit = (9 - sharpness_lvl);
65      }
66    }
67
68    if (block_inside_limit < 1) block_inside_limit = 1;
69
70    memset(lfi->lim[i], block_inside_limit, SIMD_WIDTH);
71    memset(lfi->blim[i], (2 * filt_lvl + block_inside_limit), SIMD_WIDTH);
72    memset(lfi->mblim[i], (2 * (filt_lvl + 2) + block_inside_limit),
73           SIMD_WIDTH);
74  }
75}
76
77void vp8_loop_filter_init(VP8_COMMON *cm) {
78  loop_filter_info_n *lfi = &cm->lf_info;
79  int i;
80
81  /* init limits for given sharpness*/
82  vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level);
83  cm->last_sharpness_level = cm->sharpness_level;
84
85  /* init LUT for lvl  and hev thr picking */
86  lf_init_lut(lfi);
87
88  /* init hev threshold const vectors */
89  for (i = 0; i < 4; ++i) {
90    memset(lfi->hev_thr[i], i, SIMD_WIDTH);
91  }
92}
93
94void vp8_loop_filter_frame_init(VP8_COMMON *cm, MACROBLOCKD *mbd,
95                                int default_filt_lvl) {
96  int seg,  /* segment number */
97      ref,  /* index in ref_lf_deltas */
98      mode; /* index in mode_lf_deltas */
99
100  loop_filter_info_n *lfi = &cm->lf_info;
101
102  /* update limits if sharpness has changed */
103  if (cm->last_sharpness_level != cm->sharpness_level) {
104    vp8_loop_filter_update_sharpness(lfi, cm->sharpness_level);
105    cm->last_sharpness_level = cm->sharpness_level;
106  }
107
108  for (seg = 0; seg < MAX_MB_SEGMENTS; ++seg) {
109    int lvl_seg = default_filt_lvl;
110    int lvl_ref, lvl_mode;
111
112    /* Note the baseline filter values for each segment */
113    if (mbd->segmentation_enabled) {
114      /* Abs value */
115      if (mbd->mb_segement_abs_delta == SEGMENT_ABSDATA) {
116        lvl_seg = mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
117      } else /* Delta Value */
118      {
119        lvl_seg += mbd->segment_feature_data[MB_LVL_ALT_LF][seg];
120      }
121      lvl_seg = (lvl_seg > 0) ? ((lvl_seg > 63) ? 63 : lvl_seg) : 0;
122    }
123
124    if (!mbd->mode_ref_lf_delta_enabled) {
125      /* we could get rid of this if we assume that deltas are set to
126       * zero when not in use; encoder always uses deltas
127       */
128      memset(lfi->lvl[seg][0], lvl_seg, 4 * 4);
129      continue;
130    }
131
132    /* INTRA_FRAME */
133    ref = INTRA_FRAME;
134
135    /* Apply delta for reference frame */
136    lvl_ref = lvl_seg + mbd->ref_lf_deltas[ref];
137
138    /* Apply delta for Intra modes */
139    mode = 0; /* B_PRED */
140    /* Only the split mode BPRED has a further special case */
141    lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
142    /* clamp */
143    lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0;
144
145    lfi->lvl[seg][ref][mode] = lvl_mode;
146
147    mode = 1; /* all the rest of Intra modes */
148    /* clamp */
149    lvl_mode = (lvl_ref > 0) ? (lvl_ref > 63 ? 63 : lvl_ref) : 0;
150    lfi->lvl[seg][ref][mode] = lvl_mode;
151
152    /* LAST, GOLDEN, ALT */
153    for (ref = 1; ref < MAX_REF_FRAMES; ++ref) {
154      /* Apply delta for reference frame */
155      lvl_ref = lvl_seg + mbd->ref_lf_deltas[ref];
156
157      /* Apply delta for Inter modes */
158      for (mode = 1; mode < 4; ++mode) {
159        lvl_mode = lvl_ref + mbd->mode_lf_deltas[mode];
160        /* clamp */
161        lvl_mode = (lvl_mode > 0) ? (lvl_mode > 63 ? 63 : lvl_mode) : 0;
162
163        lfi->lvl[seg][ref][mode] = lvl_mode;
164      }
165    }
166  }
167}
168
169void vp8_loop_filter_row_normal(VP8_COMMON *cm, MODE_INFO *mode_info_context,
170                                int mb_row, int post_ystride, int post_uvstride,
171                                unsigned char *y_ptr, unsigned char *u_ptr,
172                                unsigned char *v_ptr) {
173  int mb_col;
174  int filter_level;
175  loop_filter_info_n *lfi_n = &cm->lf_info;
176  loop_filter_info lfi;
177  FRAME_TYPE frame_type = cm->frame_type;
178
179  for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
180    int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
181                   mode_info_context->mbmi.mode != SPLITMV &&
182                   mode_info_context->mbmi.mb_skip_coeff);
183
184    const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
185    const int seg = mode_info_context->mbmi.segment_id;
186    const int ref_frame = mode_info_context->mbmi.ref_frame;
187
188    filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
189
190    if (filter_level) {
191      const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
192      lfi.mblim = lfi_n->mblim[filter_level];
193      lfi.blim = lfi_n->blim[filter_level];
194      lfi.lim = lfi_n->lim[filter_level];
195      lfi.hev_thr = lfi_n->hev_thr[hev_index];
196
197      if (mb_col > 0)
198        vp8_loop_filter_mbv(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride,
199                            &lfi);
200
201      if (!skip_lf)
202        vp8_loop_filter_bv(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride,
203                           &lfi);
204
205      /* don't apply across umv border */
206      if (mb_row > 0)
207        vp8_loop_filter_mbh(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride,
208                            &lfi);
209
210      if (!skip_lf)
211        vp8_loop_filter_bh(y_ptr, u_ptr, v_ptr, post_ystride, post_uvstride,
212                           &lfi);
213    }
214
215    y_ptr += 16;
216    u_ptr += 8;
217    v_ptr += 8;
218
219    mode_info_context++; /* step to next MB */
220  }
221}
222
223void vp8_loop_filter_row_simple(VP8_COMMON *cm, MODE_INFO *mode_info_context,
224                                int mb_row, int post_ystride, int post_uvstride,
225                                unsigned char *y_ptr, unsigned char *u_ptr,
226                                unsigned char *v_ptr) {
227  int mb_col;
228  int filter_level;
229  loop_filter_info_n *lfi_n = &cm->lf_info;
230  (void)post_uvstride;
231
232  for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
233    int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
234                   mode_info_context->mbmi.mode != SPLITMV &&
235                   mode_info_context->mbmi.mb_skip_coeff);
236
237    const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
238    const int seg = mode_info_context->mbmi.segment_id;
239    const int ref_frame = mode_info_context->mbmi.ref_frame;
240
241    filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
242
243    if (filter_level) {
244      if (mb_col > 0)
245        vp8_loop_filter_simple_mbv(y_ptr, post_ystride,
246                                   lfi_n->mblim[filter_level]);
247
248      if (!skip_lf)
249        vp8_loop_filter_simple_bv(y_ptr, post_ystride,
250                                  lfi_n->blim[filter_level]);
251
252      /* don't apply across umv border */
253      if (mb_row > 0)
254        vp8_loop_filter_simple_mbh(y_ptr, post_ystride,
255                                   lfi_n->mblim[filter_level]);
256
257      if (!skip_lf)
258        vp8_loop_filter_simple_bh(y_ptr, post_ystride,
259                                  lfi_n->blim[filter_level]);
260    }
261
262    y_ptr += 16;
263    u_ptr += 8;
264    v_ptr += 8;
265
266    mode_info_context++; /* step to next MB */
267  }
268}
269void vp8_loop_filter_frame(VP8_COMMON *cm, MACROBLOCKD *mbd, int frame_type) {
270  YV12_BUFFER_CONFIG *post = cm->frame_to_show;
271  loop_filter_info_n *lfi_n = &cm->lf_info;
272  loop_filter_info lfi;
273
274  int mb_row;
275  int mb_col;
276  int mb_rows = cm->mb_rows;
277  int mb_cols = cm->mb_cols;
278
279  int filter_level;
280
281  unsigned char *y_ptr, *u_ptr, *v_ptr;
282
283  /* Point at base of Mb MODE_INFO list */
284  const MODE_INFO *mode_info_context = cm->mi;
285  int post_y_stride = post->y_stride;
286  int post_uv_stride = post->uv_stride;
287
288  /* Initialize the loop filter for this frame. */
289  vp8_loop_filter_frame_init(cm, mbd, cm->filter_level);
290
291  /* Set up the buffer pointers */
292  y_ptr = post->y_buffer;
293  u_ptr = post->u_buffer;
294  v_ptr = post->v_buffer;
295
296  /* vp8_filter each macro block */
297  if (cm->filter_type == NORMAL_LOOPFILTER) {
298    for (mb_row = 0; mb_row < mb_rows; ++mb_row) {
299      for (mb_col = 0; mb_col < mb_cols; ++mb_col) {
300        int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
301                       mode_info_context->mbmi.mode != SPLITMV &&
302                       mode_info_context->mbmi.mb_skip_coeff);
303
304        const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
305        const int seg = mode_info_context->mbmi.segment_id;
306        const int ref_frame = mode_info_context->mbmi.ref_frame;
307
308        filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
309
310        if (filter_level) {
311          const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
312          lfi.mblim = lfi_n->mblim[filter_level];
313          lfi.blim = lfi_n->blim[filter_level];
314          lfi.lim = lfi_n->lim[filter_level];
315          lfi.hev_thr = lfi_n->hev_thr[hev_index];
316
317          if (mb_col > 0)
318            vp8_loop_filter_mbv(y_ptr, u_ptr, v_ptr, post_y_stride,
319                                post_uv_stride, &lfi);
320
321          if (!skip_lf)
322            vp8_loop_filter_bv(y_ptr, u_ptr, v_ptr, post_y_stride,
323                               post_uv_stride, &lfi);
324
325          /* don't apply across umv border */
326          if (mb_row > 0)
327            vp8_loop_filter_mbh(y_ptr, u_ptr, v_ptr, post_y_stride,
328                                post_uv_stride, &lfi);
329
330          if (!skip_lf)
331            vp8_loop_filter_bh(y_ptr, u_ptr, v_ptr, post_y_stride,
332                               post_uv_stride, &lfi);
333        }
334
335        y_ptr += 16;
336        u_ptr += 8;
337        v_ptr += 8;
338
339        mode_info_context++; /* step to next MB */
340      }
341      y_ptr += post_y_stride * 16 - post->y_width;
342      u_ptr += post_uv_stride * 8 - post->uv_width;
343      v_ptr += post_uv_stride * 8 - post->uv_width;
344
345      mode_info_context++; /* Skip border mb */
346    }
347  } else /* SIMPLE_LOOPFILTER */
348  {
349    for (mb_row = 0; mb_row < mb_rows; ++mb_row) {
350      for (mb_col = 0; mb_col < mb_cols; ++mb_col) {
351        int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
352                       mode_info_context->mbmi.mode != SPLITMV &&
353                       mode_info_context->mbmi.mb_skip_coeff);
354
355        const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
356        const int seg = mode_info_context->mbmi.segment_id;
357        const int ref_frame = mode_info_context->mbmi.ref_frame;
358
359        filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
360        if (filter_level) {
361          const unsigned char *mblim = lfi_n->mblim[filter_level];
362          const unsigned char *blim = lfi_n->blim[filter_level];
363
364          if (mb_col > 0)
365            vp8_loop_filter_simple_mbv(y_ptr, post_y_stride, mblim);
366
367          if (!skip_lf) vp8_loop_filter_simple_bv(y_ptr, post_y_stride, blim);
368
369          /* don't apply across umv border */
370          if (mb_row > 0)
371            vp8_loop_filter_simple_mbh(y_ptr, post_y_stride, mblim);
372
373          if (!skip_lf) vp8_loop_filter_simple_bh(y_ptr, post_y_stride, blim);
374        }
375
376        y_ptr += 16;
377        u_ptr += 8;
378        v_ptr += 8;
379
380        mode_info_context++; /* step to next MB */
381      }
382      y_ptr += post_y_stride * 16 - post->y_width;
383      u_ptr += post_uv_stride * 8 - post->uv_width;
384      v_ptr += post_uv_stride * 8 - post->uv_width;
385
386      mode_info_context++; /* Skip border mb */
387    }
388  }
389}
390
391void vp8_loop_filter_frame_yonly(VP8_COMMON *cm, MACROBLOCKD *mbd,
392                                 int default_filt_lvl) {
393  YV12_BUFFER_CONFIG *post = cm->frame_to_show;
394
395  unsigned char *y_ptr;
396  int mb_row;
397  int mb_col;
398
399  loop_filter_info_n *lfi_n = &cm->lf_info;
400  loop_filter_info lfi;
401
402  int filter_level;
403  FRAME_TYPE frame_type = cm->frame_type;
404
405  /* Point at base of Mb MODE_INFO list */
406  const MODE_INFO *mode_info_context = cm->mi;
407
408#if 0
409    if(default_filt_lvl == 0) /* no filter applied */
410        return;
411#endif
412
413  /* Initialize the loop filter for this frame. */
414  vp8_loop_filter_frame_init(cm, mbd, default_filt_lvl);
415
416  /* Set up the buffer pointers */
417  y_ptr = post->y_buffer;
418
419  /* vp8_filter each macro block */
420  for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
421    for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
422      int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
423                     mode_info_context->mbmi.mode != SPLITMV &&
424                     mode_info_context->mbmi.mb_skip_coeff);
425
426      const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
427      const int seg = mode_info_context->mbmi.segment_id;
428      const int ref_frame = mode_info_context->mbmi.ref_frame;
429
430      filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
431
432      if (filter_level) {
433        if (cm->filter_type == NORMAL_LOOPFILTER) {
434          const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
435          lfi.mblim = lfi_n->mblim[filter_level];
436          lfi.blim = lfi_n->blim[filter_level];
437          lfi.lim = lfi_n->lim[filter_level];
438          lfi.hev_thr = lfi_n->hev_thr[hev_index];
439
440          if (mb_col > 0)
441            vp8_loop_filter_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi);
442
443          if (!skip_lf)
444            vp8_loop_filter_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi);
445
446          /* don't apply across umv border */
447          if (mb_row > 0)
448            vp8_loop_filter_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi);
449
450          if (!skip_lf)
451            vp8_loop_filter_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi);
452        } else {
453          if (mb_col > 0)
454            vp8_loop_filter_simple_mbv(y_ptr, post->y_stride,
455                                       lfi_n->mblim[filter_level]);
456
457          if (!skip_lf)
458            vp8_loop_filter_simple_bv(y_ptr, post->y_stride,
459                                      lfi_n->blim[filter_level]);
460
461          /* don't apply across umv border */
462          if (mb_row > 0)
463            vp8_loop_filter_simple_mbh(y_ptr, post->y_stride,
464                                       lfi_n->mblim[filter_level]);
465
466          if (!skip_lf)
467            vp8_loop_filter_simple_bh(y_ptr, post->y_stride,
468                                      lfi_n->blim[filter_level]);
469        }
470      }
471
472      y_ptr += 16;
473      mode_info_context++; /* step to next MB */
474    }
475
476    y_ptr += post->y_stride * 16 - post->y_width;
477    mode_info_context++; /* Skip border mb */
478  }
479}
480
481void vp8_loop_filter_partial_frame(VP8_COMMON *cm, MACROBLOCKD *mbd,
482                                   int default_filt_lvl) {
483  YV12_BUFFER_CONFIG *post = cm->frame_to_show;
484
485  unsigned char *y_ptr;
486  int mb_row;
487  int mb_col;
488  int mb_cols = post->y_width >> 4;
489  int mb_rows = post->y_height >> 4;
490
491  int linestocopy;
492
493  loop_filter_info_n *lfi_n = &cm->lf_info;
494  loop_filter_info lfi;
495
496  int filter_level;
497  FRAME_TYPE frame_type = cm->frame_type;
498
499  const MODE_INFO *mode_info_context;
500
501#if 0
502    if(default_filt_lvl == 0) /* no filter applied */
503        return;
504#endif
505
506  /* Initialize the loop filter for this frame. */
507  vp8_loop_filter_frame_init(cm, mbd, default_filt_lvl);
508
509  /* number of MB rows to use in partial filtering */
510  linestocopy = mb_rows / PARTIAL_FRAME_FRACTION;
511  linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
512
513  /* Set up the buffer pointers; partial image starts at ~middle of frame */
514  y_ptr = post->y_buffer + ((post->y_height >> 5) * 16) * post->y_stride;
515  mode_info_context = cm->mi + (post->y_height >> 5) * (mb_cols + 1);
516
517  /* vp8_filter each macro block */
518  for (mb_row = 0; mb_row < (linestocopy >> 4); ++mb_row) {
519    for (mb_col = 0; mb_col < mb_cols; ++mb_col) {
520      int skip_lf = (mode_info_context->mbmi.mode != B_PRED &&
521                     mode_info_context->mbmi.mode != SPLITMV &&
522                     mode_info_context->mbmi.mb_skip_coeff);
523
524      const int mode_index = lfi_n->mode_lf_lut[mode_info_context->mbmi.mode];
525      const int seg = mode_info_context->mbmi.segment_id;
526      const int ref_frame = mode_info_context->mbmi.ref_frame;
527
528      filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
529
530      if (filter_level) {
531        if (cm->filter_type == NORMAL_LOOPFILTER) {
532          const int hev_index = lfi_n->hev_thr_lut[frame_type][filter_level];
533          lfi.mblim = lfi_n->mblim[filter_level];
534          lfi.blim = lfi_n->blim[filter_level];
535          lfi.lim = lfi_n->lim[filter_level];
536          lfi.hev_thr = lfi_n->hev_thr[hev_index];
537
538          if (mb_col > 0)
539            vp8_loop_filter_mbv(y_ptr, 0, 0, post->y_stride, 0, &lfi);
540
541          if (!skip_lf)
542            vp8_loop_filter_bv(y_ptr, 0, 0, post->y_stride, 0, &lfi);
543
544          vp8_loop_filter_mbh(y_ptr, 0, 0, post->y_stride, 0, &lfi);
545
546          if (!skip_lf)
547            vp8_loop_filter_bh(y_ptr, 0, 0, post->y_stride, 0, &lfi);
548        } else {
549          if (mb_col > 0)
550            vp8_loop_filter_simple_mbv(y_ptr, post->y_stride,
551                                       lfi_n->mblim[filter_level]);
552
553          if (!skip_lf)
554            vp8_loop_filter_simple_bv(y_ptr, post->y_stride,
555                                      lfi_n->blim[filter_level]);
556
557          vp8_loop_filter_simple_mbh(y_ptr, post->y_stride,
558                                     lfi_n->mblim[filter_level]);
559
560          if (!skip_lf)
561            vp8_loop_filter_simple_bh(y_ptr, post->y_stride,
562                                      lfi_n->blim[filter_level]);
563        }
564      }
565
566      y_ptr += 16;
567      mode_info_context += 1; /* step to next MB */
568    }
569
570    y_ptr += post->y_stride * 16 - post->y_width;
571    mode_info_context += 1; /* Skip border mb */
572  }
573}
574