Mercurial > mplayer.hg
comparison libmpcodecs/vf_ivtc.c @ 32702:7af3e6f901fd
Convert some tabs to whitespace to allow using MPlayer filter sourcecode in FFmpeg.
author | cehoyos |
---|---|
date | Fri, 14 Jan 2011 22:10:21 +0000 |
parents | a972c1a4a012 |
children | 064be070d8c8 |
comparison
equal
deleted
inserted
replaced
32701:02bc7c860503 | 32702:7af3e6f901fd |
---|---|
30 | 30 |
31 #include "libvo/fastmemcpy.h" | 31 #include "libvo/fastmemcpy.h" |
32 | 32 |
33 | 33 |
34 struct metrics { | 34 struct metrics { |
35 /* difference: total, even lines, odd lines */ | 35 /* difference: total, even lines, odd lines */ |
36 int d, e, o; | 36 int d, e, o; |
37 /* noise: temporal, spacial (current), spacial (past) */ | 37 /* noise: temporal, spacial (current), spacial (past) */ |
38 int t, s, p; | 38 int t, s, p; |
39 }; | 39 }; |
40 | 40 |
41 struct frameinfo { | 41 struct frameinfo { |
42 /* peak, relative, mean */ | 42 /* peak, relative, mean */ |
43 struct metrics p, r, m; | 43 struct metrics p, r, m; |
44 }; | 44 }; |
45 | 45 |
46 struct vf_priv_s { | 46 struct vf_priv_s { |
47 struct frameinfo fi[2]; | 47 struct frameinfo fi[2]; |
48 mp_image_t *dmpi; | 48 mp_image_t *dmpi; |
49 int first; | 49 int first; |
50 int drop, lastdrop, dropnext; | 50 int drop, lastdrop, dropnext; |
51 int inframes, outframes; | 51 int inframes, outframes; |
52 }; | 52 }; |
53 | 53 |
54 enum { | 54 enum { |
55 F_DROP, | 55 F_DROP, |
56 F_MERGE, | 56 F_MERGE, |
57 F_NEXT, | 57 F_NEXT, |
58 F_SHOW | 58 F_SHOW |
59 }; | 59 }; |
60 | 60 |
61 #if HAVE_MMX && HAVE_EBX_AVAILABLE | 61 #if HAVE_MMX && HAVE_EBX_AVAILABLE |
62 static void block_diffs_MMX(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns) | 62 static void block_diffs_MMX(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns) |
63 { | 63 { |
64 int i; | 64 int i; |
65 short out[24]; // output buffer for the partial metrics from the mmx code | 65 short out[24]; // output buffer for the partial metrics from the mmx code |
66 | 66 |
67 __asm__ ( | 67 __asm__ ( |
68 "movl $4, %%ecx \n\t" | 68 "movl $4, %%ecx \n\t" |
69 "pxor %%mm4, %%mm4 \n\t" // 4 even difference sums | 69 "pxor %%mm4, %%mm4 \n\t" // 4 even difference sums |
70 "pxor %%mm5, %%mm5 \n\t" // 4 odd difference sums | 70 "pxor %%mm5, %%mm5 \n\t" // 4 odd difference sums |
71 "pxor %%mm7, %%mm7 \n\t" // all zeros | 71 "pxor %%mm7, %%mm7 \n\t" // all zeros |
72 | 72 |
73 ASMALIGN(4) | 73 ASMALIGN(4) |
74 "1: \n\t" | 74 "1: \n\t" |
75 | 75 |
76 // Even difference | 76 // Even difference |
77 "movq (%%"REG_S"), %%mm0 \n\t" | 77 "movq (%%"REG_S"), %%mm0 \n\t" |
78 "movq (%%"REG_S"), %%mm2 \n\t" | 78 "movq (%%"REG_S"), %%mm2 \n\t" |
79 "add %%"REG_a", %%"REG_S" \n\t" | 79 "add %%"REG_a", %%"REG_S" \n\t" |
80 "movq (%%"REG_D"), %%mm1 \n\t" | 80 "movq (%%"REG_D"), %%mm1 \n\t" |
81 "add %%"REG_b", %%"REG_D" \n\t" | 81 "add %%"REG_b", %%"REG_D" \n\t" |
82 "psubusb %%mm1, %%mm2 \n\t" | 82 "psubusb %%mm1, %%mm2 \n\t" |
83 "psubusb %%mm0, %%mm1 \n\t" | 83 "psubusb %%mm0, %%mm1 \n\t" |
84 "movq %%mm2, %%mm0 \n\t" | 84 "movq %%mm2, %%mm0 \n\t" |
85 "movq %%mm1, %%mm3 \n\t" | 85 "movq %%mm1, %%mm3 \n\t" |
86 "punpcklbw %%mm7, %%mm0 \n\t" | 86 "punpcklbw %%mm7, %%mm0 \n\t" |
87 "punpcklbw %%mm7, %%mm1 \n\t" | 87 "punpcklbw %%mm7, %%mm1 \n\t" |
88 "punpckhbw %%mm7, %%mm2 \n\t" | 88 "punpckhbw %%mm7, %%mm2 \n\t" |
89 "punpckhbw %%mm7, %%mm3 \n\t" | 89 "punpckhbw %%mm7, %%mm3 \n\t" |
90 "paddw %%mm0, %%mm4 \n\t" | 90 "paddw %%mm0, %%mm4 \n\t" |
91 "paddw %%mm1, %%mm4 \n\t" | 91 "paddw %%mm1, %%mm4 \n\t" |
92 "paddw %%mm2, %%mm4 \n\t" | 92 "paddw %%mm2, %%mm4 \n\t" |
93 "paddw %%mm3, %%mm4 \n\t" | 93 "paddw %%mm3, %%mm4 \n\t" |
94 | 94 |
95 // Odd difference | 95 // Odd difference |
96 "movq (%%"REG_S"), %%mm0 \n\t" | 96 "movq (%%"REG_S"), %%mm0 \n\t" |
97 "movq (%%"REG_S"), %%mm2 \n\t" | 97 "movq (%%"REG_S"), %%mm2 \n\t" |
98 "add %%"REG_a", %%"REG_S" \n\t" | 98 "add %%"REG_a", %%"REG_S" \n\t" |
99 "movq (%%"REG_D"), %%mm1 \n\t" | 99 "movq (%%"REG_D"), %%mm1 \n\t" |
100 "add %%"REG_b", %%"REG_D" \n\t" | 100 "add %%"REG_b", %%"REG_D" \n\t" |
101 "psubusb %%mm1, %%mm2 \n\t" | 101 "psubusb %%mm1, %%mm2 \n\t" |
102 "psubusb %%mm0, %%mm1 \n\t" | 102 "psubusb %%mm0, %%mm1 \n\t" |
103 "movq %%mm2, %%mm0 \n\t" | 103 "movq %%mm2, %%mm0 \n\t" |
104 "movq %%mm1, %%mm3 \n\t" | 104 "movq %%mm1, %%mm3 \n\t" |
105 "punpcklbw %%mm7, %%mm0 \n\t" | 105 "punpcklbw %%mm7, %%mm0 \n\t" |
106 "punpcklbw %%mm7, %%mm1 \n\t" | 106 "punpcklbw %%mm7, %%mm1 \n\t" |
107 "punpckhbw %%mm7, %%mm2 \n\t" | 107 "punpckhbw %%mm7, %%mm2 \n\t" |
108 "punpckhbw %%mm7, %%mm3 \n\t" | 108 "punpckhbw %%mm7, %%mm3 \n\t" |
109 "paddw %%mm0, %%mm5 \n\t" | 109 "paddw %%mm0, %%mm5 \n\t" |
110 "paddw %%mm1, %%mm5 \n\t" | 110 "paddw %%mm1, %%mm5 \n\t" |
111 "paddw %%mm2, %%mm5 \n\t" | 111 "paddw %%mm2, %%mm5 \n\t" |
112 "paddw %%mm3, %%mm5 \n\t" | 112 "paddw %%mm3, %%mm5 \n\t" |
113 | 113 |
114 "decl %%ecx \n\t" | 114 "decl %%ecx \n\t" |
115 "jnz 1b \n\t" | 115 "jnz 1b \n\t" |
116 "movq %%mm4, (%%"REG_d") \n\t" | 116 "movq %%mm4, (%%"REG_d") \n\t" |
117 "movq %%mm5, 8(%%"REG_d") \n\t" | 117 "movq %%mm5, 8(%%"REG_d") \n\t" |
118 : | 118 : |
119 : "S" (old), "D" (new), "a" (os), "b" (ns), "d" (out) | 119 : "S" (old), "D" (new), "a" (os), "b" (ns), "d" (out) |
120 : "memory" | 120 : "memory" |
121 ); | 121 ); |
122 m->e = out[0]+out[1]+out[2]+out[3]; | 122 m->e = out[0]+out[1]+out[2]+out[3]; |
123 m->o = out[4]+out[5]+out[6]+out[7]; | 123 m->o = out[4]+out[5]+out[6]+out[7]; |
124 m->d = m->e + m->o; | 124 m->d = m->e + m->o; |
125 | 125 |
126 __asm__ ( | 126 __asm__ ( |
127 // First loop to measure first four columns | 127 // First loop to measure first four columns |
128 "movl $4, %%ecx \n\t" | 128 "movl $4, %%ecx \n\t" |
129 "pxor %%mm4, %%mm4 \n\t" // Past spacial noise | 129 "pxor %%mm4, %%mm4 \n\t" // Past spacial noise |
130 "pxor %%mm5, %%mm5 \n\t" // Temporal noise | 130 "pxor %%mm5, %%mm5 \n\t" // Temporal noise |
131 "pxor %%mm6, %%mm6 \n\t" // Current spacial noise | 131 "pxor %%mm6, %%mm6 \n\t" // Current spacial noise |
132 | 132 |
133 ASMALIGN(4) | 133 ASMALIGN(4) |
134 "2: \n\t" | 134 "2: \n\t" |
135 | 135 |
136 "movq (%%"REG_S"), %%mm0 \n\t" | 136 "movq (%%"REG_S"), %%mm0 \n\t" |
137 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t" | 137 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t" |
138 "add %%"REG_a", %%"REG_S" \n\t" | 138 "add %%"REG_a", %%"REG_S" \n\t" |
139 "add %%"REG_a", %%"REG_S" \n\t" | 139 "add %%"REG_a", %%"REG_S" \n\t" |
140 "movq (%%"REG_D"), %%mm2 \n\t" | 140 "movq (%%"REG_D"), %%mm2 \n\t" |
141 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t" | 141 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t" |
142 "add %%"REG_b", %%"REG_D" \n\t" | 142 "add %%"REG_b", %%"REG_D" \n\t" |
143 "add %%"REG_b", %%"REG_D" \n\t" | 143 "add %%"REG_b", %%"REG_D" \n\t" |
144 "punpcklbw %%mm7, %%mm0 \n\t" | 144 "punpcklbw %%mm7, %%mm0 \n\t" |
145 "punpcklbw %%mm7, %%mm1 \n\t" | 145 "punpcklbw %%mm7, %%mm1 \n\t" |
146 "punpcklbw %%mm7, %%mm2 \n\t" | 146 "punpcklbw %%mm7, %%mm2 \n\t" |
147 "punpcklbw %%mm7, %%mm3 \n\t" | 147 "punpcklbw %%mm7, %%mm3 \n\t" |
148 "paddw %%mm1, %%mm4 \n\t" | 148 "paddw %%mm1, %%mm4 \n\t" |
149 "paddw %%mm1, %%mm5 \n\t" | 149 "paddw %%mm1, %%mm5 \n\t" |
150 "paddw %%mm3, %%mm6 \n\t" | 150 "paddw %%mm3, %%mm6 \n\t" |
151 "psubw %%mm0, %%mm4 \n\t" | 151 "psubw %%mm0, %%mm4 \n\t" |
152 "psubw %%mm2, %%mm5 \n\t" | 152 "psubw %%mm2, %%mm5 \n\t" |
153 "psubw %%mm2, %%mm6 \n\t" | 153 "psubw %%mm2, %%mm6 \n\t" |
154 | 154 |
155 "decl %%ecx \n\t" | 155 "decl %%ecx \n\t" |
156 "jnz 2b \n\t" | 156 "jnz 2b \n\t" |
157 | 157 |
158 "movq %%mm0, %%mm1 \n\t" | 158 "movq %%mm0, %%mm1 \n\t" |
159 "movq %%mm0, %%mm2 \n\t" | 159 "movq %%mm0, %%mm2 \n\t" |
160 "movq %%mm0, %%mm3 \n\t" | 160 "movq %%mm0, %%mm3 \n\t" |
161 "pcmpgtw %%mm4, %%mm1 \n\t" | 161 "pcmpgtw %%mm4, %%mm1 \n\t" |
162 "pcmpgtw %%mm5, %%mm2 \n\t" | 162 "pcmpgtw %%mm5, %%mm2 \n\t" |
163 "pcmpgtw %%mm6, %%mm3 \n\t" | 163 "pcmpgtw %%mm6, %%mm3 \n\t" |
164 "pxor %%mm1, %%mm4 \n\t" | 164 "pxor %%mm1, %%mm4 \n\t" |
165 "pxor %%mm2, %%mm5 \n\t" | 165 "pxor %%mm2, %%mm5 \n\t" |
166 "pxor %%mm3, %%mm6 \n\t" | 166 "pxor %%mm3, %%mm6 \n\t" |
167 "psubw %%mm1, %%mm4 \n\t" | 167 "psubw %%mm1, %%mm4 \n\t" |
168 "psubw %%mm2, %%mm5 \n\t" | 168 "psubw %%mm2, %%mm5 \n\t" |
169 "psubw %%mm3, %%mm6 \n\t" | 169 "psubw %%mm3, %%mm6 \n\t" |
170 "movq %%mm4, (%%"REG_d") \n\t" | 170 "movq %%mm4, (%%"REG_d") \n\t" |
171 "movq %%mm5, 16(%%"REG_d") \n\t" | 171 "movq %%mm5, 16(%%"REG_d") \n\t" |
172 "movq %%mm6, 32(%%"REG_d") \n\t" | 172 "movq %%mm6, 32(%%"REG_d") \n\t" |
173 | 173 |
174 "mov %%"REG_a", %%"REG_c" \n\t" | 174 "mov %%"REG_a", %%"REG_c" \n\t" |
175 "shl $3, %%"REG_c" \n\t" | 175 "shl $3, %%"REG_c" \n\t" |
176 "sub %%"REG_c", %%"REG_S" \n\t" | 176 "sub %%"REG_c", %%"REG_S" \n\t" |
177 "mov %%"REG_b", %%"REG_c" \n\t" | 177 "mov %%"REG_b", %%"REG_c" \n\t" |
178 "shl $3, %%"REG_c" \n\t" | 178 "shl $3, %%"REG_c" \n\t" |
179 "sub %%"REG_c", %%"REG_D" \n\t" | 179 "sub %%"REG_c", %%"REG_D" \n\t" |
180 | 180 |
181 // Second loop for the last four columns | 181 // Second loop for the last four columns |
182 "movl $4, %%ecx \n\t" | 182 "movl $4, %%ecx \n\t" |
183 "pxor %%mm4, %%mm4 \n\t" | 183 "pxor %%mm4, %%mm4 \n\t" |
184 "pxor %%mm5, %%mm5 \n\t" | 184 "pxor %%mm5, %%mm5 \n\t" |
185 "pxor %%mm6, %%mm6 \n\t" | 185 "pxor %%mm6, %%mm6 \n\t" |
186 | 186 |
187 ASMALIGN(4) | 187 ASMALIGN(4) |
188 "3: \n\t" | 188 "3: \n\t" |
189 | 189 |
190 "movq (%%"REG_S"), %%mm0 \n\t" | 190 "movq (%%"REG_S"), %%mm0 \n\t" |
191 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t" | 191 "movq (%%"REG_S",%%"REG_a"), %%mm1 \n\t" |
192 "add %%"REG_a", %%"REG_S" \n\t" | 192 "add %%"REG_a", %%"REG_S" \n\t" |
193 "add %%"REG_a", %%"REG_S" \n\t" | 193 "add %%"REG_a", %%"REG_S" \n\t" |
194 "movq (%%"REG_D"), %%mm2 \n\t" | 194 "movq (%%"REG_D"), %%mm2 \n\t" |
195 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t" | 195 "movq (%%"REG_D",%%"REG_b"), %%mm3 \n\t" |
196 "add %%"REG_b", %%"REG_D" \n\t" | 196 "add %%"REG_b", %%"REG_D" \n\t" |
197 "add %%"REG_b", %%"REG_D" \n\t" | 197 "add %%"REG_b", %%"REG_D" \n\t" |
198 "punpckhbw %%mm7, %%mm0 \n\t" | 198 "punpckhbw %%mm7, %%mm0 \n\t" |
199 "punpckhbw %%mm7, %%mm1 \n\t" | 199 "punpckhbw %%mm7, %%mm1 \n\t" |
200 "punpckhbw %%mm7, %%mm2 \n\t" | 200 "punpckhbw %%mm7, %%mm2 \n\t" |
201 "punpckhbw %%mm7, %%mm3 \n\t" | 201 "punpckhbw %%mm7, %%mm3 \n\t" |
202 "paddw %%mm1, %%mm4 \n\t" | 202 "paddw %%mm1, %%mm4 \n\t" |
203 "paddw %%mm1, %%mm5 \n\t" | 203 "paddw %%mm1, %%mm5 \n\t" |
204 "paddw %%mm3, %%mm6 \n\t" | 204 "paddw %%mm3, %%mm6 \n\t" |
205 "psubw %%mm0, %%mm4 \n\t" | 205 "psubw %%mm0, %%mm4 \n\t" |
206 "psubw %%mm2, %%mm5 \n\t" | 206 "psubw %%mm2, %%mm5 \n\t" |
207 "psubw %%mm2, %%mm6 \n\t" | 207 "psubw %%mm2, %%mm6 \n\t" |
208 | 208 |
209 "decl %%ecx \n\t" | 209 "decl %%ecx \n\t" |
210 "jnz 3b \n\t" | 210 "jnz 3b \n\t" |
211 | 211 |
212 "movq %%mm0, %%mm1 \n\t" | 212 "movq %%mm0, %%mm1 \n\t" |
213 "movq %%mm0, %%mm2 \n\t" | 213 "movq %%mm0, %%mm2 \n\t" |
214 "movq %%mm0, %%mm3 \n\t" | 214 "movq %%mm0, %%mm3 \n\t" |
215 "pcmpgtw %%mm4, %%mm1 \n\t" | 215 "pcmpgtw %%mm4, %%mm1 \n\t" |
216 "pcmpgtw %%mm5, %%mm2 \n\t" | 216 "pcmpgtw %%mm5, %%mm2 \n\t" |
217 "pcmpgtw %%mm6, %%mm3 \n\t" | 217 "pcmpgtw %%mm6, %%mm3 \n\t" |
218 "pxor %%mm1, %%mm4 \n\t" | 218 "pxor %%mm1, %%mm4 \n\t" |
219 "pxor %%mm2, %%mm5 \n\t" | 219 "pxor %%mm2, %%mm5 \n\t" |
220 "pxor %%mm3, %%mm6 \n\t" | 220 "pxor %%mm3, %%mm6 \n\t" |
221 "psubw %%mm1, %%mm4 \n\t" | 221 "psubw %%mm1, %%mm4 \n\t" |
222 "psubw %%mm2, %%mm5 \n\t" | 222 "psubw %%mm2, %%mm5 \n\t" |
223 "psubw %%mm3, %%mm6 \n\t" | 223 "psubw %%mm3, %%mm6 \n\t" |
224 "movq %%mm4, 8(%%"REG_d") \n\t" | 224 "movq %%mm4, 8(%%"REG_d") \n\t" |
225 "movq %%mm5, 24(%%"REG_d") \n\t" | 225 "movq %%mm5, 24(%%"REG_d") \n\t" |
226 "movq %%mm6, 40(%%"REG_d") \n\t" | 226 "movq %%mm6, 40(%%"REG_d") \n\t" |
227 | 227 |
228 "emms \n\t" | 228 "emms \n\t" |
229 : | 229 : |
230 : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out) | 230 : "S" (old), "D" (new), "a" ((long)os), "b" ((long)ns), "d" (out) |
231 : "memory" | 231 : "memory" |
232 ); | 232 ); |
233 m->p = m->t = m->s = 0; | 233 m->p = m->t = m->s = 0; |
234 for (i=0; i<8; i++) { | 234 for (i=0; i<8; i++) { |
235 m->p += out[i]; | 235 m->p += out[i]; |
236 m->t += out[8+i]; | 236 m->t += out[8+i]; |
237 m->s += out[16+i]; | 237 m->s += out[16+i]; |
238 } | 238 } |
239 //printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s); | 239 //printf("e=%d o=%d d=%d p=%d t=%d s=%d\n", m->e, m->o, m->d, m->p, m->t, m->s); |
240 } | 240 } |
241 #endif | 241 #endif |
242 | 242 |
243 //#define MAG(a) ((a)*(a)) | 243 //#define MAG(a) ((a)*(a)) |
244 //#define MAG(a) (abs(a)) | 244 //#define MAG(a) (abs(a)) |
249 #define LOWPASS(s) ((s)[0]) | 249 #define LOWPASS(s) ((s)[0]) |
250 | 250 |
251 | 251 |
252 static void block_diffs_C(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns) | 252 static void block_diffs_C(struct metrics *m, unsigned char *old, unsigned char *new, int os, int ns) |
253 { | 253 { |
254 int x, y, e=0, o=0, s=0, p=0, t=0; | 254 int x, y, e=0, o=0, s=0, p=0, t=0; |
255 unsigned char *oldp, *newp; | 255 unsigned char *oldp, *newp; |
256 m->s = m->p = m->t = 0; | 256 m->s = m->p = m->t = 0; |
257 for (x = 8; x; x--) { | 257 for (x = 8; x; x--) { |
258 oldp = old++; | 258 oldp = old++; |
259 newp = new++; | 259 newp = new++; |
260 s = p = t = 0; | 260 s = p = t = 0; |
261 for (y = 4; y; y--) { | 261 for (y = 4; y; y--) { |
262 e += MAG(newp[0]-oldp[0]); | 262 e += MAG(newp[0]-oldp[0]); |
263 o += MAG(newp[ns]-oldp[os]); | 263 o += MAG(newp[ns]-oldp[os]); |
264 s += newp[ns]-newp[0]; | 264 s += newp[ns]-newp[0]; |
265 p += oldp[os]-oldp[0]; | 265 p += oldp[os]-oldp[0]; |
266 t += oldp[os]-newp[0]; | 266 t += oldp[os]-newp[0]; |
267 oldp += os<<1; | 267 oldp += os<<1; |
268 newp += ns<<1; | 268 newp += ns<<1; |
269 } | 269 } |
270 m->s += MAG(s); | 270 m->s += MAG(s); |
271 m->p += MAG(p); | 271 m->p += MAG(p); |
272 m->t += MAG(t); | 272 m->t += MAG(t); |
273 } | 273 } |
274 m->e = e; | 274 m->e = e; |
275 m->o = o; | 275 m->o = o; |
276 m->d = e+o; | 276 m->d = e+o; |
277 } | 277 } |
278 | 278 |
279 static void (*block_diffs)(struct metrics *, unsigned char *, unsigned char *, int, int); | 279 static void (*block_diffs)(struct metrics *, unsigned char *, unsigned char *, int, int); |
280 | 280 |
281 #define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b)) | 281 #define MAXUP(a,b) ((a) = ((a)>(b)) ? (a) : (b)) |
282 | 282 |
283 static void diff_planes(struct frameinfo *fi, | 283 static void diff_planes(struct frameinfo *fi, |
284 unsigned char *old, unsigned char *new, int w, int h, int os, int ns) | 284 unsigned char *old, unsigned char *new, int w, int h, int os, int ns) |
285 { | 285 { |
286 int x, y; | 286 int x, y; |
287 struct metrics l; | 287 struct metrics l; |
288 struct metrics *peak=&fi->p, *rel=&fi->r, *mean=&fi->m; | 288 struct metrics *peak=&fi->p, *rel=&fi->r, *mean=&fi->m; |
289 memset(peak, 0, sizeof(struct metrics)); | 289 memset(peak, 0, sizeof(struct metrics)); |
290 memset(rel, 0, sizeof(struct metrics)); | 290 memset(rel, 0, sizeof(struct metrics)); |
291 memset(mean, 0, sizeof(struct metrics)); | 291 memset(mean, 0, sizeof(struct metrics)); |
292 for (y = 0; y < h-7; y += 8) { | 292 for (y = 0; y < h-7; y += 8) { |
293 for (x = 8; x < w-8-7; x += 8) { | 293 for (x = 8; x < w-8-7; x += 8) { |
294 block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns); | 294 block_diffs(&l, old+x+y*os, new+x+y*ns, os, ns); |
295 mean->d += l.d; | 295 mean->d += l.d; |
296 mean->e += l.e; | 296 mean->e += l.e; |
297 mean->o += l.o; | 297 mean->o += l.o; |
298 mean->s += l.s; | 298 mean->s += l.s; |
299 mean->p += l.p; | 299 mean->p += l.p; |
300 mean->t += l.t; | 300 mean->t += l.t; |
301 MAXUP(peak->d, l.d); | 301 MAXUP(peak->d, l.d); |
302 MAXUP(peak->e, l.e); | 302 MAXUP(peak->e, l.e); |
303 MAXUP(peak->o, l.o); | 303 MAXUP(peak->o, l.o); |
304 MAXUP(peak->s, l.s); | 304 MAXUP(peak->s, l.s); |
305 MAXUP(peak->p, l.p); | 305 MAXUP(peak->p, l.p); |
306 MAXUP(peak->t, l.t); | 306 MAXUP(peak->t, l.t); |
307 MAXUP(rel->e, l.e-l.o); | 307 MAXUP(rel->e, l.e-l.o); |
308 MAXUP(rel->o, l.o-l.e); | 308 MAXUP(rel->o, l.o-l.e); |
309 MAXUP(rel->s, l.s-l.t); | 309 MAXUP(rel->s, l.s-l.t); |
310 MAXUP(rel->p, l.p-l.t); | 310 MAXUP(rel->p, l.p-l.t); |
311 MAXUP(rel->t, l.t-l.p); | 311 MAXUP(rel->t, l.t-l.p); |
312 MAXUP(rel->d, l.t-l.s); /* hack */ | 312 MAXUP(rel->d, l.t-l.s); /* hack */ |
313 } | 313 } |
314 } | 314 } |
315 x = (w/8-2)*(h/8); | 315 x = (w/8-2)*(h/8); |
316 mean->d /= x; | 316 mean->d /= x; |
317 mean->e /= x; | 317 mean->e /= x; |
318 mean->o /= x; | 318 mean->o /= x; |
319 mean->s /= x; | 319 mean->s /= x; |
320 mean->p /= x; | 320 mean->p /= x; |
321 mean->t /= x; | 321 mean->t /= x; |
322 } | 322 } |
323 | 323 |
324 static void diff_fields(struct frameinfo *fi, mp_image_t *old, mp_image_t *new) | 324 static void diff_fields(struct frameinfo *fi, mp_image_t *old, mp_image_t *new) |
325 { | 325 { |
326 diff_planes(fi, old->planes[0], new->planes[0], | 326 diff_planes(fi, old->planes[0], new->planes[0], |
327 new->w, new->h, old->stride[0], new->stride[0]); | 327 new->w, new->h, old->stride[0], new->stride[0]); |
328 } | 328 } |
329 | 329 |
330 static void stats(struct frameinfo *f) | 330 static void stats(struct frameinfo *f) |
331 { | 331 { |
332 mp_msg(MSGT_VFILTER, MSGL_V, " pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d\r", | 332 mp_msg(MSGT_VFILTER, MSGL_V, " pd=%d re=%d ro=%d rp=%d rt=%d rs=%d rd=%d pp=%d pt=%d ps=%d\r", |
333 f->p.d, f->r.e, f->r.o, f->r.p, f->r.t, f->r.s, f->r.d, f->p.p, f->p.t, f->p.s); | 333 f->p.d, f->r.e, f->r.o, f->r.p, f->r.t, f->r.s, f->r.d, f->p.p, f->p.t, f->p.s); |
334 } | 334 } |
335 | 335 |
336 static int foo(struct vf_priv_s *p, mp_image_t *new, mp_image_t *cur) | 336 static int foo(struct vf_priv_s *p, mp_image_t *new, mp_image_t *cur) |
337 { | 337 { |
338 struct frameinfo *f = p->fi; | 338 struct frameinfo *f = p->fi; |
339 | 339 |
340 f[0] = f[1]; | 340 f[0] = f[1]; |
341 diff_fields(&f[1], cur, new); | 341 diff_fields(&f[1], cur, new); |
342 stats(&f[1]); | 342 stats(&f[1]); |
343 | 343 |
344 // Immediately drop this frame if it's already been used. | 344 // Immediately drop this frame if it's already been used. |
345 if (p->dropnext) { | 345 if (p->dropnext) { |
346 p->dropnext = 0; | 346 p->dropnext = 0; |
347 return F_DROP; | 347 return F_DROP; |
348 } | 348 } |
349 | 349 |
350 // Sometimes a pulldown frame comes all by itself, so both | 350 // Sometimes a pulldown frame comes all by itself, so both |
351 // its top and bottom field are duplicates from the adjacent | 351 // its top and bottom field are duplicates from the adjacent |
352 // two frames. We can just drop such a frame, but we | 352 // two frames. We can just drop such a frame, but we |
353 // immediately show the next frame instead to keep the frame | 353 // immediately show the next frame instead to keep the frame |
354 // drops evenly spaced during normal 3:2 pulldown sequences. | 354 // drops evenly spaced during normal 3:2 pulldown sequences. |
355 if ((3*f[1].r.o < f[1].r.e) && (f[1].r.s < f[1].r.d)) { | 355 if ((3*f[1].r.o < f[1].r.e) && (f[1].r.s < f[1].r.d)) { |
356 p->dropnext = 1; | 356 p->dropnext = 1; |
357 return F_NEXT; | 357 return F_NEXT; |
358 } | 358 } |
359 | 359 |
360 // If none of these conditions hold, we will consider the frame | 360 // If none of these conditions hold, we will consider the frame |
361 // progressive and just show it as-is. | 361 // progressive and just show it as-is. |
362 if (!( (3*f[0].r.e < f[0].r.o) || | 362 if (!( (3*f[0].r.e < f[0].r.o) || |
363 ((2*f[0].r.d < f[0].r.s) && (f[0].r.s > 1200)) || | 363 ((2*f[0].r.d < f[0].r.s) && (f[0].r.s > 1200)) || |
364 ((2*f[1].r.t < f[1].r.p) && (f[1].r.p > 1200)) )) | 364 ((2*f[1].r.t < f[1].r.p) && (f[1].r.p > 1200)) )) |
365 return F_SHOW; | 365 return F_SHOW; |
366 | 366 |
367 // Otherwise, we have to decide whether to merge or drop. | 367 // Otherwise, we have to decide whether to merge or drop. |
368 // If the noise metric only increases minimally, we're off | 368 // If the noise metric only increases minimally, we're off |
369 // to a good start... | 369 // to a good start... |
370 if (((2*f[1].r.t < 3*f[1].r.p) && (f[1].r.t < 3600)) || | 370 if (((2*f[1].r.t < 3*f[1].r.p) && (f[1].r.t < 3600)) || |
371 (f[1].r.t < 900) || (f[1].r.d < 900)) { | 371 (f[1].r.t < 900) || (f[1].r.d < 900)) { |
372 // ...and if noise decreases or the duplicate even field | 372 // ...and if noise decreases or the duplicate even field |
373 // is detected, we go ahead with the merge. | 373 // is detected, we go ahead with the merge. |
374 if ((3*f[0].r.e < f[0].r.o) || (2*f[1].r.t < f[1].r.p)) { | 374 if ((3*f[0].r.e < f[0].r.o) || (2*f[1].r.t < f[1].r.p)) { |
375 p->dropnext = 1; | 375 p->dropnext = 1; |
376 return F_MERGE; | 376 return F_MERGE; |
377 } | 377 } |
378 } | 378 } |
379 return F_DROP; | 379 return F_DROP; |
380 } | 380 } |
381 | 381 |
382 | 382 |
383 | 383 |
384 static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field) | 384 static void copy_image(mp_image_t *dmpi, mp_image_t *mpi, int field) |
385 { | 385 { |
386 switch (field) { | 386 switch (field) { |
387 case 0: | 387 case 0: |
388 my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2, | 388 my_memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h/2, |
389 dmpi->stride[0]*2, mpi->stride[0]*2); | 389 dmpi->stride[0]*2, mpi->stride[0]*2); |
390 if (mpi->flags & MP_IMGFLAG_PLANAR) { | 390 if (mpi->flags & MP_IMGFLAG_PLANAR) { |
391 my_memcpy_pic(dmpi->planes[1], mpi->planes[1], | 391 my_memcpy_pic(dmpi->planes[1], mpi->planes[1], |
392 mpi->chroma_width, mpi->chroma_height/2, | 392 mpi->chroma_width, mpi->chroma_height/2, |
393 dmpi->stride[1]*2, mpi->stride[1]*2); | 393 dmpi->stride[1]*2, mpi->stride[1]*2); |
394 my_memcpy_pic(dmpi->planes[2], mpi->planes[2], | 394 my_memcpy_pic(dmpi->planes[2], mpi->planes[2], |
395 mpi->chroma_width, mpi->chroma_height/2, | 395 mpi->chroma_width, mpi->chroma_height/2, |
396 dmpi->stride[2]*2, mpi->stride[2]*2); | 396 dmpi->stride[2]*2, mpi->stride[2]*2); |
397 } | 397 } |
398 break; | 398 break; |
399 case 1: | 399 case 1: |
400 my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0], | 400 my_memcpy_pic(dmpi->planes[0]+dmpi->stride[0], |
401 mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2, | 401 mpi->planes[0]+mpi->stride[0], mpi->w, mpi->h/2, |
402 dmpi->stride[0]*2, mpi->stride[0]*2); | 402 dmpi->stride[0]*2, mpi->stride[0]*2); |
403 if (mpi->flags & MP_IMGFLAG_PLANAR) { | 403 if (mpi->flags & MP_IMGFLAG_PLANAR) { |
404 my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1], | 404 my_memcpy_pic(dmpi->planes[1]+dmpi->stride[1], |
405 mpi->planes[1]+mpi->stride[1], | 405 mpi->planes[1]+mpi->stride[1], |
406 mpi->chroma_width, mpi->chroma_height/2, | 406 mpi->chroma_width, mpi->chroma_height/2, |
407 dmpi->stride[1]*2, mpi->stride[1]*2); | 407 dmpi->stride[1]*2, mpi->stride[1]*2); |
408 my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2], | 408 my_memcpy_pic(dmpi->planes[2]+dmpi->stride[2], |
409 mpi->planes[2]+mpi->stride[2], | 409 mpi->planes[2]+mpi->stride[2], |
410 mpi->chroma_width, mpi->chroma_height/2, | 410 mpi->chroma_width, mpi->chroma_height/2, |
411 dmpi->stride[2]*2, mpi->stride[2]*2); | 411 dmpi->stride[2]*2, mpi->stride[2]*2); |
412 } | 412 } |
413 break; | 413 break; |
414 case 2: | 414 case 2: |
415 memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, | 415 memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, |
416 dmpi->stride[0], mpi->stride[0]); | 416 dmpi->stride[0], mpi->stride[0]); |
417 if (mpi->flags & MP_IMGFLAG_PLANAR) { | 417 if (mpi->flags & MP_IMGFLAG_PLANAR) { |
418 memcpy_pic(dmpi->planes[1], mpi->planes[1], | 418 memcpy_pic(dmpi->planes[1], mpi->planes[1], |
419 mpi->chroma_width, mpi->chroma_height, | 419 mpi->chroma_width, mpi->chroma_height, |
420 dmpi->stride[1], mpi->stride[1]); | 420 dmpi->stride[1], mpi->stride[1]); |
421 memcpy_pic(dmpi->planes[2], mpi->planes[2], | 421 memcpy_pic(dmpi->planes[2], mpi->planes[2], |
422 mpi->chroma_width, mpi->chroma_height, | 422 mpi->chroma_width, mpi->chroma_height, |
423 dmpi->stride[2], mpi->stride[2]); | 423 dmpi->stride[2], mpi->stride[2]); |
424 } | 424 } |
425 break; | 425 break; |
426 } | 426 } |
427 } | 427 } |
428 | 428 |
429 static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) | 429 static int do_put_image(struct vf_instance *vf, mp_image_t *dmpi) |
430 { | 430 { |
431 struct vf_priv_s *p = vf->priv; | 431 struct vf_priv_s *p = vf->priv; |
432 int dropflag=0; | 432 int dropflag=0; |
433 | 433 |
434 if (!p->dropnext) switch (p->drop) { | 434 if (!p->dropnext) switch (p->drop) { |
435 case 0: | 435 case 0: |
436 dropflag = 0; | 436 dropflag = 0; |
437 break; | 437 break; |
438 case 1: | 438 case 1: |
439 dropflag = (++p->lastdrop >= 5); | 439 dropflag = (++p->lastdrop >= 5); |
440 break; | 440 break; |
441 case 2: | 441 case 2: |
442 dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes); | 442 dropflag = (++p->lastdrop >= 5) && (4*p->inframes <= 5*p->outframes); |
443 break; | 443 break; |
444 } | 444 } |
445 | 445 |
446 if (dropflag) { | 446 if (dropflag) { |
447 //mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n", | 447 //mp_msg(MSGT_VFILTER, MSGL_V, "drop! [%d/%d=%g]\n", |
448 // p->outframes, p->inframes, (float)p->outframes/p->inframes); | 448 // p->outframes, p->inframes, (float)p->outframes/p->inframes); |
449 mp_msg(MSGT_VFILTER, MSGL_V, "!"); | 449 mp_msg(MSGT_VFILTER, MSGL_V, "!"); |
450 p->lastdrop = 0; | 450 p->lastdrop = 0; |
451 return 0; | 451 return 0; |
452 } | 452 } |
453 | 453 |
454 p->outframes++; | 454 p->outframes++; |
455 return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); | 455 return vf_next_put_image(vf, dmpi, MP_NOPTS_VALUE); |
456 } | 456 } |
457 | 457 |
458 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) | 458 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) |
459 { | 459 { |
460 int ret=0; | 460 int ret=0; |
461 struct vf_priv_s *p = vf->priv; | 461 struct vf_priv_s *p = vf->priv; |
462 | 462 |
463 p->inframes++; | 463 p->inframes++; |
464 | 464 |
465 if (p->first) { /* hack */ | 465 if (p->first) { /* hack */ |
466 p->first = 0; | 466 p->first = 0; |
467 return 1; | 467 return 1; |
468 } | 468 } |
469 | 469 |
470 if (!p->dmpi) p->dmpi = vf_get_image(vf->next, mpi->imgfmt, | 470 if (!p->dmpi) p->dmpi = vf_get_image(vf->next, mpi->imgfmt, |
471 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | | 471 MP_IMGTYPE_STATIC, MP_IMGFLAG_ACCEPT_STRIDE | |
472 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE, | 472 MP_IMGFLAG_PRESERVE | MP_IMGFLAG_READABLE, |
473 mpi->width, mpi->height); | 473 mpi->width, mpi->height); |
474 /* FIXME -- not correct, off by one frame! */ | 474 /* FIXME -- not correct, off by one frame! */ |
475 p->dmpi->qscale = mpi->qscale; | 475 p->dmpi->qscale = mpi->qscale; |
476 p->dmpi->qstride = mpi->qstride; | 476 p->dmpi->qstride = mpi->qstride; |
477 p->dmpi->qscale_type = mpi->qscale_type; | 477 p->dmpi->qscale_type = mpi->qscale_type; |
478 | 478 |
479 switch (foo(p, mpi, p->dmpi)) { | 479 switch (foo(p, mpi, p->dmpi)) { |
480 case F_DROP: | 480 case F_DROP: |
481 copy_image(p->dmpi, mpi, 2); | 481 copy_image(p->dmpi, mpi, 2); |
482 ret = 0; | 482 ret = 0; |
483 p->lastdrop = 0; | 483 p->lastdrop = 0; |
484 mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n"); | 484 mp_msg(MSGT_VFILTER, MSGL_V, "DROP\n"); |
485 break; | 485 break; |
486 case F_MERGE: | 486 case F_MERGE: |
487 copy_image(p->dmpi, mpi, 0); | 487 copy_image(p->dmpi, mpi, 0); |
488 ret = do_put_image(vf, p->dmpi); | 488 ret = do_put_image(vf, p->dmpi); |
489 copy_image(p->dmpi, mpi, 1); | 489 copy_image(p->dmpi, mpi, 1); |
490 mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n"); | 490 mp_msg(MSGT_VFILTER, MSGL_V, "MERGE\n"); |
491 p->dmpi = NULL; | 491 p->dmpi = NULL; |
492 break; | 492 break; |
493 case F_NEXT: | 493 case F_NEXT: |
494 copy_image(p->dmpi, mpi, 2); | 494 copy_image(p->dmpi, mpi, 2); |
495 ret = do_put_image(vf, p->dmpi); | 495 ret = do_put_image(vf, p->dmpi); |
496 mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n"); | 496 mp_msg(MSGT_VFILTER, MSGL_V, "NEXT\n"); |
497 p->dmpi = NULL; | 497 p->dmpi = NULL; |
498 break; | 498 break; |
499 case F_SHOW: | 499 case F_SHOW: |
500 ret = do_put_image(vf, p->dmpi); | 500 ret = do_put_image(vf, p->dmpi); |
501 copy_image(p->dmpi, mpi, 2); | 501 copy_image(p->dmpi, mpi, 2); |
502 mp_msg(MSGT_VFILTER, MSGL_V, "OK\n"); | 502 mp_msg(MSGT_VFILTER, MSGL_V, "OK\n"); |
503 p->dmpi = NULL; | 503 p->dmpi = NULL; |
504 break; | 504 break; |
505 } | 505 } |
506 return ret; | 506 return ret; |
507 } | 507 } |
508 | 508 |
509 static int query_format(struct vf_instance *vf, unsigned int fmt) | 509 static int query_format(struct vf_instance *vf, unsigned int fmt) |
510 { | 510 { |
511 switch (fmt) { | 511 switch (fmt) { |
512 case IMGFMT_YV12: | 512 case IMGFMT_YV12: |
513 case IMGFMT_IYUV: | 513 case IMGFMT_IYUV: |
514 case IMGFMT_I420: | 514 case IMGFMT_I420: |
515 return vf_next_query_format(vf, fmt); | 515 return vf_next_query_format(vf, fmt); |
516 } | 516 } |
517 return 0; | 517 return 0; |
518 } | 518 } |
519 | 519 |
520 static void uninit(struct vf_instance *vf) | 520 static void uninit(struct vf_instance *vf) |
521 { | 521 { |
522 free(vf->priv); | 522 free(vf->priv); |
523 } | 523 } |
524 | 524 |
525 static int vf_open(vf_instance_t *vf, char *args) | 525 static int vf_open(vf_instance_t *vf, char *args) |
526 { | 526 { |
527 struct vf_priv_s *p; | 527 struct vf_priv_s *p; |
528 vf->put_image = put_image; | 528 vf->put_image = put_image; |
529 vf->query_format = query_format; | 529 vf->query_format = query_format; |
530 vf->uninit = uninit; | 530 vf->uninit = uninit; |
531 vf->default_reqs = VFCAP_ACCEPT_STRIDE; | 531 vf->default_reqs = VFCAP_ACCEPT_STRIDE; |
532 vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); | 532 vf->priv = p = calloc(1, sizeof(struct vf_priv_s)); |
533 p->drop = 0; | 533 p->drop = 0; |
534 p->first = 1; | 534 p->first = 1; |
535 if (args) sscanf(args, "%d", &p->drop); | 535 if (args) sscanf(args, "%d", &p->drop); |
536 block_diffs = block_diffs_C; | 536 block_diffs = block_diffs_C; |
537 #if HAVE_MMX && HAVE_EBX_AVAILABLE | 537 #if HAVE_MMX && HAVE_EBX_AVAILABLE |
538 if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX; | 538 if(gCpuCaps.hasMMX) block_diffs = block_diffs_MMX; |
539 #endif | 539 #endif |
540 return 1; | 540 return 1; |
541 } | 541 } |
542 | 542 |
543 const vf_info_t vf_info_ivtc = { | 543 const vf_info_t vf_info_ivtc = { |
544 "inverse telecine, take 2", | 544 "inverse telecine, take 2", |
545 "ivtc", | 545 "ivtc", |