2 marc.hoffman@analog.com March 8, 2004
4 Altivec Acceleration for Color Space Conversion revision 0.2
6 convert I420 YV12 to RGB in various formats,
7 it rejects images that are not in 420 formats
8 it rejects images that don't have widths of multiples of 16
9 it rejects images that don't have heights of multiples of 2
10 reject defers to C simulation codes.
12 lots of optimizations to be done here
14 1. need to fix saturation code, I just couldn't get it to fly with packs and adds.
15 so we currently use max min to clip
17 2. the inefficient use of chroma loading needs a bit of brushing up
19 3. analysis of pipeline stalls needs to be done, use shark to identify pipeline stalls
22 MODIFIED to calculate coeffs from currently selected color space.
23 MODIFIED core to be a macro which you spec the output format.
24 ADDED UYVY conversion which is never called due to some thing in SWSCALE.
25 CORRECTED algorithim selection to be strict on input formats.
26 ADDED runtime detection of altivec.
28 ADDED altivec_yuv2packedX vertical scl + RGB converter
33 The C version use 25% of the processor or ~250Mips for D1 video rawvideo used as test
34 The ALTIVEC version uses 10% of the processor or ~100Mips for D1 video same sequence
38 so we have roughly 10clocks per pixel this is too high something has to be wrong.
40 OPTIMIZED clip codes to utilize vec_max and vec_packs removing the need for vec_min.
42 OPTIMIZED DST OUTPUT cache/dma controls. we are pretty much
43 guaranteed to have the input video frame it was just decompressed so
44 it probably resides in L1 caches. However we are creating the
45 output video stream this needs to use the DSTST instruction to
46 optimize for the cache. We couple this with the fact that we are
47 not going to be visiting the input buffer again so we mark it Least
48 Recently Used. This shaves 25% of the processor cycles off.
50 Now MEMCPY is the largest mips consumer in the system, probably due
51 to the inefficient X11 stuff.
53 GL libraries seem to be very slow on this machine 1.33Ghz PB running
54 Jaguar, this is not the case for my 1Ghz PB. I thought it might be
55 a versioning issues, however i have libGL.1.2.dylib for both
56 machines. ((We need to figure this out now))
58 GL2 libraries work now with patch for RGB32
60 NOTE quartz vo driver ARGB32_to_RGB24 consumes 30% of the processor
62 Integrated luma prescaling adjustment for saturation/contrast/brightness adjustment.
64 This program is free software; you can redistribute it and/or modify
65 it under the terms of the GNU General Public License as published by
66 the Free Software Foundation; either version 2 of the License, or
67 (at your option) any later version.
69 This program is distributed in the hope that it will be useful,
70 but WITHOUT ANY WARRANTY; without even the implied warranty of
71 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72 GNU General Public License for more details.
74 You should have received a copy of the GNU General Public License
75 along with this program; if not, write to the Free Software
76 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
90 #include "swscale_internal.h"
92 #undef PROFILE_THE_BEAST
95 typedef unsigned char ubyte;
96 typedef signed char sbyte;
99 /* RGB interleaver, 16 planar pels 8-bit samples per channel in
100 homogeneous vector registers x0,x1,x2 are interleaved with the
103 o0 = vec_mergeh (x0,x1);
104 o1 = vec_perm (o0, x2, perm_rgb_0);
105 o2 = vec_perm (o0, x2, perm_rgb_1);
106 o3 = vec_mergel (x0,x1);
107 o4 = vec_perm (o3,o2,perm_rgb_2);
108 o5 = vec_perm (o3,o2,perm_rgb_3);
110 perm_rgb_0: o0(RG).h v1(B) --> o1*
116 perm_rgb_1: o0(RG).h v1(B) --> o2
122 perm_rgb_2: o3(RG).l o2(rgbB.l) --> o4*
128 perm_rgb_2: o3(RG).l o2(rgbB.l) ---> o5*
136 const vector unsigned char
137 perm_rgb_0 = (const vector unsigned char)AVV(0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05,
138 0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a),
139 perm_rgb_1 = (const vector unsigned char)AVV(0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17,
140 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f),
141 perm_rgb_2 = (const vector unsigned char)AVV(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
142 0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05),
143 perm_rgb_3 = (const vector unsigned char)AVV(0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a,
144 0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f);
146 #define vec_merge3(x2,x1,x0,y0,y1,y2) \
148 typeof(x0) o0,o2,o3; \
149 o0 = vec_mergeh (x0,x1); \
150 y0 = vec_perm (o0, x2, perm_rgb_0);\
151 o2 = vec_perm (o0, x2, perm_rgb_1);\
152 o3 = vec_mergel (x0,x1); \
153 y1 = vec_perm (o3,o2,perm_rgb_2); \
154 y2 = vec_perm (o3,o2,perm_rgb_3); \
157 #define vec_mstbgr24(x0,x1,x2,ptr) \
159 typeof(x0) _0,_1,_2; \
160 vec_merge3 (x0,x1,x2,_0,_1,_2); \
161 vec_st (_0, 0, ptr++); \
162 vec_st (_1, 0, ptr++); \
163 vec_st (_2, 0, ptr++); \
166 #define vec_mstrgb24(x0,x1,x2,ptr) \
168 typeof(x0) _0,_1,_2; \
169 vec_merge3 (x2,x1,x0,_0,_1,_2); \
170 vec_st (_0, 0, ptr++); \
171 vec_st (_1, 0, ptr++); \
172 vec_st (_2, 0, ptr++); \
175 /* pack the pixels in rgb0 format
179 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr) \
182 _0 = vec_mergeh (x0,x1); \
183 _1 = vec_mergeh (x2,x3); \
184 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
185 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
186 vec_st (_2, 0*16, (T *)ptr); \
187 vec_st (_3, 1*16, (T *)ptr); \
188 _0 = vec_mergel (x0,x1); \
189 _1 = vec_mergel (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, 2*16, (T *)ptr); \
193 vec_st (_3, 3*16, (T *)ptr); \
200 | 1 -0.3441 -0.7142 |x| Cb|
207 typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
215 (vector signed short) \
216 vec_perm(x,(typeof(x))AVV(0),\
217 (vector unsigned char)AVV(0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\
218 0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07))
220 (vector signed short) \
221 vec_perm(x,(typeof(x))AVV(0),\
222 (vector unsigned char)AVV(0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\
223 0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F))
225 #define vec_clip_s16(x) \
226 vec_max (vec_min (x, (vector signed short)AVV(235,235,235,235,235,235,235,235)),\
227 (vector signed short)AVV(16, 16, 16, 16, 16, 16, 16, 16 ))
229 #define vec_packclp(x,y) \
230 (vector unsigned char)vec_packs \
231 ((vector unsigned short)vec_max (x,(vector signed short) AVV(0)), \
232 (vector unsigned short)vec_max (y,(vector signed short) AVV(0)))
234 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
237 static inline void cvtyuvtoRGB (SwsContext *c,
238 vector signed short Y, vector signed short U, vector signed short V,
239 vector signed short *R, vector signed short *G, vector signed short *B)
241 vector signed short vx,ux,uvx;
243 Y = vec_mradds (Y, c->CY, c->OY);
244 U = vec_sub (U,(vector signed short)
245 vec_splat((vector signed short)AVV(128),0));
246 V = vec_sub (V,(vector signed short)
247 vec_splat((vector signed short)AVV(128),0));
249 // ux = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
250 ux = vec_sl (U, c->CSHIFT);
251 *B = vec_mradds (ux, c->CBU, Y);
253 // vx = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
254 vx = vec_sl (V, c->CSHIFT);
255 *R = vec_mradds (vx, c->CRV, Y);
257 // uvx = ((CGU*u) + (CGV*v))>>15;
258 uvx = vec_mradds (U, c->CGU, Y);
259 *G = vec_mradds (V, c->CGV, uvx);
264 ------------------------------------------------------------------------------
266 ------------------------------------------------------------------------------
270 #define DEFCSP420_CVT(name,out_pixels) \
271 static int altivec_##name (SwsContext *c, \
272 unsigned char **in, int *instrides, \
273 int srcSliceY, int srcSliceH, \
274 unsigned char **oplanes, int *outstrides) \
279 int instrides_scl[3]; \
280 vector unsigned char y0,y1; \
282 vector signed char u,v; \
284 vector signed short Y0,Y1,Y2,Y3; \
285 vector signed short U,V; \
286 vector signed short vx,ux,uvx; \
287 vector signed short vx0,ux0,uvx0; \
288 vector signed short vx1,ux1,uvx1; \
289 vector signed short R0,G0,B0; \
290 vector signed short R1,G1,B1; \
291 vector unsigned char R,G,B; \
293 vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \
294 vector unsigned char align_perm; \
296 vector signed short \
304 vector unsigned short lCSHIFT = c->CSHIFT; \
306 ubyte *y1i = in[0]; \
307 ubyte *y2i = in[0]+instrides[0]; \
311 vector unsigned char *oute \
312 = (vector unsigned char *) \
313 (oplanes[0]+srcSliceY*outstrides[0]); \
314 vector unsigned char *outo \
315 = (vector unsigned char *) \
316 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]); \
319 instrides_scl[0] = instrides[0]*2-w; /* the loop moves y{1,2}i by w */ \
320 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */ \
321 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */ \
324 for (i=0;i<h/2;i++) { \
325 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0); \
326 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1); \
328 for (j=0;j<w/16;j++) { \
330 y1ivP = (vector unsigned char *)y1i; \
331 y2ivP = (vector unsigned char *)y2i; \
332 uivP = (vector unsigned char *)ui; \
333 vivP = (vector unsigned char *)vi; \
335 align_perm = vec_lvsl (0, y1i); \
336 y0 = (vector unsigned char)vec_perm (y1ivP[0], y1ivP[1], align_perm);\
338 align_perm = vec_lvsl (0, y2i); \
339 y1 = (vector unsigned char)vec_perm (y2ivP[0], y2ivP[1], align_perm);\
341 align_perm = vec_lvsl (0, ui); \
342 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm); \
344 align_perm = vec_lvsl (0, vi); \
345 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm); \
347 u = (vector signed char) \
348 vec_sub (u,(vector signed char) \
349 vec_splat((vector signed char)AVV(128),0));\
350 v = (vector signed char) \
351 vec_sub (v,(vector signed char) \
352 vec_splat((vector signed char)AVV(128),0));\
354 U = vec_unpackh (u); \
355 V = vec_unpackh (v); \
363 Y0 = vec_mradds (Y0, lCY, lOY); \
364 Y1 = vec_mradds (Y1, lCY, lOY); \
365 Y2 = vec_mradds (Y2, lCY, lOY); \
366 Y3 = vec_mradds (Y3, lCY, lOY); \
368 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */ \
369 ux = vec_sl (U, lCSHIFT); \
370 ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0)); \
371 ux0 = vec_mergeh (ux,ux); \
372 ux1 = vec_mergel (ux,ux); \
374 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */ \
375 vx = vec_sl (V, lCSHIFT); \
376 vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0)); \
377 vx0 = vec_mergeh (vx,vx); \
378 vx1 = vec_mergel (vx,vx); \
380 /* uvx = ((CGU*u) + (CGV*v))>>15 */ \
381 uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0)); \
382 uvx = vec_mradds (V, lCGV, uvx); \
383 uvx0 = vec_mergeh (uvx,uvx); \
384 uvx1 = vec_mergel (uvx,uvx); \
386 R0 = vec_add (Y0,vx0); \
387 G0 = vec_add (Y0,uvx0); \
388 B0 = vec_add (Y0,ux0); \
389 R1 = vec_add (Y1,vx1); \
390 G1 = vec_add (Y1,uvx1); \
391 B1 = vec_add (Y1,ux1); \
393 R = vec_packclp (R0,R1); \
394 G = vec_packclp (G0,G1); \
395 B = vec_packclp (B0,B1); \
397 out_pixels(R,G,B,oute); \
399 R0 = vec_add (Y2,vx0); \
400 G0 = vec_add (Y2,uvx0); \
401 B0 = vec_add (Y2,ux0); \
402 R1 = vec_add (Y3,vx1); \
403 G1 = vec_add (Y3,uvx1); \
404 B1 = vec_add (Y3,ux1); \
405 R = vec_packclp (R0,R1); \
406 G = vec_packclp (G0,G1); \
407 B = vec_packclp (B0,B1); \
410 out_pixels(R,G,B,outo); \
419 outo += (outstrides[0])>>4; \
420 oute += (outstrides[0])>>4; \
422 ui += instrides_scl[1]; \
423 vi += instrides_scl[2]; \
424 y1i += instrides_scl[0]; \
425 y2i += instrides_scl[0]; \
431 #define out_abgr(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),c,b,a,ptr)
432 #define out_bgra(a,b,c,ptr) vec_mstrgb32(typeof(a),c,b,a,((typeof (a))AVV(0)),ptr)
433 #define out_rgba(a,b,c,ptr) vec_mstrgb32(typeof(a),a,b,c,((typeof (a))AVV(0)),ptr)
434 #define out_argb(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,b,c,ptr)
435 #define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr)
436 #define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr)
438 DEFCSP420_CVT (yuv2_abgr, out_abgr)
440 DEFCSP420_CVT (yuv2_bgra, out_bgra)
442 static int altivec_yuv2_bgra32 (SwsContext *c,
443 unsigned char **in, int *instrides,
444 int srcSliceY, int srcSliceH,
445 unsigned char **oplanes, int *outstrides)
450 int instrides_scl[3];
451 vector unsigned char y0,y1;
453 vector signed char u,v;
455 vector signed short Y0,Y1,Y2,Y3;
456 vector signed short U,V;
457 vector signed short vx,ux,uvx;
458 vector signed short vx0,ux0,uvx0;
459 vector signed short vx1,ux1,uvx1;
460 vector signed short R0,G0,B0;
461 vector signed short R1,G1,B1;
462 vector unsigned char R,G,B;
464 vector unsigned char *uivP, *vivP;
465 vector unsigned char align_perm;
475 vector unsigned short lCSHIFT = c->CSHIFT;
478 ubyte *y2i = in[0]+w;
482 vector unsigned char *oute
483 = (vector unsigned char *)
484 (oplanes[0]+srcSliceY*outstrides[0]);
485 vector unsigned char *outo
486 = (vector unsigned char *)
487 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);
490 instrides_scl[0] = instrides[0];
491 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */
492 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */
495 for (i=0;i<h/2;i++) {
496 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);
497 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);
499 for (j=0;j<w/16;j++) {
501 y0 = vec_ldl (0,y1i);
502 y1 = vec_ldl (0,y2i);
503 uivP = (vector unsigned char *)ui;
504 vivP = (vector unsigned char *)vi;
506 align_perm = vec_lvsl (0, ui);
507 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);
509 align_perm = vec_lvsl (0, vi);
510 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);
511 u = (vector signed char)
512 vec_sub (u,(vector signed char)
513 vec_splat((vector signed char)AVV(128),0));
515 v = (vector signed char)
516 vec_sub (v, (vector signed char)
517 vec_splat((vector signed char)AVV(128),0));
528 Y0 = vec_mradds (Y0, lCY, lOY);
529 Y1 = vec_mradds (Y1, lCY, lOY);
530 Y2 = vec_mradds (Y2, lCY, lOY);
531 Y3 = vec_mradds (Y3, lCY, lOY);
533 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */
534 ux = vec_sl (U, lCSHIFT);
535 ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));
536 ux0 = vec_mergeh (ux,ux);
537 ux1 = vec_mergel (ux,ux);
539 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */
540 vx = vec_sl (V, lCSHIFT);
541 vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));
542 vx0 = vec_mergeh (vx,vx);
543 vx1 = vec_mergel (vx,vx);
544 /* uvx = ((CGU*u) + (CGV*v))>>15 */
545 uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));
546 uvx = vec_mradds (V, lCGV, uvx);
547 uvx0 = vec_mergeh (uvx,uvx);
548 uvx1 = vec_mergel (uvx,uvx);
549 R0 = vec_add (Y0,vx0);
550 G0 = vec_add (Y0,uvx0);
551 B0 = vec_add (Y0,ux0);
552 R1 = vec_add (Y1,vx1);
553 G1 = vec_add (Y1,uvx1);
554 B1 = vec_add (Y1,ux1);
555 R = vec_packclp (R0,R1);
556 G = vec_packclp (G0,G1);
557 B = vec_packclp (B0,B1);
559 out_argb(R,G,B,oute);
560 R0 = vec_add (Y2,vx0);
561 G0 = vec_add (Y2,uvx0);
562 B0 = vec_add (Y2,ux0);
563 R1 = vec_add (Y3,vx1);
564 G1 = vec_add (Y3,uvx1);
565 B1 = vec_add (Y3,ux1);
566 R = vec_packclp (R0,R1);
567 G = vec_packclp (G0,G1);
568 B = vec_packclp (B0,B1);
570 out_argb(R,G,B,outo);
578 outo += (outstrides[0])>>4;
579 oute += (outstrides[0])>>4;
581 ui += instrides_scl[1];
582 vi += instrides_scl[2];
583 y1i += instrides_scl[0];
584 y2i += instrides_scl[0];
592 DEFCSP420_CVT (yuv2_rgba, out_rgba)
593 DEFCSP420_CVT (yuv2_argb, out_argb)
594 DEFCSP420_CVT (yuv2_rgb24, out_rgb24)
595 DEFCSP420_CVT (yuv2_bgr24, out_bgr24)
598 // uyvy|uyvy|uyvy|uyvy
599 // 0123 4567 89ab cdef
601 const vector unsigned char
602 demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
605 0x10,0x0c,0x10,0x0c),
606 demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
609 0x10,0x0E,0x10,0x0E),
610 demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
613 0x10,0x0D,0x10,0x0F);
616 this is so I can play live CCIR raw video
618 static int altivec_uyvy_rgb32 (SwsContext *c,
619 unsigned char **in, int *instrides,
620 int srcSliceY, int srcSliceH,
621 unsigned char **oplanes, int *outstrides)
626 vector unsigned char uyvy;
627 vector signed short Y,U,V;
628 vector signed short vx,ux,uvx;
629 vector signed short R0,G0,B0,R1,G1,B1;
630 vector unsigned char R,G,B;
631 vector unsigned char *out;
635 out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
638 for (j=0;j<w/16;j++) {
639 uyvy = vec_ld (0, img);
640 U = (vector signed short)
641 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
643 V = (vector signed short)
644 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
646 Y = (vector signed short)
647 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
649 cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
651 uyvy = vec_ld (16, img);
652 U = (vector signed short)
653 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
655 V = (vector signed short)
656 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
658 Y = (vector signed short)
659 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
661 cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
663 R = vec_packclp (R0,R1);
664 G = vec_packclp (G0,G1);
665 B = vec_packclp (B0,B1);
667 // vec_mstbgr24 (R,G,B, out);
668 out_rgba (R,G,B,out);
678 /* Ok currently the acceleration routine only supports
679 inputs of widths a multiple of 16
680 and heights a multiple 2
682 So we just fall back to the C codes for this.
684 SwsFunc yuv2rgb_init_altivec (SwsContext *c)
686 if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))
690 and this seems not to matter too much I tried a bunch of
691 videos with abnormal widths and mplayer crashes else where.
692 mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv
693 boom with X11 bad match.
696 if ((c->srcW & 0xf) != 0) return NULL;
698 switch (c->srcFormat) {
699 case PIX_FMT_YUV410P:
700 case PIX_FMT_YUV420P:
701 /*case IMGFMT_CLPL: ??? */
705 if ((c->srcH & 0x1) != 0)
708 switch(c->dstFormat){
710 MSG_WARN("ALTIVEC: Color Space RGB24\n");
711 return altivec_yuv2_rgb24;
713 MSG_WARN("ALTIVEC: Color Space BGR24\n");
714 return altivec_yuv2_bgr24;
716 MSG_WARN("ALTIVEC: Color Space ARGB\n");
717 return altivec_yuv2_argb;
719 MSG_WARN("ALTIVEC: Color Space ABGR\n");
720 return altivec_yuv2_abgr;
722 MSG_WARN("ALTIVEC: Color Space RGBA\n");
723 return altivec_yuv2_rgba;
725 MSG_WARN("ALTIVEC: Color Space BGRA\n");
726 return altivec_yuv2_bgra;
727 default: return NULL;
731 case PIX_FMT_UYVY422:
732 switch(c->dstFormat){
734 MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
735 return altivec_uyvy_rgb32;
736 default: return NULL;
744 static uint16_t roundToInt16(int64_t f){
745 int r= (f + (1<<15))>>16;
746 if(r<-0x7FFF) return 0x8000;
747 else if(r> 0x7FFF) return 0x7FFF;
751 void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
754 signed short tmp[8] __attribute__ ((aligned(16)));
755 vector signed short vec;
758 buf.tmp[0] = ( (0xffffLL) * contrast>>8 )>>9; //cy
759 buf.tmp[1] = -256*brightness; //oy
760 buf.tmp[2] = (inv_table[0]>>3) *(contrast>>16)*(saturation>>16); //crv
761 buf.tmp[3] = (inv_table[1]>>3) *(contrast>>16)*(saturation>>16); //cbu
762 buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16)); //cgu
763 buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16)); //cgv
766 c->CSHIFT = (vector unsigned short)vec_splat_u16(2);
767 c->CY = vec_splat ((vector signed short)buf.vec, 0);
768 c->OY = vec_splat ((vector signed short)buf.vec, 1);
769 c->CRV = vec_splat ((vector signed short)buf.vec, 2);
770 c->CBU = vec_splat ((vector signed short)buf.vec, 3);
771 c->CGU = vec_splat ((vector signed short)buf.vec, 4);
772 c->CGV = vec_splat ((vector signed short)buf.vec, 5);
776 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
778 printf("%s %d ", v[i],buf.tmp[i] );
787 altivec_yuv2packedX (SwsContext *c,
788 int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
789 int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
790 uint8_t *dest, int dstW, int dstY)
794 vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V;
795 vector signed short R0,G0,B0,R1,G1,B1;
797 vector unsigned char R,G,B,pels[3];
798 vector unsigned char *out,*nout;
800 vector signed short RND = vec_splat_s16(1<<3);
801 vector unsigned short SCL = vec_splat_u16(4);
802 unsigned long scratch[16] __attribute__ ((aligned (16)));
804 vector signed short *YCoeffs, *CCoeffs;
806 YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
807 CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
809 out = (vector unsigned char *)dest;
811 for(i=0; i<dstW; i+=16){
814 /* extract 16 coeffs from lumSrc */
815 for(j=0; j<lumFilterSize; j++) {
816 X0 = vec_ld (0, &lumSrc[j][i]);
817 X1 = vec_ld (16, &lumSrc[j][i]);
818 Y0 = vec_mradds (X0, YCoeffs[j], Y0);
819 Y1 = vec_mradds (X1, YCoeffs[j], Y1);
824 /* extract 8 coeffs from U,V */
825 for(j=0; j<chrFilterSize; j++) {
826 X = vec_ld (0, &chrSrc[j][i/2]);
827 U = vec_mradds (X, CCoeffs[j], U);
828 X = vec_ld (0, &chrSrc[j][i/2+2048]);
829 V = vec_mradds (X, CCoeffs[j], V);
832 /* scale and clip signals */
833 Y0 = vec_sra (Y0, SCL);
834 Y1 = vec_sra (Y1, SCL);
835 U = vec_sra (U, SCL);
836 V = vec_sra (V, SCL);
838 Y0 = vec_clip_s16 (Y0);
839 Y1 = vec_clip_s16 (Y1);
840 U = vec_clip_s16 (U);
841 V = vec_clip_s16 (V);
844 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
845 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
847 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
848 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
849 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
852 U0 = vec_mergeh (U,U);
853 V0 = vec_mergeh (V,V);
855 U1 = vec_mergel (U,U);
856 V1 = vec_mergel (V,V);
858 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
859 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
861 R = vec_packclp (R0,R1);
862 G = vec_packclp (G0,G1);
863 B = vec_packclp (B0,B1);
865 switch(c->dstFormat) {
866 case PIX_FMT_ABGR: out_abgr (R,G,B,out); break;
867 case PIX_FMT_BGRA: out_bgra (R,G,B,out); break;
868 case PIX_FMT_RGBA: out_rgba (R,G,B,out); break;
869 case PIX_FMT_ARGB: out_argb (R,G,B,out); break;
870 case PIX_FMT_RGB24: out_rgb24 (R,G,B,out); break;
871 case PIX_FMT_BGR24: out_bgr24 (R,G,B,out); break;
874 /* If this is reached, the caller should have called yuv2packedXinC
876 static int printed_error_message;
877 if(!printed_error_message) {
878 MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
879 sws_format_name(c->dstFormat));
880 printed_error_message=1;
892 /* extract 16 coeffs from lumSrc */
893 for(j=0; j<lumFilterSize; j++) {
894 X0 = vec_ld (0, &lumSrc[j][i]);
895 X1 = vec_ld (16, &lumSrc[j][i]);
896 Y0 = vec_mradds (X0, YCoeffs[j], Y0);
897 Y1 = vec_mradds (X1, YCoeffs[j], Y1);
902 /* extract 8 coeffs from U,V */
903 for(j=0; j<chrFilterSize; j++) {
904 X = vec_ld (0, &chrSrc[j][i/2]);
905 U = vec_mradds (X, CCoeffs[j], U);
906 X = vec_ld (0, &chrSrc[j][i/2+2048]);
907 V = vec_mradds (X, CCoeffs[j], V);
910 /* scale and clip signals */
911 Y0 = vec_sra (Y0, SCL);
912 Y1 = vec_sra (Y1, SCL);
913 U = vec_sra (U, SCL);
914 V = vec_sra (V, SCL);
916 Y0 = vec_clip_s16 (Y0);
917 Y1 = vec_clip_s16 (Y1);
918 U = vec_clip_s16 (U);
919 V = vec_clip_s16 (V);
922 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
923 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
925 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
926 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
927 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
930 U0 = vec_mergeh (U,U);
931 V0 = vec_mergeh (V,V);
933 U1 = vec_mergel (U,U);
934 V1 = vec_mergel (V,V);
936 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
937 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
939 R = vec_packclp (R0,R1);
940 G = vec_packclp (G0,G1);
941 B = vec_packclp (B0,B1);
943 nout = (vector unsigned char *)scratch;
944 switch(c->dstFormat) {
945 case PIX_FMT_ABGR: out_abgr (R,G,B,nout); break;
946 case PIX_FMT_BGRA: out_bgra (R,G,B,nout); break;
947 case PIX_FMT_RGBA: out_rgba (R,G,B,nout); break;
948 case PIX_FMT_ARGB: out_argb (R,G,B,nout); break;
949 case PIX_FMT_RGB24: out_rgb24 (R,G,B,nout); break;
950 case PIX_FMT_BGR24: out_bgr24 (R,G,B,nout); break;
952 /* Unreachable, I think. */
953 MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
954 sws_format_name(c->dstFormat));
958 memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);