git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

vp8/filter.go (7.6K)

  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 }