text: 'use strict';
  
  //var abs = Math.abs;
  
  function abs(value ){
      return (value ^ (value >> 31)) - (value >> 31);
  }
  
  function saturate_int8(x) {
  
      //return min(max(x, -128), 127);
      return Math.min(Math.max(x, -128), 127);
  
  }
  
  function saturate_uint8(x) {
      //return min(max(x, 0), 255);
      return Math.min(Math.max(x, 0), 255);
  }
  
  //possible vp8_simple_filter
  function vp8_filter(pixels, pixels_off, stride, use_outer_taps) {
      var stride2 = 2 * stride;
      var p1 = pixels[pixels_off - stride2];
      var p0 = pixels[pixels_off - stride];
      var q0 = pixels[pixels_off];
      var q1 = pixels[pixels_off + stride];
  
      var a = 0;
      var f1 = 0;
      var f2 = 0;
  
      a = 3 * (q0 - p0);
  
      if (use_outer_taps)
          a += saturate_int8(p1 - q1);
  
      a = saturate_int8(a);
  
  
      if((a + 4) > 127){
          f1 = 15;
          f2 = 15;
      }else{
          f1 = (a + 4) >> 3;
          f2 = (a + 3) >> 3;
      }
      
  
      p0 = saturate_uint8(p0 + f2);
      q0 = saturate_uint8(q0 - f1);
  
      if (!use_outer_taps)
      {
  
          a = (f1 + 1) >> 1;
          p1 = saturate_uint8(p1 + a);
          q1 = saturate_uint8(q1 - a);
      }
  
      pixels[pixels_off - stride2] = p1;
      pixels[pixels_off - stride] = p0;
      pixels[pixels_off] = q0;
      pixels[pixels_off + stride] = q1;
  }
  
  function vp8_filter_2(pixels, pixels_off, use_outer_taps) {
      //console.warn(pixels_off);
      var pixels_16 = pixels.data_16[(pixels_off - 2)/2];
      var p1 = pixels_16 & 0xFF;
      var p0 = (pixels_16 >> 8 )& 0xFF;
      
      pixels_16 = pixels.data_16[(pixels_off)/2];
      var q0 = pixels_16 & 0xFF;
      var q1 = (pixels_16 >> 8 )& 0xFF;
  
      var a = 0;
      var f1 = 0;
      var f2 = 0;
  
      a = 3 * (q0 - p0);
  
      if (use_outer_taps)
          a += saturate_int8(p1 - q1);
  
      a = saturate_int8(a);
  
  
      if((a + 4) > 127){
          f1 = 15;
          f2 = 15;
      }else{
          f1 = (a + 4) >> 3;
          f2 = (a + 3) >> 3;
      }
      
  
      p0 = saturate_uint8(p0 + f2);
      q0 = saturate_uint8(q0 - f1);
  
      if (!use_outer_taps)
      {
  
          a = (f1 + 1) >> 1;
          p1 = saturate_uint8(p1 + a);
          q1 = saturate_uint8(q1 - a);
      }
  
      pixels[pixels_off - 2] = p1;
      pixels[pixels_off - 1] = p0;
      pixels[pixels_off] = q0;
      pixels[pixels_off + 1] = q1;
  }
  
  
  //vp8_loop_filter_simple_bh
  function vp8_loop_filter_bhs_c(y, y_ptr, y_stride, blimit) {
      vp8_loop_filter_simple_horizontal_edge_c(y, y_ptr + 4 * y_stride, y_stride, blimit);
      vp8_loop_filter_simple_horizontal_edge_c(y, y_ptr + 8 * y_stride, y_stride, blimit);
      vp8_loop_filter_simple_horizontal_edge_c(y, y_ptr + 12 * y_stride, y_stride, blimit);
  }
  
  //vp8_loop_filter_mbh_c
  
  function vp8_loop_filter_simple_horizontal_edge_c(src, src_off, stride, filter_limit) {
      var i = 0;
  
      for (i = 0; i < 16; i++) {
          if (simple_threshold(src, src_off, stride, filter_limit) === 1)
              vp8_filter(src, src_off, stride, 1);
  
          src_off += 1;
      }
  }
  
  function simple_threshold(pixels, pixels_off, stride, filter_limit) {
      var p1 = pixels[pixels_off - (stride << 1)];
      var p0 = pixels[pixels_off - stride];
      var q0 = pixels[pixels_off];
      var q1 = pixels[pixels_off + stride];
  
      return (((abs(p0 - q0) << 1) + (abs(p1 - q1) >> 1)) <= filter_limit) | 0;
  }
  
  function vp8_loop_filter_bvs_c(y, y_off, stride, b_limit) {
      vp8_loop_filter_simple_vertical_edge_c(y, y_off + 4, stride, b_limit);
      vp8_loop_filter_simple_vertical_edge_c(y, y_off + 8, stride, b_limit);
      vp8_loop_filter_simple_vertical_edge_c(y, y_off + 12, stride, b_limit);
  }
  
  function vp8_loop_filter_simple_vertical_edge_c(src, src_off, stride, filter_limit) {
      var i = 0;
  
      for (i = 0; i < 16; i++) {
          if (simple_threshold(src, src_off, 1, filter_limit))
              vp8_filter(src, src_off, 1, 1);
  
          src_off += stride;
      }
  }
  /*
   function vp8_loop_filter_simple_horizontal_edge_c(src, src_off, stride, filter_limit) {
   
   var i = 0;
   
   for (i = 0; i < 16; i++) {
   if (simple_threshold(src, src_off, 1, filter_limit))
   vp8_filter(src, src_off, 1, 1);
   
   src_off += stride;
   
   }
   
   }
   */
  
  function vp8_loop_filter_mbv(y, y_off, u_off, v_off, stride, uv_stride, edge_limit, interior_limit, hev_threshold) {
      //vp8_loop_filter_mbv
      filter_mb_v_edge(y, y_off, stride, edge_limit + 2,
              interior_limit, hev_threshold, 2);
      filter_mb_v_edge(y, u_off, uv_stride, edge_limit + 2,
              interior_limit, hev_threshold, 1);
      filter_mb_v_edge(y, v_off, uv_stride, edge_limit + 2,
              interior_limit, hev_threshold, 1);
  }
  
  function filter_mb_v_edge(src,
          src_off,
          stride,
          edge_limit,
          interior_limit,
          hev_threshold,
          size) {
      var i = 0;
  
      var length = size << 3;
      for (i = 0; i < length; i++) {
          if (normal_threshold(src, src_off, 1, edge_limit, interior_limit)) {
              if (high_edge_variance(src, src_off, 1, hev_threshold))
                  vp8_filter(src, src_off, 1 , 1);
              else
                  filter_mb_edge(src, src_off, 1);
          }
  
          src_off += stride;
      }
  }
  
  
  function normal_threshold(pixels, pixels_off, stride, E, I) {
  
      if (simple_threshold(pixels, pixels_off, stride, 2 * E + I) === 0)
          return 0;
  
      var p3 = pixels[pixels_off - 4 * stride];
      var p2 = pixels[pixels_off - 3 * stride];
  
      if (abs(p3 - p2) > I)
          return 0;
  
      var p1 = pixels[pixels_off - 2 * stride];
  
  
      if (abs(p2 - p1) > I)
          return 0;
  
      var p0 = pixels[pixels_off - stride];
     
      if(abs(p1 - p0) > I)
          return 0;
   
      var q2 = pixels[pixels_off + 2 * stride];
      var q3 = pixels[pixels_off + 3 * stride];
      
      if(abs(q3 - q2) > I)
          return 0;
      
      var q0 = pixels[pixels_off];
      var q1 = pixels[pixels_off + stride];
      
      if(abs(q2 - q1) > I)
          return 0;
      
      
      return abs(q1 - q0) <= I;
      
  }
  
  
  //vp8_mbfilter
  function filter_mb_edge(pixels, pixels_off, stride) {
  //var p3 = pixels[pixels_off -4*stride];
  
      var stride2 = stride << 1;
      var stride3 = 3 * stride;
  
      var p2 = pixels[pixels_off - stride3];
      var p1 = pixels[pixels_off - stride2];
      var p0 = pixels[pixels_off - stride];
      var q0 = pixels[pixels_off];
      var q1 = pixels[pixels_off + stride];
      var q2 = pixels[pixels_off + stride2];
      var w = 0, a = 0;
  
      w = saturate_int8(saturate_int8(p1 - q1) + 3 * (q0 - p0));
  
      a = (27 * w + 63) >> 7;
      p0 = saturate_uint8(p0 + a);
      q0 = saturate_uint8(q0 - a);
  
      a = (18 * w + 63) >> 7;
      p1 = saturate_uint8(p1 + a);
      q1 = saturate_uint8(q1 - a);
  
      a = (9 * w + 63) >> 7;
      p2 = saturate_uint8(p2 + a);
      q2 = saturate_uint8(q2 - a);
  
      pixels[pixels_off - stride3] = p2;
      pixels[pixels_off - stride2] = p1;
      pixels[pixels_off - stride] = p0;
      pixels[pixels_off] = q0;
      pixels[pixels_off + stride] = q1;
      pixels[pixels_off + stride2] = q2;
  
  }
  
  
  function high_edge_variance(pixels, pixels_off, stride, hev_threshold) {
  
      var p1 = pixels[pixels_off - 2 * stride];
      var p0 = pixels[pixels_off - stride];
      
  
      if(abs(p1 - p0) > hev_threshold)
          return 1;
      
      var q0 = pixels[pixels_off];
      var q1 = pixels[pixels_off + stride];
      
      return abs(q1 - q0) > hev_threshold;
  
  }
  
  function vp8_loop_filter_bv_c(y, y_off, u_off, v_off, stride, uv_stride, edge_limit, interior_limit, hev_threshold) {
      var dat = y;
      filter_subblock_v_edge(y, y_off + 4, stride, edge_limit,
              interior_limit, hev_threshold, 2);
  
      filter_subblock_v_edge(dat, y_off + 8, stride, edge_limit,
              interior_limit, hev_threshold, 2);
  
      filter_subblock_v_edge(dat, y_off + 12, stride, edge_limit,
              interior_limit, hev_threshold, 2);
  
      filter_subblock_v_edge(dat, u_off + 4, uv_stride, edge_limit,
              interior_limit, hev_threshold, 1);
  
      filter_subblock_v_edge(dat, v_off + 4, uv_stride, edge_limit,
              interior_limit, hev_threshold, 1);
  }
  
  
  function filter_subblock_v_edge(src, src_off, stride, edge_limit, interior_limit, hev_threshold, size) {
      var i = 0;
      var limit = 8 * size;
      for (i = 0; i < limit; i++) {
  
          if (normal_threshold(src, src_off, 1, edge_limit, interior_limit))
              
              vp8_filter(src, src_off, 1, high_edge_variance(src, src_off, 1, hev_threshold));
  
  
          src_off += stride;
      }
  
  
  }
  
  module.exports = {};
  module.exports.vp8_filter = vp8_filter;
  module.exports.vp8_loop_filter_bhs_c = vp8_loop_filter_bhs_c;
  module.exports.vp8_loop_filter_bvs_c = vp8_loop_filter_bvs_c;
  module.exports.vp8_loop_filter_simple_horizontal_edge_c = vp8_loop_filter_simple_horizontal_edge_c;
  module.exports.vp8_loop_filter_simple_vertical_edge_c = vp8_loop_filter_simple_vertical_edge_c;
  module.exports.vp8_loop_filter_mbv = vp8_loop_filter_mbv;
  module.exports.vp8_loop_filter_bv_c = vp8_loop_filter_bv_c;
  module.exports.filter_mb_edge = filter_mb_edge;
  module.exports.normal_threshold = normal_threshold;
  module.exports.high_edge_variance = high_edge_variance;