twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

filter.go (7797B)


      1 // Copyright 2014 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package vp8
      6 
      7 // filter2 modifies a 2-pixel wide or 2-pixel high band along an edge.
      8 func filter2(pix []byte, level, index, iStep, jStep int) {
      9 	for n := 16; n > 0; n, index = n-1, index+iStep {
     10 		p1 := int(pix[index-2*jStep])
     11 		p0 := int(pix[index-1*jStep])
     12 		q0 := int(pix[index+0*jStep])
     13 		q1 := int(pix[index+1*jStep])
     14 		if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
     15 			continue
     16 		}
     17 		a := 3*(q0-p0) + clamp127(p1-q1)
     18 		a1 := clamp15((a + 4) >> 3)
     19 		a2 := clamp15((a + 3) >> 3)
     20 		pix[index-1*jStep] = clamp255(p0 + a2)
     21 		pix[index+0*jStep] = clamp255(q0 - a1)
     22 	}
     23 }
     24 
     25 // filter246 modifies a 2-, 4- or 6-pixel wide or high band along an edge.
     26 func filter246(pix []byte, n, level, ilevel, hlevel, index, iStep, jStep int, fourNotSix bool) {
     27 	for ; n > 0; n, index = n-1, index+iStep {
     28 		p3 := int(pix[index-4*jStep])
     29 		p2 := int(pix[index-3*jStep])
     30 		p1 := int(pix[index-2*jStep])
     31 		p0 := int(pix[index-1*jStep])
     32 		q0 := int(pix[index+0*jStep])
     33 		q1 := int(pix[index+1*jStep])
     34 		q2 := int(pix[index+2*jStep])
     35 		q3 := int(pix[index+3*jStep])
     36 		if abs(p0-q0)<<1+abs(p1-q1)>>1 > level {
     37 			continue
     38 		}
     39 		if abs(p3-p2) > ilevel ||
     40 			abs(p2-p1) > ilevel ||
     41 			abs(p1-p0) > ilevel ||
     42 			abs(q1-q0) > ilevel ||
     43 			abs(q2-q1) > ilevel ||
     44 			abs(q3-q2) > ilevel {
     45 			continue
     46 		}
     47 		if abs(p1-p0) > hlevel || abs(q1-q0) > hlevel {
     48 			// Filter 2 pixels.
     49 			a := 3*(q0-p0) + clamp127(p1-q1)
     50 			a1 := clamp15((a + 4) >> 3)
     51 			a2 := clamp15((a + 3) >> 3)
     52 			pix[index-1*jStep] = clamp255(p0 + a2)
     53 			pix[index+0*jStep] = clamp255(q0 - a1)
     54 		} else if fourNotSix {
     55 			// Filter 4 pixels.
     56 			a := 3 * (q0 - p0)
     57 			a1 := clamp15((a + 4) >> 3)
     58 			a2 := clamp15((a + 3) >> 3)
     59 			a3 := (a1 + 1) >> 1
     60 			pix[index-2*jStep] = clamp255(p1 + a3)
     61 			pix[index-1*jStep] = clamp255(p0 + a2)
     62 			pix[index+0*jStep] = clamp255(q0 - a1)
     63 			pix[index+1*jStep] = clamp255(q1 - a3)
     64 		} else {
     65 			// Filter 6 pixels.
     66 			a := clamp127(3*(q0-p0) + clamp127(p1-q1))
     67 			a1 := (27*a + 63) >> 7
     68 			a2 := (18*a + 63) >> 7
     69 			a3 := (9*a + 63) >> 7
     70 			pix[index-3*jStep] = clamp255(p2 + a3)
     71 			pix[index-2*jStep] = clamp255(p1 + a2)
     72 			pix[index-1*jStep] = clamp255(p0 + a1)
     73 			pix[index+0*jStep] = clamp255(q0 - a1)
     74 			pix[index+1*jStep] = clamp255(q1 - a2)
     75 			pix[index+2*jStep] = clamp255(q2 - a3)
     76 		}
     77 	}
     78 }
     79 
     80 // simpleFilter implements the simple filter, as specified in section 15.2.
     81 func (d *Decoder) simpleFilter() {
     82 	for mby := 0; mby < d.mbh; mby++ {
     83 		for mbx := 0; mbx < d.mbw; mbx++ {
     84 			f := d.perMBFilterParams[d.mbw*mby+mbx]
     85 			if f.level == 0 {
     86 				continue
     87 			}
     88 			l := int(f.level)
     89 			yIndex := (mby*d.img.YStride + mbx) * 16
     90 			if mbx > 0 {
     91 				filter2(d.img.Y, l+4, yIndex, d.img.YStride, 1)
     92 			}
     93 			if f.inner {
     94 				filter2(d.img.Y, l, yIndex+0x4, d.img.YStride, 1)
     95 				filter2(d.img.Y, l, yIndex+0x8, d.img.YStride, 1)
     96 				filter2(d.img.Y, l, yIndex+0xc, d.img.YStride, 1)
     97 			}
     98 			if mby > 0 {
     99 				filter2(d.img.Y, l+4, yIndex, 1, d.img.YStride)
    100 			}
    101 			if f.inner {
    102 				filter2(d.img.Y, l, yIndex+d.img.YStride*0x4, 1, d.img.YStride)
    103 				filter2(d.img.Y, l, yIndex+d.img.YStride*0x8, 1, d.img.YStride)
    104 				filter2(d.img.Y, l, yIndex+d.img.YStride*0xc, 1, d.img.YStride)
    105 			}
    106 		}
    107 	}
    108 }
    109 
    110 // normalFilter implements the normal filter, as specified in section 15.3.
    111 func (d *Decoder) normalFilter() {
    112 	for mby := 0; mby < d.mbh; mby++ {
    113 		for mbx := 0; mbx < d.mbw; mbx++ {
    114 			f := d.perMBFilterParams[d.mbw*mby+mbx]
    115 			if f.level == 0 {
    116 				continue
    117 			}
    118 			l, il, hl := int(f.level), int(f.ilevel), int(f.hlevel)
    119 			yIndex := (mby*d.img.YStride + mbx) * 16
    120 			cIndex := (mby*d.img.CStride + mbx) * 8
    121 			if mbx > 0 {
    122 				filter246(d.img.Y, 16, l+4, il, hl, yIndex, d.img.YStride, 1, false)
    123 				filter246(d.img.Cb, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
    124 				filter246(d.img.Cr, 8, l+4, il, hl, cIndex, d.img.CStride, 1, false)
    125 			}
    126 			if f.inner {
    127 				filter246(d.img.Y, 16, l, il, hl, yIndex+0x4, d.img.YStride, 1, true)
    128 				filter246(d.img.Y, 16, l, il, hl, yIndex+0x8, d.img.YStride, 1, true)
    129 				filter246(d.img.Y, 16, l, il, hl, yIndex+0xc, d.img.YStride, 1, true)
    130 				filter246(d.img.Cb, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
    131 				filter246(d.img.Cr, 8, l, il, hl, cIndex+0x4, d.img.CStride, 1, true)
    132 			}
    133 			if mby > 0 {
    134 				filter246(d.img.Y, 16, l+4, il, hl, yIndex, 1, d.img.YStride, false)
    135 				filter246(d.img.Cb, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
    136 				filter246(d.img.Cr, 8, l+4, il, hl, cIndex, 1, d.img.CStride, false)
    137 			}
    138 			if f.inner {
    139 				filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x4, 1, d.img.YStride, true)
    140 				filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0x8, 1, d.img.YStride, true)
    141 				filter246(d.img.Y, 16, l, il, hl, yIndex+d.img.YStride*0xc, 1, d.img.YStride, true)
    142 				filter246(d.img.Cb, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
    143 				filter246(d.img.Cr, 8, l, il, hl, cIndex+d.img.CStride*0x4, 1, d.img.CStride, true)
    144 			}
    145 		}
    146 	}
    147 }
    148 
    149 // filterParam holds the loop filter parameters for a macroblock.
    150 type filterParam struct {
    151 	// The first three fields are thresholds used by the loop filter to smooth
    152 	// over the edges and interior of a macroblock. level is used by both the
    153 	// simple and normal filters. The inner level and high edge variance level
    154 	// are only used by the normal filter.
    155 	level, ilevel, hlevel uint8
    156 	// inner is whether the inner loop filter cannot be optimized out as a
    157 	// no-op for this particular macroblock.
    158 	inner bool
    159 }
    160 
    161 // computeFilterParams computes the loop filter parameters, as specified in
    162 // section 15.4.
    163 func (d *Decoder) computeFilterParams() {
    164 	for i := range d.filterParams {
    165 		baseLevel := d.filterHeader.level
    166 		if d.segmentHeader.useSegment {
    167 			baseLevel = d.segmentHeader.filterStrength[i]
    168 			if d.segmentHeader.relativeDelta {
    169 				baseLevel += d.filterHeader.level
    170 			}
    171 		}
    172 
    173 		for j := range d.filterParams[i] {
    174 			p := &d.filterParams[i][j]
    175 			p.inner = j != 0
    176 			level := baseLevel
    177 			if d.filterHeader.useLFDelta {
    178 				// The libwebp C code has a "TODO: only CURRENT is handled for now."
    179 				level += d.filterHeader.refLFDelta[0]
    180 				if j != 0 {
    181 					level += d.filterHeader.modeLFDelta[0]
    182 				}
    183 			}
    184 			if level <= 0 {
    185 				p.level = 0
    186 				continue
    187 			}
    188 			if level > 63 {
    189 				level = 63
    190 			}
    191 			ilevel := level
    192 			if d.filterHeader.sharpness > 0 {
    193 				if d.filterHeader.sharpness > 4 {
    194 					ilevel >>= 2
    195 				} else {
    196 					ilevel >>= 1
    197 				}
    198 				if x := int8(9 - d.filterHeader.sharpness); ilevel > x {
    199 					ilevel = x
    200 				}
    201 			}
    202 			if ilevel < 1 {
    203 				ilevel = 1
    204 			}
    205 			p.ilevel = uint8(ilevel)
    206 			p.level = uint8(2*level + ilevel)
    207 			if d.frameHeader.KeyFrame {
    208 				if level < 15 {
    209 					p.hlevel = 0
    210 				} else if level < 40 {
    211 					p.hlevel = 1
    212 				} else {
    213 					p.hlevel = 2
    214 				}
    215 			} else {
    216 				if level < 15 {
    217 					p.hlevel = 0
    218 				} else if level < 20 {
    219 					p.hlevel = 1
    220 				} else if level < 40 {
    221 					p.hlevel = 2
    222 				} else {
    223 					p.hlevel = 3
    224 				}
    225 			}
    226 		}
    227 	}
    228 }
    229 
    230 // intSize is either 32 or 64.
    231 const intSize = 32 << (^uint(0) >> 63)
    232 
    233 func abs(x int) int {
    234 	// m := -1 if x < 0. m := 0 otherwise.
    235 	m := x >> (intSize - 1)
    236 
    237 	// In two's complement representation, the negative number
    238 	// of any number (except the smallest one) can be computed
    239 	// by flipping all the bits and add 1. This is faster than
    240 	// code with a branch.
    241 	// See Hacker's Delight, section 2-4.
    242 	return (x ^ m) - m
    243 }
    244 
    245 func clamp15(x int) int {
    246 	if x < -16 {
    247 		return -16
    248 	}
    249 	if x > 15 {
    250 		return 15
    251 	}
    252 	return x
    253 }
    254 
    255 func clamp127(x int) int {
    256 	if x < -128 {
    257 		return -128
    258 	}
    259 	if x > 127 {
    260 		return 127
    261 	}
    262 	return x
    263 }
    264 
    265 func clamp255(x int) uint8 {
    266 	if x < 0 {
    267 		return 0
    268 	}
    269 	if x > 255 {
    270 		return 255
    271 	}
    272 	return uint8(x)
    273 }