LCOV - code coverage report
Current view: top level - media/libvpx/libvpx/vp8/common - loopfilter_filters.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 205 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <stdlib.h>
      12             : #include "loopfilter.h"
      13             : #include "onyxc_int.h"
      14             : 
      15             : typedef unsigned char uc;
      16             : 
      17           0 : static signed char vp8_signed_char_clamp(int t) {
      18           0 :   t = (t < -128 ? -128 : t);
      19           0 :   t = (t > 127 ? 127 : t);
      20           0 :   return (signed char)t;
      21             : }
      22             : 
      23             : /* should we apply any filter at all ( 11111111 yes, 00000000 no) */
      24           0 : static signed char vp8_filter_mask(uc limit, uc blimit, uc p3, uc p2, uc p1,
      25             :                                    uc p0, uc q0, uc q1, uc q2, uc q3) {
      26           0 :   signed char mask = 0;
      27           0 :   mask |= (abs(p3 - p2) > limit);
      28           0 :   mask |= (abs(p2 - p1) > limit);
      29           0 :   mask |= (abs(p1 - p0) > limit);
      30           0 :   mask |= (abs(q1 - q0) > limit);
      31           0 :   mask |= (abs(q2 - q1) > limit);
      32           0 :   mask |= (abs(q3 - q2) > limit);
      33           0 :   mask |= (abs(p0 - q0) * 2 + abs(p1 - q1) / 2 > blimit);
      34           0 :   return mask - 1;
      35             : }
      36             : 
      37             : /* is there high variance internal edge ( 11111111 yes, 00000000 no) */
      38           0 : static signed char vp8_hevmask(uc thresh, uc p1, uc p0, uc q0, uc q1) {
      39           0 :   signed char hev = 0;
      40           0 :   hev |= (abs(p1 - p0) > thresh) * -1;
      41           0 :   hev |= (abs(q1 - q0) > thresh) * -1;
      42           0 :   return hev;
      43             : }
      44             : 
      45           0 : static void vp8_filter(signed char mask, uc hev, uc *op1, uc *op0, uc *oq0,
      46             :                        uc *oq1) {
      47             :   signed char ps0, qs0;
      48             :   signed char ps1, qs1;
      49             :   signed char filter_value, Filter1, Filter2;
      50             :   signed char u;
      51             : 
      52           0 :   ps1 = (signed char)*op1 ^ 0x80;
      53           0 :   ps0 = (signed char)*op0 ^ 0x80;
      54           0 :   qs0 = (signed char)*oq0 ^ 0x80;
      55           0 :   qs1 = (signed char)*oq1 ^ 0x80;
      56             : 
      57             :   /* add outer taps if we have high edge variance */
      58           0 :   filter_value = vp8_signed_char_clamp(ps1 - qs1);
      59           0 :   filter_value &= hev;
      60             : 
      61             :   /* inner taps */
      62           0 :   filter_value = vp8_signed_char_clamp(filter_value + 3 * (qs0 - ps0));
      63           0 :   filter_value &= mask;
      64             : 
      65             :   /* save bottom 3 bits so that we round one side +4 and the other +3
      66             :    * if it equals 4 we'll set it to adjust by -1 to account for the fact
      67             :    * we'd round it by 3 the other way
      68             :    */
      69           0 :   Filter1 = vp8_signed_char_clamp(filter_value + 4);
      70           0 :   Filter2 = vp8_signed_char_clamp(filter_value + 3);
      71           0 :   Filter1 >>= 3;
      72           0 :   Filter2 >>= 3;
      73           0 :   u = vp8_signed_char_clamp(qs0 - Filter1);
      74           0 :   *oq0 = u ^ 0x80;
      75           0 :   u = vp8_signed_char_clamp(ps0 + Filter2);
      76           0 :   *op0 = u ^ 0x80;
      77           0 :   filter_value = Filter1;
      78             : 
      79             :   /* outer tap adjustments */
      80           0 :   filter_value += 1;
      81           0 :   filter_value >>= 1;
      82           0 :   filter_value &= ~hev;
      83             : 
      84           0 :   u = vp8_signed_char_clamp(qs1 - filter_value);
      85           0 :   *oq1 = u ^ 0x80;
      86           0 :   u = vp8_signed_char_clamp(ps1 + filter_value);
      87           0 :   *op1 = u ^ 0x80;
      88           0 : }
      89           0 : void vp8_loop_filter_horizontal_edge_c(unsigned char *s, int p, /* pitch */
      90             :                                        const unsigned char *blimit,
      91             :                                        const unsigned char *limit,
      92             :                                        const unsigned char *thresh, int count) {
      93           0 :   int hev = 0; /* high edge variance */
      94           0 :   signed char mask = 0;
      95           0 :   int i = 0;
      96             : 
      97             :   /* loop filter designed to work using chars so that we can make maximum use
      98             :    * of 8 bit simd instructions.
      99             :    */
     100             :   do {
     101           0 :     mask = vp8_filter_mask(limit[0], blimit[0], s[-4 * p], s[-3 * p], s[-2 * p],
     102           0 :                            s[-1 * p], s[0 * p], s[1 * p], s[2 * p], s[3 * p]);
     103             : 
     104           0 :     hev = vp8_hevmask(thresh[0], s[-2 * p], s[-1 * p], s[0 * p], s[1 * p]);
     105             : 
     106           0 :     vp8_filter(mask, hev, s - 2 * p, s - 1 * p, s, s + 1 * p);
     107             : 
     108           0 :     ++s;
     109           0 :   } while (++i < count * 8);
     110           0 : }
     111             : 
     112           0 : void vp8_loop_filter_vertical_edge_c(unsigned char *s, int p,
     113             :                                      const unsigned char *blimit,
     114             :                                      const unsigned char *limit,
     115             :                                      const unsigned char *thresh, int count) {
     116           0 :   int hev = 0; /* high edge variance */
     117           0 :   signed char mask = 0;
     118           0 :   int i = 0;
     119             : 
     120             :   /* loop filter designed to work using chars so that we can make maximum use
     121             :    * of 8 bit simd instructions.
     122             :    */
     123             :   do {
     124           0 :     mask = vp8_filter_mask(limit[0], blimit[0], s[-4], s[-3], s[-2], s[-1],
     125           0 :                            s[0], s[1], s[2], s[3]);
     126             : 
     127           0 :     hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
     128             : 
     129           0 :     vp8_filter(mask, hev, s - 2, s - 1, s, s + 1);
     130             : 
     131           0 :     s += p;
     132           0 :   } while (++i < count * 8);
     133           0 : }
     134             : 
     135           0 : static void vp8_mbfilter(signed char mask, uc hev, uc *op2, uc *op1, uc *op0,
     136             :                          uc *oq0, uc *oq1, uc *oq2) {
     137             :   signed char s, u;
     138             :   signed char filter_value, Filter1, Filter2;
     139           0 :   signed char ps2 = (signed char)*op2 ^ 0x80;
     140           0 :   signed char ps1 = (signed char)*op1 ^ 0x80;
     141           0 :   signed char ps0 = (signed char)*op0 ^ 0x80;
     142           0 :   signed char qs0 = (signed char)*oq0 ^ 0x80;
     143           0 :   signed char qs1 = (signed char)*oq1 ^ 0x80;
     144           0 :   signed char qs2 = (signed char)*oq2 ^ 0x80;
     145             : 
     146             :   /* add outer taps if we have high edge variance */
     147           0 :   filter_value = vp8_signed_char_clamp(ps1 - qs1);
     148           0 :   filter_value = vp8_signed_char_clamp(filter_value + 3 * (qs0 - ps0));
     149           0 :   filter_value &= mask;
     150             : 
     151           0 :   Filter2 = filter_value;
     152           0 :   Filter2 &= hev;
     153             : 
     154             :   /* save bottom 3 bits so that we round one side +4 and the other +3 */
     155           0 :   Filter1 = vp8_signed_char_clamp(Filter2 + 4);
     156           0 :   Filter2 = vp8_signed_char_clamp(Filter2 + 3);
     157           0 :   Filter1 >>= 3;
     158           0 :   Filter2 >>= 3;
     159           0 :   qs0 = vp8_signed_char_clamp(qs0 - Filter1);
     160           0 :   ps0 = vp8_signed_char_clamp(ps0 + Filter2);
     161             : 
     162             :   /* only apply wider filter if not high edge variance */
     163           0 :   filter_value &= ~hev;
     164           0 :   Filter2 = filter_value;
     165             : 
     166             :   /* roughly 3/7th difference across boundary */
     167           0 :   u = vp8_signed_char_clamp((63 + Filter2 * 27) >> 7);
     168           0 :   s = vp8_signed_char_clamp(qs0 - u);
     169           0 :   *oq0 = s ^ 0x80;
     170           0 :   s = vp8_signed_char_clamp(ps0 + u);
     171           0 :   *op0 = s ^ 0x80;
     172             : 
     173             :   /* roughly 2/7th difference across boundary */
     174           0 :   u = vp8_signed_char_clamp((63 + Filter2 * 18) >> 7);
     175           0 :   s = vp8_signed_char_clamp(qs1 - u);
     176           0 :   *oq1 = s ^ 0x80;
     177           0 :   s = vp8_signed_char_clamp(ps1 + u);
     178           0 :   *op1 = s ^ 0x80;
     179             : 
     180             :   /* roughly 1/7th difference across boundary */
     181           0 :   u = vp8_signed_char_clamp((63 + Filter2 * 9) >> 7);
     182           0 :   s = vp8_signed_char_clamp(qs2 - u);
     183           0 :   *oq2 = s ^ 0x80;
     184           0 :   s = vp8_signed_char_clamp(ps2 + u);
     185           0 :   *op2 = s ^ 0x80;
     186           0 : }
     187             : 
     188           0 : void vp8_mbloop_filter_horizontal_edge_c(unsigned char *s, int p,
     189             :                                          const unsigned char *blimit,
     190             :                                          const unsigned char *limit,
     191             :                                          const unsigned char *thresh,
     192             :                                          int count) {
     193           0 :   signed char hev = 0; /* high edge variance */
     194           0 :   signed char mask = 0;
     195           0 :   int i = 0;
     196             : 
     197             :   /* loop filter designed to work using chars so that we can make maximum use
     198             :    * of 8 bit simd instructions.
     199             :    */
     200             :   do {
     201           0 :     mask = vp8_filter_mask(limit[0], blimit[0], s[-4 * p], s[-3 * p], s[-2 * p],
     202           0 :                            s[-1 * p], s[0 * p], s[1 * p], s[2 * p], s[3 * p]);
     203             : 
     204           0 :     hev = vp8_hevmask(thresh[0], s[-2 * p], s[-1 * p], s[0 * p], s[1 * p]);
     205             : 
     206           0 :     vp8_mbfilter(mask, hev, s - 3 * p, s - 2 * p, s - 1 * p, s, s + 1 * p,
     207           0 :                  s + 2 * p);
     208             : 
     209           0 :     ++s;
     210           0 :   } while (++i < count * 8);
     211           0 : }
     212             : 
     213           0 : void vp8_mbloop_filter_vertical_edge_c(unsigned char *s, int p,
     214             :                                        const unsigned char *blimit,
     215             :                                        const unsigned char *limit,
     216             :                                        const unsigned char *thresh, int count) {
     217           0 :   signed char hev = 0; /* high edge variance */
     218           0 :   signed char mask = 0;
     219           0 :   int i = 0;
     220             : 
     221             :   do {
     222           0 :     mask = vp8_filter_mask(limit[0], blimit[0], s[-4], s[-3], s[-2], s[-1],
     223           0 :                            s[0], s[1], s[2], s[3]);
     224             : 
     225           0 :     hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
     226             : 
     227           0 :     vp8_mbfilter(mask, hev, s - 3, s - 2, s - 1, s, s + 1, s + 2);
     228             : 
     229           0 :     s += p;
     230           0 :   } while (++i < count * 8);
     231           0 : }
     232             : 
     233             : /* should we apply any filter at all ( 11111111 yes, 00000000 no) */
     234           0 : static signed char vp8_simple_filter_mask(uc blimit, uc p1, uc p0, uc q0,
     235             :                                           uc q1) {
     236             :   /* Why does this cause problems for win32?
     237             :    * error C2143: syntax error : missing ';' before 'type'
     238             :    *  (void) limit;
     239             :    */
     240           0 :   signed char mask = (abs(p0 - q0) * 2 + abs(p1 - q1) / 2 <= blimit) * -1;
     241           0 :   return mask;
     242             : }
     243             : 
     244           0 : static void vp8_simple_filter(signed char mask, uc *op1, uc *op0, uc *oq0,
     245             :                               uc *oq1) {
     246             :   signed char filter_value, Filter1, Filter2;
     247           0 :   signed char p1 = (signed char)*op1 ^ 0x80;
     248           0 :   signed char p0 = (signed char)*op0 ^ 0x80;
     249           0 :   signed char q0 = (signed char)*oq0 ^ 0x80;
     250           0 :   signed char q1 = (signed char)*oq1 ^ 0x80;
     251             :   signed char u;
     252             : 
     253           0 :   filter_value = vp8_signed_char_clamp(p1 - q1);
     254           0 :   filter_value = vp8_signed_char_clamp(filter_value + 3 * (q0 - p0));
     255           0 :   filter_value &= mask;
     256             : 
     257             :   /* save bottom 3 bits so that we round one side +4 and the other +3 */
     258           0 :   Filter1 = vp8_signed_char_clamp(filter_value + 4);
     259           0 :   Filter1 >>= 3;
     260           0 :   u = vp8_signed_char_clamp(q0 - Filter1);
     261           0 :   *oq0 = u ^ 0x80;
     262             : 
     263           0 :   Filter2 = vp8_signed_char_clamp(filter_value + 3);
     264           0 :   Filter2 >>= 3;
     265           0 :   u = vp8_signed_char_clamp(p0 + Filter2);
     266           0 :   *op0 = u ^ 0x80;
     267           0 : }
     268             : 
     269           0 : void vp8_loop_filter_simple_horizontal_edge_c(unsigned char *s, int p,
     270             :                                               const unsigned char *blimit) {
     271           0 :   signed char mask = 0;
     272           0 :   int i = 0;
     273             : 
     274             :   do {
     275           0 :     mask = vp8_simple_filter_mask(blimit[0], s[-2 * p], s[-1 * p], s[0 * p],
     276           0 :                                   s[1 * p]);
     277           0 :     vp8_simple_filter(mask, s - 2 * p, s - 1 * p, s, s + 1 * p);
     278           0 :     ++s;
     279           0 :   } while (++i < 16);
     280           0 : }
     281             : 
     282           0 : void vp8_loop_filter_simple_vertical_edge_c(unsigned char *s, int p,
     283             :                                             const unsigned char *blimit) {
     284           0 :   signed char mask = 0;
     285           0 :   int i = 0;
     286             : 
     287             :   do {
     288           0 :     mask = vp8_simple_filter_mask(blimit[0], s[-2], s[-1], s[0], s[1]);
     289           0 :     vp8_simple_filter(mask, s - 2, s - 1, s, s + 1);
     290           0 :     s += p;
     291           0 :   } while (++i < 16);
     292           0 : }
     293             : 
     294             : /* Horizontal MB filtering */
     295           0 : void vp8_loop_filter_mbh_c(unsigned char *y_ptr, unsigned char *u_ptr,
     296             :                            unsigned char *v_ptr, int y_stride, int uv_stride,
     297             :                            loop_filter_info *lfi) {
     298           0 :   vp8_mbloop_filter_horizontal_edge_c(y_ptr, y_stride, lfi->mblim, lfi->lim,
     299             :                                       lfi->hev_thr, 2);
     300             : 
     301           0 :   if (u_ptr) {
     302           0 :     vp8_mbloop_filter_horizontal_edge_c(u_ptr, uv_stride, lfi->mblim, lfi->lim,
     303             :                                         lfi->hev_thr, 1);
     304             :   }
     305             : 
     306           0 :   if (v_ptr) {
     307           0 :     vp8_mbloop_filter_horizontal_edge_c(v_ptr, uv_stride, lfi->mblim, lfi->lim,
     308             :                                         lfi->hev_thr, 1);
     309             :   }
     310           0 : }
     311             : 
     312             : /* Vertical MB Filtering */
     313           0 : void vp8_loop_filter_mbv_c(unsigned char *y_ptr, unsigned char *u_ptr,
     314             :                            unsigned char *v_ptr, int y_stride, int uv_stride,
     315             :                            loop_filter_info *lfi) {
     316           0 :   vp8_mbloop_filter_vertical_edge_c(y_ptr, y_stride, lfi->mblim, lfi->lim,
     317             :                                     lfi->hev_thr, 2);
     318             : 
     319           0 :   if (u_ptr) {
     320           0 :     vp8_mbloop_filter_vertical_edge_c(u_ptr, uv_stride, lfi->mblim, lfi->lim,
     321             :                                       lfi->hev_thr, 1);
     322             :   }
     323             : 
     324           0 :   if (v_ptr) {
     325           0 :     vp8_mbloop_filter_vertical_edge_c(v_ptr, uv_stride, lfi->mblim, lfi->lim,
     326             :                                       lfi->hev_thr, 1);
     327             :   }
     328           0 : }
     329             : 
     330             : /* Horizontal B Filtering */
     331           0 : void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr,
     332             :                           unsigned char *v_ptr, int y_stride, int uv_stride,
     333             :                           loop_filter_info *lfi) {
     334           0 :   vp8_loop_filter_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->blim,
     335             :                                     lfi->lim, lfi->hev_thr, 2);
     336           0 :   vp8_loop_filter_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->blim,
     337             :                                     lfi->lim, lfi->hev_thr, 2);
     338           0 :   vp8_loop_filter_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->blim,
     339             :                                     lfi->lim, lfi->hev_thr, 2);
     340             : 
     341           0 :   if (u_ptr) {
     342           0 :     vp8_loop_filter_horizontal_edge_c(u_ptr + 4 * uv_stride, uv_stride,
     343             :                                       lfi->blim, lfi->lim, lfi->hev_thr, 1);
     344             :   }
     345             : 
     346           0 :   if (v_ptr) {
     347           0 :     vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride,
     348             :                                       lfi->blim, lfi->lim, lfi->hev_thr, 1);
     349             :   }
     350           0 : }
     351             : 
     352           0 : void vp8_loop_filter_bhs_c(unsigned char *y_ptr, int y_stride,
     353             :                            const unsigned char *blimit) {
     354           0 :   vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride,
     355             :                                            blimit);
     356           0 :   vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride,
     357             :                                            blimit);
     358           0 :   vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride,
     359             :                                            blimit);
     360           0 : }
     361             : 
     362             : /* Vertical B Filtering */
     363           0 : void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr,
     364             :                           unsigned char *v_ptr, int y_stride, int uv_stride,
     365             :                           loop_filter_info *lfi) {
     366           0 :   vp8_loop_filter_vertical_edge_c(y_ptr + 4, y_stride, lfi->blim, lfi->lim,
     367             :                                   lfi->hev_thr, 2);
     368           0 :   vp8_loop_filter_vertical_edge_c(y_ptr + 8, y_stride, lfi->blim, lfi->lim,
     369             :                                   lfi->hev_thr, 2);
     370           0 :   vp8_loop_filter_vertical_edge_c(y_ptr + 12, y_stride, lfi->blim, lfi->lim,
     371             :                                   lfi->hev_thr, 2);
     372             : 
     373           0 :   if (u_ptr) {
     374           0 :     vp8_loop_filter_vertical_edge_c(u_ptr + 4, uv_stride, lfi->blim, lfi->lim,
     375             :                                     lfi->hev_thr, 1);
     376             :   }
     377             : 
     378           0 :   if (v_ptr) {
     379           0 :     vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->blim, lfi->lim,
     380             :                                     lfi->hev_thr, 1);
     381             :   }
     382           0 : }
     383             : 
     384           0 : void vp8_loop_filter_bvs_c(unsigned char *y_ptr, int y_stride,
     385             :                            const unsigned char *blimit) {
     386           0 :   vp8_loop_filter_simple_vertical_edge_c(y_ptr + 4, y_stride, blimit);
     387           0 :   vp8_loop_filter_simple_vertical_edge_c(y_ptr + 8, y_stride, blimit);
     388           0 :   vp8_loop_filter_simple_vertical_edge_c(y_ptr + 12, y_stride, blimit);
     389           0 : }

Generated by: LCOV version 1.13