2 Copyright (C) 2001 Michael Niedermayer (michaelni@gmx.at)
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 doVertDefFilter Ec Ec e e
28 doHorizDefFilter Ec Ec e e
30 Vertical RKAlgo1 E a a
31 Horizontal RKAlgo1 a a
34 LinIpolDeinterlace e E E*
35 CubicIpolDeinterlace a e e*
36 LinBlendDeinterlace e E E*
37 MedianDeinterlace# Ec Ec
40 * i dont have a 3dnow CPU -> its untested, but noone said it doesnt work so it seems to work
41 # more or less selfinvented filters so the exactness isnt too meaningfull
42 E = Exact implementation
43 e = allmost exact implementation (slightly different rounding,...)
44 a = alternative / approximate impl
45 c = checked against the other implementations (-vo md5)
50 verify that everything workes as it should (how?)
51 reduce the time wasted on the mem transfer
52 implement everything in C at least (done at the moment but ...)
53 unroll stuff if instructions depend too much on the prior one
54 we use 8x8 blocks for the horizontal filters, opendivx seems to use 8x4?
55 move YScale thing to the end instead of fixing QP
56 write a faster and higher quality deblocking filter :)
57 make the mainloop more flexible (variable number of blocks at once
58 (the if/else stuff per block is slowing things down)
59 compare the quality & speed of all filters
63 try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks
65 commandline option for the deblock thresholds
69 //Changelog: use the CVS log
71 #include "../config.h"
82 //#define DEBUG_BRIGHTNESS
83 #include "postprocess.h"
85 #define MIN(a,b) ((a) > (b) ? (b) : (a))
86 #define MAX(a,b) ((a) < (b) ? (b) : (a))
87 #define ABS(a) ((a) > 0 ? (a) : (-(a)))
88 #define SIGN(a) ((a) > 0 ? 1 : -1)
91 #define PAVGB(a,b) "pavgb " #a ", " #b " \n\t"
92 #elif defined (HAVE_3DNOW)
93 #define PAVGB(a,b) "pavgusb " #a ", " #b " \n\t"
97 #define PMINUB(a,b,t) "pminub " #a ", " #b " \n\t"
98 #elif defined (HAVE_MMX)
99 #define PMINUB(b,a,t) \
100 "movq " #a ", " #t " \n\t"\
101 "psubusb " #b ", " #t " \n\t"\
102 "psubb " #t ", " #a " \n\t"
106 #define PMAXUB(a,b) "pmaxub " #a ", " #b " \n\t"
107 #elif defined (HAVE_MMX)
108 #define PMAXUB(a,b) \
109 "psubusb " #a ", " #b " \n\t"\
110 "paddb " #a ", " #b " \n\t"
114 #define GET_MODE_BUFFER_SIZE 500
115 #define OPTIONS_ARRAY_SIZE 10
118 static volatile uint64_t __attribute__((aligned(8))) packedYOffset= 0x0000000000000000LL;
119 static volatile uint64_t __attribute__((aligned(8))) packedYScale= 0x0100010001000100LL;
120 static uint64_t __attribute__((aligned(8))) w05= 0x0005000500050005LL;
121 static uint64_t __attribute__((aligned(8))) w20= 0x0020002000200020LL;
122 static uint64_t __attribute__((aligned(8))) w1400= 0x1400140014001400LL;
123 static uint64_t __attribute__((aligned(8))) bm00000001= 0x00000000000000FFLL;
124 static uint64_t __attribute__((aligned(8))) bm00010000= 0x000000FF00000000LL;
125 static uint64_t __attribute__((aligned(8))) bm00001000= 0x00000000FF000000LL;
126 static uint64_t __attribute__((aligned(8))) bm10000000= 0xFF00000000000000LL;
127 static uint64_t __attribute__((aligned(8))) bm10000001= 0xFF000000000000FFLL;
128 static uint64_t __attribute__((aligned(8))) bm11000011= 0xFFFF00000000FFFFLL;
129 static uint64_t __attribute__((aligned(8))) bm00000011= 0x000000000000FFFFLL;
130 static uint64_t __attribute__((aligned(8))) bm11111110= 0xFFFFFFFFFFFFFF00LL;
131 static uint64_t __attribute__((aligned(8))) bm11000000= 0xFFFF000000000000LL;
132 static uint64_t __attribute__((aligned(8))) bm00011000= 0x000000FFFF000000LL;
133 static uint64_t __attribute__((aligned(8))) bm00110011= 0x0000FFFF0000FFFFLL;
134 static uint64_t __attribute__((aligned(8))) bm11001100= 0xFFFF0000FFFF0000LL;
135 static uint64_t __attribute__((aligned(8))) b00= 0x0000000000000000LL;
136 static uint64_t __attribute__((aligned(8))) b01= 0x0101010101010101LL;
137 static uint64_t __attribute__((aligned(8))) b02= 0x0202020202020202LL;
138 static uint64_t __attribute__((aligned(8))) b0F= 0x0F0F0F0F0F0F0F0FLL;
139 static uint64_t __attribute__((aligned(8))) b04= 0x0404040404040404LL;
140 static uint64_t __attribute__((aligned(8))) b08= 0x0808080808080808LL;
141 static uint64_t __attribute__((aligned(8))) bFF= 0xFFFFFFFFFFFFFFFFLL;
142 static uint64_t __attribute__((aligned(8))) b20= 0x2020202020202020LL;
143 static uint64_t __attribute__((aligned(8))) b80= 0x8080808080808080LL;
144 static uint64_t __attribute__((aligned(8))) b7E= 0x7E7E7E7E7E7E7E7ELL;
145 static uint64_t __attribute__((aligned(8))) b7C= 0x7C7C7C7C7C7C7C7CLL;
146 static uint64_t __attribute__((aligned(8))) b3F= 0x3F3F3F3F3F3F3F3FLL;
147 static uint64_t __attribute__((aligned(8))) temp0=0;
148 static uint64_t __attribute__((aligned(8))) temp1=0;
149 static uint64_t __attribute__((aligned(8))) temp2=0;
150 static uint64_t __attribute__((aligned(8))) temp3=0;
151 static uint64_t __attribute__((aligned(8))) temp4=0;
152 static uint64_t __attribute__((aligned(8))) temp5=0;
153 static uint64_t __attribute__((aligned(8))) pQPb=0;
154 static uint64_t __attribute__((aligned(8))) pQPb2=0;
155 static uint8_t __attribute__((aligned(8))) tempBlocks[8*16*2]; //used for the horizontal code
156 static uint32_t __attribute__((aligned(4))) maxTmpNoise[4];
158 static uint64_t packedYOffset= 0x0000000000000000LL;
159 static uint64_t packedYScale= 0x0100010001000100LL;
160 static uint8_t tempBlocks[8*16*2]; //used for the horizontal code
163 int hFlatnessThreshold= 56 - 16;
164 int vFlatnessThreshold= 56 - 16;
166 //amount of "black" u r willing to loose to get a brightness corrected picture
167 double maxClippedThreshold= 0.01;
172 static struct PPFilter filters[]=
174 {"hb", "hdeblock", 1, 1, 3, H_DEBLOCK},
175 {"vb", "vdeblock", 1, 2, 4, V_DEBLOCK},
176 {"vr", "rkvdeblock", 1, 2, 4, H_RK1_FILTER},
177 {"h1", "x1hdeblock", 1, 1, 3, H_X1_FILTER},
178 {"v1", "x1vdeblock", 1, 2, 4, V_X1_FILTER},
179 {"dr", "dering", 1, 5, 6, DERING},
180 {"al", "autolevels", 0, 1, 2, LEVEL_FIX},
181 {"lb", "linblenddeint", 0, 1, 6, LINEAR_BLEND_DEINT_FILTER},
182 {"li", "linipoldeint", 0, 1, 6, LINEAR_IPOL_DEINT_FILTER},
183 {"ci", "cubicipoldeint", 0, 1, 6, CUBIC_IPOL_DEINT_FILTER},
184 {"md", "mediandeint", 0, 1, 6, MEDIAN_DEINT_FILTER},
185 {"tn", "tmpnoise", 1, 7, 8, TEMP_NOISE_FILTER},
186 {NULL, NULL,0,0,0,0} //End Marker
189 static char *replaceTable[]=
191 "default", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
192 "de", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
193 "fast", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
194 "fa", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400",
199 static inline void unusedVariableWarningFixer()
202 packedYOffset + packedYScale + w05 + w20 + w1400 + bm00000001 + bm00010000
203 + bm00001000 + bm10000000 + bm10000001 + bm11000011 + bm00000011 + bm11111110
204 + bm11000000 + bm00011000 + bm00110011 + bm11001100 + b00 + b01 + b02 + b0F
205 + bFF + b20 + b04+ b08 + pQPb2 + b80 + b7E + b7C + b3F + temp0 + temp1 + temp2 + temp3 + temp4
206 + temp5 + pQPb== 0) b00=0;
211 static inline long long rdtsc()
214 asm volatile( "rdtsc\n\t"
217 // printf("%d\n", int(l/1000));
223 static inline void prefetchnta(void *p)
225 asm volatile( "prefetchnta (%0)\n\t"
230 static inline void prefetcht0(void *p)
232 asm volatile( "prefetcht0 (%0)\n\t"
237 static inline void prefetcht1(void *p)
239 asm volatile( "prefetcht1 (%0)\n\t"
244 static inline void prefetcht2(void *p)
246 asm volatile( "prefetcht2 (%0)\n\t"
252 //FIXME? |255-0| = 1 (shouldnt be a problem ...)
254 * Check if the middle 8x8 Block in the given 8x16 block is flat
256 static inline int isVertDC(uint8_t src[], int stride){
261 src+= stride*4; // src points to begin of the 8x8 Block
264 "leal (%1, %2), %%eax \n\t"
265 "leal (%%eax, %2, 4), %%ebx \n\t"
266 // 0 1 2 3 4 5 6 7 8 9
267 // %1 eax eax+%2 eax+2%2 %1+4%2 ebx ebx+%2 ebx+2%2 %1+8%2 ebx+4%2
268 "movq b7E, %%mm7 \n\t" // mm7 = 0x7F
269 "movq b7C, %%mm6 \n\t" // mm6 = 0x7D
270 "movq (%1), %%mm0 \n\t"
271 "movq (%%eax), %%mm1 \n\t"
272 "psubb %%mm1, %%mm0 \n\t" // mm0 = differnece
273 "paddb %%mm7, %%mm0 \n\t"
274 "pcmpgtb %%mm6, %%mm0 \n\t"
276 "movq (%%eax,%2), %%mm2 \n\t"
277 "psubb %%mm2, %%mm1 \n\t"
278 "paddb %%mm7, %%mm1 \n\t"
279 "pcmpgtb %%mm6, %%mm1 \n\t"
280 "paddb %%mm1, %%mm0 \n\t"
282 "movq (%%eax, %2, 2), %%mm1 \n\t"
283 "psubb %%mm1, %%mm2 \n\t"
284 "paddb %%mm7, %%mm2 \n\t"
285 "pcmpgtb %%mm6, %%mm2 \n\t"
286 "paddb %%mm2, %%mm0 \n\t"
288 "movq (%1, %2, 4), %%mm2 \n\t"
289 "psubb %%mm2, %%mm1 \n\t"
290 "paddb %%mm7, %%mm1 \n\t"
291 "pcmpgtb %%mm6, %%mm1 \n\t"
292 "paddb %%mm1, %%mm0 \n\t"
294 "movq (%%ebx), %%mm1 \n\t"
295 "psubb %%mm1, %%mm2 \n\t"
296 "paddb %%mm7, %%mm2 \n\t"
297 "pcmpgtb %%mm6, %%mm2 \n\t"
298 "paddb %%mm2, %%mm0 \n\t"
300 "movq (%%ebx, %2), %%mm2 \n\t"
301 "psubb %%mm2, %%mm1 \n\t"
302 "paddb %%mm7, %%mm1 \n\t"
303 "pcmpgtb %%mm6, %%mm1 \n\t"
304 "paddb %%mm1, %%mm0 \n\t"
306 "movq (%%ebx, %2, 2), %%mm1 \n\t"
307 "psubb %%mm1, %%mm2 \n\t"
308 "paddb %%mm7, %%mm2 \n\t"
309 "pcmpgtb %%mm6, %%mm2 \n\t"
310 "paddb %%mm2, %%mm0 \n\t"
313 "movq %%mm0, %%mm1 \n\t"
314 "psrlw $8, %%mm0 \n\t"
315 "paddb %%mm1, %%mm0 \n\t"
317 "pshufw $0xF9, %%mm0, %%mm1 \n\t"
318 "paddb %%mm1, %%mm0 \n\t"
319 "pshufw $0xFE, %%mm0, %%mm1 \n\t"
321 "movq %%mm0, %%mm1 \n\t"
322 "psrlq $16, %%mm0 \n\t"
323 "paddb %%mm1, %%mm0 \n\t"
324 "movq %%mm0, %%mm1 \n\t"
325 "psrlq $32, %%mm0 \n\t"
327 "paddb %%mm1, %%mm0 \n\t"
328 "movd %%mm0, %0 \n\t"
330 : "r" (src), "r" (stride)
334 numEq= (256 - numEq) &0xFF;
337 for(y=0; y<BLOCK_SIZE-1; y++)
339 if(((src[0] - src[0+stride] + 1)&0xFFFF) < 3) numEq++;
340 if(((src[1] - src[1+stride] + 1)&0xFFFF) < 3) numEq++;
341 if(((src[2] - src[2+stride] + 1)&0xFFFF) < 3) numEq++;
342 if(((src[3] - src[3+stride] + 1)&0xFFFF) < 3) numEq++;
343 if(((src[4] - src[4+stride] + 1)&0xFFFF) < 3) numEq++;
344 if(((src[5] - src[5+stride] + 1)&0xFFFF) < 3) numEq++;
345 if(((src[6] - src[6+stride] + 1)&0xFFFF) < 3) numEq++;
346 if(((src[7] - src[7+stride] + 1)&0xFFFF) < 3) numEq++;
350 /* if(abs(numEq - asmEq) > 0)
352 printf("\nasm:%d c:%d\n", asmEq, numEq);
353 for(int y=0; y<8; y++)
355 for(int x=0; x<8; x++)
357 printf("%d ", temp[x + y*stride]);
363 // for(int i=0; i<numEq/8; i++) src[i]=255;
364 return (numEq > vFlatnessThreshold) ? 1 : 0;
367 static inline int isVertMinMaxOk(uint8_t src[], int stride, int QP)
374 "movq (%1, %2), %%mm0 \n\t"
375 "movq (%1, %2, 8), %%mm1 \n\t"
376 "movq %%mm0, %%mm2 \n\t"
377 "psubusb %%mm1, %%mm0 \n\t"
378 "psubusb %%mm2, %%mm1 \n\t"
379 "por %%mm1, %%mm0 \n\t" // ABS Diff
381 "movq pQPb, %%mm7 \n\t" // QP,..., QP
382 "paddusb %%mm7, %%mm7 \n\t" // 2QP ... 2QP
383 "psubusb %%mm7, %%mm0 \n\t" // Diff <= 2QP -> 0
384 "pcmpeqd b00, %%mm0 \n\t"
385 "psrlq $16, %%mm0 \n\t"
386 "pcmpeqd bFF, %%mm0 \n\t"
387 // "movd %%mm0, (%1, %2, 4)\n\t"
388 "movd %%mm0, %0 \n\t"
390 : "r" (src), "r" (stride)
398 for(x=0; x<BLOCK_SIZE; x++)
400 if(abs((int)src[x + stride] - (int)src[x + (stride<<3)]) > 2*QP) isOk2=0;
402 /* if(isOk && !isOk2 || !isOk && isOk2)
404 printf("\nasm:%d c:%d QP:%d\n", isOk, isOk2, QP);
405 for(int y=0; y<9; y++)
407 for(int x=0; x<8; x++)
409 printf("%d ", src[x + y*stride]);
421 * Do a vertical low pass filter on the 8x16 block (only write to the 8x8 block in the middle)
422 * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16
424 static inline void doVertLowPass(uint8_t *src, int stride, int QP)
426 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
428 asm volatile( //"movv %0 %1 %2\n\t"
429 "movq pQPb, %%mm0 \n\t" // QP,..., QP
431 "movq (%0), %%mm6 \n\t"
432 "movq (%0, %1), %%mm5 \n\t"
433 "movq %%mm5, %%mm1 \n\t"
434 "movq %%mm6, %%mm2 \n\t"
435 "psubusb %%mm6, %%mm5 \n\t"
436 "psubusb %%mm1, %%mm2 \n\t"
437 "por %%mm5, %%mm2 \n\t" // ABS Diff of lines
438 "psubusb %%mm0, %%mm2 \n\t" // diff <= QP -> 0
439 "pcmpeqb b00, %%mm2 \n\t" // diff <= QP -> FF
441 "pand %%mm2, %%mm6 \n\t"
442 "pandn %%mm1, %%mm2 \n\t"
443 "por %%mm2, %%mm6 \n\t"// First Line to Filter
445 "movq (%0, %1, 8), %%mm5 \n\t"
446 "leal (%0, %1, 4), %%eax \n\t"
447 "leal (%0, %1, 8), %%ebx \n\t"
448 "subl %1, %%ebx \n\t"
449 "addl %1, %0 \n\t" // %0 points to line 1 not 0
450 "movq (%0, %1, 8), %%mm7 \n\t"
451 "movq %%mm5, %%mm1 \n\t"
452 "movq %%mm7, %%mm2 \n\t"
453 "psubusb %%mm7, %%mm5 \n\t"
454 "psubusb %%mm1, %%mm2 \n\t"
455 "por %%mm5, %%mm2 \n\t" // ABS Diff of lines
456 "psubusb %%mm0, %%mm2 \n\t" // diff <= QP -> 0
457 "pcmpeqb b00, %%mm2 \n\t" // diff <= QP -> FF
459 "pand %%mm2, %%mm7 \n\t"
460 "pandn %%mm1, %%mm2 \n\t"
461 "por %%mm2, %%mm7 \n\t" // First Line to Filter
465 // %0 %0+%1 %0+2%1 eax %0+4%1 eax+2%1 ebx eax+4%1
470 "movq (%0, %1), %%mm0 \n\t" // 1
471 "movq %%mm0, %%mm1 \n\t" // 1
472 PAVGB(%%mm6, %%mm0) //1 1 /2
473 PAVGB(%%mm6, %%mm0) //3 1 /4
475 "movq (%0, %1, 4), %%mm2 \n\t" // 1
476 "movq %%mm2, %%mm5 \n\t" // 1
477 PAVGB((%%eax), %%mm2) // 11 /2
478 PAVGB((%0, %1, 2), %%mm2) // 211 /4
479 "movq %%mm2, %%mm3 \n\t" // 211 /4
480 "movq (%0), %%mm4 \n\t" // 1
481 PAVGB(%%mm4, %%mm3) // 4 211 /8
482 PAVGB(%%mm0, %%mm3) //642211 /16
483 "movq %%mm3, (%0) \n\t" // X
484 // mm1=2 mm2=3(211) mm4=1 mm5=5 mm6=0 mm7=9
485 "movq %%mm1, %%mm0 \n\t" // 1
486 PAVGB(%%mm6, %%mm0) //1 1 /2
487 "movq %%mm4, %%mm3 \n\t" // 1
488 PAVGB((%0,%1,2), %%mm3) // 1 1 /2
489 PAVGB((%%eax,%1,2), %%mm5) // 11 /2
490 PAVGB((%%eax), %%mm5) // 211 /4
491 PAVGB(%%mm5, %%mm3) // 2 2211 /8
492 PAVGB(%%mm0, %%mm3) //4242211 /16
493 "movq %%mm3, (%0,%1) \n\t" // X
494 // mm1=2 mm2=3(211) mm4=1 mm5=4(211) mm6=0 mm7=9
495 PAVGB(%%mm4, %%mm6) //11 /2
496 "movq (%%ebx), %%mm0 \n\t" // 1
497 PAVGB((%%eax, %1, 2), %%mm0) // 11/2
498 "movq %%mm0, %%mm3 \n\t" // 11/2
499 PAVGB(%%mm1, %%mm0) // 2 11/4
500 PAVGB(%%mm6, %%mm0) //222 11/8
501 PAVGB(%%mm2, %%mm0) //22242211/16
502 "movq (%0, %1, 2), %%mm2 \n\t" // 1
503 "movq %%mm0, (%0, %1, 2) \n\t" // X
504 // mm1=2 mm2=3 mm3=6(11) mm4=1 mm5=4(211) mm6=0(11) mm7=9
505 "movq (%%eax, %1, 4), %%mm0 \n\t" // 1
506 PAVGB((%%ebx), %%mm0) // 11 /2
507 PAVGB(%%mm0, %%mm6) //11 11 /4
508 PAVGB(%%mm1, %%mm4) // 11 /2
509 PAVGB(%%mm2, %%mm1) // 11 /2
510 PAVGB(%%mm1, %%mm6) //1122 11 /8
511 PAVGB(%%mm5, %%mm6) //112242211 /16
512 "movq (%%eax), %%mm5 \n\t" // 1
513 "movq %%mm6, (%%eax) \n\t" // X
514 // mm0=7(11) mm1=2(11) mm2=3 mm3=6(11) mm4=1(11) mm5=4 mm7=9
515 "movq (%%eax, %1, 4), %%mm6 \n\t" // 1
516 PAVGB(%%mm7, %%mm6) // 11 /2
517 PAVGB(%%mm4, %%mm6) // 11 11 /4
518 PAVGB(%%mm3, %%mm6) // 11 2211 /8
519 PAVGB(%%mm5, %%mm2) // 11 /2
520 "movq (%0, %1, 4), %%mm4 \n\t" // 1
521 PAVGB(%%mm4, %%mm2) // 112 /4
522 PAVGB(%%mm2, %%mm6) // 112242211 /16
523 "movq %%mm6, (%0, %1, 4) \n\t" // X
524 // mm0=7(11) mm1=2(11) mm2=3(112) mm3=6(11) mm4=5 mm5=4 mm7=9
525 PAVGB(%%mm7, %%mm1) // 11 2 /4
526 PAVGB(%%mm4, %%mm5) // 11 /2
527 PAVGB(%%mm5, %%mm0) // 11 11 /4
528 "movq (%%eax, %1, 2), %%mm6 \n\t" // 1
529 PAVGB(%%mm6, %%mm1) // 11 4 2 /8
530 PAVGB(%%mm0, %%mm1) // 11224222 /16
531 "movq %%mm1, (%%eax, %1, 2) \n\t" // X
532 // mm2=3(112) mm3=6(11) mm4=5 mm5=4(11) mm6=6 mm7=9
533 PAVGB((%%ebx), %%mm2) // 112 4 /8
534 "movq (%%eax, %1, 4), %%mm0 \n\t" // 1
535 PAVGB(%%mm0, %%mm6) // 1 1 /2
536 PAVGB(%%mm7, %%mm6) // 1 12 /4
537 PAVGB(%%mm2, %%mm6) // 1122424 /4
538 "movq %%mm6, (%%ebx) \n\t" // X
539 // mm0=8 mm3=6(11) mm4=5 mm5=4(11) mm7=9
540 PAVGB(%%mm7, %%mm5) // 11 2 /4
541 PAVGB(%%mm7, %%mm5) // 11 6 /8
543 PAVGB(%%mm3, %%mm0) // 112 /4
544 PAVGB(%%mm0, %%mm5) // 112246 /16
545 "movq %%mm5, (%%eax, %1, 4) \n\t" // X
549 : "r" (src), "r" (stride)
553 const int l1= stride;
554 const int l2= stride + l1;
555 const int l3= stride + l2;
556 const int l4= stride + l3;
557 const int l5= stride + l4;
558 const int l6= stride + l5;
559 const int l7= stride + l6;
560 const int l8= stride + l7;
561 const int l9= stride + l8;
564 for(x=0; x<BLOCK_SIZE; x++)
566 const int first= ABS(src[0] - src[l1]) < QP ? src[0] : src[l1];
567 const int last= ABS(src[l8] - src[l9]) < QP ? src[l9] : src[l8];
570 sums[0] = first + src[l1];
571 sums[1] = src[l1] + src[l2];
572 sums[2] = src[l2] + src[l3];
573 sums[3] = src[l3] + src[l4];
574 sums[4] = src[l4] + src[l5];
575 sums[5] = src[l5] + src[l6];
576 sums[6] = src[l6] + src[l7];
577 sums[7] = src[l7] + src[l8];
578 sums[8] = src[l8] + last;
580 src[l1]= ((sums[0]<<2) + ((first + sums[2])<<1) + sums[4] + 8)>>4;
581 src[l2]= ((src[l2]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4;
582 src[l3]= ((src[l3]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4;
583 src[l4]= ((src[l4]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4;
584 src[l5]= ((src[l5]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4;
585 src[l6]= ((src[l6]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4;
586 src[l7]= (((last + src[l7])<<2) + ((src[l8] + sums[5])<<1) + sums[3] + 8)>>4;
587 src[l8]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4;
596 * Experimental implementation of the filter (Algorithm 1) described in a paper from Ramkishor & Karandikar
597 * values are correctly clipped (MMX2)
598 * values are wraparound (C)
599 * conclusion: its fast, but introduces ugly horizontal patterns if there is a continious gradient
606 static inline void vertRK1Filter(uint8_t *src, int stride, int QP)
608 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
612 "pxor %%mm7, %%mm7 \n\t" // 0
613 "movq b80, %%mm6 \n\t" // MIN_SIGNED_BYTE
614 "leal (%0, %1), %%eax \n\t"
615 "leal (%%eax, %1, 4), %%ebx \n\t"
616 // 0 1 2 3 4 5 6 7 8 9
617 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
618 "movq pQPb, %%mm0 \n\t" // QP,..., QP
619 "movq %%mm0, %%mm1 \n\t" // QP,..., QP
620 "paddusb b02, %%mm0 \n\t"
621 "psrlw $2, %%mm0 \n\t"
622 "pand b3F, %%mm0 \n\t" // QP/4,..., QP/4
623 "paddusb %%mm1, %%mm0 \n\t" // QP*1.25 ...
624 "movq (%0, %1, 4), %%mm2 \n\t" // line 4
625 "movq (%%ebx), %%mm3 \n\t" // line 5
626 "movq %%mm2, %%mm4 \n\t" // line 4
627 "pcmpeqb %%mm5, %%mm5 \n\t" // -1
628 "pxor %%mm2, %%mm5 \n\t" // -line 4 - 1
630 "paddb %%mm6, %%mm5 \n\t" // (l5-l4)/2
631 "psubusb %%mm3, %%mm4 \n\t"
632 "psubusb %%mm2, %%mm3 \n\t"
633 "por %%mm3, %%mm4 \n\t" // |l4 - l5|
634 "psubusb %%mm0, %%mm4 \n\t"
635 "pcmpeqb %%mm7, %%mm4 \n\t"
636 "pand %%mm4, %%mm5 \n\t" // d/2
638 // "paddb %%mm6, %%mm2 \n\t" // line 4 + 0x80
639 "paddb %%mm5, %%mm2 \n\t"
640 // "psubb %%mm6, %%mm2 \n\t"
641 "movq %%mm2, (%0,%1, 4) \n\t"
643 "movq (%%ebx), %%mm2 \n\t"
644 // "paddb %%mm6, %%mm2 \n\t" // line 5 + 0x80
645 "psubb %%mm5, %%mm2 \n\t"
646 // "psubb %%mm6, %%mm2 \n\t"
647 "movq %%mm2, (%%ebx) \n\t"
649 "paddb %%mm6, %%mm5 \n\t"
650 "psrlw $2, %%mm5 \n\t"
651 "pand b3F, %%mm5 \n\t"
652 "psubb b20, %%mm5 \n\t" // (l5-l4)/8
654 "movq (%%eax, %1, 2), %%mm2 \n\t"
655 "paddb %%mm6, %%mm2 \n\t" // line 3 + 0x80
656 "paddsb %%mm5, %%mm2 \n\t"
657 "psubb %%mm6, %%mm2 \n\t"
658 "movq %%mm2, (%%eax, %1, 2) \n\t"
660 "movq (%%ebx, %1), %%mm2 \n\t"
661 "paddb %%mm6, %%mm2 \n\t" // line 6 + 0x80
662 "psubsb %%mm5, %%mm2 \n\t"
663 "psubb %%mm6, %%mm2 \n\t"
664 "movq %%mm2, (%%ebx, %1) \n\t"
667 : "r" (src), "r" (stride)
671 const int l1= stride;
672 const int l2= stride + l1;
673 const int l3= stride + l2;
674 const int l4= stride + l3;
675 const int l5= stride + l4;
676 const int l6= stride + l5;
677 // const int l7= stride + l6;
678 // const int l8= stride + l7;
679 // const int l9= stride + l8;
681 const int QP15= QP + (QP>>2);
683 for(x=0; x<BLOCK_SIZE; x++)
685 const int v = (src[x+l5] - src[x+l4]);
700 * Experimental Filter 1
701 * will not damage linear gradients
702 * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter
703 * can only smooth blocks at the expected locations (it cant smooth them if they did move)
704 * MMX2 version does correct clipping C version doesnt
706 static inline void vertX1Filter(uint8_t *src, int stride, int QP)
708 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
712 "pxor %%mm7, %%mm7 \n\t" // 0
713 // "movq b80, %%mm6 \n\t" // MIN_SIGNED_BYTE
714 "leal (%0, %1), %%eax \n\t"
715 "leal (%%eax, %1, 4), %%ebx \n\t"
716 // 0 1 2 3 4 5 6 7 8 9
717 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
718 "movq (%%eax, %1, 2), %%mm0 \n\t" // line 3
719 "movq (%0, %1, 4), %%mm1 \n\t" // line 4
720 "movq %%mm1, %%mm2 \n\t" // line 4
721 "psubusb %%mm0, %%mm1 \n\t"
722 "psubusb %%mm2, %%mm0 \n\t"
723 "por %%mm1, %%mm0 \n\t" // |l2 - l3|
724 "movq (%%ebx), %%mm3 \n\t" // line 5
725 "movq (%%ebx, %1), %%mm4 \n\t" // line 6
726 "movq %%mm3, %%mm5 \n\t" // line 5
727 "psubusb %%mm4, %%mm3 \n\t"
728 "psubusb %%mm5, %%mm4 \n\t"
729 "por %%mm4, %%mm3 \n\t" // |l5 - l6|
730 PAVGB(%%mm3, %%mm0) // (|l2 - l3| + |l5 - l6|)/2
731 "movq %%mm2, %%mm1 \n\t" // line 4
732 "psubusb %%mm5, %%mm2 \n\t"
733 "movq %%mm2, %%mm4 \n\t"
734 "pcmpeqb %%mm7, %%mm2 \n\t" // (l4 - l5) <= 0 ? -1 : 0
735 "psubusb %%mm1, %%mm5 \n\t"
736 "por %%mm5, %%mm4 \n\t" // |l4 - l5|
737 "psubusb %%mm0, %%mm4 \n\t" //d = MAX(0, |l4-l5| - (|l2-l3| + |l5-l6|)/2)
738 "movq %%mm4, %%mm3 \n\t" // d
739 "psubusb pQPb, %%mm4 \n\t"
740 "pcmpeqb %%mm7, %%mm4 \n\t" // d <= QP ? -1 : 0
741 "psubusb b01, %%mm3 \n\t"
742 "pand %%mm4, %%mm3 \n\t" // d <= QP ? d : 0
744 PAVGB(%%mm7, %%mm3) // d/2
745 "movq %%mm3, %%mm1 \n\t" // d/2
746 PAVGB(%%mm7, %%mm3) // d/4
747 PAVGB(%%mm1, %%mm3) // 3*d/8
749 "movq (%0, %1, 4), %%mm0 \n\t" // line 4
750 "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
751 "psubusb %%mm3, %%mm0 \n\t"
752 "pxor %%mm2, %%mm0 \n\t"
753 "movq %%mm0, (%0, %1, 4) \n\t" // line 4
755 "movq (%%ebx), %%mm0 \n\t" // line 5
756 "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
757 "paddusb %%mm3, %%mm0 \n\t"
758 "pxor %%mm2, %%mm0 \n\t"
759 "movq %%mm0, (%%ebx) \n\t" // line 5
761 PAVGB(%%mm7, %%mm1) // d/4
763 "movq (%%eax, %1, 2), %%mm0 \n\t" // line 3
764 "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l4-1 : l4
765 "psubusb %%mm1, %%mm0 \n\t"
766 "pxor %%mm2, %%mm0 \n\t"
767 "movq %%mm0, (%%eax, %1, 2) \n\t" // line 3
769 "movq (%%ebx, %1), %%mm0 \n\t" // line 6
770 "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l5-1 : l5
771 "paddusb %%mm1, %%mm0 \n\t"
772 "pxor %%mm2, %%mm0 \n\t"
773 "movq %%mm0, (%%ebx, %1) \n\t" // line 6
775 PAVGB(%%mm7, %%mm1) // d/8
777 "movq (%%eax, %1), %%mm0 \n\t" // line 2
778 "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l2-1 : l2
779 "psubusb %%mm1, %%mm0 \n\t"
780 "pxor %%mm2, %%mm0 \n\t"
781 "movq %%mm0, (%%eax, %1) \n\t" // line 2
783 "movq (%%ebx, %1, 2), %%mm0 \n\t" // line 7
784 "pxor %%mm2, %%mm0 \n\t" //(l4 - l5) <= 0 ? -l7-1 : l7
785 "paddusb %%mm1, %%mm0 \n\t"
786 "pxor %%mm2, %%mm0 \n\t"
787 "movq %%mm0, (%%ebx, %1, 2) \n\t" // line 7
790 : "r" (src), "r" (stride)
795 const int l1= stride;
796 const int l2= stride + l1;
797 const int l3= stride + l2;
798 const int l4= stride + l3;
799 const int l5= stride + l4;
800 const int l6= stride + l5;
801 const int l7= stride + l6;
802 // const int l8= stride + l7;
803 // const int l9= stride + l8;
807 for(x=0; x<BLOCK_SIZE; x++)
809 int a= src[l3] - src[l4];
810 int b= src[l4] - src[l5];
811 int c= src[l5] - src[l6];
813 int d= ABS(b) - ((ABS(a) + ABS(c))>>1);
818 int v = d * SIGN(-b);
831 const int l1= stride;
832 const int l2= stride + l1;
833 const int l3= stride + l2;
834 const int l4= stride + l3;
835 const int l5= stride + l4;
836 const int l6= stride + l5;
837 const int l7= stride + l6;
838 const int l8= stride + l7;
839 const int l9= stride + l8;
840 for(int x=0; x<BLOCK_SIZE; x++)
849 if(ABS(v4-v5)<QP && ABS(v4-v5) - (ABS(v3-v4) + ABS(v5-v6))>0 )
851 src[l3] = (6*v2 + 4*v3 + 3*v4 + 2*v5 + v6 )/16;
852 src[l4] = (3*v2 + 3*v3 + 4*v4 + 3*v5 + 2*v6 + v7 )/16;
853 src[l5] = (1*v2 + 2*v3 + 3*v4 + 4*v5 + 3*v6 + 3*v7)/16;
854 src[l6] = ( 1*v3 + 2*v4 + 3*v5 + 4*v6 + 6*v7)/16;
862 static inline void doVertDefFilter(uint8_t src[], int stride, int QP)
864 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
867 const int l1= stride;
868 const int l2= stride + l1;
869 const int l3= stride + l2;
870 const int l4= (int)tmp - (int)src - stride*3;
871 const int l5= (int)tmp - (int)src - stride*3 + 8;
872 const int l6= stride*3 + l3;
873 const int l7= stride + l6;
874 const int l8= stride + l7;
876 memcpy(tmp, src+stride*7, 8);
877 memcpy(tmp+8, src+stride*8, 8);
882 #if 0 //sligtly more accurate and slightly slower
883 "pxor %%mm7, %%mm7 \n\t" // 0
884 "leal (%0, %1), %%eax \n\t"
885 "leal (%%eax, %1, 4), %%ebx \n\t"
887 // %0 %0+%1 %0+2%1 eax+2%1 %0+4%1 eax+4%1 ebx+%1 ebx+2%1
888 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1
891 "movq (%0, %1, 2), %%mm0 \n\t" // l2
892 "movq (%0), %%mm1 \n\t" // l0
893 "movq %%mm0, %%mm2 \n\t" // l2
894 PAVGB(%%mm7, %%mm0) // ~l2/2
895 PAVGB(%%mm1, %%mm0) // ~(l2 + 2l0)/4
896 PAVGB(%%mm2, %%mm0) // ~(5l2 + 2l0)/8
898 "movq (%%eax), %%mm1 \n\t" // l1
899 "movq (%%eax, %1, 2), %%mm3 \n\t" // l3
900 "movq %%mm1, %%mm4 \n\t" // l1
901 PAVGB(%%mm7, %%mm1) // ~l1/2
902 PAVGB(%%mm3, %%mm1) // ~(l1 + 2l3)/4
903 PAVGB(%%mm4, %%mm1) // ~(5l1 + 2l3)/8
905 "movq %%mm0, %%mm4 \n\t" // ~(5l2 + 2l0)/8
906 "psubusb %%mm1, %%mm0 \n\t"
907 "psubusb %%mm4, %%mm1 \n\t"
908 "por %%mm0, %%mm1 \n\t" // ~|2l0 - 5l1 + 5l2 - 2l3|/8
909 // mm1= |lenergy|, mm2= l2, mm3= l3, mm7=0
911 "movq (%0, %1, 4), %%mm0 \n\t" // l4
912 "movq %%mm0, %%mm4 \n\t" // l4
913 PAVGB(%%mm7, %%mm0) // ~l4/2
914 PAVGB(%%mm2, %%mm0) // ~(l4 + 2l2)/4
915 PAVGB(%%mm4, %%mm0) // ~(5l4 + 2l2)/8
917 "movq (%%ebx), %%mm2 \n\t" // l5
918 "movq %%mm3, %%mm5 \n\t" // l3
919 PAVGB(%%mm7, %%mm3) // ~l3/2
920 PAVGB(%%mm2, %%mm3) // ~(l3 + 2l5)/4
921 PAVGB(%%mm5, %%mm3) // ~(5l3 + 2l5)/8
923 "movq %%mm0, %%mm6 \n\t" // ~(5l4 + 2l2)/8
924 "psubusb %%mm3, %%mm0 \n\t"
925 "psubusb %%mm6, %%mm3 \n\t"
926 "por %%mm0, %%mm3 \n\t" // ~|2l2 - 5l3 + 5l4 - 2l5|/8
927 "pcmpeqb %%mm7, %%mm0 \n\t" // SIGN(2l2 - 5l3 + 5l4 - 2l5)
928 // mm0= SIGN(menergy), mm1= |lenergy|, mm2= l5, mm3= |menergy|, mm4=l4, mm5= l3, mm7=0
930 "movq (%%ebx, %1), %%mm6 \n\t" // l6
931 "movq %%mm6, %%mm5 \n\t" // l6
932 PAVGB(%%mm7, %%mm6) // ~l6/2
933 PAVGB(%%mm4, %%mm6) // ~(l6 + 2l4)/4
934 PAVGB(%%mm5, %%mm6) // ~(5l6 + 2l4)/8
936 "movq (%%ebx, %1, 2), %%mm5 \n\t" // l7
937 "movq %%mm2, %%mm4 \n\t" // l5
938 PAVGB(%%mm7, %%mm2) // ~l5/2
939 PAVGB(%%mm5, %%mm2) // ~(l5 + 2l7)/4
940 PAVGB(%%mm4, %%mm2) // ~(5l5 + 2l7)/8
942 "movq %%mm6, %%mm4 \n\t" // ~(5l6 + 2l4)/8
943 "psubusb %%mm2, %%mm6 \n\t"
944 "psubusb %%mm4, %%mm2 \n\t"
945 "por %%mm6, %%mm2 \n\t" // ~|2l4 - 5l5 + 5l6 - 2l7|/8
946 // mm0= SIGN(menergy), mm1= |lenergy|/8, mm2= |renergy|/8, mm3= |menergy|/8, mm7=0
949 PMINUB(%%mm2, %%mm1, %%mm4) // MIN(|lenergy|,|renergy|)/8
950 "movq pQPb, %%mm4 \n\t" // QP //FIXME QP+1 ?
951 "paddusb b01, %%mm4 \n\t"
952 "pcmpgtb %%mm3, %%mm4 \n\t" // |menergy|/8 < QP
953 "psubusb %%mm1, %%mm3 \n\t" // d=|menergy|/8-MIN(|lenergy|,|renergy|)/8
954 "pand %%mm4, %%mm3 \n\t"
956 "movq %%mm3, %%mm1 \n\t"
957 // "psubusb b01, %%mm3 \n\t"
960 "paddusb %%mm1, %%mm3 \n\t"
961 // "paddusb b01, %%mm3 \n\t"
963 "movq (%%eax, %1, 2), %%mm6 \n\t" //l3
964 "movq (%0, %1, 4), %%mm5 \n\t" //l4
965 "movq (%0, %1, 4), %%mm4 \n\t" //l4
966 "psubusb %%mm6, %%mm5 \n\t"
967 "psubusb %%mm4, %%mm6 \n\t"
968 "por %%mm6, %%mm5 \n\t" // |l3-l4|
969 "pcmpeqb %%mm7, %%mm6 \n\t" // SIGN(l3-l4)
970 "pxor %%mm6, %%mm0 \n\t"
971 "pand %%mm0, %%mm3 \n\t"
972 PMINUB(%%mm5, %%mm3, %%mm0)
974 "psubusb b01, %%mm3 \n\t"
977 "movq (%%eax, %1, 2), %%mm0 \n\t"
978 "movq (%0, %1, 4), %%mm2 \n\t"
979 "pxor %%mm6, %%mm0 \n\t"
980 "pxor %%mm6, %%mm2 \n\t"
981 "psubb %%mm3, %%mm0 \n\t"
982 "paddb %%mm3, %%mm2 \n\t"
983 "pxor %%mm6, %%mm0 \n\t"
984 "pxor %%mm6, %%mm2 \n\t"
985 "movq %%mm0, (%%eax, %1, 2) \n\t"
986 "movq %%mm2, (%0, %1, 4) \n\t"
989 "leal (%0, %1), %%eax \n\t"
990 "pcmpeqb %%mm6, %%mm6 \n\t" // -1
992 // %0 %0+%1 %0+2%1 eax+2%1 %0+4%1 eax+4%1 ebx+%1 ebx+2%1
993 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1
996 "movq (%%eax, %1, 2), %%mm1 \n\t" // l3
997 "movq (%0, %1, 4), %%mm0 \n\t" // l4
998 "pxor %%mm6, %%mm1 \n\t" // -l3-1
999 PAVGB(%%mm1, %%mm0) // -q+128 = (l4-l3+256)/2
1000 // mm1=-l3-1, mm0=128-q
1002 "movq (%%eax, %1, 4), %%mm2 \n\t" // l5
1003 "movq (%%eax, %1), %%mm3 \n\t" // l2
1004 "pxor %%mm6, %%mm2 \n\t" // -l5-1
1005 "movq %%mm2, %%mm5 \n\t" // -l5-1
1006 "movq b80, %%mm4 \n\t" // 128
1007 "leal (%%eax, %1, 4), %%ebx \n\t"
1008 PAVGB(%%mm3, %%mm2) // (l2-l5+256)/2
1009 PAVGB(%%mm0, %%mm4) // ~(l4-l3)/4 + 128
1010 PAVGB(%%mm2, %%mm4) // ~(l2-l5)/4 +(l4-l3)/8 + 128
1011 PAVGB(%%mm0, %%mm4) // ~(l2-l5)/8 +5(l4-l3)/16 + 128
1012 // mm1=-l3-1, mm0=128-q, mm3=l2, mm4=menergy/16 + 128, mm5= -l5-1
1014 "movq (%%eax), %%mm2 \n\t" // l1
1015 "pxor %%mm6, %%mm2 \n\t" // -l1-1
1016 PAVGB(%%mm3, %%mm2) // (l2-l1+256)/2
1017 PAVGB((%0), %%mm1) // (l0-l3+256)/2
1018 "movq b80, %%mm3 \n\t" // 128
1019 PAVGB(%%mm2, %%mm3) // ~(l2-l1)/4 + 128
1020 PAVGB(%%mm1, %%mm3) // ~(l0-l3)/4 +(l2-l1)/8 + 128
1021 PAVGB(%%mm2, %%mm3) // ~(l0-l3)/8 +5(l2-l1)/16 + 128
1022 // mm0=128-q, mm3=lenergy/16 + 128, mm4= menergy/16 + 128, mm5= -l5-1
1024 PAVGB((%%ebx, %1), %%mm5) // (l6-l5+256)/2
1025 "movq (%%ebx, %1, 2), %%mm1 \n\t" // l7
1026 "pxor %%mm6, %%mm1 \n\t" // -l7-1
1027 PAVGB((%0, %1, 4), %%mm1) // (l4-l7+256)/2
1028 "movq b80, %%mm2 \n\t" // 128
1029 PAVGB(%%mm5, %%mm2) // ~(l6-l5)/4 + 128
1030 PAVGB(%%mm1, %%mm2) // ~(l4-l7)/4 +(l6-l5)/8 + 128
1031 PAVGB(%%mm5, %%mm2) // ~(l4-l7)/8 +5(l6-l5)/16 + 128
1032 // mm0=128-q, mm2=renergy/16 + 128, mm3=lenergy/16 + 128, mm4= menergy/16 + 128
1034 "movq b00, %%mm1 \n\t" // 0
1035 "movq b00, %%mm5 \n\t" // 0
1036 "psubb %%mm2, %%mm1 \n\t" // 128 - renergy/16
1037 "psubb %%mm3, %%mm5 \n\t" // 128 - lenergy/16
1038 PMAXUB(%%mm1, %%mm2) // 128 + |renergy/16|
1039 PMAXUB(%%mm5, %%mm3) // 128 + |lenergy/16|
1040 PMINUB(%%mm2, %%mm3, %%mm1) // 128 + MIN(|lenergy|,|renergy|)/16
1042 // mm0=128-q, mm3=128 + MIN(|lenergy|,|renergy|)/16, mm4= menergy/16 + 128
1044 "movq b00, %%mm7 \n\t" // 0
1045 "movq pQPb, %%mm2 \n\t" // QP
1046 PAVGB(%%mm6, %%mm2) // 128 + QP/2
1047 "psubb %%mm6, %%mm2 \n\t"
1049 "movq %%mm4, %%mm1 \n\t"
1050 "pcmpgtb %%mm7, %%mm1 \n\t" // SIGN(menergy)
1051 "pxor %%mm1, %%mm4 \n\t"
1052 "psubb %%mm1, %%mm4 \n\t" // 128 + |menergy|/16
1053 "pcmpgtb %%mm4, %%mm2 \n\t" // |menergy|/16 < QP/2
1054 "psubusb %%mm3, %%mm4 \n\t" //d=|menergy|/16 - MIN(|lenergy|,|renergy|)/16
1055 // mm0=128-q, mm1= SIGN(menergy), mm2= |menergy|/16 < QP/2, mm4= d/16
1057 "movq %%mm4, %%mm3 \n\t" // d
1058 "psubusb b01, %%mm4 \n\t"
1059 PAVGB(%%mm7, %%mm4) // d/32
1060 PAVGB(%%mm7, %%mm4) // (d + 32)/64
1061 "paddb %%mm3, %%mm4 \n\t" // 5d/64
1062 "pand %%mm2, %%mm4 \n\t"
1064 "movq b80, %%mm5 \n\t" // 128
1065 "psubb %%mm0, %%mm5 \n\t" // q
1066 "paddsb %%mm6, %%mm5 \n\t" // fix bad rounding
1067 "pcmpgtb %%mm5, %%mm7 \n\t" // SIGN(q)
1068 "pxor %%mm7, %%mm5 \n\t"
1070 PMINUB(%%mm5, %%mm4, %%mm3) // MIN(|q|, 5d/64)
1071 "pxor %%mm1, %%mm7 \n\t" // SIGN(d*q)
1073 "pand %%mm7, %%mm4 \n\t"
1074 "movq (%%eax, %1, 2), %%mm0 \n\t"
1075 "movq (%0, %1, 4), %%mm2 \n\t"
1076 "pxor %%mm1, %%mm0 \n\t"
1077 "pxor %%mm1, %%mm2 \n\t"
1078 "paddb %%mm4, %%mm0 \n\t"
1079 "psubb %%mm4, %%mm2 \n\t"
1080 "pxor %%mm1, %%mm0 \n\t"
1081 "pxor %%mm1, %%mm2 \n\t"
1082 "movq %%mm0, (%%eax, %1, 2) \n\t"
1083 "movq %%mm2, (%0, %1, 4) \n\t"
1086 : "r" (src), "r" (stride)
1094 for(x=0; x<BLOCK_SIZE; x++)
1096 const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
1097 if(ABS(middleEnergy)< 8*QP)
1099 const int q=(src[l4] - src[l5])/2;
1100 const int leftEnergy= 5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
1101 const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
1103 int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) );
1107 d*= SIGN(-middleEnergy);
1131 int d= src[x+y*stride] - tmp[x+(y-4)*8];
1142 src[0] = src[7] = src[stride*7] = src[(stride+1)*7]=255;
1146 if(num%1000000 == 0)
1148 printf(" %d %d %d %d\n", num, sum, max, bias);
1154 #elif defined (HAVE_MMX)
1158 "pxor %%mm7, %%mm7 \n\t"
1159 "leal (%0, %1), %%eax \n\t"
1160 "leal (%%eax, %1, 4), %%ebx \n\t"
1162 // %0 %0+%1 %0+2%1 eax+2%1 %0+4%1 eax+4%1 ebx+%1 ebx+2%1
1163 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1
1165 "movq (%0), %%mm0 \n\t"
1166 "movq %%mm0, %%mm1 \n\t"
1167 "punpcklbw %%mm7, %%mm0 \n\t" // low part of line 0
1168 "punpckhbw %%mm7, %%mm1 \n\t" // high part of line 0
1170 "movq (%%eax), %%mm2 \n\t"
1171 "movq %%mm2, %%mm3 \n\t"
1172 "punpcklbw %%mm7, %%mm2 \n\t" // low part of line 1
1173 "punpckhbw %%mm7, %%mm3 \n\t" // high part of line 1
1175 "movq (%%eax, %1), %%mm4 \n\t"
1176 "movq %%mm4, %%mm5 \n\t"
1177 "punpcklbw %%mm7, %%mm4 \n\t" // low part of line 2
1178 "punpckhbw %%mm7, %%mm5 \n\t" // high part of line 2
1180 "paddw %%mm0, %%mm0 \n\t" // 2L0
1181 "paddw %%mm1, %%mm1 \n\t" // 2H0
1182 "psubw %%mm4, %%mm2 \n\t" // L1 - L2
1183 "psubw %%mm5, %%mm3 \n\t" // H1 - H2
1184 "psubw %%mm2, %%mm0 \n\t" // 2L0 - L1 + L2
1185 "psubw %%mm3, %%mm1 \n\t" // 2H0 - H1 + H2
1187 "psllw $2, %%mm2 \n\t" // 4L1 - 4L2
1188 "psllw $2, %%mm3 \n\t" // 4H1 - 4H2
1189 "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2
1190 "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2
1192 "movq (%%eax, %1, 2), %%mm2 \n\t"
1193 "movq %%mm2, %%mm3 \n\t"
1194 "punpcklbw %%mm7, %%mm2 \n\t" // L3
1195 "punpckhbw %%mm7, %%mm3 \n\t" // H3
1197 "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2 - L3
1198 "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2 - H3
1199 "psubw %%mm2, %%mm0 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
1200 "psubw %%mm3, %%mm1 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
1201 "movq %%mm0, temp0 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
1202 "movq %%mm1, temp1 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
1204 "movq (%0, %1, 4), %%mm0 \n\t"
1205 "movq %%mm0, %%mm1 \n\t"
1206 "punpcklbw %%mm7, %%mm0 \n\t" // L4
1207 "punpckhbw %%mm7, %%mm1 \n\t" // H4
1209 "psubw %%mm0, %%mm2 \n\t" // L3 - L4
1210 "psubw %%mm1, %%mm3 \n\t" // H3 - H4
1211 "movq %%mm2, temp2 \n\t" // L3 - L4
1212 "movq %%mm3, temp3 \n\t" // H3 - H4
1213 "paddw %%mm4, %%mm4 \n\t" // 2L2
1214 "paddw %%mm5, %%mm5 \n\t" // 2H2
1215 "psubw %%mm2, %%mm4 \n\t" // 2L2 - L3 + L4
1216 "psubw %%mm3, %%mm5 \n\t" // 2H2 - H3 + H4
1218 "psllw $2, %%mm2 \n\t" // 4L3 - 4L4
1219 "psllw $2, %%mm3 \n\t" // 4H3 - 4H4
1220 "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4
1221 "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4
1223 "movq (%%ebx), %%mm2 \n\t"
1224 "movq %%mm2, %%mm3 \n\t"
1225 "punpcklbw %%mm7, %%mm2 \n\t" // L5
1226 "punpckhbw %%mm7, %%mm3 \n\t" // H5
1227 "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4 - L5
1228 "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4 - H5
1229 "psubw %%mm2, %%mm4 \n\t" // 2L2 - 5L3 + 5L4 - 2L5
1230 "psubw %%mm3, %%mm5 \n\t" // 2H2 - 5H3 + 5H4 - 2H5
1232 "movq (%%ebx, %1), %%mm6 \n\t"
1233 "punpcklbw %%mm7, %%mm6 \n\t" // L6
1234 "psubw %%mm6, %%mm2 \n\t" // L5 - L6
1235 "movq (%%ebx, %1), %%mm6 \n\t"
1236 "punpckhbw %%mm7, %%mm6 \n\t" // H6
1237 "psubw %%mm6, %%mm3 \n\t" // H5 - H6
1239 "paddw %%mm0, %%mm0 \n\t" // 2L4
1240 "paddw %%mm1, %%mm1 \n\t" // 2H4
1241 "psubw %%mm2, %%mm0 \n\t" // 2L4 - L5 + L6
1242 "psubw %%mm3, %%mm1 \n\t" // 2H4 - H5 + H6
1244 "psllw $2, %%mm2 \n\t" // 4L5 - 4L6
1245 "psllw $2, %%mm3 \n\t" // 4H5 - 4H6
1246 "psubw %%mm2, %%mm0 \n\t" // 2L4 - 5L5 + 5L6
1247 "psubw %%mm3, %%mm1 \n\t" // 2H4 - 5H5 + 5H6
1249 "movq (%%ebx, %1, 2), %%mm2 \n\t"
1250 "movq %%mm2, %%mm3 \n\t"
1251 "punpcklbw %%mm7, %%mm2 \n\t" // L7
1252 "punpckhbw %%mm7, %%mm3 \n\t" // H7
1254 "paddw %%mm2, %%mm2 \n\t" // 2L7
1255 "paddw %%mm3, %%mm3 \n\t" // 2H7
1256 "psubw %%mm2, %%mm0 \n\t" // 2L4 - 5L5 + 5L6 - 2L7
1257 "psubw %%mm3, %%mm1 \n\t" // 2H4 - 5H5 + 5H6 - 2H7
1259 "movq temp0, %%mm2 \n\t" // 2L0 - 5L1 + 5L2 - 2L3
1260 "movq temp1, %%mm3 \n\t" // 2H0 - 5H1 + 5H2 - 2H3
1263 "movq %%mm7, %%mm6 \n\t" // 0
1264 "psubw %%mm0, %%mm6 \n\t"
1265 "pmaxsw %%mm6, %%mm0 \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
1266 "movq %%mm7, %%mm6 \n\t" // 0
1267 "psubw %%mm1, %%mm6 \n\t"
1268 "pmaxsw %%mm6, %%mm1 \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
1269 "movq %%mm7, %%mm6 \n\t" // 0
1270 "psubw %%mm2, %%mm6 \n\t"
1271 "pmaxsw %%mm6, %%mm2 \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
1272 "movq %%mm7, %%mm6 \n\t" // 0
1273 "psubw %%mm3, %%mm6 \n\t"
1274 "pmaxsw %%mm6, %%mm3 \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
1276 "movq %%mm7, %%mm6 \n\t" // 0
1277 "pcmpgtw %%mm0, %%mm6 \n\t"
1278 "pxor %%mm6, %%mm0 \n\t"
1279 "psubw %%mm6, %%mm0 \n\t" // |2L4 - 5L5 + 5L6 - 2L7|
1280 "movq %%mm7, %%mm6 \n\t" // 0
1281 "pcmpgtw %%mm1, %%mm6 \n\t"
1282 "pxor %%mm6, %%mm1 \n\t"
1283 "psubw %%mm6, %%mm1 \n\t" // |2H4 - 5H5 + 5H6 - 2H7|
1284 "movq %%mm7, %%mm6 \n\t" // 0
1285 "pcmpgtw %%mm2, %%mm6 \n\t"
1286 "pxor %%mm6, %%mm2 \n\t"
1287 "psubw %%mm6, %%mm2 \n\t" // |2L0 - 5L1 + 5L2 - 2L3|
1288 "movq %%mm7, %%mm6 \n\t" // 0
1289 "pcmpgtw %%mm3, %%mm6 \n\t"
1290 "pxor %%mm6, %%mm3 \n\t"
1291 "psubw %%mm6, %%mm3 \n\t" // |2H0 - 5H1 + 5H2 - 2H3|
1295 "pminsw %%mm2, %%mm0 \n\t"
1296 "pminsw %%mm3, %%mm1 \n\t"
1298 "movq %%mm0, %%mm6 \n\t"
1299 "psubusw %%mm2, %%mm6 \n\t"
1300 "psubw %%mm6, %%mm0 \n\t"
1301 "movq %%mm1, %%mm6 \n\t"
1302 "psubusw %%mm3, %%mm6 \n\t"
1303 "psubw %%mm6, %%mm1 \n\t"
1306 "movq %%mm7, %%mm6 \n\t" // 0
1307 "pcmpgtw %%mm4, %%mm6 \n\t" // sign(2L2 - 5L3 + 5L4 - 2L5)
1308 "pxor %%mm6, %%mm4 \n\t"
1309 "psubw %%mm6, %%mm4 \n\t" // |2L2 - 5L3 + 5L4 - 2L5|
1310 "pcmpgtw %%mm5, %%mm7 \n\t" // sign(2H2 - 5H3 + 5H4 - 2H5)
1311 "pxor %%mm7, %%mm5 \n\t"
1312 "psubw %%mm7, %%mm5 \n\t" // |2H2 - 5H3 + 5H4 - 2H5|
1314 "movd %2, %%mm2 \n\t" // QP
1315 "punpcklwd %%mm2, %%mm2 \n\t"
1316 "punpcklwd %%mm2, %%mm2 \n\t"
1317 "psllw $3, %%mm2 \n\t" // 8QP
1318 "movq %%mm2, %%mm3 \n\t" // 8QP
1319 "pcmpgtw %%mm4, %%mm2 \n\t"
1320 "pcmpgtw %%mm5, %%mm3 \n\t"
1321 "pand %%mm2, %%mm4 \n\t"
1322 "pand %%mm3, %%mm5 \n\t"
1325 "psubusw %%mm0, %%mm4 \n\t" // hd
1326 "psubusw %%mm1, %%mm5 \n\t" // ld
1329 "movq w05, %%mm2 \n\t" // 5
1330 "pmullw %%mm2, %%mm4 \n\t"
1331 "pmullw %%mm2, %%mm5 \n\t"
1332 "movq w20, %%mm2 \n\t" // 32
1333 "paddw %%mm2, %%mm4 \n\t"
1334 "paddw %%mm2, %%mm5 \n\t"
1335 "psrlw $6, %%mm4 \n\t"
1336 "psrlw $6, %%mm5 \n\t"
1339 "movq w06, %%mm2 \n\t" // 6
1340 "paddw %%mm2, %%mm4 \n\t"
1341 "paddw %%mm2, %%mm5 \n\t"
1342 "movq w1400, %%mm2 \n\t" // 1400h = 5120 = 5/64*2^16
1343 //FIXME if *5/64 is supposed to be /13 then we should use 5041 instead of 5120
1344 "pmulhw %%mm2, %%mm4 \n\t" // hd/13
1345 "pmulhw %%mm2, %%mm5 \n\t" // ld/13
1348 "movq temp2, %%mm0 \n\t" // L3 - L4
1349 "movq temp3, %%mm1 \n\t" // H3 - H4
1351 "pxor %%mm2, %%mm2 \n\t"
1352 "pxor %%mm3, %%mm3 \n\t"
1354 "pcmpgtw %%mm0, %%mm2 \n\t" // sign (L3-L4)
1355 "pcmpgtw %%mm1, %%mm3 \n\t" // sign (H3-H4)
1356 "pxor %%mm2, %%mm0 \n\t"
1357 "pxor %%mm3, %%mm1 \n\t"
1358 "psubw %%mm2, %%mm0 \n\t" // |L3-L4|
1359 "psubw %%mm3, %%mm1 \n\t" // |H3-H4|
1360 "psrlw $1, %%mm0 \n\t" // |L3 - L4|/2
1361 "psrlw $1, %%mm1 \n\t" // |H3 - H4|/2
1363 "pxor %%mm6, %%mm2 \n\t"
1364 "pxor %%mm7, %%mm3 \n\t"
1365 "pand %%mm2, %%mm4 \n\t"
1366 "pand %%mm3, %%mm5 \n\t"
1369 "pminsw %%mm0, %%mm4 \n\t"
1370 "pminsw %%mm1, %%mm5 \n\t"
1372 "movq %%mm4, %%mm2 \n\t"
1373 "psubusw %%mm0, %%mm2 \n\t"
1374 "psubw %%mm2, %%mm4 \n\t"
1375 "movq %%mm5, %%mm2 \n\t"
1376 "psubusw %%mm1, %%mm2 \n\t"
1377 "psubw %%mm2, %%mm5 \n\t"
1379 "pxor %%mm6, %%mm4 \n\t"
1380 "pxor %%mm7, %%mm5 \n\t"
1381 "psubw %%mm6, %%mm4 \n\t"
1382 "psubw %%mm7, %%mm5 \n\t"
1383 "packsswb %%mm5, %%mm4 \n\t"
1384 "movq (%%eax, %1, 2), %%mm0 \n\t"
1385 "paddb %%mm4, %%mm0 \n\t"
1386 "movq %%mm0, (%%eax, %1, 2) \n\t"
1387 "movq (%0, %1, 4), %%mm0 \n\t"
1388 "psubb %%mm4, %%mm0 \n\t"
1389 "movq %%mm0, (%0, %1, 4) \n\t"
1392 : "r" (src), "r" (stride), "r" (QP)
1396 const int l1= stride;
1397 const int l2= stride + l1;
1398 const int l3= stride + l2;
1399 const int l4= stride + l3;
1400 const int l5= stride + l4;
1401 const int l6= stride + l5;
1402 const int l7= stride + l6;
1403 const int l8= stride + l7;
1404 // const int l9= stride + l8;
1407 for(x=0; x<BLOCK_SIZE; x++)
1409 const int middleEnergy= 5*(src[l5] - src[l4]) + 2*(src[l3] - src[l6]);
1410 if(ABS(middleEnergy) < 8*QP)
1412 const int q=(src[l4] - src[l5])/2;
1413 const int leftEnergy= 5*(src[l3] - src[l2]) + 2*(src[l1] - src[l4]);
1414 const int rightEnergy= 5*(src[l7] - src[l6]) + 2*(src[l5] - src[l8]);
1416 int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) );
1420 d*= SIGN(-middleEnergy);
1441 static inline void dering(uint8_t src[], int stride, int QP)
1443 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1445 "movq pQPb, %%mm0 \n\t"
1446 "paddusb %%mm0, %%mm0 \n\t"
1447 "movq %%mm0, pQPb2 \n\t"
1449 "leal (%0, %1), %%eax \n\t"
1450 "leal (%%eax, %1, 4), %%ebx \n\t"
1451 // 0 1 2 3 4 5 6 7 8 9
1452 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
1454 "pcmpeqb %%mm6, %%mm6 \n\t"
1455 "pxor %%mm7, %%mm7 \n\t"
1457 #define FIND_MIN_MAX(addr)\
1458 "movq " #addr ", %%mm0 \n\t"\
1459 "pminub %%mm0, %%mm6 \n\t"\
1460 "pmaxub %%mm0, %%mm7 \n\t"
1462 #define FIND_MIN_MAX(addr)\
1463 "movq " #addr ", %%mm0 \n\t"\
1464 "movq %%mm6, %%mm1 \n\t"\
1465 "psubusb %%mm0, %%mm7 \n\t"\
1466 "paddb %%mm0, %%mm7 \n\t"\
1467 "psubusb %%mm0, %%mm1 \n\t"\
1468 "psubb %%mm1, %%mm6 \n\t"
1471 FIND_MIN_MAX((%%eax))
1472 FIND_MIN_MAX((%%eax, %1))
1473 FIND_MIN_MAX((%%eax, %1, 2))
1474 FIND_MIN_MAX((%0, %1, 4))
1475 FIND_MIN_MAX((%%ebx))
1476 FIND_MIN_MAX((%%ebx, %1))
1477 FIND_MIN_MAX((%%ebx, %1, 2))
1478 FIND_MIN_MAX((%0, %1, 8))
1480 "movq %%mm6, %%mm4 \n\t"
1481 "psrlq $8, %%mm6 \n\t"
1483 "pminub %%mm4, %%mm6 \n\t" // min of pixels
1484 "pshufw $0xF9, %%mm6, %%mm4 \n\t"
1485 "pminub %%mm4, %%mm6 \n\t" // min of pixels
1486 "pshufw $0xFE, %%mm6, %%mm4 \n\t"
1487 "pminub %%mm4, %%mm6 \n\t"
1489 "movq %%mm6, %%mm1 \n\t"
1490 "psubusb %%mm4, %%mm1 \n\t"
1491 "psubb %%mm1, %%mm6 \n\t"
1492 "movq %%mm6, %%mm4 \n\t"
1493 "psrlq $16, %%mm6 \n\t"
1494 "movq %%mm6, %%mm1 \n\t"
1495 "psubusb %%mm4, %%mm1 \n\t"
1496 "psubb %%mm1, %%mm6 \n\t"
1497 "movq %%mm6, %%mm4 \n\t"
1498 "psrlq $32, %%mm6 \n\t"
1499 "movq %%mm6, %%mm1 \n\t"
1500 "psubusb %%mm4, %%mm1 \n\t"
1501 "psubb %%mm1, %%mm6 \n\t"
1505 "movq %%mm7, %%mm4 \n\t"
1506 "psrlq $8, %%mm7 \n\t"
1508 "pmaxub %%mm4, %%mm7 \n\t" // max of pixels
1509 "pshufw $0xF9, %%mm7, %%mm4 \n\t"
1510 "pmaxub %%mm4, %%mm7 \n\t"
1511 "pshufw $0xFE, %%mm7, %%mm4 \n\t"
1512 "pmaxub %%mm4, %%mm7 \n\t"
1514 "psubusb %%mm4, %%mm7 \n\t"
1515 "paddb %%mm4, %%mm7 \n\t"
1516 "movq %%mm7, %%mm4 \n\t"
1517 "psrlq $16, %%mm7 \n\t"
1518 "psubusb %%mm4, %%mm7 \n\t"
1519 "paddb %%mm4, %%mm7 \n\t"
1520 "movq %%mm7, %%mm4 \n\t"
1521 "psrlq $32, %%mm7 \n\t"
1522 "psubusb %%mm4, %%mm7 \n\t"
1523 "paddb %%mm4, %%mm7 \n\t"
1525 PAVGB(%%mm6, %%mm7) // a=(max + min)/2
1526 "punpcklbw %%mm7, %%mm7 \n\t"
1527 "punpcklbw %%mm7, %%mm7 \n\t"
1528 "punpcklbw %%mm7, %%mm7 \n\t"
1529 "movq %%mm7, temp0 \n\t"
1531 "movq (%0), %%mm0 \n\t" // L10
1532 "movq %%mm0, %%mm1 \n\t" // L10
1533 "movq %%mm0, %%mm2 \n\t" // L10
1534 "psllq $8, %%mm1 \n\t"
1535 "psrlq $8, %%mm2 \n\t"
1536 "movd -4(%0), %%mm3 \n\t"
1537 "movd 8(%0), %%mm4 \n\t"
1538 "psrlq $24, %%mm3 \n\t"
1539 "psllq $56, %%mm4 \n\t"
1540 "por %%mm3, %%mm1 \n\t" // L00
1541 "por %%mm4, %%mm2 \n\t" // L20
1542 "movq %%mm1, %%mm3 \n\t" // L00
1543 PAVGB(%%mm2, %%mm1) // (L20 + L00)/2
1544 PAVGB(%%mm0, %%mm1) // (L20 + L00 + 2L10)/4
1545 "psubusb %%mm7, %%mm0 \n\t"
1546 "psubusb %%mm7, %%mm2 \n\t"
1547 "psubusb %%mm7, %%mm3 \n\t"
1548 "pcmpeqb b00, %%mm0 \n\t" // L10 > a ? 0 : -1
1549 "pcmpeqb b00, %%mm2 \n\t" // L20 > a ? 0 : -1
1550 "pcmpeqb b00, %%mm3 \n\t" // L00 > a ? 0 : -1
1551 "paddb %%mm2, %%mm0 \n\t"
1552 "paddb %%mm3, %%mm0 \n\t"
1554 "movq (%%eax), %%mm2 \n\t" // L11
1555 "movq %%mm2, %%mm3 \n\t" // L11
1556 "movq %%mm2, %%mm4 \n\t" // L11
1557 "psllq $8, %%mm3 \n\t"
1558 "psrlq $8, %%mm4 \n\t"
1559 "movd -4(%%eax), %%mm5 \n\t"
1560 "movd 8(%%eax), %%mm6 \n\t"
1561 "psrlq $24, %%mm5 \n\t"
1562 "psllq $56, %%mm6 \n\t"
1563 "por %%mm5, %%mm3 \n\t" // L01
1564 "por %%mm6, %%mm4 \n\t" // L21
1565 "movq %%mm3, %%mm5 \n\t" // L01
1566 PAVGB(%%mm4, %%mm3) // (L21 + L01)/2
1567 PAVGB(%%mm2, %%mm3) // (L21 + L01 + 2L11)/4
1568 "psubusb %%mm7, %%mm2 \n\t"
1569 "psubusb %%mm7, %%mm4 \n\t"
1570 "psubusb %%mm7, %%mm5 \n\t"
1571 "pcmpeqb b00, %%mm2 \n\t" // L11 > a ? 0 : -1
1572 "pcmpeqb b00, %%mm4 \n\t" // L21 > a ? 0 : -1
1573 "pcmpeqb b00, %%mm5 \n\t" // L01 > a ? 0 : -1
1574 "paddb %%mm4, %%mm2 \n\t"
1575 "paddb %%mm5, %%mm2 \n\t"
1577 #define DERING_CORE(dst,src,ppsx,psx,sx,pplx,plx,lx,t0,t1) \
1578 "movq " #src ", " #sx " \n\t" /* src[0] */\
1579 "movq " #sx ", " #lx " \n\t" /* src[0] */\
1580 "movq " #sx ", " #t0 " \n\t" /* src[0] */\
1581 "psllq $8, " #lx " \n\t"\
1582 "psrlq $8, " #t0 " \n\t"\
1583 "movd -4" #src ", " #t1 " \n\t"\
1584 "psrlq $24, " #t1 " \n\t"\
1585 "por " #t1 ", " #lx " \n\t" /* src[-1] */\
1586 "movd 8" #src ", " #t1 " \n\t"\
1587 "psllq $56, " #t1 " \n\t"\
1588 "por " #t1 ", " #t0 " \n\t" /* src[+1] */\
1589 "movq " #lx ", " #t1 " \n\t" /* src[-1] */\
1590 PAVGB(t0, lx) /* (src[-1] + src[+1])/2 */\
1591 PAVGB(sx, lx) /* (src[-1] + 2src[0] + src[+1])/4 */\
1593 "movq " #lx ", temp1 \n\t"\
1594 "movq temp0, " #lx " \n\t"\
1595 "psubusb " #lx ", " #t1 " \n\t"\
1596 "psubusb " #lx ", " #t0 " \n\t"\
1597 "psubusb " #lx ", " #sx " \n\t"\
1598 "movq b00, " #lx " \n\t"\
1599 "pcmpeqb " #lx ", " #t1 " \n\t" /* src[-1] > a ? 0 : -1*/\
1600 "pcmpeqb " #lx ", " #t0 " \n\t" /* src[+1] > a ? 0 : -1*/\
1601 "pcmpeqb " #lx ", " #sx " \n\t" /* src[0] > a ? 0 : -1*/\
1602 "paddb " #t1 ", " #t0 " \n\t"\
1603 "paddb " #t0 ", " #sx " \n\t"\
1605 PAVGB(plx, pplx) /* filtered */\
1606 "movq " #dst ", " #t0 " \n\t" /* dst */\
1607 "movq " #t0 ", " #t1 " \n\t" /* dst */\
1608 "psubusb pQPb2, " #t0 " \n\t"\
1609 "paddusb pQPb2, " #t1 " \n\t"\
1611 PMINUB(t1, pplx, t0)\
1612 "paddb " #sx ", " #ppsx " \n\t"\
1613 "paddb " #psx ", " #ppsx " \n\t"\
1614 "#paddb b02, " #ppsx " \n\t"\
1615 "pand b08, " #ppsx " \n\t"\
1616 "pcmpeqb " #lx ", " #ppsx " \n\t"\
1617 "pand " #ppsx ", " #pplx " \n\t"\
1618 "pandn " #dst ", " #ppsx " \n\t"\
1619 "por " #pplx ", " #ppsx " \n\t"\
1620 "movq " #ppsx ", " #dst " \n\t"\
1621 "movq temp1, " #lx " \n\t"
1638 //DERING_CORE(dst,src ,ppsx ,psx ,sx ,pplx ,plx ,lx ,t0 ,t1)
1639 DERING_CORE((%%eax),(%%eax, %1) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1640 DERING_CORE((%%eax, %1),(%%eax, %1, 2) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1641 DERING_CORE((%%eax, %1, 2),(%0, %1, 4) ,%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
1642 DERING_CORE((%0, %1, 4),(%%ebx) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1643 DERING_CORE((%%ebx),(%%ebx, %1) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1644 DERING_CORE((%%ebx, %1), (%%ebx, %1, 2),%%mm4,%%mm0,%%mm2,%%mm5,%%mm1,%%mm3,%%mm6,%%mm7)
1645 DERING_CORE((%%ebx, %1, 2),(%0, %1, 8) ,%%mm0,%%mm2,%%mm4,%%mm1,%%mm3,%%mm5,%%mm6,%%mm7)
1646 DERING_CORE((%0, %1, 8),(%%ebx, %1, 4) ,%%mm2,%%mm4,%%mm0,%%mm3,%%mm5,%%mm1,%%mm6,%%mm7)
1649 : : "r" (src), "r" (stride), "r" (QP)
1667 if(*p > max) max= *p;
1668 if(*p < min) min= *p;
1671 avg= (min + max + 1)/2;
1680 if(*p > avg) t |= (1<<x);
1684 t &= (t<<1) & (t>>1);
1691 int t = s[y-1] & s[y] & s[y+1];
1700 int f= (*(p-stride-1)) + 2*(*(p-stride)) + (*(p-stride+1))
1701 +2*(*(p -1)) + 4*(*p ) + 2*(*(p +1))
1702 +(*(p+stride-1)) + 2*(*(p+stride)) + (*(p+stride+1));
1705 if (*p + 2*QP < f) *p= *p + 2*QP;
1706 else if(*p - 2*QP > f) *p= *p - 2*QP;
1716 * Deinterlaces the given block
1717 * will be called for every 8x8 block and can read & write from line 4-15
1718 * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1719 * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1721 static inline void deInterlaceInterpolateLinear(uint8_t src[], int stride)
1723 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1726 "leal (%0, %1), %%eax \n\t"
1727 "leal (%%eax, %1, 4), %%ebx \n\t"
1728 // 0 1 2 3 4 5 6 7 8 9
1729 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
1731 "movq (%0), %%mm0 \n\t"
1732 "movq (%%eax, %1), %%mm1 \n\t"
1734 "movq %%mm0, (%%eax) \n\t"
1735 "movq (%0, %1, 4), %%mm0 \n\t"
1737 "movq %%mm1, (%%eax, %1, 2) \n\t"
1738 "movq (%%ebx, %1), %%mm1 \n\t"
1740 "movq %%mm0, (%%ebx) \n\t"
1741 "movq (%0, %1, 8), %%mm0 \n\t"
1743 "movq %%mm1, (%%ebx, %1, 2) \n\t"
1745 : : "r" (src), "r" (stride)
1753 src[stride] = (src[0] + src[stride*2])>>1;
1754 src[stride*3] = (src[stride*2] + src[stride*4])>>1;
1755 src[stride*5] = (src[stride*4] + src[stride*6])>>1;
1756 src[stride*7] = (src[stride*6] + src[stride*8])>>1;
1763 * Deinterlaces the given block
1764 * will be called for every 8x8 block and can read & write from line 4-15
1765 * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1766 * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1767 * this filter will read lines 3-15 and write 7-13
1768 * no cliping in C version
1770 static inline void deInterlaceInterpolateCubic(uint8_t src[], int stride)
1772 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1775 "leal (%0, %1), %%eax \n\t"
1776 "leal (%%eax, %1, 4), %%ebx \n\t"
1777 "leal (%%ebx, %1, 4), %%ecx \n\t"
1778 "addl %1, %%ecx \n\t"
1779 "pxor %%mm7, %%mm7 \n\t"
1780 // 0 1 2 3 4 5 6 7 8 9 10
1781 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1 ecx
1783 #define DEINT_CUBIC(a,b,c,d,e)\
1784 "movq " #a ", %%mm0 \n\t"\
1785 "movq " #b ", %%mm1 \n\t"\
1786 "movq " #d ", %%mm2 \n\t"\
1787 "movq " #e ", %%mm3 \n\t"\
1788 PAVGB(%%mm2, %%mm1) /* (b+d) /2 */\
1789 PAVGB(%%mm3, %%mm0) /* a(a+e) /2 */\
1790 "movq %%mm0, %%mm2 \n\t"\
1791 "punpcklbw %%mm7, %%mm0 \n\t"\
1792 "punpckhbw %%mm7, %%mm2 \n\t"\
1793 "movq %%mm1, %%mm3 \n\t"\
1794 "punpcklbw %%mm7, %%mm1 \n\t"\
1795 "punpckhbw %%mm7, %%mm3 \n\t"\
1796 "psubw %%mm1, %%mm0 \n\t" /* L(a+e - (b+d))/2 */\
1797 "psubw %%mm3, %%mm2 \n\t" /* H(a+e - (b+d))/2 */\
1798 "psraw $3, %%mm0 \n\t" /* L(a+e - (b+d))/16 */\
1799 "psraw $3, %%mm2 \n\t" /* H(a+e - (b+d))/16 */\
1800 "psubw %%mm0, %%mm1 \n\t" /* L(9b + 9d - a - e)/16 */\
1801 "psubw %%mm2, %%mm3 \n\t" /* H(9b + 9d - a - e)/16 */\
1802 "packuswb %%mm3, %%mm1 \n\t"\
1803 "movq %%mm1, " #c " \n\t"
1805 DEINT_CUBIC((%0), (%%eax, %1), (%%eax, %1, 2), (%0, %1, 4), (%%ebx, %1))
1806 DEINT_CUBIC((%%eax, %1), (%0, %1, 4), (%%ebx), (%%ebx, %1), (%0, %1, 8))
1807 DEINT_CUBIC((%0, %1, 4), (%%ebx, %1), (%%ebx, %1, 2), (%0, %1, 8), (%%ecx))
1808 DEINT_CUBIC((%%ebx, %1), (%0, %1, 8), (%%ebx, %1, 4), (%%ecx), (%%ecx, %1, 2))
1810 : : "r" (src), "r" (stride)
1811 : "%eax", "%ebx", "ecx"
1818 src[stride*3] = (-src[0] + 9*src[stride*2] + 9*src[stride*4] - src[stride*6])>>4;
1819 src[stride*5] = (-src[stride*2] + 9*src[stride*4] + 9*src[stride*6] - src[stride*8])>>4;
1820 src[stride*7] = (-src[stride*4] + 9*src[stride*6] + 9*src[stride*8] - src[stride*10])>>4;
1821 src[stride*9] = (-src[stride*6] + 9*src[stride*8] + 9*src[stride*10] - src[stride*12])>>4;
1828 * Deinterlaces the given block
1829 * will be called for every 8x8 block and can read & write from line 4-15
1830 * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1831 * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1832 * will shift the image up by 1 line (FIXME if this is a problem)
1833 * this filter will read lines 4-13 and write 4-11
1835 static inline void deInterlaceBlendLinear(uint8_t src[], int stride)
1837 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
1840 "leal (%0, %1), %%eax \n\t"
1841 "leal (%%eax, %1, 4), %%ebx \n\t"
1842 // 0 1 2 3 4 5 6 7 8 9
1843 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
1845 "movq (%0), %%mm0 \n\t" // L0
1846 "movq (%%eax, %1), %%mm1 \n\t" // L2
1847 PAVGB(%%mm1, %%mm0) // L0+L2
1848 "movq (%%eax), %%mm2 \n\t" // L1
1850 "movq %%mm0, (%0) \n\t"
1851 "movq (%%eax, %1, 2), %%mm0 \n\t" // L3
1852 PAVGB(%%mm0, %%mm2) // L1+L3
1853 PAVGB(%%mm1, %%mm2) // 2L2 + L1 + L3
1854 "movq %%mm2, (%%eax) \n\t"
1855 "movq (%0, %1, 4), %%mm2 \n\t" // L4
1856 PAVGB(%%mm2, %%mm1) // L2+L4
1857 PAVGB(%%mm0, %%mm1) // 2L3 + L2 + L4
1858 "movq %%mm1, (%%eax, %1) \n\t"
1859 "movq (%%ebx), %%mm1 \n\t" // L5
1860 PAVGB(%%mm1, %%mm0) // L3+L5
1861 PAVGB(%%mm2, %%mm0) // 2L4 + L3 + L5
1862 "movq %%mm0, (%%eax, %1, 2) \n\t"
1863 "movq (%%ebx, %1), %%mm0 \n\t" // L6
1864 PAVGB(%%mm0, %%mm2) // L4+L6
1865 PAVGB(%%mm1, %%mm2) // 2L5 + L4 + L6
1866 "movq %%mm2, (%0, %1, 4) \n\t"
1867 "movq (%%ebx, %1, 2), %%mm2 \n\t" // L7
1868 PAVGB(%%mm2, %%mm1) // L5+L7
1869 PAVGB(%%mm0, %%mm1) // 2L6 + L5 + L7
1870 "movq %%mm1, (%%ebx) \n\t"
1871 "movq (%0, %1, 8), %%mm1 \n\t" // L8
1872 PAVGB(%%mm1, %%mm0) // L6+L8
1873 PAVGB(%%mm2, %%mm0) // 2L7 + L6 + L8
1874 "movq %%mm0, (%%ebx, %1) \n\t"
1875 "movq (%%ebx, %1, 4), %%mm0 \n\t" // L9
1876 PAVGB(%%mm0, %%mm2) // L7+L9
1877 PAVGB(%%mm1, %%mm2) // 2L8 + L7 + L9
1878 "movq %%mm2, (%%ebx, %1, 2) \n\t"
1881 : : "r" (src), "r" (stride)
1889 src[0 ] = (src[0 ] + 2*src[stride ] + src[stride*2])>>2;
1890 src[stride ] = (src[stride ] + 2*src[stride*2] + src[stride*3])>>2;
1891 src[stride*2] = (src[stride*2] + 2*src[stride*3] + src[stride*4])>>2;
1892 src[stride*3] = (src[stride*3] + 2*src[stride*4] + src[stride*5])>>2;
1893 src[stride*4] = (src[stride*4] + 2*src[stride*5] + src[stride*6])>>2;
1894 src[stride*5] = (src[stride*5] + 2*src[stride*6] + src[stride*7])>>2;
1895 src[stride*6] = (src[stride*6] + 2*src[stride*7] + src[stride*8])>>2;
1896 src[stride*7] = (src[stride*7] + 2*src[stride*8] + src[stride*9])>>2;
1903 * Deinterlaces the given block
1904 * will be called for every 8x8 block and can read & write from line 4-15,
1905 * lines 0-3 have been passed through the deblock / dering filters allready, but can be read too
1906 * lines 4-12 will be read into the deblocking filter and should be deinterlaced
1908 static inline void deInterlaceMedian(uint8_t src[], int stride)
1914 "leal (%0, %1), %%eax \n\t"
1915 "leal (%%eax, %1, 4), %%ebx \n\t"
1916 // 0 1 2 3 4 5 6 7 8 9
1917 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
1919 "movq (%0), %%mm0 \n\t" //
1920 "movq (%%eax, %1), %%mm2 \n\t" //
1921 "movq (%%eax), %%mm1 \n\t" //
1922 "movq %%mm0, %%mm3 \n\t"
1923 "pmaxub %%mm1, %%mm0 \n\t" //
1924 "pminub %%mm3, %%mm1 \n\t" //
1925 "pmaxub %%mm2, %%mm1 \n\t" //
1926 "pminub %%mm1, %%mm0 \n\t"
1927 "movq %%mm0, (%%eax) \n\t"
1929 "movq (%0, %1, 4), %%mm0 \n\t" //
1930 "movq (%%eax, %1, 2), %%mm1 \n\t" //
1931 "movq %%mm2, %%mm3 \n\t"
1932 "pmaxub %%mm1, %%mm2 \n\t" //
1933 "pminub %%mm3, %%mm1 \n\t" //
1934 "pmaxub %%mm0, %%mm1 \n\t" //
1935 "pminub %%mm1, %%mm2 \n\t"
1936 "movq %%mm2, (%%eax, %1, 2) \n\t"
1938 "movq (%%ebx), %%mm2 \n\t" //
1939 "movq (%%ebx, %1), %%mm1 \n\t" //
1940 "movq %%mm2, %%mm3 \n\t"
1941 "pmaxub %%mm0, %%mm2 \n\t" //
1942 "pminub %%mm3, %%mm0 \n\t" //
1943 "pmaxub %%mm1, %%mm0 \n\t" //
1944 "pminub %%mm0, %%mm2 \n\t"
1945 "movq %%mm2, (%%ebx) \n\t"
1947 "movq (%%ebx, %1, 2), %%mm2 \n\t" //
1948 "movq (%0, %1, 8), %%mm0 \n\t" //
1949 "movq %%mm2, %%mm3 \n\t"
1950 "pmaxub %%mm0, %%mm2 \n\t" //
1951 "pminub %%mm3, %%mm0 \n\t" //
1952 "pmaxub %%mm1, %%mm0 \n\t" //
1953 "pminub %%mm0, %%mm2 \n\t"
1954 "movq %%mm2, (%%ebx, %1, 2) \n\t"
1957 : : "r" (src), "r" (stride)
1961 #else // MMX without MMX2
1963 "leal (%0, %1), %%eax \n\t"
1964 "leal (%%eax, %1, 4), %%ebx \n\t"
1965 // 0 1 2 3 4 5 6 7 8 9
1966 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
1967 "pxor %%mm7, %%mm7 \n\t"
1969 #define MEDIAN(a,b,c)\
1970 "movq " #a ", %%mm0 \n\t"\
1971 "movq " #b ", %%mm2 \n\t"\
1972 "movq " #c ", %%mm1 \n\t"\
1973 "movq %%mm0, %%mm3 \n\t"\
1974 "movq %%mm1, %%mm4 \n\t"\
1975 "movq %%mm2, %%mm5 \n\t"\
1976 "psubusb %%mm1, %%mm3 \n\t"\
1977 "psubusb %%mm2, %%mm4 \n\t"\
1978 "psubusb %%mm0, %%mm5 \n\t"\
1979 "pcmpeqb %%mm7, %%mm3 \n\t"\
1980 "pcmpeqb %%mm7, %%mm4 \n\t"\
1981 "pcmpeqb %%mm7, %%mm5 \n\t"\
1982 "movq %%mm3, %%mm6 \n\t"\
1983 "pxor %%mm4, %%mm3 \n\t"\
1984 "pxor %%mm5, %%mm4 \n\t"\
1985 "pxor %%mm6, %%mm5 \n\t"\
1986 "por %%mm3, %%mm1 \n\t"\
1987 "por %%mm4, %%mm2 \n\t"\
1988 "por %%mm5, %%mm0 \n\t"\
1989 "pand %%mm2, %%mm0 \n\t"\
1990 "pand %%mm1, %%mm0 \n\t"\
1991 "movq %%mm0, " #b " \n\t"
1993 MEDIAN((%0), (%%eax), (%%eax, %1))
1994 MEDIAN((%%eax, %1), (%%eax, %1, 2), (%0, %1, 4))
1995 MEDIAN((%0, %1, 4), (%%ebx), (%%ebx, %1))
1996 MEDIAN((%%ebx, %1), (%%ebx, %1, 2), (%0, %1, 8))
1998 : : "r" (src), "r" (stride)
2008 src[0 ] = (src[0 ] + 2*src[stride ] + src[stride*2])>>2;
2009 src[stride ] = (src[stride ] + 2*src[stride*2] + src[stride*3])>>2;
2010 src[stride*2] = (src[stride*2] + 2*src[stride*3] + src[stride*4])>>2;
2011 src[stride*3] = (src[stride*3] + 2*src[stride*4] + src[stride*5])>>2;
2012 src[stride*4] = (src[stride*4] + 2*src[stride*5] + src[stride*6])>>2;
2013 src[stride*5] = (src[stride*5] + 2*src[stride*6] + src[stride*7])>>2;
2014 src[stride*6] = (src[stride*6] + 2*src[stride*7] + src[stride*8])>>2;
2015 src[stride*7] = (src[stride*7] + 2*src[stride*8] + src[stride*9])>>2;
2023 * transposes and shift the given 8x8 Block into dst1 and dst2
2025 static inline void transpose1(uint8_t *dst1, uint8_t *dst2, uint8_t *src, int srcStride)
2028 "leal (%0, %1), %%eax \n\t"
2029 "leal (%%eax, %1, 4), %%ebx \n\t"
2030 // 0 1 2 3 4 5 6 7 8 9
2031 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
2032 "movq (%0), %%mm0 \n\t" // 12345678
2033 "movq (%%eax), %%mm1 \n\t" // abcdefgh
2034 "movq %%mm0, %%mm2 \n\t" // 12345678
2035 "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
2036 "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
2038 "movq (%%eax, %1), %%mm1 \n\t"
2039 "movq (%%eax, %1, 2), %%mm3 \n\t"
2040 "movq %%mm1, %%mm4 \n\t"
2041 "punpcklbw %%mm3, %%mm1 \n\t"
2042 "punpckhbw %%mm3, %%mm4 \n\t"
2044 "movq %%mm0, %%mm3 \n\t"
2045 "punpcklwd %%mm1, %%mm0 \n\t"
2046 "punpckhwd %%mm1, %%mm3 \n\t"
2047 "movq %%mm2, %%mm1 \n\t"
2048 "punpcklwd %%mm4, %%mm2 \n\t"
2049 "punpckhwd %%mm4, %%mm1 \n\t"
2051 "movd %%mm0, 128(%2) \n\t"
2052 "psrlq $32, %%mm0 \n\t"
2053 "movd %%mm0, 144(%2) \n\t"
2054 "movd %%mm3, 160(%2) \n\t"
2055 "psrlq $32, %%mm3 \n\t"
2056 "movd %%mm3, 176(%2) \n\t"
2057 "movd %%mm3, 48(%3) \n\t"
2058 "movd %%mm2, 192(%2) \n\t"
2059 "movd %%mm2, 64(%3) \n\t"
2060 "psrlq $32, %%mm2 \n\t"
2061 "movd %%mm2, 80(%3) \n\t"
2062 "movd %%mm1, 96(%3) \n\t"
2063 "psrlq $32, %%mm1 \n\t"
2064 "movd %%mm1, 112(%3) \n\t"
2066 "movq (%0, %1, 4), %%mm0 \n\t" // 12345678
2067 "movq (%%ebx), %%mm1 \n\t" // abcdefgh
2068 "movq %%mm0, %%mm2 \n\t" // 12345678
2069 "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
2070 "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
2072 "movq (%%ebx, %1), %%mm1 \n\t"
2073 "movq (%%ebx, %1, 2), %%mm3 \n\t"
2074 "movq %%mm1, %%mm4 \n\t"
2075 "punpcklbw %%mm3, %%mm1 \n\t"
2076 "punpckhbw %%mm3, %%mm4 \n\t"
2078 "movq %%mm0, %%mm3 \n\t"
2079 "punpcklwd %%mm1, %%mm0 \n\t"
2080 "punpckhwd %%mm1, %%mm3 \n\t"
2081 "movq %%mm2, %%mm1 \n\t"
2082 "punpcklwd %%mm4, %%mm2 \n\t"
2083 "punpckhwd %%mm4, %%mm1 \n\t"
2085 "movd %%mm0, 132(%2) \n\t"
2086 "psrlq $32, %%mm0 \n\t"
2087 "movd %%mm0, 148(%2) \n\t"
2088 "movd %%mm3, 164(%2) \n\t"
2089 "psrlq $32, %%mm3 \n\t"
2090 "movd %%mm3, 180(%2) \n\t"
2091 "movd %%mm3, 52(%3) \n\t"
2092 "movd %%mm2, 196(%2) \n\t"
2093 "movd %%mm2, 68(%3) \n\t"
2094 "psrlq $32, %%mm2 \n\t"
2095 "movd %%mm2, 84(%3) \n\t"
2096 "movd %%mm1, 100(%3) \n\t"
2097 "psrlq $32, %%mm1 \n\t"
2098 "movd %%mm1, 116(%3) \n\t"
2101 :: "r" (src), "r" (srcStride), "r" (dst1), "r" (dst2)
2107 * transposes the given 8x8 block
2109 static inline void transpose2(uint8_t *dst, int dstStride, uint8_t *src)
2112 "leal (%0, %1), %%eax \n\t"
2113 "leal (%%eax, %1, 4), %%ebx \n\t"
2114 // 0 1 2 3 4 5 6 7 8 9
2115 // %0 eax eax+%1 eax+2%1 %0+4%1 ebx ebx+%1 ebx+2%1 %0+8%1 ebx+4%1
2116 "movq (%2), %%mm0 \n\t" // 12345678
2117 "movq 16(%2), %%mm1 \n\t" // abcdefgh
2118 "movq %%mm0, %%mm2 \n\t" // 12345678
2119 "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
2120 "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
2122 "movq 32(%2), %%mm1 \n\t"
2123 "movq 48(%2), %%mm3 \n\t"
2124 "movq %%mm1, %%mm4 \n\t"
2125 "punpcklbw %%mm3, %%mm1 \n\t"
2126 "punpckhbw %%mm3, %%mm4 \n\t"
2128 "movq %%mm0, %%mm3 \n\t"
2129 "punpcklwd %%mm1, %%mm0 \n\t"
2130 "punpckhwd %%mm1, %%mm3 \n\t"
2131 "movq %%mm2, %%mm1 \n\t"
2132 "punpcklwd %%mm4, %%mm2 \n\t"
2133 "punpckhwd %%mm4, %%mm1 \n\t"
2135 "movd %%mm0, (%0) \n\t"
2136 "psrlq $32, %%mm0 \n\t"
2137 "movd %%mm0, (%%eax) \n\t"
2138 "movd %%mm3, (%%eax, %1) \n\t"
2139 "psrlq $32, %%mm3 \n\t"
2140 "movd %%mm3, (%%eax, %1, 2) \n\t"
2141 "movd %%mm2, (%0, %1, 4) \n\t"
2142 "psrlq $32, %%mm2 \n\t"
2143 "movd %%mm2, (%%ebx) \n\t"
2144 "movd %%mm1, (%%ebx, %1) \n\t"
2145 "psrlq $32, %%mm1 \n\t"
2146 "movd %%mm1, (%%ebx, %1, 2) \n\t"
2149 "movq 64(%2), %%mm0 \n\t" // 12345678
2150 "movq 80(%2), %%mm1 \n\t" // abcdefgh
2151 "movq %%mm0, %%mm2 \n\t" // 12345678
2152 "punpcklbw %%mm1, %%mm0 \n\t" // 1a2b3c4d
2153 "punpckhbw %%mm1, %%mm2 \n\t" // 5e6f7g8h
2155 "movq 96(%2), %%mm1 \n\t"
2156 "movq 112(%2), %%mm3 \n\t"
2157 "movq %%mm1, %%mm4 \n\t"
2158 "punpcklbw %%mm3, %%mm1 \n\t"
2159 "punpckhbw %%mm3, %%mm4 \n\t"
2161 "movq %%mm0, %%mm3 \n\t"
2162 "punpcklwd %%mm1, %%mm0 \n\t"
2163 "punpckhwd %%mm1, %%mm3 \n\t"
2164 "movq %%mm2, %%mm1 \n\t"
2165 "punpcklwd %%mm4, %%mm2 \n\t"
2166 "punpckhwd %%mm4, %%mm1 \n\t"
2168 "movd %%mm0, 4(%0) \n\t"
2169 "psrlq $32, %%mm0 \n\t"
2170 "movd %%mm0, 4(%%eax) \n\t"
2171 "movd %%mm3, 4(%%eax, %1) \n\t"
2172 "psrlq $32, %%mm3 \n\t"
2173 "movd %%mm3, 4(%%eax, %1, 2) \n\t"
2174 "movd %%mm2, 4(%0, %1, 4) \n\t"
2175 "psrlq $32, %%mm2 \n\t"
2176 "movd %%mm2, 4(%%ebx) \n\t"
2177 "movd %%mm1, 4(%%ebx, %1) \n\t"
2178 "psrlq $32, %%mm1 \n\t"
2179 "movd %%mm1, 4(%%ebx, %1, 2) \n\t"
2181 :: "r" (dst), "r" (dstStride), "r" (src)
2186 //static int test=0;
2188 static void inline tempNoiseReducer(uint8_t *src, int stride,
2189 uint8_t *tempBlured, uint32_t *tempBluredPast, int *maxNoise)
2191 #define FAST_L2_DIFF
2192 //#define L1_DIFF //u should change the thresholds too if u try that one
2193 #if defined (HAVE_MMX2) || defined (HAVE_3DNOW)
2195 "leal (%2, %2, 2), %%eax \n\t" // 3*stride
2196 "leal (%2, %2, 4), %%ebx \n\t" // 5*stride
2197 "leal (%%ebx, %2, 2), %%ecx \n\t" // 7*stride
2198 // 0 1 2 3 4 5 6 7 8 9
2199 // %x %x+%2 %x+2%2 %x+eax %x+4%2 %x+ebx %x+2eax %x+ecx %x+8%2
2201 #ifdef L1_DIFF //needs mmx2
2202 "movq (%0), %%mm0 \n\t" // L0
2203 "psadbw (%1), %%mm0 \n\t" // |L0-R0|
2204 "movq (%0, %2), %%mm1 \n\t" // L1
2205 "psadbw (%1, %2), %%mm1 \n\t" // |L1-R1|
2206 "movq (%0, %2, 2), %%mm2 \n\t" // L2
2207 "psadbw (%1, %2, 2), %%mm2 \n\t" // |L2-R2|
2208 "movq (%0, %%eax), %%mm3 \n\t" // L3
2209 "psadbw (%1, %%eax), %%mm3 \n\t" // |L3-R3|
2211 "movq (%0, %2, 4), %%mm4 \n\t" // L4
2212 "paddw %%mm1, %%mm0 \n\t"
2213 "psadbw (%1, %2, 4), %%mm4 \n\t" // |L4-R4|
2214 "movq (%0, %%ebx), %%mm5 \n\t" // L5
2215 "paddw %%mm2, %%mm0 \n\t"
2216 "psadbw (%1, %%ebx), %%mm5 \n\t" // |L5-R5|
2217 "movq (%0, %%eax, 2), %%mm6 \n\t" // L6
2218 "paddw %%mm3, %%mm0 \n\t"
2219 "psadbw (%1, %%eax, 2), %%mm6 \n\t" // |L6-R6|
2220 "movq (%0, %%ecx), %%mm7 \n\t" // L7
2221 "paddw %%mm4, %%mm0 \n\t"
2222 "psadbw (%1, %%ecx), %%mm7 \n\t" // |L7-R7|
2223 "paddw %%mm5, %%mm6 \n\t"
2224 "paddw %%mm7, %%mm6 \n\t"
2225 "paddw %%mm6, %%mm0 \n\t"
2226 #elif defined (FAST_L2_DIFF)
2227 "pcmpeqb %%mm7, %%mm7 \n\t"
2228 "movq b80, %%mm6 \n\t"
2229 "pxor %%mm0, %%mm0 \n\t"
2230 #define L2_DIFF_CORE(a, b)\
2231 "movq " #a ", %%mm5 \n\t"\
2232 "movq " #b ", %%mm2 \n\t"\
2233 "pxor %%mm7, %%mm2 \n\t"\
2234 PAVGB(%%mm2, %%mm5)\
2235 "paddb %%mm6, %%mm5 \n\t"\
2236 "movq %%mm5, %%mm2 \n\t"\
2237 "psllw $8, %%mm5 \n\t"\
2238 "pmaddwd %%mm5, %%mm5 \n\t"\
2239 "pmaddwd %%mm2, %%mm2 \n\t"\
2240 "paddd %%mm2, %%mm5 \n\t"\
2241 "psrld $14, %%mm5 \n\t"\
2242 "paddd %%mm5, %%mm0 \n\t"
2244 L2_DIFF_CORE((%0), (%1))
2245 L2_DIFF_CORE((%0, %2), (%1, %2))
2246 L2_DIFF_CORE((%0, %2, 2), (%1, %2, 2))
2247 L2_DIFF_CORE((%0, %%eax), (%1, %%eax))
2248 L2_DIFF_CORE((%0, %2, 4), (%1, %2, 4))
2249 L2_DIFF_CORE((%0, %%ebx), (%1, %%ebx))
2250 L2_DIFF_CORE((%0, %%eax,2), (%1, %%eax,2))
2251 L2_DIFF_CORE((%0, %%ecx), (%1, %%ecx))
2254 "pxor %%mm7, %%mm7 \n\t"
2255 "pxor %%mm0, %%mm0 \n\t"
2256 #define L2_DIFF_CORE(a, b)\
2257 "movq " #a ", %%mm5 \n\t"\
2258 "movq " #b ", %%mm2 \n\t"\
2259 "movq %%mm5, %%mm1 \n\t"\
2260 "movq %%mm2, %%mm3 \n\t"\
2261 "punpcklbw %%mm7, %%mm5 \n\t"\
2262 "punpckhbw %%mm7, %%mm1 \n\t"\
2263 "punpcklbw %%mm7, %%mm2 \n\t"\
2264 "punpckhbw %%mm7, %%mm3 \n\t"\
2265 "psubw %%mm2, %%mm5 \n\t"\
2266 "psubw %%mm3, %%mm1 \n\t"\
2267 "pmaddwd %%mm5, %%mm5 \n\t"\
2268 "pmaddwd %%mm1, %%mm1 \n\t"\
2269 "paddd %%mm1, %%mm5 \n\t"\
2270 "paddd %%mm5, %%mm0 \n\t"
2272 L2_DIFF_CORE((%0), (%1))
2273 L2_DIFF_CORE((%0, %2), (%1, %2))
2274 L2_DIFF_CORE((%0, %2, 2), (%1, %2, 2))
2275 L2_DIFF_CORE((%0, %%eax), (%1, %%eax))
2276 L2_DIFF_CORE((%0, %2, 4), (%1, %2, 4))
2277 L2_DIFF_CORE((%0, %%ebx), (%1, %%ebx))
2278 L2_DIFF_CORE((%0, %%eax,2), (%1, %%eax,2))
2279 L2_DIFF_CORE((%0, %%ecx), (%1, %%ecx))
2283 "movq %%mm0, %%mm4 \n\t"
2284 "psrlq $32, %%mm0 \n\t"
2285 "paddd %%mm0, %%mm4 \n\t"
2286 "movd %%mm4, %%ecx \n\t"
2287 "shll $2, %%ecx \n\t"
2288 "movl %3, %%ebx \n\t"
2289 "addl -4(%%ebx), %%ecx \n\t"
2290 "addl 4(%%ebx), %%ecx \n\t"
2291 "addl -1024(%%ebx), %%ecx \n\t"
2292 "addl $4, %%ecx \n\t"
2293 "addl 1024(%%ebx), %%ecx \n\t"
2294 "shrl $3, %%ecx \n\t"
2295 "movl %%ecx, (%%ebx) \n\t"
2296 "leal (%%eax, %2, 2), %%ebx \n\t" // 5*stride
2298 // "movl %3, %%ecx \n\t"
2299 // "movl %%ecx, test \n\t"
2301 "cmpl 4+maxTmpNoise, %%ecx \n\t"
2303 "cmpl 8+maxTmpNoise, %%ecx \n\t"
2306 "leal (%%ebx, %2, 2), %%ecx \n\t" // 7*stride
2307 "movq (%0), %%mm0 \n\t" // L0
2308 "movq (%0, %2), %%mm1 \n\t" // L1
2309 "movq (%0, %2, 2), %%mm2 \n\t" // L2
2310 "movq (%0, %%eax), %%mm3 \n\t" // L3
2311 "movq (%0, %2, 4), %%mm4 \n\t" // L4
2312 "movq (%0, %%ebx), %%mm5 \n\t" // L5
2313 "movq (%0, %%eax, 2), %%mm6 \n\t" // L6
2314 "movq (%0, %%ecx), %%mm7 \n\t" // L7
2315 "movq %%mm0, (%1) \n\t" // L0
2316 "movq %%mm1, (%1, %2) \n\t" // L1
2317 "movq %%mm2, (%1, %2, 2) \n\t" // L2
2318 "movq %%mm3, (%1, %%eax) \n\t" // L3
2319 "movq %%mm4, (%1, %2, 4) \n\t" // L4
2320 "movq %%mm5, (%1, %%ebx) \n\t" // L5
2321 "movq %%mm6, (%1, %%eax, 2) \n\t" // L6
2322 "movq %%mm7, (%1, %%ecx) \n\t" // L7
2326 "leal (%%ebx, %2, 2), %%ecx \n\t" // 7*stride
2327 "movq (%0), %%mm0 \n\t" // L0
2328 "pavgb (%1), %%mm0 \n\t" // L0
2329 "movq (%0, %2), %%mm1 \n\t" // L1
2330 "pavgb (%1, %2), %%mm1 \n\t" // L1
2331 "movq (%0, %2, 2), %%mm2 \n\t" // L2
2332 "pavgb (%1, %2, 2), %%mm2 \n\t" // L2
2333 "movq (%0, %%eax), %%mm3 \n\t" // L3
2334 "pavgb (%1, %%eax), %%mm3 \n\t" // L3
2335 "movq (%0, %2, 4), %%mm4 \n\t" // L4
2336 "pavgb (%1, %2, 4), %%mm4 \n\t" // L4
2337 "movq (%0, %%ebx), %%mm5 \n\t" // L5
2338 "pavgb (%1, %%ebx), %%mm5 \n\t" // L5
2339 "movq (%0, %%eax, 2), %%mm6 \n\t" // L6
2340 "pavgb (%1, %%eax, 2), %%mm6 \n\t" // L6
2341 "movq (%0, %%ecx), %%mm7 \n\t" // L7
2342 "pavgb (%1, %%ecx), %%mm7 \n\t" // L7
2343 "movq %%mm0, (%1) \n\t" // R0
2344 "movq %%mm1, (%1, %2) \n\t" // R1
2345 "movq %%mm2, (%1, %2, 2) \n\t" // R2
2346 "movq %%mm3, (%1, %%eax) \n\t" // R3
2347 "movq %%mm4, (%1, %2, 4) \n\t" // R4
2348 "movq %%mm5, (%1, %%ebx) \n\t" // R5
2349 "movq %%mm6, (%1, %%eax, 2) \n\t" // R6
2350 "movq %%mm7, (%1, %%ecx) \n\t" // R7
2351 "movq %%mm0, (%0) \n\t" // L0
2352 "movq %%mm1, (%0, %2) \n\t" // L1
2353 "movq %%mm2, (%0, %2, 2) \n\t" // L2
2354 "movq %%mm3, (%0, %%eax) \n\t" // L3
2355 "movq %%mm4, (%0, %2, 4) \n\t" // L4
2356 "movq %%mm5, (%0, %%ebx) \n\t" // L5
2357 "movq %%mm6, (%0, %%eax, 2) \n\t" // L6
2358 "movq %%mm7, (%0, %%ecx) \n\t" // L7
2362 "cmpl maxTmpNoise, %%ecx \n\t"
2365 "leal (%%ebx, %2, 2), %%ecx \n\t" // 7*stride
2366 "movq (%0), %%mm0 \n\t" // L0
2367 "movq (%0, %2), %%mm1 \n\t" // L1
2368 "movq (%0, %2, 2), %%mm2 \n\t" // L2
2369 "movq (%0, %%eax), %%mm3 \n\t" // L3
2370 "movq (%1), %%mm4 \n\t" // R0
2371 "movq (%1, %2), %%mm5 \n\t" // R1
2372 "movq (%1, %2, 2), %%mm6 \n\t" // R2
2373 "movq (%1, %%eax), %%mm7 \n\t" // R3
2382 "movq %%mm0, (%1) \n\t" // R0
2383 "movq %%mm1, (%1, %2) \n\t" // R1
2384 "movq %%mm2, (%1, %2, 2) \n\t" // R2
2385 "movq %%mm3, (%1, %%eax) \n\t" // R3
2386 "movq %%mm0, (%0) \n\t" // L0
2387 "movq %%mm1, (%0, %2) \n\t" // L1
2388 "movq %%mm2, (%0, %2, 2) \n\t" // L2
2389 "movq %%mm3, (%0, %%eax) \n\t" // L3
2391 "movq (%0, %2, 4), %%mm0 \n\t" // L4
2392 "movq (%0, %%ebx), %%mm1 \n\t" // L5
2393 "movq (%0, %%eax, 2), %%mm2 \n\t" // L6
2394 "movq (%0, %%ecx), %%mm3 \n\t" // L7
2395 "movq (%1, %2, 4), %%mm4 \n\t" // R4
2396 "movq (%1, %%ebx), %%mm5 \n\t" // R5
2397 "movq (%1, %%eax, 2), %%mm6 \n\t" // R6
2398 "movq (%1, %%ecx), %%mm7 \n\t" // R7
2407 "movq %%mm0, (%1, %2, 4) \n\t" // R4
2408 "movq %%mm1, (%1, %%ebx) \n\t" // R5
2409 "movq %%mm2, (%1, %%eax, 2) \n\t" // R6
2410 "movq %%mm3, (%1, %%ecx) \n\t" // R7
2411 "movq %%mm0, (%0, %2, 4) \n\t" // L4
2412 "movq %%mm1, (%0, %%ebx) \n\t" // L5
2413 "movq %%mm2, (%0, %%eax, 2) \n\t" // L6
2414 "movq %%mm3, (%0, %%ecx) \n\t" // L7
2418 "leal (%%ebx, %2, 2), %%ecx \n\t" // 7*stride
2419 "movq (%0), %%mm0 \n\t" // L0
2420 "movq (%0, %2), %%mm1 \n\t" // L1
2421 "movq (%0, %2, 2), %%mm2 \n\t" // L2
2422 "movq (%0, %%eax), %%mm3 \n\t" // L3
2423 "movq (%1), %%mm4 \n\t" // R0
2424 "movq (%1, %2), %%mm5 \n\t" // R1
2425 "movq (%1, %2, 2), %%mm6 \n\t" // R2
2426 "movq (%1, %%eax), %%mm7 \n\t" // R3
2439 "movq %%mm0, (%1) \n\t" // R0
2440 "movq %%mm1, (%1, %2) \n\t" // R1
2441 "movq %%mm2, (%1, %2, 2) \n\t" // R2
2442 "movq %%mm3, (%1, %%eax) \n\t" // R3
2443 "movq %%mm0, (%0) \n\t" // L0
2444 "movq %%mm1, (%0, %2) \n\t" // L1
2445 "movq %%mm2, (%0, %2, 2) \n\t" // L2
2446 "movq %%mm3, (%0, %%eax) \n\t" // L3
2448 "movq (%0, %2, 4), %%mm0 \n\t" // L4
2449 "movq (%0, %%ebx), %%mm1 \n\t" // L5
2450 "movq (%0, %%eax, 2), %%mm2 \n\t" // L6
2451 "movq (%0, %%ecx), %%mm3 \n\t" // L7
2452 "movq (%1, %2, 4), %%mm4 \n\t" // R4
2453 "movq (%1, %%ebx), %%mm5 \n\t" // R5
2454 "movq (%1, %%eax, 2), %%mm6 \n\t" // R6
2455 "movq (%1, %%ecx), %%mm7 \n\t" // R7
2468 "movq %%mm0, (%1, %2, 4) \n\t" // R4
2469 "movq %%mm1, (%1, %%ebx) \n\t" // R5
2470 "movq %%mm2, (%1, %%eax, 2) \n\t" // R6
2471 "movq %%mm3, (%1, %%ecx) \n\t" // R7
2472 "movq %%mm0, (%0, %2, 4) \n\t" // L4
2473 "movq %%mm1, (%0, %%ebx) \n\t" // L5
2474 "movq %%mm2, (%0, %%eax, 2) \n\t" // L6
2475 "movq %%mm3, (%0, %%ecx) \n\t" // L7
2479 :: "r" (src), "r" (tempBlured), "r"(stride), "m" (tempBluredPast)
2480 : "%eax", "%ebx", "%ecx", "memory"
2482 //printf("%d\n", test);
2494 int ref= tempBlured[ x + y*stride ];
2495 int cur= src[ x + y*stride ];
2497 // if(x==0 || x==7) d1+= d1>>1;
2498 // if(y==0 || y==7) d1+= d1>>1;
2507 +(*(tempBluredPast-256))
2508 +(*(tempBluredPast-1))+ (*(tempBluredPast+1))
2509 +(*(tempBluredPast+256))
2512 // ((*tempBluredPast)*3 + d + 2)>>2;
2514 //printf("%d %d %d\n", maxNoise[0], maxNoise[1], maxNoise[2]);
2518 64 32 16 8 4 2 1 (1)
2519 64 48 36 27 20 15 11 (33) (approx)
2520 64 56 49 43 37 33 29 (200) (approx)
2531 int ref= tempBlured[ x + y*stride ];
2532 int cur= src[ x + y*stride ];
2533 tempBlured[ x + y*stride ]=
2534 src[ x + y*stride ]=
2546 tempBlured[ x + y*stride ]= src[ x + y*stride ];
2560 int ref= tempBlured[ x + y*stride ];
2561 int cur= src[ x + y*stride ];
2562 tempBlured[ x + y*stride ]=
2563 src[ x + y*stride ]=
2564 (ref*7 + cur + 4)>>3;
2575 int ref= tempBlured[ x + y*stride ];
2576 int cur= src[ x + y*stride ];
2577 tempBlured[ x + y*stride ]=
2578 src[ x + y*stride ]=
2579 (ref*3 + cur + 2)>>2;
2587 #ifdef HAVE_ODIVX_POSTPROCESS
2588 #include "../opendivx/postprocess.h"
2592 static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height,
2593 QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode);
2595 /* -pp Command line Help
2596 NOTE/FIXME: put this at an appropriate place (--help, html docs, man mplayer)?
2598 -pp <filterName>[:<option>[:<option>...]][,[-]<filterName>[:<option>...]]...
2601 -pp vdeblock:autoq,hdeblock:autoq,linblenddeint -pp default,-vdeblock
2603 -pp vb:a,hb:a,lb -pp de,-vb
2608 short long name short long option Description
2609 * * a autoq cpu power dependant enabler
2610 c chrom chrominance filtring enabled
2611 y nochrom chrominance filtring disabled
2612 hb hdeblock horizontal deblocking filter
2613 vb vdeblock vertical deblocking filter
2615 h1 x1hdeblock Experimental horizontal deblock filter 1
2616 v1 x1vdeblock Experimental vertical deblock filter 1
2617 dr dering not implemented yet
2618 al autolevels automatic brightness / contrast fixer
2619 f fullyrange stretch luminance range to (0..255)
2620 lb linblenddeint linear blend deinterlacer
2621 li linipoldeint linear interpolating deinterlacer
2622 ci cubicipoldeint cubic interpolating deinterlacer
2623 md mediandeint median deinterlacer
2624 de default hdeblock:a,vdeblock:a,dering:a,autolevels
2625 fa fast x1hdeblock:a,x1vdeblock:a,dering:a,autolevels
2626 tn tmpnoise (3 Thresholds) Temporal Noise Reducer
2630 * returns a PPMode struct which will have a non 0 error variable if an error occured
2631 * name is the string after "-pp" on the command line
2632 * quality is a number from 0 to GET_PP_QUALITY_MAX
2634 struct PPMode getPPModeByNameAndQuality(char *name, int quality)
2636 char temp[GET_MODE_BUFFER_SIZE];
2638 char *filterDelimiters= ",";
2639 char *optionDelimiters= ":";
2640 struct PPMode ppMode= {0,0,0,0,0,0,{150,200,400}};
2643 strncpy(temp, name, GET_MODE_BUFFER_SIZE);
2645 printf("%s\n", name);
2649 int q= 1000000; //GET_PP_QUALITY_MAX;
2652 char *options[OPTIONS_ARRAY_SIZE];
2655 int numOfUnknownOptions=0;
2656 int enable=1; //does the user want us to enabled or disabled the filter
2658 filterToken= strtok(p, filterDelimiters);
2659 if(filterToken == NULL) break;
2660 p+= strlen(filterToken) + 1; // p points to next filterToken
2661 filterName= strtok(filterToken, optionDelimiters);
2662 printf("%s::%s\n", filterToken, filterName);
2664 if(*filterName == '-')
2670 for(;;){ //for all options
2671 option= strtok(NULL, optionDelimiters);
2672 if(option == NULL) break;
2674 printf("%s\n", option);
2675 if(!strcmp("autoq", option) || !strcmp("a", option)) q= quality;
2676 else if(!strcmp("nochrom", option) || !strcmp("y", option)) chrom=0;
2677 else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1;
2680 options[numOfUnknownOptions] = option;
2681 numOfUnknownOptions++;
2683 if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break;
2685 options[numOfUnknownOptions] = NULL;
2687 /* replace stuff from the replace Table */
2688 for(i=0; replaceTable[2*i]!=NULL; i++)
2690 if(!strcmp(replaceTable[2*i], filterName))
2692 int newlen= strlen(replaceTable[2*i + 1]);
2696 if(p==NULL) p= temp, *p=0; //last filter
2697 else p--, *p=','; //not last filter
2700 spaceLeft= (int)p - (int)temp + plen;
2701 if(spaceLeft + newlen >= GET_MODE_BUFFER_SIZE)
2706 memmove(p + newlen, p, plen+1);
2707 memcpy(p, replaceTable[2*i + 1], newlen);
2712 for(i=0; filters[i].shortName!=NULL; i++)
2714 // printf("Compareing %s, %s, %s\n", filters[i].shortName,filters[i].longName, filterName);
2715 if( !strcmp(filters[i].longName, filterName)
2716 || !strcmp(filters[i].shortName, filterName))
2718 ppMode.lumMode &= ~filters[i].mask;
2719 ppMode.chromMode &= ~filters[i].mask;
2722 if(!enable) break; // user wants to disable it
2724 if(q >= filters[i].minLumQuality)
2725 ppMode.lumMode|= filters[i].mask;
2726 if(chrom==1 || (chrom==-1 && filters[i].chromDefault))
2727 if(q >= filters[i].minChromQuality)
2728 ppMode.chromMode|= filters[i].mask;
2730 if(filters[i].mask == LEVEL_FIX)
2733 ppMode.minAllowedY= 16;
2734 ppMode.maxAllowedY= 234;
2735 for(o=0; options[o]!=NULL; o++)
2736 if( !strcmp(options[o],"fullyrange")
2737 ||!strcmp(options[o],"f"))
2739 ppMode.minAllowedY= 0;
2740 ppMode.maxAllowedY= 255;
2741 numOfUnknownOptions--;
2744 else if(filters[i].mask == TEMP_NOISE_FILTER)
2748 ppMode.maxTmpNoise[0]= 150;
2749 ppMode.maxTmpNoise[1]= 200;
2750 ppMode.maxTmpNoise[2]= 400;
2752 for(o=0; options[o]!=NULL; o++)
2755 ppMode.maxTmpNoise[numOfNoises]=
2756 strtol(options[o], &tail, 0);
2757 if(tail!=options[o])
2760 numOfUnknownOptions--;
2761 if(numOfNoises >= 3) break;
2767 if(!filterNameOk) ppMode.error++;
2768 ppMode.error += numOfUnknownOptions;
2771 #ifdef HAVE_ODIVX_POSTPROCESS
2772 if(ppMode.lumMode & H_DEBLOCK) ppMode.oldMode |= PP_DEBLOCK_Y_H;
2773 if(ppMode.lumMode & V_DEBLOCK) ppMode.oldMode |= PP_DEBLOCK_Y_V;
2774 if(ppMode.chromMode & H_DEBLOCK) ppMode.oldMode |= PP_DEBLOCK_C_H;
2775 if(ppMode.chromMode & V_DEBLOCK) ppMode.oldMode |= PP_DEBLOCK_C_V;
2776 if(ppMode.lumMode & DERING) ppMode.oldMode |= PP_DERING_Y;
2777 if(ppMode.chromMode & DERING) ppMode.oldMode |= PP_DERING_C;
2784 * Obsolete, dont use it, use postprocess2() instead
2786 void postprocess(unsigned char * src[], int src_stride,
2787 unsigned char * dst[], int dst_stride,
2788 int horizontal_size, int vertical_size,
2789 QP_STORE_T *QP_store, int QP_stride,
2792 struct PPMode ppMode;
2793 static QP_STORE_T zeroArray[2048/8];
2797 ppMode= getPPModeByNameAndQuality("fast,default,-hdeblock,-vdeblock,tmpnoise:150:200:300", qual);
2801 printf("\n%X %X %X %X :%d: %d %d %d\n", ppMode.lumMode, ppMode.chromMode, ppMode.oldMode, ppMode.error,
2802 qual, ppMode.maxTmpNoise[0], ppMode.maxTmpNoise[1], ppMode.maxTmpNoise[2]);
2803 postprocess2(src, src_stride, dst, dst_stride,
2804 horizontal_size, vertical_size, QP_store, QP_stride, &ppMode);
2810 QP_store= zeroArray;
2814 ppMode.lumMode= mode;
2815 mode= ((mode&0xFF)>>4) | (mode&0xFFFFFF00);
2816 ppMode.chromMode= mode;
2817 ppMode.maxTmpNoise[0]= 700;
2818 ppMode.maxTmpNoise[1]= 1500;
2819 ppMode.maxTmpNoise[2]= 3000;
2821 #ifdef HAVE_ODIVX_POSTPROCESS
2822 // Note: I could make this shit outside of this file, but it would mean one
2823 // more function call...
2825 odivx_postprocess(src,src_stride,dst,dst_stride,horizontal_size,vertical_size,QP_store,QP_stride,mode);
2830 postProcess(src[0], src_stride, dst[0], dst_stride,
2831 horizontal_size, vertical_size, QP_store, QP_stride, 0, &ppMode);
2833 horizontal_size >>= 1;
2834 vertical_size >>= 1;
2840 postProcess(src[1], src_stride, dst[1], dst_stride,
2841 horizontal_size, vertical_size, QP_store, QP_stride, 1, &ppMode);
2842 postProcess(src[2], src_stride, dst[2], dst_stride,
2843 horizontal_size, vertical_size, QP_store, QP_stride, 2, &ppMode);
2847 memset(dst[1], 128, dst_stride*vertical_size);
2848 memset(dst[2], 128, dst_stride*vertical_size);
2849 // memcpy(dst[1], src[1], src_stride*horizontal_size);
2850 // memcpy(dst[2], src[2], src_stride*horizontal_size);
2854 void postprocess2(unsigned char * src[], int src_stride,
2855 unsigned char * dst[], int dst_stride,
2856 int horizontal_size, int vertical_size,
2857 QP_STORE_T *QP_store, int QP_stride,
2858 struct PPMode *mode)
2861 static QP_STORE_T zeroArray[2048/8];