Mercurial > mplayer.hg
annotate postproc/postprocess.c @ 8556:ecff1745d189
Document things from the start.
Inspired by a patch from Thomas Jarosch <tomj@simonv.com>.
author | diego |
---|---|
date | Tue, 24 Dec 2002 18:41:20 +0000 |
parents | 6fadfa315113 |
children | 11888c95481b |
rev | line source |
---|---|
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
1 /* |
3964 | 2 Copyright (C) 2001-2002 Michael Niedermayer (michaelni@gmx.at) |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
3 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
4 This program is free software; you can redistribute it and/or modify |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
5 it under the terms of the GNU General Public License as published by |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
6 the Free Software Foundation; either version 2 of the License, or |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
7 (at your option) any later version. |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
8 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
9 This program is distributed in the hope that it will be useful, |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
12 GNU General Public License for more details. |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
13 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
14 You should have received a copy of the GNU General Public License |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
15 along with this program; if not, write to the Free Software |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
17 */ |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
18 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
19 /* |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
20 C MMX MMX2 3DNow |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
21 isVertDC Ec Ec |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
22 isVertMinMaxOk Ec Ec |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
23 doVertLowPass E e e |
3013 | 24 doVertDefFilter Ec Ec e e |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
25 isHorizDC Ec Ec |
2454
b74c2a08eac9
much better horizontal filters (transpose & use the vertical ones) :)
michael
parents:
2437
diff
changeset
|
26 isHorizMinMaxOk a E |
b74c2a08eac9
much better horizontal filters (transpose & use the vertical ones) :)
michael
parents:
2437
diff
changeset
|
27 doHorizLowPass E e e |
3013 | 28 doHorizDefFilter Ec Ec e e |
2477 | 29 deRing E e e* |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
30 Vertical RKAlgo1 E a a |
2461
60f16575bece
fixed difference with -vo md5 between doVertDefFilter() C and MMX / MMX2 versions
michael
parents:
2454
diff
changeset
|
31 Horizontal RKAlgo1 a a |
2860 | 32 Vertical X1# a E E |
33 Horizontal X1# a E E | |
2246 | 34 LinIpolDeinterlace e E E* |
35 CubicIpolDeinterlace a e e* | |
36 LinBlendDeinterlace e E E* | |
2860 | 37 MedianDeinterlace# Ec Ec |
2895
dd3fabd01df0
temp denoiser changes: (a-b)^2 instead of |a-b| and MMX2/3DNOW version
michael
parents:
2860
diff
changeset
|
38 TempDeNoiser# E e e |
2860 | 39 |
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 | |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
42 E = Exact implementation |
2246 | 43 e = allmost exact implementation (slightly different rounding,...) |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
44 a = alternative / approximate impl |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
45 c = checked against the other implementations (-vo md5) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
46 */ |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
47 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
48 /* |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
49 TODO: |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
50 reduce the time wasted on the mem transfer |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
51 unroll stuff if instructions depend too much on the prior one |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
52 move YScale thing to the end instead of fixing QP |
2159 | 53 write a faster and higher quality deblocking filter :) |
2168
21a8f158d19f
bugfixes: last 3 lines not brightness/contrast corrected
michael
parents:
2159
diff
changeset
|
54 make the mainloop more flexible (variable number of blocks at once |
21a8f158d19f
bugfixes: last 3 lines not brightness/contrast corrected
michael
parents:
2159
diff
changeset
|
55 (the if/else stuff per block is slowing things down) |
2179 | 56 compare the quality & speed of all filters |
57 split this huge file | |
2570 | 58 optimize c versions |
2860 | 59 try to unroll inner for(x=0 ... loop to avoid these damn if(x ... checks |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
60 ... |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
61 */ |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
62 |
2221 | 63 //Changelog: use the CVS log |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
64 |
2775 | 65 #include "../config.h" |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
66 #include <inttypes.h> |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
67 #include <stdio.h> |
2168
21a8f158d19f
bugfixes: last 3 lines not brightness/contrast corrected
michael
parents:
2159
diff
changeset
|
68 #include <stdlib.h> |
2389 | 69 #include <string.h> |
2476 | 70 #ifdef HAVE_MALLOC_H |
71 #include <malloc.h> | |
72 #endif | |
2159 | 73 //#undef HAVE_MMX2 |
74 //#define HAVE_3DNOW | |
75 //#undef HAVE_MMX | |
3099 | 76 //#undef ARCH_X86 |
3013 | 77 //#define DEBUG_BRIGHTNESS |
8107 | 78 #ifndef PIC |
7946 | 79 #include "../libvo/fastmemcpy.h" |
8107 | 80 #endif |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
81 #include "postprocess.h" |
8038 | 82 #include "postprocess_internal.h" |
4248 | 83 #include "../mangle.h" |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
84 |
2189 | 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) | |
89 | |
2389 | 90 #define GET_MODE_BUFFER_SIZE 500 |
91 #define OPTIONS_ARRAY_SIZE 10 | |
7946 | 92 #define BLOCK_SIZE 8 |
93 #define TEMP_STRIDE 8 | |
94 //#define NUM_BLOCKS_AT_ONCE 16 //not used yet | |
2389 | 95 |
3099 | 96 #ifdef ARCH_X86 |
2742
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
97 static uint64_t __attribute__((aligned(8))) w05= 0x0005000500050005LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
98 static uint64_t __attribute__((aligned(8))) w20= 0x0020002000200020LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
99 static uint64_t __attribute__((aligned(8))) b00= 0x0000000000000000LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
100 static uint64_t __attribute__((aligned(8))) b01= 0x0101010101010101LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
101 static uint64_t __attribute__((aligned(8))) b02= 0x0202020202020202LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
102 static uint64_t __attribute__((aligned(8))) b08= 0x0808080808080808LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
103 static uint64_t __attribute__((aligned(8))) b80= 0x8080808080808080LL; |
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
104 #endif |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
105 |
7963 | 106 static int verbose= 0; |
3771 | 107 |
7963 | 108 static const int deringThreshold= 20; |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
109 |
7946 | 110 |
2389 | 111 static struct PPFilter filters[]= |
112 { | |
113 {"hb", "hdeblock", 1, 1, 3, H_DEBLOCK}, | |
114 {"vb", "vdeblock", 1, 2, 4, V_DEBLOCK}, | |
7946 | 115 /* {"hr", "rkhdeblock", 1, 1, 3, H_RK1_FILTER}, |
116 {"vr", "rkvdeblock", 1, 2, 4, V_RK1_FILTER},*/ | |
2389 | 117 {"h1", "x1hdeblock", 1, 1, 3, H_X1_FILTER}, |
118 {"v1", "x1vdeblock", 1, 2, 4, V_X1_FILTER}, | |
119 {"dr", "dering", 1, 5, 6, DERING}, | |
120 {"al", "autolevels", 0, 1, 2, LEVEL_FIX}, | |
3817 | 121 {"lb", "linblenddeint", 1, 1, 4, LINEAR_BLEND_DEINT_FILTER}, |
122 {"li", "linipoldeint", 1, 1, 4, LINEAR_IPOL_DEINT_FILTER}, | |
123 {"ci", "cubicipoldeint", 1, 1, 4, CUBIC_IPOL_DEINT_FILTER}, | |
124 {"md", "mediandeint", 1, 1, 4, MEDIAN_DEINT_FILTER}, | |
7946 | 125 {"fd", "ffmpegdeint", 1, 1, 4, FFMPEG_DEINT_FILTER}, |
2860 | 126 {"tn", "tmpnoise", 1, 7, 8, TEMP_NOISE_FILTER}, |
3964 | 127 {"fq", "forcequant", 1, 0, 0, FORCE_QUANT}, |
2389 | 128 {NULL, NULL,0,0,0,0} //End Marker |
129 }; | |
130 | |
131 static char *replaceTable[]= | |
132 { | |
2860 | 133 "default", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", |
134 "de", "hdeblock:a,vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", | |
135 "fast", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", | |
136 "fa", "x1hdeblock:a,x1vdeblock:a,dering:a,autolevels,tmpnoise:a:150:200:400", | |
2389 | 137 NULL //End Marker |
138 }; | |
139 | |
7946 | 140 #ifdef ARCH_X86 |
2461
60f16575bece
fixed difference with -vo md5 between doVertDefFilter() C and MMX / MMX2 versions
michael
parents:
2454
diff
changeset
|
141 static inline void unusedVariableWarningFixer() |
60f16575bece
fixed difference with -vo md5 between doVertDefFilter() C and MMX / MMX2 versions
michael
parents:
2454
diff
changeset
|
142 { |
7946 | 143 if(w05 + w20 + b00 + b01 + b02 + b08 + b80 == 0) b00=0; |
2461
60f16575bece
fixed difference with -vo md5 between doVertDefFilter() C and MMX / MMX2 versions
michael
parents:
2454
diff
changeset
|
144 } |
2742
d5636499cafd
minor changes (fixed some warnings, added attribute aligned(8) stuff)
michael
parents:
2595
diff
changeset
|
145 #endif |
2461
60f16575bece
fixed difference with -vo md5 between doVertDefFilter() C and MMX / MMX2 versions
michael
parents:
2454
diff
changeset
|
146 |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
147 |
7946 | 148 #ifdef ARCH_X86 |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
149 static inline void prefetchnta(void *p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
150 { |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
151 asm volatile( "prefetchnta (%0)\n\t" |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
152 : : "r" (p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
153 ); |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
154 } |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
155 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
156 static inline void prefetcht0(void *p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
157 { |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
158 asm volatile( "prefetcht0 (%0)\n\t" |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
159 : : "r" (p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
160 ); |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
161 } |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
162 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
163 static inline void prefetcht1(void *p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
164 { |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
165 asm volatile( "prefetcht1 (%0)\n\t" |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
166 : : "r" (p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
167 ); |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
168 } |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
169 |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
170 static inline void prefetcht2(void *p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
171 { |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
172 asm volatile( "prefetcht2 (%0)\n\t" |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
173 : : "r" (p) |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
174 ); |
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
175 } |
2185 | 176 #endif |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
177 |
3099 | 178 // The horizontal Functions exist only in C cuz the MMX code is faster with vertical filters and transposing |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
179 |
3032 | 180 /** |
181 * Check if the given 8x8 Block is mostly "flat" | |
182 */ | |
7946 | 183 static inline int isHorizDC(uint8_t src[], int stride, PPContext *c) |
3032 | 184 { |
185 int numEq= 0; | |
186 int y; | |
7960 | 187 const int dcOffset= ((c->QP*c->ppMode.baseDcDiff)>>8) + 1; |
188 const int dcThreshold= dcOffset*2 + 1; | |
3032 | 189 for(y=0; y<BLOCK_SIZE; y++) |
190 { | |
7946 | 191 if(((unsigned)(src[0] - src[1] + dcOffset)) < dcThreshold) numEq++; |
192 if(((unsigned)(src[1] - src[2] + dcOffset)) < dcThreshold) numEq++; | |
193 if(((unsigned)(src[2] - src[3] + dcOffset)) < dcThreshold) numEq++; | |
194 if(((unsigned)(src[3] - src[4] + dcOffset)) < dcThreshold) numEq++; | |
195 if(((unsigned)(src[4] - src[5] + dcOffset)) < dcThreshold) numEq++; | |
196 if(((unsigned)(src[5] - src[6] + dcOffset)) < dcThreshold) numEq++; | |
197 if(((unsigned)(src[6] - src[7] + dcOffset)) < dcThreshold) numEq++; | |
3032 | 198 src+= stride; |
199 } | |
7946 | 200 return numEq > c->ppMode.flatnessThreshold; |
201 } | |
202 | |
203 /** | |
204 * Check if the middle 8x8 Block in the given 8x16 block is flat | |
205 */ | |
206 static inline int isVertDC_C(uint8_t src[], int stride, PPContext *c){ | |
207 int numEq= 0; | |
208 int y; | |
7960 | 209 const int dcOffset= ((c->QP*c->ppMode.baseDcDiff)>>8) + 1; |
210 const int dcThreshold= dcOffset*2 + 1; | |
7946 | 211 src+= stride*4; // src points to begin of the 8x8 Block |
212 for(y=0; y<BLOCK_SIZE-1; y++) | |
213 { | |
214 if(((unsigned)(src[0] - src[0+stride] + dcOffset)) < dcThreshold) numEq++; | |
215 if(((unsigned)(src[1] - src[1+stride] + dcOffset)) < dcThreshold) numEq++; | |
216 if(((unsigned)(src[2] - src[2+stride] + dcOffset)) < dcThreshold) numEq++; | |
217 if(((unsigned)(src[3] - src[3+stride] + dcOffset)) < dcThreshold) numEq++; | |
218 if(((unsigned)(src[4] - src[4+stride] + dcOffset)) < dcThreshold) numEq++; | |
219 if(((unsigned)(src[5] - src[5+stride] + dcOffset)) < dcThreshold) numEq++; | |
220 if(((unsigned)(src[6] - src[6+stride] + dcOffset)) < dcThreshold) numEq++; | |
221 if(((unsigned)(src[7] - src[7+stride] + dcOffset)) < dcThreshold) numEq++; | |
222 src+= stride; | |
223 } | |
224 return numEq > c->ppMode.flatnessThreshold; | |
3032 | 225 } |
226 | |
227 static inline int isHorizMinMaxOk(uint8_t src[], int stride, int QP) | |
228 { | |
229 if(abs(src[0] - src[7]) > 2*QP) return 0; | |
230 | |
231 return 1; | |
232 } | |
233 | |
234 static inline void doHorizDefFilter(uint8_t dst[], int stride, int QP) | |
235 { | |
236 int y; | |
237 for(y=0; y<BLOCK_SIZE; y++) | |
238 { | |
239 const int middleEnergy= 5*(dst[4] - dst[5]) + 2*(dst[2] - dst[5]); | |
240 | |
241 if(ABS(middleEnergy) < 8*QP) | |
242 { | |
243 const int q=(dst[3] - dst[4])/2; | |
244 const int leftEnergy= 5*(dst[2] - dst[1]) + 2*(dst[0] - dst[3]); | |
245 const int rightEnergy= 5*(dst[6] - dst[5]) + 2*(dst[4] - dst[7]); | |
246 | |
247 int d= ABS(middleEnergy) - MIN( ABS(leftEnergy), ABS(rightEnergy) ); | |
248 d= MAX(d, 0); | |
249 | |
250 d= (5*d + 32) >> 6; | |
251 d*= SIGN(-middleEnergy); | |
252 | |
253 if(q>0) | |
254 { | |
255 d= d<0 ? 0 : d; | |
256 d= d>q ? q : d; | |
257 } | |
258 else | |
259 { | |
260 d= d>0 ? 0 : d; | |
261 d= d<q ? q : d; | |
262 } | |
263 | |
264 dst[3]-= d; | |
265 dst[4]+= d; | |
266 } | |
267 dst+= stride; | |
268 } | |
269 } | |
270 | |
271 /** | |
272 * Do a horizontal low pass filter on the 10x8 block (dst points to middle 8x8 Block) | |
273 * using the 9-Tap Filter (1,1,2,2,4,2,2,1,1)/16 (C version) | |
274 */ | |
275 static inline void doHorizLowPass(uint8_t dst[], int stride, int QP) | |
276 { | |
277 | |
278 int y; | |
279 for(y=0; y<BLOCK_SIZE; y++) | |
280 { | |
281 const int first= ABS(dst[-1] - dst[0]) < QP ? dst[-1] : dst[0]; | |
282 const int last= ABS(dst[8] - dst[7]) < QP ? dst[8] : dst[7]; | |
283 | |
284 int sums[9]; | |
285 sums[0] = first + dst[0]; | |
286 sums[1] = dst[0] + dst[1]; | |
287 sums[2] = dst[1] + dst[2]; | |
288 sums[3] = dst[2] + dst[3]; | |
289 sums[4] = dst[3] + dst[4]; | |
290 sums[5] = dst[4] + dst[5]; | |
291 sums[6] = dst[5] + dst[6]; | |
292 sums[7] = dst[6] + dst[7]; | |
293 sums[8] = dst[7] + last; | |
294 | |
295 dst[0]= ((sums[0]<<2) + ((first + sums[2])<<1) + sums[4] + 8)>>4; | |
296 dst[1]= ((dst[1]<<2) + ((first + sums[0] + sums[3])<<1) + sums[5] + 8)>>4; | |
297 dst[2]= ((dst[2]<<2) + ((first + sums[1] + sums[4])<<1) + sums[6] + 8)>>4; | |
298 dst[3]= ((dst[3]<<2) + ((sums[2] + sums[5])<<1) + sums[0] + sums[7] + 8)>>4; | |
299 dst[4]= ((dst[4]<<2) + ((sums[3] + sums[6])<<1) + sums[1] + sums[8] + 8)>>4; | |
300 dst[5]= ((dst[5]<<2) + ((last + sums[7] + sums[4])<<1) + sums[2] + 8)>>4; | |
301 dst[6]= (((last + dst[6])<<2) + ((dst[7] + sums[5])<<1) + sums[3] + 8)>>4; | |
302 dst[7]= ((sums[8]<<2) + ((last + sums[6])<<1) + sums[4] + 8)>>4; | |
303 | |
304 dst+= stride; | |
305 } | |
306 } | |
307 | |
3099 | 308 /** |
309 * Experimental Filter 1 (Horizontal) | |
310 * will not damage linear gradients | |
311 * Flat blocks should look like they where passed through the (1,1,2,2,4,2,2,1,1) 9-Tap filter | |
312 * can only smooth blocks at the expected locations (it cant smooth them if they did move) | |
313 * MMX2 version does correct clipping C version doesnt | |
314 * not identical with the vertical one | |
315 */ | |
316 static inline void horizX1Filter(uint8_t *src, int stride, int QP) | |
2158
508468a75be0
new postprocess code by Michael Niedermayer (michaelni@gmx.at)
arpi
parents:
diff
changeset
|
317 { |
3099 | 318 int y; |
319 static uint64_t *lut= NULL; | |
320 if(lut==NULL) | |
321 { | |
322 int i; | |
323 lut= (uint64_t*)memalign(8, 256*8); | |
324 for(i=0; i<256; i++) | |
325 { | |
326 int v= i < 128 ? 2*i : 2*(i-256); | |
327 /* | |
328 //Simulate 112242211 9-Tap filter | |
329 uint64_t a= (v/16) & 0xFF; | |
330 uint64_t b= (v/8) & 0xFF; | |
331 uint64_t c= (v/4) & 0xFF; | |
332 uint64_t d= (3*v/8) & 0xFF; | |
333 */ | |
334 //Simulate piecewise linear interpolation | |
335 uint64_t a= (v/16) & 0xFF; | |
336 uint64_t b= (v*3/16) & 0xFF; | |
337 uint64_t c= (v*5/16) & 0xFF; | |
338 uint64_t d= (7*v/16) & 0xFF; | |
339 uint64_t A= (0x100 - a)&0xFF; | |
340 uint64_t B= (0x100 - b)&0xFF; | |
341 uint64_t C= (0x100 - c)&0xFF; | |
342 uint64_t D= (0x100 - c)&0xFF; | |
2473 | 343 |
3099 | 344 lut[i] = (a<<56) | (b<<48) | (c<<40) | (d<<32) | |
345 (D<<24) | (C<<16) | (B<<8) | (A); | |
346 //lut[i] = (v<<32) | (v<<24); | |
2477 | 347 } |
348 } | |
349 | |
3099 | 350 for(y=0; y<BLOCK_SIZE; y++) |
2477 | 351 { |
3099 | 352 int a= src[1] - src[2]; |
353 int b= src[3] - src[4]; | |
354 int c= src[5] - src[6]; | |
2477 | 355 |
3099 | 356 int d= MAX(ABS(b) - (ABS(a) + ABS(c))/2, 0); |
3093 | 357 |
3099 | 358 if(d < QP) |
3093 | 359 { |
3099 | 360 int v = d * SIGN(-b); |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
361 |
3099 | 362 src[1] +=v/8; |
363 src[2] +=v/4; | |
364 src[3] +=3*v/8; | |
365 src[4] -=3*v/8; | |
366 src[5] -=v/4; | |
367 src[6] -=v/8; | |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
368 |
3099 | 369 } |
370 src+=stride; | |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
371 } |
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
372 } |
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
373 |
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
374 |
3151 | 375 //Note: we have C, MMX, MMX2, 3DNOW version there is no 3DNOW+MMX2 one |
3099 | 376 //Plain C versions |
3151 | 377 #if !defined (HAVE_MMX) || defined (RUNTIME_CPUDETECT) |
378 #define COMPILE_C | |
379 #endif | |
380 | |
7946 | 381 #ifdef ARCH_X86 |
3151 | 382 |
383 #if (defined (HAVE_MMX) && !defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT) | |
384 #define COMPILE_MMX | |
385 #endif | |
386 | |
387 #if defined (HAVE_MMX2) || defined (RUNTIME_CPUDETECT) | |
388 #define COMPILE_MMX2 | |
389 #endif | |
390 | |
391 #if (defined (HAVE_3DNOW) && !defined (HAVE_MMX2)) || defined (RUNTIME_CPUDETECT) | |
392 #define COMPILE_3DNOW | |
393 #endif | |
7946 | 394 #endif //ARCH_X86 |
3151 | 395 |
396 #undef HAVE_MMX | |
397 #undef HAVE_MMX2 | |
398 #undef HAVE_3DNOW | |
399 #undef ARCH_X86 | |
400 | |
401 #ifdef COMPILE_C | |
3099 | 402 #undef HAVE_MMX |
403 #undef HAVE_MMX2 | |
404 #undef HAVE_3DNOW | |
405 #undef ARCH_X86 | |
406 #define RENAME(a) a ## _C | |
407 #include "postprocess_template.c" | |
3151 | 408 #endif |
2203
f90b6e259dc8
rewrote the horizontal lowpass filter to fix a bug which caused a blocky look
michael
parents:
2195
diff
changeset
|
409 |
3099 | 410 //MMX versions |
3151 | 411 #ifdef COMPILE_MMX |
3099 | 412 #undef RENAME |
413 #define HAVE_MMX | |
414 #undef HAVE_MMX2 | |
415 #undef HAVE_3DNOW | |
416 #define ARCH_X86 | |
417 #define RENAME(a) a ## _MMX | |
418 #include "postprocess_template.c" | |
3151 | 419 #endif |
2454
b74c2a08eac9
much better horizontal filters (transpose & use the vertical ones) :)
michael
parents:
2437
diff
changeset
|
420 |
3099 | 421 //MMX2 versions |
3151 | 422 #ifdef COMPILE_MMX2 |
3099 | 423 #undef RENAME |
424 #define HAVE_MMX | |
425 #define HAVE_MMX2 | |
426 #undef HAVE_3DNOW | |
427 #define ARCH_X86 | |
428 #define RENAME(a) a ## _MMX2 | |
429 #include "postprocess_template.c" | |
3151 | 430 #endif |
2454
b74c2a08eac9
much better horizontal filters (transpose & use the vertical ones) :)
michael
parents:
2437
diff
changeset
|
431 |
3099 | 432 //3DNOW versions |
3151 | 433 #ifdef COMPILE_3DNOW |
3099 | 434 #undef RENAME |
435 #define HAVE_MMX | |
436 #undef HAVE_MMX2 | |
437 #define HAVE_3DNOW | |
438 #define ARCH_X86 | |
439 #define RENAME(a) a ## _3DNow | |
440 #include "postprocess_template.c" | |
3151 | 441 #endif |
2454
b74c2a08eac9
much better horizontal filters (transpose & use the vertical ones) :)
michael
parents:
2437
diff
changeset
|
442 |
3099 | 443 // minor note: the HAVE_xyz is messed up after that line so dont use it |
2454
b74c2a08eac9
much better horizontal filters (transpose & use the vertical ones) :)
michael
parents:
2437
diff
changeset
|
444 |
3099 | 445 static inline void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, |
8038 | 446 QP_STORE_T QPs[], int QPStride, int isColor, pp_mode_t *vm, pp_context_t *vc) |
2860 | 447 { |
7946 | 448 PPContext *c= (PPContext *)vc; |
8038 | 449 PPMode *ppMode= (PPMode *)vm; |
7946 | 450 c->ppMode= *ppMode; //FIXME |
451 | |
3099 | 452 // useing ifs here as they are faster than function pointers allthough the |
453 // difference wouldnt be messureable here but its much better because | |
454 // someone might exchange the cpu whithout restarting mplayer ;) | |
3151 | 455 #ifdef RUNTIME_CPUDETECT |
7946 | 456 #ifdef ARCH_X86 |
3099 | 457 // ordered per speed fasterst first |
7985 | 458 if(c->cpuCaps & PP_CPU_CAPS_MMX2) |
7946 | 459 postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
7985 | 460 else if(c->cpuCaps & PP_CPU_CAPS_3DNOW) |
7946 | 461 postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
7985 | 462 else if(c->cpuCaps & PP_CPU_CAPS_MMX) |
7946 | 463 postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
3099 | 464 else |
7946 | 465 postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
2895
dd3fabd01df0
temp denoiser changes: (a-b)^2 instead of |a-b| and MMX2/3DNOW version
michael
parents:
2860
diff
changeset
|
466 #else |
7946 | 467 postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
2895
dd3fabd01df0
temp denoiser changes: (a-b)^2 instead of |a-b| and MMX2/3DNOW version
michael
parents:
2860
diff
changeset
|
468 #endif |
3151 | 469 #else //RUNTIME_CPUDETECT |
470 #ifdef HAVE_MMX2 | |
7946 | 471 postProcess_MMX2(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
3151 | 472 #elif defined (HAVE_3DNOW) |
7946 | 473 postProcess_3DNow(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
3151 | 474 #elif defined (HAVE_MMX) |
7946 | 475 postProcess_MMX(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
3151 | 476 #else |
7946 | 477 postProcess_C(src, srcStride, dst, dstStride, width, height, QPs, QPStride, isColor, c); |
3151 | 478 #endif |
479 #endif //!RUNTIME_CPUDETECT | |
2860 | 480 } |
481 | |
3099 | 482 //static void postProcess(uint8_t src[], int srcStride, uint8_t dst[], int dstStride, int width, int height, |
483 // QP_STORE_T QPs[], int QPStride, int isColor, struct PPMode *ppMode); | |
2159 | 484 |
2389 | 485 /* -pp Command line Help |
486 */ | |
7984
a57c1fc0c2fc
change qscale type to int8 and fix qscale ordering
michael
parents:
7972
diff
changeset
|
487 char *pp_help= |
8076 | 488 "<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n" |
3976 | 489 "long form example:\n" |
8076 | 490 "vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n" |
3976 | 491 "short form example:\n" |
8076 | 492 "vb:a/hb:a/lb de,-vb\n" |
3976 | 493 "more examples:\n" |
7986 | 494 "tn:64:128:256\n" |
3976 | 495 "Filters Options\n" |
496 "short long name short long option Description\n" | |
497 "* * a autoq cpu power dependant enabler\n" | |
498 " c chrom chrominance filtring enabled\n" | |
499 " y nochrom chrominance filtring disabled\n" | |
500 "hb hdeblock (2 Threshold) horizontal deblocking filter\n" | |
8076 | 501 " 1. difference factor: default=64, higher -> more deblocking\n" |
502 " 2. flatness threshold: default=40, lower -> more deblocking\n" | |
3976 | 503 " the h & v deblocking filters share these\n" |
504 " so u cant set different thresholds for h / v\n" | |
505 "vb vdeblock (2 Threshold) vertical deblocking filter\n" | |
506 "h1 x1hdeblock Experimental h deblock filter 1\n" | |
507 "v1 x1vdeblock Experimental v deblock filter 1\n" | |
508 "dr dering Deringing filter\n" | |
509 "al autolevels automatic brightness / contrast\n" | |
510 " f fullyrange stretch luminance to (0..255)\n" | |
511 "lb linblenddeint linear blend deinterlacer\n" | |
512 "li linipoldeint linear interpolating deinterlace\n" | |
513 "ci cubicipoldeint cubic interpolating deinterlacer\n" | |
514 "md mediandeint median deinterlacer\n" | |
7946 | 515 "fd ffmpegdeint ffmpeg deinterlacer\n" |
3976 | 516 "de default hb:a,vb:a,dr:a,al\n" |
517 "fa fast h1:a,v1:a,dr:a,al\n" | |
518 "tn tmpnoise (3 Thresholds) Temporal Noise Reducer\n" | |
519 " 1. <= 2. <= 3. larger -> stronger filtering\n" | |
520 "fq forceQuant <quantizer> Force quantizer\n" | |
521 ; | |
2389 | 522 |
8038 | 523 pp_mode_t *pp_get_mode_by_name_and_quality(char *name, int quality) |
2389 | 524 { |
525 char temp[GET_MODE_BUFFER_SIZE]; | |
526 char *p= temp; | |
7946 | 527 char *filterDelimiters= ",/"; |
2389 | 528 char *optionDelimiters= ":"; |
8038 | 529 struct PPMode *ppMode; |
2389 | 530 char *filterToken; |
531 | |
8038 | 532 ppMode= memalign(8, sizeof(PPMode)); |
533 | |
534 ppMode->lumMode= 0; | |
535 ppMode->chromMode= 0; | |
536 ppMode->maxTmpNoise[0]= 700; | |
537 ppMode->maxTmpNoise[1]= 1500; | |
538 ppMode->maxTmpNoise[2]= 3000; | |
539 ppMode->maxAllowedY= 234; | |
540 ppMode->minAllowedY= 16; | |
541 ppMode->baseDcDiff= 256/4; | |
542 ppMode->flatnessThreshold= 56-16; | |
543 ppMode->maxClippedThreshold= 0.01; | |
544 ppMode->error=0; | |
7963 | 545 |
2389 | 546 strncpy(temp, name, GET_MODE_BUFFER_SIZE); |
547 | |
4143 | 548 if(verbose>1) printf("pp: %s\n", name); |
2860 | 549 |
2389 | 550 for(;;){ |
551 char *filterName; | |
8040 | 552 int q= 1000000; //PP_QUALITY_MAX; |
2389 | 553 int chrom=-1; |
554 char *option; | |
555 char *options[OPTIONS_ARRAY_SIZE]; | |
556 int i; | |
557 int filterNameOk=0; | |
558 int numOfUnknownOptions=0; | |
559 int enable=1; //does the user want us to enabled or disabled the filter | |
560 | |
561 filterToken= strtok(p, filterDelimiters); | |
562 if(filterToken == NULL) break; | |
2860 | 563 p+= strlen(filterToken) + 1; // p points to next filterToken |
2389 | 564 filterName= strtok(filterToken, optionDelimiters); |
4143 | 565 if(verbose>1) printf("pp: %s::%s\n", filterToken, filterName); |
2389 | 566 |
567 if(*filterName == '-') | |
568 { | |
569 enable=0; | |
570 filterName++; | |
571 } | |
2860 | 572 |
2389 | 573 for(;;){ //for all options |
574 option= strtok(NULL, optionDelimiters); | |
575 if(option == NULL) break; | |
576 | |
4143 | 577 if(verbose>1) printf("pp: option: %s\n", option); |
2389 | 578 if(!strcmp("autoq", option) || !strcmp("a", option)) q= quality; |
579 else if(!strcmp("nochrom", option) || !strcmp("y", option)) chrom=0; | |
580 else if(!strcmp("chrom", option) || !strcmp("c", option)) chrom=1; | |
581 else | |
582 { | |
583 options[numOfUnknownOptions] = option; | |
584 numOfUnknownOptions++; | |
585 } | |
586 if(numOfUnknownOptions >= OPTIONS_ARRAY_SIZE-1) break; | |
587 } | |
2860 | 588 options[numOfUnknownOptions] = NULL; |
2389 | 589 |
590 /* replace stuff from the replace Table */ | |
591 for(i=0; replaceTable[2*i]!=NULL; i++) | |
592 { | |
593 if(!strcmp(replaceTable[2*i], filterName)) | |
594 { | |
595 int newlen= strlen(replaceTable[2*i + 1]); | |
596 int plen; | |
597 int spaceLeft; | |
598 | |
599 if(p==NULL) p= temp, *p=0; //last filter | |
600 else p--, *p=','; //not last filter | |
601 | |
602 plen= strlen(p); | |
6164
aee9c32349a9
applied 64bit patch from Ulrich Hecht <uli at suse dot de>
alex
parents:
4257
diff
changeset
|
603 spaceLeft= p - temp + plen; |
2389 | 604 if(spaceLeft + newlen >= GET_MODE_BUFFER_SIZE) |
605 { | |
8038 | 606 ppMode->error++; |
2389 | 607 break; |
608 } | |
609 memmove(p + newlen, p, plen+1); | |
610 memcpy(p, replaceTable[2*i + 1], newlen); | |
611 filterNameOk=1; | |
612 } | |
613 } | |
614 | |
615 for(i=0; filters[i].shortName!=NULL; i++) | |
616 { | |
2860 | 617 // printf("Compareing %s, %s, %s\n", filters[i].shortName,filters[i].longName, filterName); |
2389 | 618 if( !strcmp(filters[i].longName, filterName) |
619 || !strcmp(filters[i].shortName, filterName)) | |
620 { | |
8038 | 621 ppMode->lumMode &= ~filters[i].mask; |
622 ppMode->chromMode &= ~filters[i].mask; | |
2389 | 623 |
624 filterNameOk=1; | |
625 if(!enable) break; // user wants to disable it | |
626 | |
627 if(q >= filters[i].minLumQuality) | |
8038 | 628 ppMode->lumMode|= filters[i].mask; |
2389 | 629 if(chrom==1 || (chrom==-1 && filters[i].chromDefault)) |
630 if(q >= filters[i].minChromQuality) | |
8038 | 631 ppMode->chromMode|= filters[i].mask; |
2389 | 632 |
633 if(filters[i].mask == LEVEL_FIX) | |
634 { | |
635 int o; | |
8038 | 636 ppMode->minAllowedY= 16; |
637 ppMode->maxAllowedY= 234; | |
2389 | 638 for(o=0; options[o]!=NULL; o++) |
3832
d05cfaf5f0f2
minor brightness/contrast bugfix / moved some global vars into ppMode
michael
parents:
3817
diff
changeset
|
639 { |
2389 | 640 if( !strcmp(options[o],"fullyrange") |
641 ||!strcmp(options[o],"f")) | |
642 { | |
8038 | 643 ppMode->minAllowedY= 0; |
644 ppMode->maxAllowedY= 255; | |
2389 | 645 numOfUnknownOptions--; |
646 } | |
3832
d05cfaf5f0f2
minor brightness/contrast bugfix / moved some global vars into ppMode
michael
parents:
3817
diff
changeset
|
647 } |
2389 | 648 } |
2860 | 649 else if(filters[i].mask == TEMP_NOISE_FILTER) |
650 { | |
651 int o; | |
652 int numOfNoises=0; | |
653 | |
654 for(o=0; options[o]!=NULL; o++) | |
655 { | |
656 char *tail; | |
8038 | 657 ppMode->maxTmpNoise[numOfNoises]= |
2860 | 658 strtol(options[o], &tail, 0); |
659 if(tail!=options[o]) | |
660 { | |
661 numOfNoises++; | |
662 numOfUnknownOptions--; | |
663 if(numOfNoises >= 3) break; | |
664 } | |
665 } | |
666 } | |
3817 | 667 else if(filters[i].mask == V_DEBLOCK || filters[i].mask == H_DEBLOCK) |
668 { | |
669 int o; | |
670 | |
671 for(o=0; options[o]!=NULL && o<2; o++) | |
672 { | |
673 char *tail; | |
674 int val= strtol(options[o], &tail, 0); | |
675 if(tail==options[o]) break; | |
676 | |
677 numOfUnknownOptions--; | |
8038 | 678 if(o==0) ppMode->baseDcDiff= val; |
679 else ppMode->flatnessThreshold= val; | |
3817 | 680 } |
681 } | |
3964 | 682 else if(filters[i].mask == FORCE_QUANT) |
683 { | |
684 int o; | |
8038 | 685 ppMode->forcedQuant= 15; |
3964 | 686 |
687 for(o=0; options[o]!=NULL && o<1; o++) | |
688 { | |
689 char *tail; | |
690 int val= strtol(options[o], &tail, 0); | |
691 if(tail==options[o]) break; | |
692 | |
693 numOfUnknownOptions--; | |
8038 | 694 ppMode->forcedQuant= val; |
3964 | 695 } |
696 } | |
2389 | 697 } |
698 } | |
8038 | 699 if(!filterNameOk) ppMode->error++; |
700 ppMode->error += numOfUnknownOptions; | |
2389 | 701 } |
702 | |
8038 | 703 if(verbose>1) printf("pp: lumMode=%X, chromMode=%X\n", ppMode->lumMode, ppMode->chromMode); |
704 if(ppMode->error) | |
705 { | |
706 fprintf(stderr, "%d errors in postprocess string \"%s\"\n", ppMode->error, name); | |
707 free(ppMode); | |
708 return NULL; | |
709 } | |
2389 | 710 return ppMode; |
711 } | |
712 | |
8038 | 713 void pp_free_mode(pp_mode_t *mode){ |
714 if(mode) free(mode); | |
715 } | |
716 | |
717 pp_context_t *pp_get_context(int width, int height, int cpuCaps){ | |
7946 | 718 PPContext *c= memalign(32, sizeof(PPContext)); |
719 int i; | |
7960 | 720 int mbWidth = (width+15)>>4; |
721 int mbHeight= (height+15)>>4; | |
7985 | 722 |
723 c->cpuCaps= cpuCaps; | |
7946 | 724 |
725 c->tempBlocks= (uint8_t*)memalign(8, 2*16*8); | |
726 c->yHistogram= (uint64_t*)memalign(8, 256*sizeof(uint64_t)); | |
727 for(i=0; i<256; i++) | |
728 c->yHistogram[i]= width*height/64*15/256; | |
729 | |
730 for(i=0; i<3; i++) | |
3987 | 731 { |
7946 | 732 //Note:the +17*1024 is just there so i dont have to worry about r/w over te end |
733 c->tempBlured[i]= (uint8_t*)memalign(8, ((width+7)&(~7))*2*((height+7)&(~7)) + 17*1024); //FIXME dstStride instead of width | |
734 c->tempBluredPast[i]= (uint32_t*)memalign(8, 256*((height+7)&(~7))/2 + 17*1024); | |
735 | |
736 memset(c->tempBlured[i], 0, ((width+7)&(~7))*2*((height+7)&(~7)) + 17*1024); | |
737 memset(c->tempBluredPast[i], 0, 256*((height+7)&(~7))/2 + 17*1024); | |
3987 | 738 } |
739 | |
7946 | 740 c->tempDst= (uint8_t*)memalign(8, 1024*24); |
741 c->tempSrc= (uint8_t*)memalign(8, 1024*24); | |
742 c->tempDstBlock= (uint8_t*)memalign(8, 1024*24); | |
743 c->tempSrcBlock= (uint8_t*)memalign(8, 1024*24); | |
744 c->deintTemp= (uint8_t*)memalign(8, width+16); | |
7960 | 745 c->nonBQPTable= (QP_STORE_T*)memalign(8, mbWidth*mbHeight*sizeof(QP_STORE_T)); |
746 memset(c->nonBQPTable, 0, mbWidth*mbHeight*sizeof(QP_STORE_T)); | |
3771 | 747 |
7946 | 748 c->frameNum=-1; |
3771 | 749 |
7946 | 750 return c; |
3771 | 751 } |
752 | |
7961 | 753 void pp_free_context(void *vc){ |
7946 | 754 PPContext *c = (PPContext*)vc; |
755 int i; | |
756 | |
757 for(i=0; i<3; i++) free(c->tempBlured[i]); | |
758 for(i=0; i<3; i++) free(c->tempBluredPast[i]); | |
759 | |
760 free(c->tempBlocks); | |
761 free(c->yHistogram); | |
762 free(c->tempDst); | |
763 free(c->tempSrc); | |
764 free(c->tempDstBlock); | |
765 free(c->tempSrcBlock); | |
766 free(c->deintTemp); | |
7960 | 767 free(c->nonBQPTable); |
7946 | 768 |
769 free(c); | |
770 } | |
771 | |
7961 | 772 void pp_postprocess(uint8_t * src[3], int srcStride[3], |
7946 | 773 uint8_t * dst[3], int dstStride[3], |
7960 | 774 int width, int height, |
7946 | 775 QP_STORE_T *QP_store, int QPStride, |
8038 | 776 pp_mode_t *vm, void *vc, int pict_type) |
2389 | 777 { |
7960 | 778 int mbWidth = (width+15)>>4; |
779 int mbHeight= (height+15)>>4; | |
3964 | 780 QP_STORE_T quantArray[2048/8]; |
8038 | 781 PPMode *mode = (PPMode*)vm; |
7960 | 782 PPContext *c = (PPContext*)vc; |
7946 | 783 |
3964 | 784 if(QP_store==NULL || (mode->lumMode & FORCE_QUANT)) |
2808 | 785 { |
3964 | 786 int i; |
787 QP_store= quantArray; | |
7946 | 788 QPStride= 0; |
3964 | 789 if(mode->lumMode & FORCE_QUANT) |
790 for(i=0; i<2048/8; i++) quantArray[i]= mode->forcedQuant; | |
791 else | |
792 for(i=0; i<2048/8; i++) quantArray[i]= 1; | |
2808 | 793 } |
7960 | 794 if(0){ |
795 int x,y; | |
796 for(y=0; y<mbHeight; y++){ | |
797 for(x=0; x<mbWidth; x++){ | |
798 printf("%2d ", QP_store[x + y*QPStride]); | |
799 } | |
800 printf("\n"); | |
801 } | |
802 printf("\n"); | |
803 } | |
804 //printf("pict_type:%d\n", pict_type); | |
7968 | 805 |
7960 | 806 if(pict_type!=3) |
807 { | |
808 int x,y; | |
809 for(y=0; y<mbHeight; y++){ | |
810 for(x=0; x<mbWidth; x++){ | |
811 int qscale= QP_store[x + y*QPStride]; | |
812 if(qscale&~31) | |
813 qscale=31; | |
814 c->nonBQPTable[y*mbWidth + x]= qscale; | |
815 } | |
816 } | |
817 } | |
2808 | 818 |
7963 | 819 if(verbose>2) |
4143 | 820 { |
821 printf("using npp filters 0x%X/0x%X\n", mode->lumMode, mode->chromMode); | |
822 } | |
823 | |
7946 | 824 postProcess(src[0], srcStride[0], dst[0], dstStride[0], |
7960 | 825 width, height, QP_store, QPStride, 0, mode, c); |
2389 | 826 |
7960 | 827 width = (width +1)>>1; |
828 height = (height+1)>>1; | |
2389 | 829 |
3094
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
830 if(mode->chromMode) |
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
831 { |
7946 | 832 postProcess(src[1], srcStride[1], dst[1], dstStride[1], |
7960 | 833 width, height, QP_store, QPStride, 1, mode, c); |
7946 | 834 postProcess(src[2], srcStride[2], dst[2], dstStride[2], |
7960 | 835 width, height, QP_store, QPStride, 2, mode, c); |
3094
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
836 } |
7946 | 837 else if(srcStride[1] == dstStride[1] && srcStride[2] == dstStride[2]) |
3094
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
838 { |
7960 | 839 memcpy(dst[1], src[1], srcStride[1]*height); |
840 memcpy(dst[2], src[2], srcStride[2]*height); | |
3094
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
841 } |
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
842 else |
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
843 { |
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
844 int y; |
7960 | 845 for(y=0; y<height; y++) |
3094
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
846 { |
7960 | 847 memcpy(&(dst[1][y*dstStride[1]]), &(src[1][y*srcStride[1]]), width); |
848 memcpy(&(dst[2][y*dstStride[2]]), &(src[2][y*srcStride[2]]), width); | |
3094
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
849 } |
4150aff2ac17
use fastmemcpy for chrominance if no chrominance filtering is done
michael
parents:
3093
diff
changeset
|
850 } |
2389 | 851 } |
852 |