Mercurial > mplayer.hg
annotate libswscale/ppc/yuv2rgb_altivec.c @ 29265:8f7e539305a0
Restore old license file after whitspace removal in previous commit.
Legal stuff is very fragile and shouldn't be changed, even for
whitespace cosmetics.
author | bircoph |
---|---|
date | Wed, 13 May 2009 18:42:38 +0000 |
parents | 882a1f5613e1 |
children | 880c5d014d37 |
rev | line source |
---|---|
29028 | 1 /* |
2 * AltiVec acceleration for colorspace conversion | |
3 * | |
4 * copyright (C) 2004 Marc Hoffman <marc.hoffman@analog.com> | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 /* | |
24 Convert I420 YV12 to RGB in various formats, | |
25 it rejects images that are not in 420 formats, | |
26 it rejects images that don't have widths of multiples of 16, | |
27 it rejects images that don't have heights of multiples of 2. | |
28 Reject defers to C simulation code. | |
29 | |
30 Lots of optimizations to be done here. | |
31 | |
32 1. Need to fix saturation code. I just couldn't get it to fly with packs | |
33 and adds, so we currently use max/min to clip. | |
34 | |
35 2. The inefficient use of chroma loading needs a bit of brushing up. | |
36 | |
37 3. Analysis of pipeline stalls needs to be done. Use shark to identify | |
38 pipeline stalls. | |
39 | |
40 | |
41 MODIFIED to calculate coeffs from currently selected color space. | |
42 MODIFIED core to be a macro where you specify the output format. | |
43 ADDED UYVY conversion which is never called due to some thing in swscale. | |
44 CORRECTED algorithim selection to be strict on input formats. | |
45 ADDED runtime detection of AltiVec. | |
46 | |
47 ADDED altivec_yuv2packedX vertical scl + RGB converter | |
48 | |
49 March 27,2004 | |
50 PERFORMANCE ANALYSIS | |
51 | |
52 The C version uses 25% of the processor or ~250Mips for D1 video rawvideo | |
53 used as test. | |
54 The AltiVec version uses 10% of the processor or ~100Mips for D1 video | |
55 same sequence. | |
56 | |
57 720 * 480 * 30 ~10MPS | |
58 | |
59 so we have roughly 10 clocks per pixel. This is too high, something has | |
60 to be wrong. | |
61 | |
62 OPTIMIZED clip codes to utilize vec_max and vec_packs removing the | |
63 need for vec_min. | |
64 | |
65 OPTIMIZED DST OUTPUT cache/DMA controls. We are pretty much guaranteed to have | |
66 the input video frame, it was just decompressed so it probably resides in L1 | |
67 caches. However, we are creating the output video stream. This needs to use the | |
68 DSTST instruction to optimize for the cache. We couple this with the fact that | |
69 we are not going to be visiting the input buffer again so we mark it Least | |
70 Recently Used. This shaves 25% of the processor cycles off. | |
71 | |
72 Now memcpy is the largest mips consumer in the system, probably due | |
73 to the inefficient X11 stuff. | |
74 | |
75 GL libraries seem to be very slow on this machine 1.33Ghz PB running | |
76 Jaguar, this is not the case for my 1Ghz PB. I thought it might be | |
77 a versioning issue, however I have libGL.1.2.dylib for both | |
78 machines. (We need to figure this out now.) | |
79 | |
80 GL2 libraries work now with patch for RGB32. | |
81 | |
82 NOTE: quartz vo driver ARGB32_to_RGB24 consumes 30% of the processor. | |
83 | |
84 Integrated luma prescaling adjustment for saturation/contrast/brightness | |
85 adjustment. | |
86 */ | |
87 | |
88 #include <stdio.h> | |
89 #include <stdlib.h> | |
90 #include <string.h> | |
91 #include <inttypes.h> | |
92 #include <assert.h> | |
93 #include "config.h" | |
94 #include "libswscale/rgb2rgb.h" | |
95 #include "libswscale/swscale.h" | |
96 #include "libswscale/swscale_internal.h" | |
97 | |
98 #undef PROFILE_THE_BEAST | |
99 #undef INC_SCALING | |
100 | |
101 typedef unsigned char ubyte; | |
102 typedef signed char sbyte; | |
103 | |
104 | |
105 /* RGB interleaver, 16 planar pels 8-bit samples per channel in | |
106 homogeneous vector registers x0,x1,x2 are interleaved with the | |
107 following technique: | |
108 | |
109 o0 = vec_mergeh (x0,x1); | |
110 o1 = vec_perm (o0, x2, perm_rgb_0); | |
111 o2 = vec_perm (o0, x2, perm_rgb_1); | |
112 o3 = vec_mergel (x0,x1); | |
113 o4 = vec_perm (o3,o2,perm_rgb_2); | |
114 o5 = vec_perm (o3,o2,perm_rgb_3); | |
115 | |
116 perm_rgb_0: o0(RG).h v1(B) --> o1* | |
117 0 1 2 3 4 | |
118 rgbr|gbrg|brgb|rgbr | |
119 0010 0100 1001 0010 | |
120 0102 3145 2673 894A | |
121 | |
122 perm_rgb_1: o0(RG).h v1(B) --> o2 | |
123 0 1 2 3 4 | |
124 gbrg|brgb|bbbb|bbbb | |
125 0100 1001 1111 1111 | |
126 B5CD 6EF7 89AB CDEF | |
127 | |
128 perm_rgb_2: o3(RG).l o2(rgbB.l) --> o4* | |
129 0 1 2 3 4 | |
130 gbrg|brgb|rgbr|gbrg | |
131 1111 1111 0010 0100 | |
132 89AB CDEF 0182 3945 | |
133 | |
134 perm_rgb_2: o3(RG).l o2(rgbB.l) ---> o5* | |
135 0 1 2 3 4 | |
136 brgb|rgbr|gbrg|brgb | |
137 1001 0010 0100 1001 | |
138 a67b 89cA BdCD eEFf | |
139 | |
140 */ | |
141 static | |
142 const vector unsigned char | |
143 perm_rgb_0 = {0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05, | |
144 0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a}, | |
145 perm_rgb_1 = {0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17, | |
146 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}, | |
147 perm_rgb_2 = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17, | |
148 0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05}, | |
149 perm_rgb_3 = {0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a, | |
150 0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f}; | |
151 | |
152 #define vec_merge3(x2,x1,x0,y0,y1,y2) \ | |
153 do { \ | |
154 __typeof__(x0) o0,o2,o3; \ | |
155 o0 = vec_mergeh (x0,x1); \ | |
156 y0 = vec_perm (o0, x2, perm_rgb_0); \ | |
157 o2 = vec_perm (o0, x2, perm_rgb_1); \ | |
158 o3 = vec_mergel (x0,x1); \ | |
159 y1 = vec_perm (o3,o2,perm_rgb_2); \ | |
160 y2 = vec_perm (o3,o2,perm_rgb_3); \ | |
161 } while(0) | |
162 | |
163 #define vec_mstbgr24(x0,x1,x2,ptr) \ | |
164 do { \ | |
165 __typeof__(x0) _0,_1,_2; \ | |
166 vec_merge3 (x0,x1,x2,_0,_1,_2); \ | |
167 vec_st (_0, 0, ptr++); \ | |
168 vec_st (_1, 0, ptr++); \ | |
169 vec_st (_2, 0, ptr++); \ | |
170 } while (0); | |
171 | |
172 #define vec_mstrgb24(x0,x1,x2,ptr) \ | |
173 do { \ | |
174 __typeof__(x0) _0,_1,_2; \ | |
175 vec_merge3 (x2,x1,x0,_0,_1,_2); \ | |
176 vec_st (_0, 0, ptr++); \ | |
177 vec_st (_1, 0, ptr++); \ | |
178 vec_st (_2, 0, ptr++); \ | |
179 } while (0); | |
180 | |
181 /* pack the pixels in rgb0 format | |
182 msb R | |
183 lsb 0 | |
184 */ | |
185 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr) \ | |
186 do { \ | |
187 T _0,_1,_2,_3; \ | |
188 _0 = vec_mergeh (x0,x1); \ | |
189 _1 = vec_mergeh (x2,x3); \ | |
190 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \ | |
191 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \ | |
192 vec_st (_2, 0*16, (T *)ptr); \ | |
193 vec_st (_3, 1*16, (T *)ptr); \ | |
194 _0 = vec_mergel (x0,x1); \ | |
195 _1 = vec_mergel (x2,x3); \ | |
196 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \ | |
197 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \ | |
198 vec_st (_2, 2*16, (T *)ptr); \ | |
199 vec_st (_3, 3*16, (T *)ptr); \ | |
200 ptr += 4; \ | |
201 } while (0); | |
202 | |
203 /* | |
204 | |
205 | 1 0 1.4021 | | Y | | |
206 | 1 -0.3441 -0.7142 |x| Cb| | |
207 | 1 1.7718 0 | | Cr| | |
208 | |
209 | |
210 Y: [-128 127] | |
211 Cb/Cr : [-128 127] | |
212 | |
213 typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode. | |
214 | |
215 */ | |
216 | |
217 | |
218 | |
219 | |
220 #define vec_unh(x) \ | |
221 (vector signed short) \ | |
222 vec_perm(x,(__typeof__(x)){0}, \ | |
223 ((vector unsigned char){0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\ | |
224 0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07})) | |
225 #define vec_unl(x) \ | |
226 (vector signed short) \ | |
227 vec_perm(x,(__typeof__(x)){0}, \ | |
228 ((vector unsigned char){0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\ | |
229 0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F})) | |
230 | |
231 #define vec_clip_s16(x) \ | |
232 vec_max (vec_min (x, ((vector signed short){235,235,235,235,235,235,235,235})), \ | |
233 ((vector signed short){ 16, 16, 16, 16, 16, 16, 16, 16})) | |
234 | |
235 #define vec_packclp(x,y) \ | |
236 (vector unsigned char)vec_packs \ | |
237 ((vector unsigned short)vec_max (x,((vector signed short) {0})), \ | |
238 (vector unsigned short)vec_max (y,((vector signed short) {0}))) | |
239 | |
240 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(__typeof__(a),((__typeof__ (a)){255}),a,a,a,ptr) | |
241 | |
242 | |
243 static inline void cvtyuvtoRGB (SwsContext *c, | |
244 vector signed short Y, vector signed short U, vector signed short V, | |
245 vector signed short *R, vector signed short *G, vector signed short *B) | |
246 { | |
247 vector signed short vx,ux,uvx; | |
248 | |
249 Y = vec_mradds (Y, c->CY, c->OY); | |
250 U = vec_sub (U,(vector signed short) | |
251 vec_splat((vector signed short){128},0)); | |
252 V = vec_sub (V,(vector signed short) | |
253 vec_splat((vector signed short){128},0)); | |
254 | |
255 // ux = (CBU*(u<<c->CSHIFT)+0x4000)>>15; | |
256 ux = vec_sl (U, c->CSHIFT); | |
257 *B = vec_mradds (ux, c->CBU, Y); | |
258 | |
259 // vx = (CRV*(v<<c->CSHIFT)+0x4000)>>15; | |
260 vx = vec_sl (V, c->CSHIFT); | |
261 *R = vec_mradds (vx, c->CRV, Y); | |
262 | |
263 // uvx = ((CGU*u) + (CGV*v))>>15; | |
264 uvx = vec_mradds (U, c->CGU, Y); | |
265 *G = vec_mradds (V, c->CGV, uvx); | |
266 } | |
267 | |
268 | |
269 /* | |
270 ------------------------------------------------------------------------------ | |
271 CS converters | |
272 ------------------------------------------------------------------------------ | |
273 */ | |
274 | |
275 | |
276 #define DEFCSP420_CVT(name,out_pixels) \ | |
277 static int altivec_##name (SwsContext *c, \ | |
278 unsigned char **in, int *instrides, \ | |
279 int srcSliceY, int srcSliceH, \ | |
280 unsigned char **oplanes, int *outstrides) \ | |
281 { \ | |
282 int w = c->srcW; \ | |
283 int h = srcSliceH; \ | |
284 int i,j; \ | |
285 int instrides_scl[3]; \ | |
286 vector unsigned char y0,y1; \ | |
287 \ | |
288 vector signed char u,v; \ | |
289 \ | |
290 vector signed short Y0,Y1,Y2,Y3; \ | |
291 vector signed short U,V; \ | |
292 vector signed short vx,ux,uvx; \ | |
293 vector signed short vx0,ux0,uvx0; \ | |
294 vector signed short vx1,ux1,uvx1; \ | |
295 vector signed short R0,G0,B0; \ | |
296 vector signed short R1,G1,B1; \ | |
297 vector unsigned char R,G,B; \ | |
298 \ | |
299 vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \ | |
300 vector unsigned char align_perm; \ | |
301 \ | |
302 vector signed short \ | |
303 lCY = c->CY, \ | |
304 lOY = c->OY, \ | |
305 lCRV = c->CRV, \ | |
306 lCBU = c->CBU, \ | |
307 lCGU = c->CGU, \ | |
308 lCGV = c->CGV; \ | |
309 \ | |
310 vector unsigned short lCSHIFT = c->CSHIFT; \ | |
311 \ | |
312 ubyte *y1i = in[0]; \ | |
313 ubyte *y2i = in[0]+instrides[0]; \ | |
314 ubyte *ui = in[1]; \ | |
315 ubyte *vi = in[2]; \ | |
316 \ | |
317 vector unsigned char *oute \ | |
318 = (vector unsigned char *) \ | |
319 (oplanes[0]+srcSliceY*outstrides[0]); \ | |
320 vector unsigned char *outo \ | |
321 = (vector unsigned char *) \ | |
322 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]); \ | |
323 \ | |
324 \ | |
325 instrides_scl[0] = instrides[0]*2-w; /* the loop moves y{1,2}i by w */ \ | |
326 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */ \ | |
327 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */ \ | |
328 \ | |
329 \ | |
330 for (i=0;i<h/2;i++) { \ | |
331 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0); \ | |
332 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1); \ | |
333 \ | |
334 for (j=0;j<w/16;j++) { \ | |
335 \ | |
336 y1ivP = (vector unsigned char *)y1i; \ | |
337 y2ivP = (vector unsigned char *)y2i; \ | |
338 uivP = (vector unsigned char *)ui; \ | |
339 vivP = (vector unsigned char *)vi; \ | |
340 \ | |
341 align_perm = vec_lvsl (0, y1i); \ | |
342 y0 = (vector unsigned char) \ | |
343 vec_perm (y1ivP[0], y1ivP[1], align_perm); \ | |
344 \ | |
345 align_perm = vec_lvsl (0, y2i); \ | |
346 y1 = (vector unsigned char) \ | |
347 vec_perm (y2ivP[0], y2ivP[1], align_perm); \ | |
348 \ | |
349 align_perm = vec_lvsl (0, ui); \ | |
350 u = (vector signed char) \ | |
351 vec_perm (uivP[0], uivP[1], align_perm); \ | |
352 \ | |
353 align_perm = vec_lvsl (0, vi); \ | |
354 v = (vector signed char) \ | |
355 vec_perm (vivP[0], vivP[1], align_perm); \ | |
356 \ | |
357 u = (vector signed char) \ | |
358 vec_sub (u,(vector signed char) \ | |
359 vec_splat((vector signed char){128},0)); \ | |
360 v = (vector signed char) \ | |
361 vec_sub (v,(vector signed char) \ | |
362 vec_splat((vector signed char){128},0)); \ | |
363 \ | |
364 U = vec_unpackh (u); \ | |
365 V = vec_unpackh (v); \ | |
366 \ | |
367 \ | |
368 Y0 = vec_unh (y0); \ | |
369 Y1 = vec_unl (y0); \ | |
370 Y2 = vec_unh (y1); \ | |
371 Y3 = vec_unl (y1); \ | |
372 \ | |
373 Y0 = vec_mradds (Y0, lCY, lOY); \ | |
374 Y1 = vec_mradds (Y1, lCY, lOY); \ | |
375 Y2 = vec_mradds (Y2, lCY, lOY); \ | |
376 Y3 = vec_mradds (Y3, lCY, lOY); \ | |
377 \ | |
378 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */ \ | |
379 ux = vec_sl (U, lCSHIFT); \ | |
380 ux = vec_mradds (ux, lCBU, (vector signed short){0}); \ | |
381 ux0 = vec_mergeh (ux,ux); \ | |
382 ux1 = vec_mergel (ux,ux); \ | |
383 \ | |
384 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */ \ | |
385 vx = vec_sl (V, lCSHIFT); \ | |
386 vx = vec_mradds (vx, lCRV, (vector signed short){0}); \ | |
387 vx0 = vec_mergeh (vx,vx); \ | |
388 vx1 = vec_mergel (vx,vx); \ | |
389 \ | |
390 /* uvx = ((CGU*u) + (CGV*v))>>15 */ \ | |
391 uvx = vec_mradds (U, lCGU, (vector signed short){0}); \ | |
392 uvx = vec_mradds (V, lCGV, uvx); \ | |
393 uvx0 = vec_mergeh (uvx,uvx); \ | |
394 uvx1 = vec_mergel (uvx,uvx); \ | |
395 \ | |
396 R0 = vec_add (Y0,vx0); \ | |
397 G0 = vec_add (Y0,uvx0); \ | |
398 B0 = vec_add (Y0,ux0); \ | |
399 R1 = vec_add (Y1,vx1); \ | |
400 G1 = vec_add (Y1,uvx1); \ | |
401 B1 = vec_add (Y1,ux1); \ | |
402 \ | |
403 R = vec_packclp (R0,R1); \ | |
404 G = vec_packclp (G0,G1); \ | |
405 B = vec_packclp (B0,B1); \ | |
406 \ | |
407 out_pixels(R,G,B,oute); \ | |
408 \ | |
409 R0 = vec_add (Y2,vx0); \ | |
410 G0 = vec_add (Y2,uvx0); \ | |
411 B0 = vec_add (Y2,ux0); \ | |
412 R1 = vec_add (Y3,vx1); \ | |
413 G1 = vec_add (Y3,uvx1); \ | |
414 B1 = vec_add (Y3,ux1); \ | |
415 R = vec_packclp (R0,R1); \ | |
416 G = vec_packclp (G0,G1); \ | |
417 B = vec_packclp (B0,B1); \ | |
418 \ | |
419 \ | |
420 out_pixels(R,G,B,outo); \ | |
421 \ | |
422 y1i += 16; \ | |
423 y2i += 16; \ | |
424 ui += 8; \ | |
425 vi += 8; \ | |
426 \ | |
427 } \ | |
428 \ | |
429 outo += (outstrides[0])>>4; \ | |
430 oute += (outstrides[0])>>4; \ | |
431 \ | |
432 ui += instrides_scl[1]; \ | |
433 vi += instrides_scl[2]; \ | |
434 y1i += instrides_scl[0]; \ | |
435 y2i += instrides_scl[0]; \ | |
436 } \ | |
437 return srcSliceH; \ | |
438 } | |
439 | |
440 | |
441 #define out_abgr(a,b,c,ptr) vec_mstrgb32(__typeof__(a),((__typeof__ (a)){255}),c,b,a,ptr) | |
442 #define out_bgra(a,b,c,ptr) vec_mstrgb32(__typeof__(a),c,b,a,((__typeof__ (a)){255}),ptr) | |
443 #define out_rgba(a,b,c,ptr) vec_mstrgb32(__typeof__(a),a,b,c,((__typeof__ (a)){255}),ptr) | |
444 #define out_argb(a,b,c,ptr) vec_mstrgb32(__typeof__(a),((__typeof__ (a)){255}),a,b,c,ptr) | |
445 #define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr) | |
446 #define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr) | |
447 | |
448 DEFCSP420_CVT (yuv2_abgr, out_abgr) | |
449 #if 1 | |
450 DEFCSP420_CVT (yuv2_bgra, out_bgra) | |
451 #else | |
452 static int altivec_yuv2_bgra32 (SwsContext *c, | |
453 unsigned char **in, int *instrides, | |
454 int srcSliceY, int srcSliceH, | |
455 unsigned char **oplanes, int *outstrides) | |
456 { | |
457 int w = c->srcW; | |
458 int h = srcSliceH; | |
459 int i,j; | |
460 int instrides_scl[3]; | |
461 vector unsigned char y0,y1; | |
462 | |
463 vector signed char u,v; | |
464 | |
465 vector signed short Y0,Y1,Y2,Y3; | |
466 vector signed short U,V; | |
467 vector signed short vx,ux,uvx; | |
468 vector signed short vx0,ux0,uvx0; | |
469 vector signed short vx1,ux1,uvx1; | |
470 vector signed short R0,G0,B0; | |
471 vector signed short R1,G1,B1; | |
472 vector unsigned char R,G,B; | |
473 | |
474 vector unsigned char *uivP, *vivP; | |
475 vector unsigned char align_perm; | |
476 | |
477 vector signed short | |
478 lCY = c->CY, | |
479 lOY = c->OY, | |
480 lCRV = c->CRV, | |
481 lCBU = c->CBU, | |
482 lCGU = c->CGU, | |
483 lCGV = c->CGV; | |
484 | |
485 vector unsigned short lCSHIFT = c->CSHIFT; | |
486 | |
487 ubyte *y1i = in[0]; | |
488 ubyte *y2i = in[0]+w; | |
489 ubyte *ui = in[1]; | |
490 ubyte *vi = in[2]; | |
491 | |
492 vector unsigned char *oute | |
493 = (vector unsigned char *) | |
494 (oplanes[0]+srcSliceY*outstrides[0]); | |
495 vector unsigned char *outo | |
496 = (vector unsigned char *) | |
497 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]); | |
498 | |
499 | |
500 instrides_scl[0] = instrides[0]; | |
501 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */ | |
502 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */ | |
503 | |
504 | |
505 for (i=0;i<h/2;i++) { | |
506 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0); | |
507 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1); | |
508 | |
509 for (j=0;j<w/16;j++) { | |
510 | |
511 y0 = vec_ldl (0,y1i); | |
512 y1 = vec_ldl (0,y2i); | |
513 uivP = (vector unsigned char *)ui; | |
514 vivP = (vector unsigned char *)vi; | |
515 | |
516 align_perm = vec_lvsl (0, ui); | |
517 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm); | |
518 | |
519 align_perm = vec_lvsl (0, vi); | |
520 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm); | |
521 u = (vector signed char) | |
522 vec_sub (u,(vector signed char) | |
523 vec_splat((vector signed char){128},0)); | |
524 | |
525 v = (vector signed char) | |
526 vec_sub (v, (vector signed char) | |
527 vec_splat((vector signed char){128},0)); | |
528 | |
529 U = vec_unpackh (u); | |
530 V = vec_unpackh (v); | |
531 | |
532 | |
533 Y0 = vec_unh (y0); | |
534 Y1 = vec_unl (y0); | |
535 Y2 = vec_unh (y1); | |
536 Y3 = vec_unl (y1); | |
537 | |
538 Y0 = vec_mradds (Y0, lCY, lOY); | |
539 Y1 = vec_mradds (Y1, lCY, lOY); | |
540 Y2 = vec_mradds (Y2, lCY, lOY); | |
541 Y3 = vec_mradds (Y3, lCY, lOY); | |
542 | |
543 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */ | |
544 ux = vec_sl (U, lCSHIFT); | |
545 ux = vec_mradds (ux, lCBU, (vector signed short){0}); | |
546 ux0 = vec_mergeh (ux,ux); | |
547 ux1 = vec_mergel (ux,ux); | |
548 | |
549 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */ | |
550 vx = vec_sl (V, lCSHIFT); | |
551 vx = vec_mradds (vx, lCRV, (vector signed short){0}); | |
552 vx0 = vec_mergeh (vx,vx); | |
553 vx1 = vec_mergel (vx,vx); | |
554 /* uvx = ((CGU*u) + (CGV*v))>>15 */ | |
555 uvx = vec_mradds (U, lCGU, (vector signed short){0}); | |
556 uvx = vec_mradds (V, lCGV, uvx); | |
557 uvx0 = vec_mergeh (uvx,uvx); | |
558 uvx1 = vec_mergel (uvx,uvx); | |
559 R0 = vec_add (Y0,vx0); | |
560 G0 = vec_add (Y0,uvx0); | |
561 B0 = vec_add (Y0,ux0); | |
562 R1 = vec_add (Y1,vx1); | |
563 G1 = vec_add (Y1,uvx1); | |
564 B1 = vec_add (Y1,ux1); | |
565 R = vec_packclp (R0,R1); | |
566 G = vec_packclp (G0,G1); | |
567 B = vec_packclp (B0,B1); | |
568 | |
569 out_argb(R,G,B,oute); | |
570 R0 = vec_add (Y2,vx0); | |
571 G0 = vec_add (Y2,uvx0); | |
572 B0 = vec_add (Y2,ux0); | |
573 R1 = vec_add (Y3,vx1); | |
574 G1 = vec_add (Y3,uvx1); | |
575 B1 = vec_add (Y3,ux1); | |
576 R = vec_packclp (R0,R1); | |
577 G = vec_packclp (G0,G1); | |
578 B = vec_packclp (B0,B1); | |
579 | |
580 out_argb(R,G,B,outo); | |
581 y1i += 16; | |
582 y2i += 16; | |
583 ui += 8; | |
584 vi += 8; | |
585 | |
586 } | |
587 | |
588 outo += (outstrides[0])>>4; | |
589 oute += (outstrides[0])>>4; | |
590 | |
591 ui += instrides_scl[1]; | |
592 vi += instrides_scl[2]; | |
593 y1i += instrides_scl[0]; | |
594 y2i += instrides_scl[0]; | |
595 } | |
596 return srcSliceH; | |
597 } | |
598 | |
599 #endif | |
600 | |
601 | |
602 DEFCSP420_CVT (yuv2_rgba, out_rgba) | |
603 DEFCSP420_CVT (yuv2_argb, out_argb) | |
604 DEFCSP420_CVT (yuv2_rgb24, out_rgb24) | |
605 DEFCSP420_CVT (yuv2_bgr24, out_bgr24) | |
606 | |
607 | |
608 // uyvy|uyvy|uyvy|uyvy | |
609 // 0123 4567 89ab cdef | |
610 static | |
611 const vector unsigned char | |
612 demux_u = {0x10,0x00,0x10,0x00, | |
613 0x10,0x04,0x10,0x04, | |
614 0x10,0x08,0x10,0x08, | |
615 0x10,0x0c,0x10,0x0c}, | |
616 demux_v = {0x10,0x02,0x10,0x02, | |
617 0x10,0x06,0x10,0x06, | |
618 0x10,0x0A,0x10,0x0A, | |
619 0x10,0x0E,0x10,0x0E}, | |
620 demux_y = {0x10,0x01,0x10,0x03, | |
621 0x10,0x05,0x10,0x07, | |
622 0x10,0x09,0x10,0x0B, | |
623 0x10,0x0D,0x10,0x0F}; | |
624 | |
625 /* | |
626 this is so I can play live CCIR raw video | |
627 */ | |
628 static int altivec_uyvy_rgb32 (SwsContext *c, | |
629 unsigned char **in, int *instrides, | |
630 int srcSliceY, int srcSliceH, | |
631 unsigned char **oplanes, int *outstrides) | |
632 { | |
633 int w = c->srcW; | |
634 int h = srcSliceH; | |
635 int i,j; | |
636 vector unsigned char uyvy; | |
637 vector signed short Y,U,V; | |
638 vector signed short R0,G0,B0,R1,G1,B1; | |
639 vector unsigned char R,G,B; | |
640 vector unsigned char *out; | |
641 ubyte *img; | |
642 | |
643 img = in[0]; | |
644 out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]); | |
645 | |
646 for (i=0;i<h;i++) { | |
647 for (j=0;j<w/16;j++) { | |
648 uyvy = vec_ld (0, img); | |
649 U = (vector signed short) | |
650 vec_perm (uyvy, (vector unsigned char){0}, demux_u); | |
651 | |
652 V = (vector signed short) | |
653 vec_perm (uyvy, (vector unsigned char){0}, demux_v); | |
654 | |
655 Y = (vector signed short) | |
656 vec_perm (uyvy, (vector unsigned char){0}, demux_y); | |
657 | |
658 cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0); | |
659 | |
660 uyvy = vec_ld (16, img); | |
661 U = (vector signed short) | |
662 vec_perm (uyvy, (vector unsigned char){0}, demux_u); | |
663 | |
664 V = (vector signed short) | |
665 vec_perm (uyvy, (vector unsigned char){0}, demux_v); | |
666 | |
667 Y = (vector signed short) | |
668 vec_perm (uyvy, (vector unsigned char){0}, demux_y); | |
669 | |
670 cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1); | |
671 | |
672 R = vec_packclp (R0,R1); | |
673 G = vec_packclp (G0,G1); | |
674 B = vec_packclp (B0,B1); | |
675 | |
676 // vec_mstbgr24 (R,G,B, out); | |
677 out_rgba (R,G,B,out); | |
678 | |
679 img += 32; | |
680 } | |
681 } | |
682 return srcSliceH; | |
683 } | |
684 | |
685 | |
686 | |
687 /* Ok currently the acceleration routine only supports | |
688 inputs of widths a multiple of 16 | |
689 and heights a multiple 2 | |
690 | |
691 So we just fall back to the C codes for this. | |
692 */ | |
693 SwsFunc ff_yuv2rgb_init_altivec(SwsContext *c) | |
694 { | |
695 if (!(c->flags & SWS_CPU_CAPS_ALTIVEC)) | |
696 return NULL; | |
697 | |
698 /* | |
699 and this seems not to matter too much I tried a bunch of | |
700 videos with abnormal widths and MPlayer crashes elsewhere. | |
701 mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv | |
702 boom with X11 bad match. | |
703 | |
704 */ | |
705 if ((c->srcW & 0xf) != 0) return NULL; | |
706 | |
707 switch (c->srcFormat) { | |
708 case PIX_FMT_YUV410P: | |
709 case PIX_FMT_YUV420P: | |
710 /*case IMGFMT_CLPL: ??? */ | |
711 case PIX_FMT_GRAY8: | |
712 case PIX_FMT_NV12: | |
713 case PIX_FMT_NV21: | |
714 if ((c->srcH & 0x1) != 0) | |
715 return NULL; | |
716 | |
717 switch(c->dstFormat){ | |
718 case PIX_FMT_RGB24: | |
719 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space RGB24\n"); | |
720 return altivec_yuv2_rgb24; | |
721 case PIX_FMT_BGR24: | |
722 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space BGR24\n"); | |
723 return altivec_yuv2_bgr24; | |
724 case PIX_FMT_ARGB: | |
725 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space ARGB\n"); | |
726 return altivec_yuv2_argb; | |
727 case PIX_FMT_ABGR: | |
728 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space ABGR\n"); | |
729 return altivec_yuv2_abgr; | |
730 case PIX_FMT_RGBA: | |
731 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space RGBA\n"); | |
732 return altivec_yuv2_rgba; | |
733 case PIX_FMT_BGRA: | |
734 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space BGRA\n"); | |
735 return altivec_yuv2_bgra; | |
736 default: return NULL; | |
737 } | |
738 break; | |
739 | |
740 case PIX_FMT_UYVY422: | |
741 switch(c->dstFormat){ | |
742 case PIX_FMT_BGR32: | |
743 av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space UYVY -> RGB32\n"); | |
744 return altivec_uyvy_rgb32; | |
745 default: return NULL; | |
746 } | |
747 break; | |
748 | |
749 } | |
750 return NULL; | |
751 } | |
752 | |
753 void ff_yuv2rgb_init_tables_altivec(SwsContext *c, const int inv_table[4], int brightness, int contrast, int saturation) | |
754 { | |
755 union { | |
756 signed short tmp[8] __attribute__ ((aligned(16))); | |
757 vector signed short vec; | |
758 } buf; | |
759 | |
760 buf.tmp[0] = ((0xffffLL) * contrast>>8)>>9; //cy | |
761 buf.tmp[1] = -256*brightness; //oy | |
762 buf.tmp[2] = (inv_table[0]>>3) *(contrast>>16)*(saturation>>16); //crv | |
763 buf.tmp[3] = (inv_table[1]>>3) *(contrast>>16)*(saturation>>16); //cbu | |
764 buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16)); //cgu | |
765 buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16)); //cgv | |
766 | |
767 | |
768 c->CSHIFT = (vector unsigned short)vec_splat_u16(2); | |
769 c->CY = vec_splat ((vector signed short)buf.vec, 0); | |
770 c->OY = vec_splat ((vector signed short)buf.vec, 1); | |
771 c->CRV = vec_splat ((vector signed short)buf.vec, 2); | |
772 c->CBU = vec_splat ((vector signed short)buf.vec, 3); | |
773 c->CGU = vec_splat ((vector signed short)buf.vec, 4); | |
774 c->CGV = vec_splat ((vector signed short)buf.vec, 5); | |
775 #if 0 | |
776 { | |
777 int i; | |
778 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"}; | |
779 for (i=0; i<6; i++) | |
780 printf("%s %d ", v[i],buf.tmp[i] ); | |
781 printf("\n"); | |
782 } | |
783 #endif | |
784 return; | |
785 } | |
786 | |
787 | |
788 void | |
789 ff_yuv2packedX_altivec(SwsContext *c, | |
29239
882a1f5613e1
Add missing const qualifiers to AltiVec function parameters where appropriate.
diego
parents:
29028
diff
changeset
|
790 const int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize, |
882a1f5613e1
Add missing const qualifiers to AltiVec function parameters where appropriate.
diego
parents:
29028
diff
changeset
|
791 const int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize, |
29028 | 792 uint8_t *dest, int dstW, int dstY) |
793 { | |
794 int i,j; | |
795 vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V; | |
796 vector signed short R0,G0,B0,R1,G1,B1; | |
797 | |
798 vector unsigned char R,G,B; | |
799 vector unsigned char *out,*nout; | |
800 | |
801 vector signed short RND = vec_splat_s16(1<<3); | |
802 vector unsigned short SCL = vec_splat_u16(4); | |
803 unsigned long scratch[16] __attribute__ ((aligned (16))); | |
804 | |
805 vector signed short *YCoeffs, *CCoeffs; | |
806 | |
807 YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize; | |
808 CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize; | |
809 | |
810 out = (vector unsigned char *)dest; | |
811 | |
812 for (i=0; i<dstW; i+=16){ | |
813 Y0 = RND; | |
814 Y1 = RND; | |
815 /* extract 16 coeffs from lumSrc */ | |
816 for (j=0; j<lumFilterSize; j++) { | |
817 X0 = vec_ld (0, &lumSrc[j][i]); | |
818 X1 = vec_ld (16, &lumSrc[j][i]); | |
819 Y0 = vec_mradds (X0, YCoeffs[j], Y0); | |
820 Y1 = vec_mradds (X1, YCoeffs[j], Y1); | |
821 } | |
822 | |
823 U = RND; | |
824 V = RND; | |
825 /* extract 8 coeffs from U,V */ | |
826 for (j=0; j<chrFilterSize; j++) { | |
827 X = vec_ld (0, &chrSrc[j][i/2]); | |
828 U = vec_mradds (X, CCoeffs[j], U); | |
829 X = vec_ld (0, &chrSrc[j][i/2+2048]); | |
830 V = vec_mradds (X, CCoeffs[j], V); | |
831 } | |
832 | |
833 /* scale and clip signals */ | |
834 Y0 = vec_sra (Y0, SCL); | |
835 Y1 = vec_sra (Y1, SCL); | |
836 U = vec_sra (U, SCL); | |
837 V = vec_sra (V, SCL); | |
838 | |
839 Y0 = vec_clip_s16 (Y0); | |
840 Y1 = vec_clip_s16 (Y1); | |
841 U = vec_clip_s16 (U); | |
842 V = vec_clip_s16 (V); | |
843 | |
844 /* now we have | |
845 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15 | |
846 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7 | |
847 | |
848 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15 | |
849 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7 | |
850 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7 | |
851 */ | |
852 | |
853 U0 = vec_mergeh (U,U); | |
854 V0 = vec_mergeh (V,V); | |
855 | |
856 U1 = vec_mergel (U,U); | |
857 V1 = vec_mergel (V,V); | |
858 | |
859 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0); | |
860 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1); | |
861 | |
862 R = vec_packclp (R0,R1); | |
863 G = vec_packclp (G0,G1); | |
864 B = vec_packclp (B0,B1); | |
865 | |
866 switch(c->dstFormat) { | |
867 case PIX_FMT_ABGR: out_abgr (R,G,B,out); break; | |
868 case PIX_FMT_BGRA: out_bgra (R,G,B,out); break; | |
869 case PIX_FMT_RGBA: out_rgba (R,G,B,out); break; | |
870 case PIX_FMT_ARGB: out_argb (R,G,B,out); break; | |
871 case PIX_FMT_RGB24: out_rgb24 (R,G,B,out); break; | |
872 case PIX_FMT_BGR24: out_bgr24 (R,G,B,out); break; | |
873 default: | |
874 { | |
875 /* If this is reached, the caller should have called yuv2packedXinC | |
876 instead. */ | |
877 static int printed_error_message; | |
878 if (!printed_error_message) { | |
879 av_log(c, AV_LOG_ERROR, "altivec_yuv2packedX doesn't support %s output\n", | |
880 sws_format_name(c->dstFormat)); | |
881 printed_error_message=1; | |
882 } | |
883 return; | |
884 } | |
885 } | |
886 } | |
887 | |
888 if (i < dstW) { | |
889 i -= 16; | |
890 | |
891 Y0 = RND; | |
892 Y1 = RND; | |
893 /* extract 16 coeffs from lumSrc */ | |
894 for (j=0; j<lumFilterSize; j++) { | |
895 X0 = vec_ld (0, &lumSrc[j][i]); | |
896 X1 = vec_ld (16, &lumSrc[j][i]); | |
897 Y0 = vec_mradds (X0, YCoeffs[j], Y0); | |
898 Y1 = vec_mradds (X1, YCoeffs[j], Y1); | |
899 } | |
900 | |
901 U = RND; | |
902 V = RND; | |
903 /* extract 8 coeffs from U,V */ | |
904 for (j=0; j<chrFilterSize; j++) { | |
905 X = vec_ld (0, &chrSrc[j][i/2]); | |
906 U = vec_mradds (X, CCoeffs[j], U); | |
907 X = vec_ld (0, &chrSrc[j][i/2+2048]); | |
908 V = vec_mradds (X, CCoeffs[j], V); | |
909 } | |
910 | |
911 /* scale and clip signals */ | |
912 Y0 = vec_sra (Y0, SCL); | |
913 Y1 = vec_sra (Y1, SCL); | |
914 U = vec_sra (U, SCL); | |
915 V = vec_sra (V, SCL); | |
916 | |
917 Y0 = vec_clip_s16 (Y0); | |
918 Y1 = vec_clip_s16 (Y1); | |
919 U = vec_clip_s16 (U); | |
920 V = vec_clip_s16 (V); | |
921 | |
922 /* now we have | |
923 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15 | |
924 U = u0 u1 u2 u3 u4 u5 u6 u7 V = v0 v1 v2 v3 v4 v5 v6 v7 | |
925 | |
926 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15 | |
927 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7 | |
928 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7 | |
929 */ | |
930 | |
931 U0 = vec_mergeh (U,U); | |
932 V0 = vec_mergeh (V,V); | |
933 | |
934 U1 = vec_mergel (U,U); | |
935 V1 = vec_mergel (V,V); | |
936 | |
937 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0); | |
938 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1); | |
939 | |
940 R = vec_packclp (R0,R1); | |
941 G = vec_packclp (G0,G1); | |
942 B = vec_packclp (B0,B1); | |
943 | |
944 nout = (vector unsigned char *)scratch; | |
945 switch(c->dstFormat) { | |
946 case PIX_FMT_ABGR: out_abgr (R,G,B,nout); break; | |
947 case PIX_FMT_BGRA: out_bgra (R,G,B,nout); break; | |
948 case PIX_FMT_RGBA: out_rgba (R,G,B,nout); break; | |
949 case PIX_FMT_ARGB: out_argb (R,G,B,nout); break; | |
950 case PIX_FMT_RGB24: out_rgb24 (R,G,B,nout); break; | |
951 case PIX_FMT_BGR24: out_bgr24 (R,G,B,nout); break; | |
952 default: | |
953 /* Unreachable, I think. */ | |
954 av_log(c, AV_LOG_ERROR, "altivec_yuv2packedX doesn't support %s output\n", | |
955 sws_format_name(c->dstFormat)); | |
956 return; | |
957 } | |
958 | |
959 memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4); | |
960 } | |
961 | |
962 } |