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.
76 #include "swscale_internal.h"
77 #include "libmpcodecs/img_format.h" //FIXME try to reduce dependency of such stuff
79 #undef PROFILE_THE_BEAST
82 typedef unsigned char ubyte;
83 typedef signed char sbyte;
86 /* RGB interleaver, 16 planar pels 8-bit samples per channel in
87 homogeneous vector registers x0,x1,x2 are interleaved with the
90 o0 = vec_mergeh (x0,x1);
91 o1 = vec_perm (o0, x2, perm_rgb_0);
92 o2 = vec_perm (o0, x2, perm_rgb_1);
93 o3 = vec_mergel (x0,x1);
94 o4 = vec_perm (o3,o2,perm_rgb_2);
95 o5 = vec_perm (o3,o2,perm_rgb_3);
97 perm_rgb_0: o0(RG).h v1(B) --> o1*
103 perm_rgb_1: o0(RG).h v1(B) --> o2
109 perm_rgb_2: o3(RG).l o2(rgbB.l) --> o4*
115 perm_rgb_2: o3(RG).l o2(rgbB.l) ---> o5*
123 const vector unsigned char
124 perm_rgb_0 = (const vector unsigned char)AVV(0x00,0x01,0x10,0x02,0x03,0x11,0x04,0x05,
125 0x12,0x06,0x07,0x13,0x08,0x09,0x14,0x0a),
126 perm_rgb_1 = (const vector unsigned char)AVV(0x0b,0x15,0x0c,0x0d,0x16,0x0e,0x0f,0x17,
127 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f),
128 perm_rgb_2 = (const vector unsigned char)AVV(0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
129 0x00,0x01,0x18,0x02,0x03,0x19,0x04,0x05),
130 perm_rgb_3 = (const vector unsigned char)AVV(0x1a,0x06,0x07,0x1b,0x08,0x09,0x1c,0x0a,
131 0x0b,0x1d,0x0c,0x0d,0x1e,0x0e,0x0f,0x1f);
133 #define vec_merge3(x2,x1,x0,y0,y1,y2) \
135 typeof(x0) o0,o2,o3; \
136 o0 = vec_mergeh (x0,x1); \
137 y0 = vec_perm (o0, x2, perm_rgb_0);\
138 o2 = vec_perm (o0, x2, perm_rgb_1);\
139 o3 = vec_mergel (x0,x1); \
140 y1 = vec_perm (o3,o2,perm_rgb_2); \
141 y2 = vec_perm (o3,o2,perm_rgb_3); \
144 #define vec_mstbgr24(x0,x1,x2,ptr) \
146 typeof(x0) _0,_1,_2; \
147 vec_merge3 (x0,x1,x2,_0,_1,_2); \
148 vec_st (_0, 0, ptr++); \
149 vec_st (_1, 0, ptr++); \
150 vec_st (_2, 0, ptr++); \
153 #define vec_mstrgb24(x0,x1,x2,ptr) \
155 typeof(x0) _0,_1,_2; \
156 vec_merge3 (x2,x1,x0,_0,_1,_2); \
157 vec_st (_0, 0, ptr++); \
158 vec_st (_1, 0, ptr++); \
159 vec_st (_2, 0, ptr++); \
162 /* pack the pixels in rgb0 format
166 #define vec_mstrgb32(T,x0,x1,x2,x3,ptr) \
169 _0 = vec_mergeh (x0,x1); \
170 _1 = vec_mergeh (x2,x3); \
171 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
172 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
173 vec_st (_2, 0*16, (T *)ptr); \
174 vec_st (_3, 1*16, (T *)ptr); \
175 _0 = vec_mergel (x0,x1); \
176 _1 = vec_mergel (x2,x3); \
177 _2 = (T)vec_mergeh ((vector unsigned short)_0,(vector unsigned short)_1); \
178 _3 = (T)vec_mergel ((vector unsigned short)_0,(vector unsigned short)_1); \
179 vec_st (_2, 2*16, (T *)ptr); \
180 vec_st (_3, 3*16, (T *)ptr); \
187 | 1 -0.3441 -0.7142 |x| Cb|
194 typical yuv conversion work on Y: 0-255 this version has been optimized for jpeg decode.
202 (vector signed short) \
203 vec_perm(x,(typeof(x))AVV(0),\
204 (vector unsigned char)AVV(0x10,0x00,0x10,0x01,0x10,0x02,0x10,0x03,\
205 0x10,0x04,0x10,0x05,0x10,0x06,0x10,0x07))
207 (vector signed short) \
208 vec_perm(x,(typeof(x))AVV(0),\
209 (vector unsigned char)AVV(0x10,0x08,0x10,0x09,0x10,0x0A,0x10,0x0B,\
210 0x10,0x0C,0x10,0x0D,0x10,0x0E,0x10,0x0F))
212 #define vec_clip_s16(x) \
213 vec_max (vec_min (x, (vector signed short)AVV(235,235,235,235,235,235,235,235)),\
214 (vector signed short)AVV(16, 16, 16, 16, 16, 16, 16, 16 ))
216 #define vec_packclp(x,y) \
217 (vector unsigned char)vec_packs \
218 ((vector unsigned short)vec_max (x,(vector signed short) AVV(0)), \
219 (vector unsigned short)vec_max (y,(vector signed short) AVV(0)))
221 //#define out_pixels(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,a,a,ptr)
224 static inline void cvtyuvtoRGB (SwsContext *c,
225 vector signed short Y, vector signed short U, vector signed short V,
226 vector signed short *R, vector signed short *G, vector signed short *B)
228 vector signed short vx,ux,uvx;
230 Y = vec_mradds (Y, c->CY, c->OY);
231 U = vec_sub (U,(vector signed short)
232 vec_splat((vector signed short)AVV(128),0));
233 V = vec_sub (V,(vector signed short)
234 vec_splat((vector signed short)AVV(128),0));
236 // ux = (CBU*(u<<c->CSHIFT)+0x4000)>>15;
237 ux = vec_sl (U, c->CSHIFT);
238 *B = vec_mradds (ux, c->CBU, Y);
240 // vx = (CRV*(v<<c->CSHIFT)+0x4000)>>15;
241 vx = vec_sl (V, c->CSHIFT);
242 *R = vec_mradds (vx, c->CRV, Y);
244 // uvx = ((CGU*u) + (CGV*v))>>15;
245 uvx = vec_mradds (U, c->CGU, Y);
246 *G = vec_mradds (V, c->CGV, uvx);
251 ------------------------------------------------------------------------------
253 ------------------------------------------------------------------------------
257 #define DEFCSP420_CVT(name,out_pixels) \
258 static int altivec_##name (SwsContext *c, \
259 unsigned char **in, int *instrides, \
260 int srcSliceY, int srcSliceH, \
261 unsigned char **oplanes, int *outstrides) \
266 int instrides_scl[3]; \
267 vector unsigned char y0,y1; \
269 vector signed char u,v; \
271 vector signed short Y0,Y1,Y2,Y3; \
272 vector signed short U,V; \
273 vector signed short vx,ux,uvx; \
274 vector signed short vx0,ux0,uvx0; \
275 vector signed short vx1,ux1,uvx1; \
276 vector signed short R0,G0,B0; \
277 vector signed short R1,G1,B1; \
278 vector unsigned char R,G,B; \
280 vector unsigned char *y1ivP, *y2ivP, *uivP, *vivP; \
281 vector unsigned char align_perm; \
283 vector signed short \
291 vector unsigned short lCSHIFT = c->CSHIFT; \
293 ubyte *y1i = in[0]; \
294 ubyte *y2i = in[0]+instrides[0]; \
298 vector unsigned char *oute \
299 = (vector unsigned char *) \
300 (oplanes[0]+srcSliceY*outstrides[0]); \
301 vector unsigned char *outo \
302 = (vector unsigned char *) \
303 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]); \
306 instrides_scl[0] = instrides[0]*2-w; /* the loop moves y{1,2}i by w */ \
307 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */ \
308 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */ \
311 for (i=0;i<h/2;i++) { \
312 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0); \
313 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1); \
315 for (j=0;j<w/16;j++) { \
317 y1ivP = (vector unsigned char *)y1i; \
318 y2ivP = (vector unsigned char *)y2i; \
319 uivP = (vector unsigned char *)ui; \
320 vivP = (vector unsigned char *)vi; \
322 align_perm = vec_lvsl (0, y1i); \
323 y0 = (vector unsigned char)vec_perm (y1ivP[0], y1ivP[1], align_perm);\
325 align_perm = vec_lvsl (0, y2i); \
326 y1 = (vector unsigned char)vec_perm (y2ivP[0], y2ivP[1], align_perm);\
328 align_perm = vec_lvsl (0, ui); \
329 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm); \
331 align_perm = vec_lvsl (0, vi); \
332 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm); \
334 u = (vector signed char) \
335 vec_sub (u,(vector signed char) \
336 vec_splat((vector signed char)AVV(128),0));\
337 v = (vector signed char) \
338 vec_sub (v,(vector signed char) \
339 vec_splat((vector signed char)AVV(128),0));\
341 U = vec_unpackh (u); \
342 V = vec_unpackh (v); \
350 Y0 = vec_mradds (Y0, lCY, lOY); \
351 Y1 = vec_mradds (Y1, lCY, lOY); \
352 Y2 = vec_mradds (Y2, lCY, lOY); \
353 Y3 = vec_mradds (Y3, lCY, lOY); \
355 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */ \
356 ux = vec_sl (U, lCSHIFT); \
357 ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0)); \
358 ux0 = vec_mergeh (ux,ux); \
359 ux1 = vec_mergel (ux,ux); \
361 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */ \
362 vx = vec_sl (V, lCSHIFT); \
363 vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0)); \
364 vx0 = vec_mergeh (vx,vx); \
365 vx1 = vec_mergel (vx,vx); \
367 /* uvx = ((CGU*u) + (CGV*v))>>15 */ \
368 uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0)); \
369 uvx = vec_mradds (V, lCGV, uvx); \
370 uvx0 = vec_mergeh (uvx,uvx); \
371 uvx1 = vec_mergel (uvx,uvx); \
373 R0 = vec_add (Y0,vx0); \
374 G0 = vec_add (Y0,uvx0); \
375 B0 = vec_add (Y0,ux0); \
376 R1 = vec_add (Y1,vx1); \
377 G1 = vec_add (Y1,uvx1); \
378 B1 = vec_add (Y1,ux1); \
380 R = vec_packclp (R0,R1); \
381 G = vec_packclp (G0,G1); \
382 B = vec_packclp (B0,B1); \
384 out_pixels(R,G,B,oute); \
386 R0 = vec_add (Y2,vx0); \
387 G0 = vec_add (Y2,uvx0); \
388 B0 = vec_add (Y2,ux0); \
389 R1 = vec_add (Y3,vx1); \
390 G1 = vec_add (Y3,uvx1); \
391 B1 = vec_add (Y3,ux1); \
392 R = vec_packclp (R0,R1); \
393 G = vec_packclp (G0,G1); \
394 B = vec_packclp (B0,B1); \
397 out_pixels(R,G,B,outo); \
406 outo += (outstrides[0])>>4; \
407 oute += (outstrides[0])>>4; \
409 ui += instrides_scl[1]; \
410 vi += instrides_scl[2]; \
411 y1i += instrides_scl[0]; \
412 y2i += instrides_scl[0]; \
418 #define out_abgr(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),c,b,a,ptr)
419 #define out_bgra(a,b,c,ptr) vec_mstrgb32(typeof(a),c,b,a,((typeof (a))AVV(0)),ptr)
420 #define out_rgba(a,b,c,ptr) vec_mstrgb32(typeof(a),a,b,c,((typeof (a))AVV(0)),ptr)
421 #define out_argb(a,b,c,ptr) vec_mstrgb32(typeof(a),((typeof (a))AVV(0)),a,b,c,ptr)
422 #define out_rgb24(a,b,c,ptr) vec_mstrgb24(a,b,c,ptr)
423 #define out_bgr24(a,b,c,ptr) vec_mstbgr24(a,b,c,ptr)
425 DEFCSP420_CVT (yuv2_abgr, out_abgr)
427 DEFCSP420_CVT (yuv2_bgra, out_bgra)
429 static int altivec_yuv2_bgra32 (SwsContext *c,
430 unsigned char **in, int *instrides,
431 int srcSliceY, int srcSliceH,
432 unsigned char **oplanes, int *outstrides)
437 int instrides_scl[3];
438 vector unsigned char y0,y1;
440 vector signed char u,v;
442 vector signed short Y0,Y1,Y2,Y3;
443 vector signed short U,V;
444 vector signed short vx,ux,uvx;
445 vector signed short vx0,ux0,uvx0;
446 vector signed short vx1,ux1,uvx1;
447 vector signed short R0,G0,B0;
448 vector signed short R1,G1,B1;
449 vector unsigned char R,G,B;
451 vector unsigned char *uivP, *vivP;
452 vector unsigned char align_perm;
462 vector unsigned short lCSHIFT = c->CSHIFT;
465 ubyte *y2i = in[0]+w;
469 vector unsigned char *oute
470 = (vector unsigned char *)
471 (oplanes[0]+srcSliceY*outstrides[0]);
472 vector unsigned char *outo
473 = (vector unsigned char *)
474 (oplanes[0]+srcSliceY*outstrides[0]+outstrides[0]);
477 instrides_scl[0] = instrides[0];
478 instrides_scl[1] = instrides[1]-w/2; /* the loop moves ui by w/2 */
479 instrides_scl[2] = instrides[2]-w/2; /* the loop moves vi by w/2 */
482 for (i=0;i<h/2;i++) {
483 vec_dstst (outo, (0x02000002|(((w*3+32)/32)<<16)), 0);
484 vec_dstst (oute, (0x02000002|(((w*3+32)/32)<<16)), 1);
486 for (j=0;j<w/16;j++) {
488 y0 = vec_ldl (0,y1i);
489 y1 = vec_ldl (0,y2i);
490 uivP = (vector unsigned char *)ui;
491 vivP = (vector unsigned char *)vi;
493 align_perm = vec_lvsl (0, ui);
494 u = (vector signed char)vec_perm (uivP[0], uivP[1], align_perm);
496 align_perm = vec_lvsl (0, vi);
497 v = (vector signed char)vec_perm (vivP[0], vivP[1], align_perm);
498 u = (vector signed char)
499 vec_sub (u,(vector signed char)
500 vec_splat((vector signed char)AVV(128),0));
502 v = (vector signed char)
503 vec_sub (v, (vector signed char)
504 vec_splat((vector signed char)AVV(128),0));
515 Y0 = vec_mradds (Y0, lCY, lOY);
516 Y1 = vec_mradds (Y1, lCY, lOY);
517 Y2 = vec_mradds (Y2, lCY, lOY);
518 Y3 = vec_mradds (Y3, lCY, lOY);
520 /* ux = (CBU*(u<<CSHIFT)+0x4000)>>15 */
521 ux = vec_sl (U, lCSHIFT);
522 ux = vec_mradds (ux, lCBU, (vector signed short)AVV(0));
523 ux0 = vec_mergeh (ux,ux);
524 ux1 = vec_mergel (ux,ux);
526 /* vx = (CRV*(v<<CSHIFT)+0x4000)>>15; */
527 vx = vec_sl (V, lCSHIFT);
528 vx = vec_mradds (vx, lCRV, (vector signed short)AVV(0));
529 vx0 = vec_mergeh (vx,vx);
530 vx1 = vec_mergel (vx,vx);
531 /* uvx = ((CGU*u) + (CGV*v))>>15 */
532 uvx = vec_mradds (U, lCGU, (vector signed short)AVV(0));
533 uvx = vec_mradds (V, lCGV, uvx);
534 uvx0 = vec_mergeh (uvx,uvx);
535 uvx1 = vec_mergel (uvx,uvx);
536 R0 = vec_add (Y0,vx0);
537 G0 = vec_add (Y0,uvx0);
538 B0 = vec_add (Y0,ux0);
539 R1 = vec_add (Y1,vx1);
540 G1 = vec_add (Y1,uvx1);
541 B1 = vec_add (Y1,ux1);
542 R = vec_packclp (R0,R1);
543 G = vec_packclp (G0,G1);
544 B = vec_packclp (B0,B1);
546 out_argb(R,G,B,oute);
547 R0 = vec_add (Y2,vx0);
548 G0 = vec_add (Y2,uvx0);
549 B0 = vec_add (Y2,ux0);
550 R1 = vec_add (Y3,vx1);
551 G1 = vec_add (Y3,uvx1);
552 B1 = vec_add (Y3,ux1);
553 R = vec_packclp (R0,R1);
554 G = vec_packclp (G0,G1);
555 B = vec_packclp (B0,B1);
557 out_argb(R,G,B,outo);
565 outo += (outstrides[0])>>4;
566 oute += (outstrides[0])>>4;
568 ui += instrides_scl[1];
569 vi += instrides_scl[2];
570 y1i += instrides_scl[0];
571 y2i += instrides_scl[0];
579 DEFCSP420_CVT (yuv2_rgba, out_rgba)
580 DEFCSP420_CVT (yuv2_argb, out_argb)
581 DEFCSP420_CVT (yuv2_rgb24, out_rgb24)
582 DEFCSP420_CVT (yuv2_bgr24, out_bgr24)
585 // uyvy|uyvy|uyvy|uyvy
586 // 0123 4567 89ab cdef
588 const vector unsigned char
589 demux_u = (const vector unsigned char)AVV(0x10,0x00,0x10,0x00,
592 0x10,0x0c,0x10,0x0c),
593 demux_v = (const vector unsigned char)AVV(0x10,0x02,0x10,0x02,
596 0x10,0x0E,0x10,0x0E),
597 demux_y = (const vector unsigned char)AVV(0x10,0x01,0x10,0x03,
600 0x10,0x0D,0x10,0x0F);
603 this is so I can play live CCIR raw video
605 static int altivec_uyvy_rgb32 (SwsContext *c,
606 unsigned char **in, int *instrides,
607 int srcSliceY, int srcSliceH,
608 unsigned char **oplanes, int *outstrides)
613 vector unsigned char uyvy;
614 vector signed short Y,U,V;
615 vector signed short vx,ux,uvx;
616 vector signed short R0,G0,B0,R1,G1,B1;
617 vector unsigned char R,G,B;
618 vector unsigned char *out;
622 out = (vector unsigned char *)(oplanes[0]+srcSliceY*outstrides[0]);
625 for (j=0;j<w/16;j++) {
626 uyvy = vec_ld (0, img);
627 U = (vector signed short)
628 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
630 V = (vector signed short)
631 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
633 Y = (vector signed short)
634 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
636 cvtyuvtoRGB (c, Y,U,V,&R0,&G0,&B0);
638 uyvy = vec_ld (16, img);
639 U = (vector signed short)
640 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_u);
642 V = (vector signed short)
643 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_v);
645 Y = (vector signed short)
646 vec_perm (uyvy, (vector unsigned char)AVV(0), demux_y);
648 cvtyuvtoRGB (c, Y,U,V,&R1,&G1,&B1);
650 R = vec_packclp (R0,R1);
651 G = vec_packclp (G0,G1);
652 B = vec_packclp (B0,B1);
654 // vec_mstbgr24 (R,G,B, out);
655 out_rgba (R,G,B,out);
665 /* Ok currently the acceleration routine only supports
666 inputs of widths a multiple of 16
667 and heights a multiple 2
669 So we just fall back to the C codes for this.
671 SwsFunc yuv2rgb_init_altivec (SwsContext *c)
673 if (!(c->flags & SWS_CPU_CAPS_ALTIVEC))
677 and this seems not to matter too much I tried a bunch of
678 videos with abnormal widths and mplayer crashes else where.
679 mplayer -vo x11 -rawvideo on:w=350:h=240 raw-350x240.eyuv
680 boom with X11 bad match.
683 if ((c->srcW & 0xf) != 0) return NULL;
685 switch (c->srcFormat) {
696 if ((c->srcH & 0x1) != 0)
699 switch(c->dstFormat){
701 MSG_WARN("ALTIVEC: Color Space RGB24\n");
702 return altivec_yuv2_rgb24;
704 MSG_WARN("ALTIVEC: Color Space BGR24\n");
705 return altivec_yuv2_bgr24;
707 MSG_WARN("ALTIVEC: Color Space ARGB\n");
708 return altivec_yuv2_argb;
710 MSG_WARN("ALTIVEC: Color Space ABGR\n");
711 return altivec_yuv2_abgr;
713 MSG_WARN("ALTIVEC: Color Space RGBA\n");
714 return altivec_yuv2_rgba;
716 MSG_WARN("ALTIVEC: Color Space BGRA\n");
717 return altivec_yuv2_bgra;
718 default: return NULL;
723 switch(c->dstFormat){
725 MSG_WARN("ALTIVEC: Color Space UYVY -> RGB32\n");
726 return altivec_uyvy_rgb32;
727 default: return NULL;
735 static uint16_t roundToInt16(int64_t f){
736 int r= (f + (1<<15))>>16;
737 if(r<-0x7FFF) return 0x8000;
738 else if(r> 0x7FFF) return 0x7FFF;
742 void yuv2rgb_altivec_init_tables (SwsContext *c, const int inv_table[4],int brightness,int contrast, int saturation)
745 signed short tmp[8] __attribute__ ((aligned(16)));
746 vector signed short vec;
749 buf.tmp[0] = ( (0xffffLL) * contrast>>8 )>>9; //cy
750 buf.tmp[1] = -256*brightness; //oy
751 buf.tmp[2] = (inv_table[0]>>3) *(contrast>>16)*(saturation>>16); //crv
752 buf.tmp[3] = (inv_table[1]>>3) *(contrast>>16)*(saturation>>16); //cbu
753 buf.tmp[4] = -((inv_table[2]>>1)*(contrast>>16)*(saturation>>16)); //cgu
754 buf.tmp[5] = -((inv_table[3]>>1)*(contrast>>16)*(saturation>>16)); //cgv
757 c->CSHIFT = (vector unsigned short)vec_splat_u16(2);
758 c->CY = vec_splat ((vector signed short)buf.vec, 0);
759 c->OY = vec_splat ((vector signed short)buf.vec, 1);
760 c->CRV = vec_splat ((vector signed short)buf.vec, 2);
761 c->CBU = vec_splat ((vector signed short)buf.vec, 3);
762 c->CGU = vec_splat ((vector signed short)buf.vec, 4);
763 c->CGV = vec_splat ((vector signed short)buf.vec, 5);
767 char *v[6]={"cy","oy","crv","cbu","cgu","cgv"};
769 printf("%s %d ", v[i],buf.tmp[i] );
778 altivec_yuv2packedX (SwsContext *c,
779 int16_t *lumFilter, int16_t **lumSrc, int lumFilterSize,
780 int16_t *chrFilter, int16_t **chrSrc, int chrFilterSize,
781 uint8_t *dest, int dstW, int dstY)
785 vector signed short X,X0,X1,Y0,U0,V0,Y1,U1,V1,U,V;
786 vector signed short R0,G0,B0,R1,G1,B1;
788 vector unsigned char R,G,B,pels[3];
789 vector unsigned char *out,*nout;
791 vector signed short RND = vec_splat_s16(1<<3);
792 vector unsigned short SCL = vec_splat_u16(4);
793 unsigned long scratch[16] __attribute__ ((aligned (16)));
795 vector signed short *YCoeffs, *CCoeffs;
797 YCoeffs = c->vYCoeffsBank+dstY*lumFilterSize;
798 CCoeffs = c->vCCoeffsBank+dstY*chrFilterSize;
800 out = (vector unsigned char *)dest;
802 for(i=0; i<dstW; i+=16){
805 /* extract 16 coeffs from lumSrc */
806 for(j=0; j<lumFilterSize; j++) {
807 X0 = vec_ld (0, &lumSrc[j][i]);
808 X1 = vec_ld (16, &lumSrc[j][i]);
809 Y0 = vec_mradds (X0, YCoeffs[j], Y0);
810 Y1 = vec_mradds (X1, YCoeffs[j], Y1);
815 /* extract 8 coeffs from U,V */
816 for(j=0; j<chrFilterSize; j++) {
817 X = vec_ld (0, &chrSrc[j][i/2]);
818 U = vec_mradds (X, CCoeffs[j], U);
819 X = vec_ld (0, &chrSrc[j][i/2+2048]);
820 V = vec_mradds (X, CCoeffs[j], V);
823 /* scale and clip signals */
824 Y0 = vec_sra (Y0, SCL);
825 Y1 = vec_sra (Y1, SCL);
826 U = vec_sra (U, SCL);
827 V = vec_sra (V, SCL);
829 Y0 = vec_clip_s16 (Y0);
830 Y1 = vec_clip_s16 (Y1);
831 U = vec_clip_s16 (U);
832 V = vec_clip_s16 (V);
835 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
836 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
838 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
839 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
840 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
843 U0 = vec_mergeh (U,U);
844 V0 = vec_mergeh (V,V);
846 U1 = vec_mergel (U,U);
847 V1 = vec_mergel (V,V);
849 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
850 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
852 R = vec_packclp (R0,R1);
853 G = vec_packclp (G0,G1);
854 B = vec_packclp (B0,B1);
856 switch(c->dstFormat) {
857 case IMGFMT_ABGR: out_abgr (R,G,B,out); break;
858 case IMGFMT_BGRA: out_bgra (R,G,B,out); break;
859 case IMGFMT_RGBA: out_rgba (R,G,B,out); break;
860 case IMGFMT_ARGB: out_argb (R,G,B,out); break;
861 case IMGFMT_RGB24: out_rgb24 (R,G,B,out); break;
862 case IMGFMT_BGR24: out_bgr24 (R,G,B,out); break;
865 /* If this is reached, the caller should have called yuv2packedXinC
867 static int printed_error_message;
868 if(!printed_error_message) {
869 MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
870 sws_format_name(c->dstFormat));
871 printed_error_message=1;
883 /* extract 16 coeffs from lumSrc */
884 for(j=0; j<lumFilterSize; j++) {
885 X0 = vec_ld (0, &lumSrc[j][i]);
886 X1 = vec_ld (16, &lumSrc[j][i]);
887 Y0 = vec_mradds (X0, YCoeffs[j], Y0);
888 Y1 = vec_mradds (X1, YCoeffs[j], Y1);
893 /* extract 8 coeffs from U,V */
894 for(j=0; j<chrFilterSize; j++) {
895 X = vec_ld (0, &chrSrc[j][i/2]);
896 U = vec_mradds (X, CCoeffs[j], U);
897 X = vec_ld (0, &chrSrc[j][i/2+2048]);
898 V = vec_mradds (X, CCoeffs[j], V);
901 /* scale and clip signals */
902 Y0 = vec_sra (Y0, SCL);
903 Y1 = vec_sra (Y1, SCL);
904 U = vec_sra (U, SCL);
905 V = vec_sra (V, SCL);
907 Y0 = vec_clip_s16 (Y0);
908 Y1 = vec_clip_s16 (Y1);
909 U = vec_clip_s16 (U);
910 V = vec_clip_s16 (V);
913 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
914 U= u0 u1 u2 u3 u4 u5 u6 u7 V= v0 v1 v2 v3 v4 v5 v6 v7
916 Y0= y0 y1 y2 y3 y4 y5 y6 y7 Y1= y8 y9 y10 y11 y12 y13 y14 y15
917 U0= u0 u0 u1 u1 u2 u2 u3 u3 U1= u4 u4 u5 u5 u6 u6 u7 u7
918 V0= v0 v0 v1 v1 v2 v2 v3 v3 V1= v4 v4 v5 v5 v6 v6 v7 v7
921 U0 = vec_mergeh (U,U);
922 V0 = vec_mergeh (V,V);
924 U1 = vec_mergel (U,U);
925 V1 = vec_mergel (V,V);
927 cvtyuvtoRGB (c, Y0,U0,V0,&R0,&G0,&B0);
928 cvtyuvtoRGB (c, Y1,U1,V1,&R1,&G1,&B1);
930 R = vec_packclp (R0,R1);
931 G = vec_packclp (G0,G1);
932 B = vec_packclp (B0,B1);
934 nout = (vector unsigned char *)scratch;
935 switch(c->dstFormat) {
936 case IMGFMT_ABGR: out_abgr (R,G,B,nout); break;
937 case IMGFMT_BGRA: out_bgra (R,G,B,nout); break;
938 case IMGFMT_RGBA: out_rgba (R,G,B,nout); break;
939 case IMGFMT_ARGB: out_argb (R,G,B,nout); break;
940 case IMGFMT_RGB24: out_rgb24 (R,G,B,nout); break;
941 case IMGFMT_BGR24: out_bgr24 (R,G,B,nout); break;
943 /* Unreachable, I think. */
944 MSG_ERR("altivec_yuv2packedX doesn't support %s output\n",
945 sws_format_name(c->dstFormat));
949 memcpy (&((uint32_t*)dest)[i], scratch, (dstW-i)/4);